@abtnode/core 1.17.8-beta-20260109-075740-5f484e08 → 1.17.8-beta-20260111-112953-aed5ff39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/lib/api/team/access-key-manager.js +104 -0
  2. package/lib/api/team/invitation-manager.js +461 -0
  3. package/lib/api/team/notification-manager.js +189 -0
  4. package/lib/api/team/oauth-manager.js +60 -0
  5. package/lib/api/team/org-crud-manager.js +202 -0
  6. package/lib/api/team/org-manager.js +56 -0
  7. package/lib/api/team/org-member-manager.js +403 -0
  8. package/lib/api/team/org-query-manager.js +126 -0
  9. package/lib/api/team/org-resource-manager.js +186 -0
  10. package/lib/api/team/passport-manager.js +670 -0
  11. package/lib/api/team/rbac-manager.js +335 -0
  12. package/lib/api/team/session-manager.js +540 -0
  13. package/lib/api/team/store-manager.js +198 -0
  14. package/lib/api/team/tag-manager.js +230 -0
  15. package/lib/api/team/user-auth-manager.js +132 -0
  16. package/lib/api/team/user-manager.js +78 -0
  17. package/lib/api/team/user-query-manager.js +299 -0
  18. package/lib/api/team/user-social-manager.js +354 -0
  19. package/lib/api/team/user-update-manager.js +224 -0
  20. package/lib/api/team/verify-code-manager.js +161 -0
  21. package/lib/api/team.js +439 -3287
  22. package/lib/blocklet/manager/disk/auth-manager.js +68 -0
  23. package/lib/blocklet/manager/disk/backup-manager.js +288 -0
  24. package/lib/blocklet/manager/disk/cleanup-manager.js +157 -0
  25. package/lib/blocklet/manager/disk/component-manager.js +83 -0
  26. package/lib/blocklet/manager/disk/config-manager.js +191 -0
  27. package/lib/blocklet/manager/disk/controller-manager.js +64 -0
  28. package/lib/blocklet/manager/disk/delete-reset-manager.js +328 -0
  29. package/lib/blocklet/manager/disk/download-manager.js +96 -0
  30. package/lib/blocklet/manager/disk/env-config-manager.js +311 -0
  31. package/lib/blocklet/manager/disk/federated-manager.js +651 -0
  32. package/lib/blocklet/manager/disk/hook-manager.js +124 -0
  33. package/lib/blocklet/manager/disk/install-component-manager.js +95 -0
  34. package/lib/blocklet/manager/disk/install-core-manager.js +448 -0
  35. package/lib/blocklet/manager/disk/install-download-manager.js +313 -0
  36. package/lib/blocklet/manager/disk/install-manager.js +36 -0
  37. package/lib/blocklet/manager/disk/install-upgrade-manager.js +340 -0
  38. package/lib/blocklet/manager/disk/job-manager.js +467 -0
  39. package/lib/blocklet/manager/disk/lifecycle-manager.js +26 -0
  40. package/lib/blocklet/manager/disk/notification-manager.js +343 -0
  41. package/lib/blocklet/manager/disk/query-manager.js +562 -0
  42. package/lib/blocklet/manager/disk/settings-manager.js +507 -0
  43. package/lib/blocklet/manager/disk/start-manager.js +611 -0
  44. package/lib/blocklet/manager/disk/stop-restart-manager.js +292 -0
  45. package/lib/blocklet/manager/disk/update-manager.js +153 -0
  46. package/lib/blocklet/manager/disk.js +669 -5796
  47. package/lib/blocklet/manager/helper/blue-green-start-blocklet.js +5 -0
  48. package/lib/blocklet/manager/lock.js +18 -0
  49. package/lib/event/index.js +28 -24
  50. package/lib/util/blocklet/app-utils.js +192 -0
  51. package/lib/util/blocklet/blocklet-loader.js +258 -0
  52. package/lib/util/blocklet/config-manager.js +232 -0
  53. package/lib/util/blocklet/did-document.js +240 -0
  54. package/lib/util/blocklet/environment.js +555 -0
  55. package/lib/util/blocklet/health-check.js +449 -0
  56. package/lib/util/blocklet/install-utils.js +365 -0
  57. package/lib/util/blocklet/logo.js +57 -0
  58. package/lib/util/blocklet/meta-utils.js +269 -0
  59. package/lib/util/blocklet/port-manager.js +141 -0
  60. package/lib/util/blocklet/process-manager.js +504 -0
  61. package/lib/util/blocklet/runtime-info.js +105 -0
  62. package/lib/util/blocklet/validation.js +418 -0
  63. package/lib/util/blocklet.js +98 -3066
  64. package/lib/util/wallet-app-notification.js +40 -0
  65. package/package.json +22 -22
@@ -0,0 +1,651 @@
1
+ const pick = require('lodash/pick');
2
+ const remove = require('lodash/remove');
3
+ const isNil = require('lodash/isNil');
4
+ const uniqBy = require('lodash/uniqBy');
5
+ const { joinURL } = require('ufo');
6
+ const pLimit = require('p-limit');
7
+ const pRetry = require('p-retry');
8
+ const pMap = require('p-map');
9
+ const logger = require('@abtnode/logger')('@abtnode/core:blocklet:manager:federated');
10
+ const { getBlockletInfo } = require('@blocklet/meta/lib/info');
11
+ const { FEDERATED, USER_PROFILE_SYNC_FIELDS, WELLKNOWN_SERVICE_PATH_PREFIX } = require('@abtnode/constant');
12
+ const normalizePathPrefix = require('@abtnode/util/lib/normalize-path-prefix');
13
+ const {
14
+ callFederated,
15
+ syncFederated: _syncFederated,
16
+ getFederatedMaster,
17
+ generateSiteInfo,
18
+ findFederatedSite,
19
+ safeGetFederated,
20
+ shouldSyncFederated,
21
+ getUserAvatarUrl,
22
+ } = require('@abtnode/auth/lib/util/federated');
23
+ const { BlockletEvents, BlockletInternalEvents } = require('@blocklet/constant');
24
+
25
+ const states = require('../../../states');
26
+ const request = require('../../../util/request');
27
+
28
+ /**
29
+ * Join federated login
30
+ * @param {Object} manager - BlockletManager instance
31
+ * @param {Object} params
32
+ * @param {Object} context
33
+ * @returns {Promise<Object>}
34
+ */
35
+ async function joinFederatedLogin(manager, { appUrl, did }, context) {
36
+ const url = new URL(appUrl);
37
+ // master service api 的地址
38
+ url.pathname = joinURL(WELLKNOWN_SERVICE_PATH_PREFIX, '/api/federated/join');
39
+
40
+ const blocklet = await manager.getBlocklet(did);
41
+ const nodeInfo = await states.node.read();
42
+ const blockletInfo = getBlockletInfo(blocklet, nodeInfo.sk);
43
+ const domainAliases = await manager.getDomainAliases({ blocklet, nodeInfo });
44
+ const { permanentWallet } = blockletInfo;
45
+ const memberSite = {
46
+ appId: blocklet.appDid,
47
+ appPid: blocklet.appPid,
48
+ aliasDid: (blocklet.migratedFrom || []).map((x) => x.appDid),
49
+ appName: blockletInfo.name,
50
+ appDescription: blockletInfo.description,
51
+ appUrl: blockletInfo.appUrl,
52
+ aliasDomain: domainAliases.map((x) => x.value),
53
+ appLogo:
54
+ blocklet.environmentObj.BLOCKLET_APP_LOGO ||
55
+ normalizePathPrefix(joinURL(WELLKNOWN_SERVICE_PATH_PREFIX, '/blocklet/logo')) ||
56
+ '/',
57
+ appLogoRect: blocklet.environmentObj.BLOCKLET_APP_LOGO_RECT,
58
+ did: permanentWallet.address,
59
+ pk: permanentWallet.publicKey,
60
+ serverId: nodeInfo.did,
61
+ serverVersion: nodeInfo.version,
62
+ version: blockletInfo.version,
63
+ };
64
+
65
+ logger.info('Apply to join federated login', {
66
+ memberSite: pick(memberSite, ['appId', 'appPid', 'appName', 'appDescription', 'appUrl']),
67
+ masterAppUrl: appUrl,
68
+ });
69
+
70
+ let data;
71
+ try {
72
+ const result = await pRetry(
73
+ () =>
74
+ request.post(url.href, {
75
+ // 初次申请时,member 不在站点群中,不需要对数据进行加密
76
+ site: memberSite,
77
+ }),
78
+ { retries: 3 }
79
+ );
80
+ data = result.data;
81
+ } catch (error) {
82
+ const errorMsg = error?.response?.data;
83
+ logger.error('Failed to join federated login', { error, errorMsg, did, url: url.href });
84
+ throw new Error(errorMsg || 'Failed to join federated login');
85
+ }
86
+
87
+ await states.blockletExtras.setSettings(blocklet.appPid, {
88
+ federated: {
89
+ config: {
90
+ appId: blocklet.appDid,
91
+ appPid: blocklet.appPid,
92
+ isMaster: false,
93
+ },
94
+ sites: data.sites,
95
+ },
96
+ });
97
+
98
+ const newState = await manager.getBlocklet(did);
99
+ manager.emit(BlockletInternalEvents.appSettingChanged, { appDid: did });
100
+ manager.emit(BlockletEvents.updated, { ...newState, context });
101
+ return newState;
102
+ }
103
+
104
+ /**
105
+ * Quit federated login
106
+ * member 退出统一登录站点群
107
+ * @param {Object} manager - BlockletManager instance
108
+ * @param {Object} params
109
+ * @param {string} params.did - blocklet pid
110
+ * @param {string} [params.targetDid] - 要退出的目标 blocklet pid, 如果未设置,则代表退出自身
111
+ * @param {Object} context
112
+ * @returns {Promise<Object>}
113
+ */
114
+ async function quitFederatedLogin(manager, { did, targetDid }, context) {
115
+ const blocklet = await manager.getBlocklet(did);
116
+ const masterSite = getFederatedMaster(blocklet);
117
+ if (masterSite) {
118
+ // master 可以指定删除一个 member
119
+ if (masterSite.appPid === did && targetDid && targetDid !== did) {
120
+ const memberSite = findFederatedSite(blocklet, targetDid);
121
+
122
+ if (memberSite) {
123
+ await manager.syncFederated({
124
+ did,
125
+ data: {
126
+ sites: [
127
+ {
128
+ ...memberSite,
129
+ action: 'delete',
130
+ },
131
+ ],
132
+ },
133
+ });
134
+ try {
135
+ const nodeInfo = await states.node.read();
136
+ const blockletInfo = getBlockletInfo(blocklet, nodeInfo.sk);
137
+ const { permanentWallet } = blockletInfo;
138
+ await callFederated({
139
+ action: 'disband',
140
+ permanentWallet,
141
+ site: memberSite,
142
+ data: {},
143
+ });
144
+ } catch (error) {
145
+ logger.error('Failed to disband memberSite', {
146
+ error,
147
+ did,
148
+ memberSite,
149
+ });
150
+ }
151
+ const federated = safeGetFederated(blocklet, { isMaster: true });
152
+ remove(federated.sites, (item) => item.appPid === targetDid);
153
+ await states.blockletExtras.setSettings(blocklet.appPid, { federated });
154
+ }
155
+ } else {
156
+ // member 向 mater 申请退出
157
+ const nodeInfo = await states.node.read();
158
+ const blockletInfo = getBlockletInfo(blocklet, nodeInfo.sk);
159
+ const { permanentWallet } = blockletInfo;
160
+ logger.info('Quit federated login', {
161
+ memberSite: {
162
+ appId: blocklet.appDid,
163
+ appPid: blocklet.appPid,
164
+ appName: blockletInfo.name,
165
+ appDescription: blockletInfo.description,
166
+ appUrl: blockletInfo.appUrl,
167
+ },
168
+ masterAppUrl: masterSite.appUrl,
169
+ });
170
+ try {
171
+ await callFederated({
172
+ action: 'quit',
173
+ site: masterSite,
174
+ permanentWallet,
175
+ data: {
176
+ memberPid: blocklet.appPid,
177
+ },
178
+ });
179
+ } catch (error) {
180
+ logger.error('Failed to quit blocklet, will still quit federated by itself', { error, did });
181
+ }
182
+ await states.blockletExtras.setSettings(blocklet.appPid, {
183
+ federated: null,
184
+ });
185
+ }
186
+ } else {
187
+ await states.blockletExtras.setSettings(blocklet.appPid, {
188
+ federated: null,
189
+ });
190
+ }
191
+
192
+ const newState = await manager.getBlocklet(did);
193
+ manager.emit(BlockletInternalEvents.appSettingChanged, { appDid: did });
194
+ manager.emit(BlockletEvents.updated, { ...newState, context });
195
+ return newState;
196
+ }
197
+
198
+ /**
199
+ * Disband federated login
200
+ * master 解散统一登录站点群
201
+ * @param {Object} manager - BlockletManager instance
202
+ * @param {Object} params
203
+ * @param {string} params.did - blocklet pid
204
+ * @param {Object} context
205
+ * @returns {Promise<Object>}
206
+ */
207
+ async function disbandFederatedLogin(manager, { did }, context) {
208
+ const blocklet = await manager.getBlocklet(did);
209
+ const federated = safeGetFederated(blocklet, { isMaster: true });
210
+ const masterSite = getFederatedMaster(blocklet);
211
+ // 只有 Master 可以调用这个逻辑
212
+ if (masterSite?.appPid === did) {
213
+ const nodeInfo = await states.node.read();
214
+ const blockletInfo = getBlockletInfo(blocklet, nodeInfo.sk);
215
+ const { permanentWallet } = blockletInfo;
216
+ logger.info('Disband federated login', {
217
+ memberSite: {
218
+ appId: blocklet.appDid,
219
+ appPid: blocklet.appPid,
220
+ appName: blockletInfo.name,
221
+ appDescription: blockletInfo.description,
222
+ appUrl: blockletInfo.appUrl,
223
+ },
224
+ masterAppUrl: masterSite.appUrl,
225
+ });
226
+ const limitSync = pLimit(FEDERATED.SYNC_LIMIT);
227
+
228
+ const disbandQueue = federated.sites
229
+ .filter((item) => item.appPid !== did)
230
+ .map((item) => {
231
+ return limitSync(async () => {
232
+ try {
233
+ await callFederated({
234
+ action: 'disband',
235
+ permanentWallet,
236
+ site: item,
237
+ data: {},
238
+ });
239
+ } catch (error) {
240
+ logger.error('Failed to notify member disband', {
241
+ error,
242
+ did,
243
+ memberSite: item,
244
+ });
245
+ }
246
+ });
247
+ });
248
+ await Promise.all(disbandQueue);
249
+ await states.blockletExtras.setSettings(blocklet.appPid, {
250
+ federated: null,
251
+ });
252
+ }
253
+ const newState = await manager.getBlocklet(did);
254
+ manager.emit(BlockletInternalEvents.appSettingChanged, { appDid: did });
255
+ manager.emit(BlockletEvents.updated, { ...newState, context });
256
+ return newState;
257
+ }
258
+
259
+ /**
260
+ * Set federated config
261
+ * @param {Object} manager - BlockletManager instance
262
+ * @param {Object} params
263
+ * @param {string} params.did - blocklet pid
264
+ * @param {Object} params.config - federated 配置内容
265
+ * @param {Object} context
266
+ * @returns {Promise<Object>}
267
+ */
268
+ async function setFederated(manager, { did, config }, context) {
269
+ await states.blockletExtras.setSettings(did, { federated: config });
270
+
271
+ const newBlockletState = await manager.getBlocklet(did);
272
+ manager.emit(BlockletInternalEvents.appSettingChanged, { appDid: did });
273
+ manager.emit(BlockletEvents.updated, { ...newBlockletState, context });
274
+ return newBlockletState;
275
+ }
276
+
277
+ /**
278
+ * Audit federated login
279
+ * @param {Object} manager - BlockletManager instance
280
+ * @param {Object} params
281
+ * @param {string} params.did - master blocklet pid
282
+ * @param {string} params.memberPid - member blocklet pid
283
+ * @param {'approved'|'revoked'|'rejected'} params.status - member blocklet status
284
+ * @returns {Promise<Object>}
285
+ */
286
+ async function auditFederatedLogin(manager, { memberPid, did, status }) {
287
+ const blocklet = await manager.getBlocklet(did);
288
+ const teamDid = blocklet.appPid;
289
+
290
+ const federated = safeGetFederated(blocklet, { isMaster: true });
291
+ const memberSite = federated.sites.find((item) => item.appPid === memberPid);
292
+ memberSite.status = status;
293
+ if (isNil(federated.config.isMaster)) {
294
+ const masterSite = federated.sites.find((item) => item.appPid === teamDid);
295
+
296
+ masterSite.isMaster = true;
297
+ federated.config.isMaster = true;
298
+ }
299
+ // 有审批操作的一方,自动成为 master
300
+ const newState = await setFederated(manager, {
301
+ did: teamDid,
302
+ config: federated,
303
+ });
304
+ logger.info('Audit member join federated login', {
305
+ memberSite: pick(memberSite, ['appId', 'appPid', 'appName', 'appDescription', 'appUrl']),
306
+ status,
307
+ });
308
+
309
+ const nodeInfo = await states.node.read();
310
+ const { permanentWallet } = getBlockletInfo(blocklet, nodeInfo.sk);
311
+
312
+ if (status === 'approved') {
313
+ // 必须先通知所有成员站点,该站点已经成功加入,后续该站点才能成功拉取所有站点的信息
314
+ await manager.syncFederated({
315
+ did,
316
+ data: {
317
+ sites: [
318
+ {
319
+ ...memberSite,
320
+ action: 'upsert',
321
+ },
322
+ ],
323
+ },
324
+ });
325
+ }
326
+
327
+ try {
328
+ await callFederated({
329
+ action: 'audit-res',
330
+ permanentWallet,
331
+ site: memberSite,
332
+ data: {
333
+ masterPid: teamDid,
334
+ status,
335
+ },
336
+ });
337
+ } catch (error) {
338
+ logger.error('Failed to post audit result to member site', { error, did });
339
+ throw error;
340
+ }
341
+ return newState;
342
+ }
343
+
344
+ /**
345
+ * Update user info and sync federated
346
+ * @param {Object} manager - BlockletManager instance
347
+ * @param {Object} params
348
+ * @param {string} params.teamDid - master blocklet pid
349
+ * @param {Object} params.updated - 更新后的用户信息
350
+ * @returns {Promise<void>}
351
+ */
352
+ async function updateUserInfoAndSyncFederated(manager, { teamDid, updated }) {
353
+ try {
354
+ const { sourceAppPid } = updated;
355
+ const blocklet = await manager.getBlocklet(teamDid);
356
+
357
+ const masterSite = getFederatedMaster(blocklet);
358
+ if (shouldSyncFederated(blocklet, sourceAppPid)) {
359
+ const data = pick(updated, USER_PROFILE_SYNC_FIELDS);
360
+ if (data.avatar) {
361
+ data.avatar = getUserAvatarUrl(data.avatar, blocklet);
362
+ }
363
+
364
+ await manager.syncFederated({
365
+ did: blocklet.appPid,
366
+ userFields: USER_PROFILE_SYNC_FIELDS,
367
+ data: {
368
+ users: [
369
+ {
370
+ ...data,
371
+ action: 'syncProfile',
372
+ sourceAppPid: sourceAppPid || masterSite.appPid,
373
+ },
374
+ ],
375
+ },
376
+ });
377
+ }
378
+ } catch (error) {
379
+ logger.error('Failed to update user info and sync federated', {
380
+ teamDid,
381
+ sourceAppPid: updated.sourceAppPid,
382
+ userDid: updated.did,
383
+ error,
384
+ });
385
+ }
386
+ }
387
+
388
+ /**
389
+ * Update user extra
390
+ * @param {Object} manager - BlockletManager instance
391
+ * @param {Object} args
392
+ * @returns {Promise<Object>}
393
+ */
394
+ async function updateUserExtra(manager, args) {
395
+ try {
396
+ if (args.extra) {
397
+ try {
398
+ args.extra = JSON.parse(args.extra);
399
+ } catch (err) {
400
+ throw new Error('extra should be a valid json string');
401
+ }
402
+ }
403
+
404
+ const updated = await manager.teamAPI.updateUser({
405
+ teamDid: args.teamDid,
406
+ user: pick(args, ['did', 'remark', 'extra']),
407
+ });
408
+
409
+ // 异步更新站点群其他站点的用户信息
410
+ updateUserInfoAndSyncFederated(manager, { teamDid: args.teamDid, updated });
411
+
412
+ return updated;
413
+ } catch (err) {
414
+ logger.error('Failed to update user extra', { err });
415
+ throw err;
416
+ }
417
+ }
418
+
419
+ /**
420
+ * Update user info and sync
421
+ * @param {Object} manager - BlockletManager instance
422
+ * @param {Object} params
423
+ * @param {string} params.teamDid
424
+ * @param {Object} params.user
425
+ * @returns {Promise<Object>}
426
+ */
427
+ async function updateUserInfoAndSync(manager, { teamDid, user }, { generateUserUpdateData }) {
428
+ try {
429
+ const existingUser = await manager.teamAPI.getUser({ teamDid, user: { did: user.did } });
430
+ if (!existingUser) {
431
+ throw new Error('User not found');
432
+ }
433
+ const updateData = generateUserUpdateData(user, existingUser);
434
+ const updated = await manager.teamAPI.updateUser({ teamDid, user: updateData });
435
+
436
+ // 异步更新站点群其他站点的用户信息
437
+ updateUserInfoAndSyncFederated(manager, { teamDid, updated });
438
+
439
+ return updated;
440
+ } catch (err) {
441
+ logger.error('user profile sync failed', { err });
442
+ throw err;
443
+ }
444
+ }
445
+
446
+ /**
447
+ * Sync federated
448
+ * @param {Object} manager - BlockletManager instance
449
+ * @param {Object} params
450
+ * @returns {Promise<Array>}
451
+ */
452
+ async function syncFederated(manager, { did, data, syncSites, allowStatus, userFields, siteFields } = {}) {
453
+ if (!did) {
454
+ logger.error('SyncFederated failed: did is required');
455
+ return [];
456
+ }
457
+ const blocklet = await manager.getBlocklet(did);
458
+ if (!blocklet) {
459
+ logger.error(`SyncFederated failed: Blocklet not found for did: ${did}`);
460
+ return [];
461
+ }
462
+
463
+ const nodeInfo = await states.node.read();
464
+ const result = await _syncFederated({
465
+ blocklet,
466
+ data,
467
+ syncSites,
468
+ allowStatus,
469
+ userFields,
470
+ siteFields,
471
+ nodeInfo,
472
+ });
473
+ return result;
474
+ }
475
+
476
+ /**
477
+ * Login federated
478
+ * @param {Object} manager - BlockletManager instance
479
+ * @param {Object} params
480
+ * @returns {Promise<Object>}
481
+ */
482
+ async function loginFederated(manager, { did, site, data }) {
483
+ const blocklet = await manager.getBlocklet(did);
484
+ const nodeInfo = await states.node.read();
485
+ const { permanentWallet } = getBlockletInfo(blocklet, nodeInfo.sk);
486
+ const result = await callFederated({
487
+ action: 'loginByMaster',
488
+ data,
489
+ permanentWallet,
490
+ site,
491
+ });
492
+ return result;
493
+ }
494
+
495
+ /**
496
+ * Sync master authorization
497
+ * @param {Object} manager - BlockletManager instance
498
+ * @param {Object} params
499
+ * @returns {Promise<Object>}
500
+ */
501
+ async function syncMasterAuthorization(manager, { did }) {
502
+ // 1. 获取 master 的站点信息
503
+ // 2. 向 master 请求 Authorization 数据
504
+ // 3. 更新 delegation 和 roles 映射
505
+ const blocklet = await manager.getBlocklet(did);
506
+ const teamDid = blocklet.appPid;
507
+ const masterSite = getFederatedMaster(blocklet);
508
+ const nodeInfo = await states.node.read();
509
+ const blockletInfo = getBlockletInfo(blocklet, nodeInfo.sk);
510
+ const { permanentWallet } = blockletInfo;
511
+ const result = await callFederated({
512
+ action: 'getMasterAuthorization',
513
+ permanentWallet,
514
+ site: masterSite,
515
+ });
516
+ const { delegation, roles } = result;
517
+
518
+ const trustedPassports = blocklet.trustedPassports || [];
519
+ // NOTICE: 当前仅在可信列表中不包含 master 站点时执行添加操作
520
+ const hasTrustedPassport = trustedPassports.find((item) => item.issuerDid === masterSite.appPid);
521
+ if (!hasTrustedPassport) {
522
+ // NOTICE: teamAPI.configTrustedPassports 和 teamManager.configTrustedPassports 传参的格式是不一样的
523
+ await manager.teamAPI.configTrustedPassports({
524
+ teamDid,
525
+ trustedPassports: [
526
+ ...trustedPassports,
527
+ {
528
+ issuerDid: masterSite.appPid,
529
+ remark: 'Generated on join federated login',
530
+ mappings: roles.map((item) => {
531
+ return {
532
+ from: { passport: item.name },
533
+ to: { role: 'guest' },
534
+ };
535
+ }),
536
+ },
537
+ ],
538
+ });
539
+ }
540
+
541
+ const federated = safeGetFederated(blocklet);
542
+ federated.config.delegation = delegation;
543
+
544
+ const newBlockletState = await setFederated(manager, {
545
+ did: teamDid,
546
+ config: federated,
547
+ });
548
+
549
+ return newBlockletState;
550
+ }
551
+
552
+ /**
553
+ * Sync federated config
554
+ * @param {Object} manager - BlockletManager instance
555
+ * @param {Object} params
556
+ * @returns {Promise<Object>}
557
+ */
558
+ async function syncFederatedConfig(manager, { did }) {
559
+ const blocklet = await manager.getBlocklet(did);
560
+ const teamDid = blocklet.appPid;
561
+ const masterSite = getFederatedMaster(blocklet);
562
+ const federated = safeGetFederated(blocklet);
563
+ const nodeInfo = await states.node.read();
564
+ const domainAliases = await manager.getDomainAliases({ blocklet, nodeInfo });
565
+ const selfConfig = await generateSiteInfo({ nodeInfo, blocklet, domainAliases });
566
+ const { permanentWallet } = getBlockletInfo(blocklet, nodeInfo.sk);
567
+
568
+ const isSelfMaster = masterSite?.appPid === teamDid;
569
+
570
+ let siteInfoList = [];
571
+ if (isSelfMaster) {
572
+ siteInfoList = await pMap(
573
+ // FIXME: @zhanghan 需要对 sites 做一次去重处理
574
+ uniqBy(federated.sites, 'appPid'),
575
+ async (item) => {
576
+ if (item.appPid === teamDid) {
577
+ return {
578
+ ...selfConfig,
579
+ status: item.status,
580
+ isMaster: isSelfMaster ? true : item.isMaster,
581
+ };
582
+ }
583
+
584
+ try {
585
+ const siteItemConfig = await callFederated({
586
+ action: 'getConfig',
587
+ permanentWallet,
588
+ site: item,
589
+ data: {},
590
+ });
591
+ return {
592
+ ...siteItemConfig,
593
+ status: item.status,
594
+ isMaster: isSelfMaster ? false : item.isMaster,
595
+ };
596
+ } catch (error) {
597
+ logger.error('Failed to get site info, use outdate site-info', {
598
+ error,
599
+ site: item,
600
+ });
601
+ return item;
602
+ }
603
+ },
604
+ { concurrency: FEDERATED.SYNC_LIMIT }
605
+ );
606
+ } else {
607
+ siteInfoList = await callFederated({
608
+ action: 'pullFederatedSites',
609
+ permanentWallet,
610
+ site: masterSite,
611
+ data: {},
612
+ });
613
+ }
614
+ federated.sites = siteInfoList;
615
+
616
+ const newBlockletState = await setFederated(manager, {
617
+ did: teamDid,
618
+ config: federated,
619
+ });
620
+ if (isSelfMaster) {
621
+ await syncFederated(manager, {
622
+ did,
623
+ data: {
624
+ sites: siteInfoList.filter((x) => !['pending'].includes(x.status)).map((x) => ({ ...x, action: 'upsert' })),
625
+ },
626
+ });
627
+ } else {
628
+ await syncFederated(manager, {
629
+ did,
630
+ data: {
631
+ sites: [{ ...selfConfig, action: 'upsert' }],
632
+ },
633
+ });
634
+ }
635
+ return newBlockletState;
636
+ }
637
+
638
+ module.exports = {
639
+ joinFederatedLogin,
640
+ quitFederatedLogin,
641
+ disbandFederatedLogin,
642
+ setFederated,
643
+ auditFederatedLogin,
644
+ updateUserInfoAndSyncFederated,
645
+ updateUserExtra,
646
+ updateUserInfoAndSync,
647
+ syncFederated,
648
+ loginFederated,
649
+ syncMasterAuthorization,
650
+ syncFederatedConfig,
651
+ };