@abtnode/core 1.16.14-beta-dc99d0a2 → 1.16.14-beta-a90ba909

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.
@@ -51,6 +51,7 @@ const { update: updateMetaFile } = require('@blocklet/meta/lib/file');
51
51
  const { titleSchema, updateMountPointSchema, environmentNameSchema } = require('@blocklet/meta/lib/schema');
52
52
  const { emailConfigSchema } = require('@blocklet/sdk/lib/validators/email');
53
53
  const Lock = require('@abtnode/util/lib/lock');
54
+ const defaults = require('lodash/defaults');
54
55
 
55
56
  const {
56
57
  BlockletStatus,
@@ -3245,6 +3246,13 @@ class DiskBlockletManager extends BaseBlockletManager {
3245
3246
  appDid,
3246
3247
  meta: { did: appPid },
3247
3248
  } = blocklet;
3249
+
3250
+ const exist = await this.backupQueue.get(appDid);
3251
+
3252
+ if (exist) {
3253
+ throw new Error('A backup for this app is already in progress, abort!');
3254
+ }
3255
+
3248
3256
  const endpoint = getBackupEndpoint(blocklet.environments);
3249
3257
 
3250
3258
  const backup = await states.backup.start({
@@ -3266,6 +3274,8 @@ class DiskBlockletManager extends BaseBlockletManager {
3266
3274
  },
3267
3275
  appDid
3268
3276
  );
3277
+
3278
+ return blocklet;
3269
3279
  } catch (error) {
3270
3280
  logger.error(error);
3271
3281
  throw error;
@@ -3281,6 +3291,8 @@ class DiskBlockletManager extends BaseBlockletManager {
3281
3291
 
3282
3292
  const diskBackup = new DiskBackup({ appDid, event: this });
3283
3293
  await diskBackup.backup();
3294
+
3295
+ return blocklet;
3284
3296
  }
3285
3297
 
3286
3298
  /**
@@ -3419,21 +3431,24 @@ class DiskBlockletManager extends BaseBlockletManager {
3419
3431
  class FederatedBlockletManager extends DiskBlockletManager {
3420
3432
  /**
3421
3433
  * Joins federated login.
3422
- * @param {{appUrl: string, did: string;}} options - The federated login appUrl.
3423
- * @returns {Promise<any>} The data received from the appUrl.
3434
+ * @param {object} options
3435
+ * @param {{string}} options.did - blocklet pid
3436
+ * @param {{string}} options.appUrl - 申请加入统一登录的 master appUrl
3437
+ * @returns {Promise<any>} 更新后的 blocklet 数据
3424
3438
  */
3425
3439
  async joinFederatedLogin({ appUrl, did }) {
3426
3440
  const url = new URL(appUrl);
3441
+ // master service api 的地址
3427
3442
  url.pathname = `${WELLKNOWN_SERVICE_PATH_PREFIX}/api/federated/join`;
3428
3443
 
3429
3444
  const blocklet = await this.getBlocklet(did);
3430
3445
  const nodeInfo = await states.node.read();
3431
3446
  const blockletInfo = getBlockletInfo(blocklet, nodeInfo.sk);
3432
- const { permanentWallet, wallet } = blockletInfo;
3447
+ const { permanentWallet } = blockletInfo;
3433
3448
  const memberSite = {
3434
- appId: wallet.address,
3435
- appPid: permanentWallet.address,
3436
- migratedFrom: blocklet.migratedFrom || [],
3449
+ appId: blocklet.appDid,
3450
+ appPid: blocklet.appPid,
3451
+ aliasDid: (blocklet.migratedFrom || []).map((item) => item.appDid),
3437
3452
  appName: blockletInfo.name,
3438
3453
  appDescription: blockletInfo.description,
3439
3454
  appUrl: blockletInfo.appUrl,
@@ -3442,33 +3457,99 @@ class FederatedBlockletManager extends DiskBlockletManager {
3442
3457
  normalizePathPrefix(`${WELLKNOWN_SERVICE_PATH_PREFIX}/blocklet/logo`) ||
3443
3458
  '/',
3444
3459
  appLogoRect: blocklet.environmentObj.BLOCKLET_APP_LOGO_RECT,
3445
- did: blockletInfo.did,
3460
+ did: permanentWallet.address,
3446
3461
  pk: permanentWallet.publicKey,
3447
3462
  serverId: nodeInfo.did,
3448
3463
  serverVersion: nodeInfo.version,
3449
3464
  version: blockletInfo.version,
3450
3465
  };
3451
3466
 
3452
- const { data } = await request.post(url.href, {
3453
- // 初次申请时,member 不在站点群中,不需要对数据进行加密
3454
- site: memberSite,
3467
+ logger.info('Apply to join federated login', {
3468
+ memberSite: pick(memberSite, ['appId', 'appPid', 'appName', 'appDescription', 'appUrl']),
3469
+ masterAppUrl: appUrl,
3455
3470
  });
3456
- await states.blockletExtras.setSettings(blocklet.meta.did, {
3471
+
3472
+ let data;
3473
+ try {
3474
+ const result = await request.post(url.href, {
3475
+ // 初次申请时,member 不在站点群中,不需要对数据进行加密
3476
+ site: memberSite,
3477
+ });
3478
+ data = result.data;
3479
+ } catch (error) {
3480
+ logger.error('Failed to join federated login', { error, did, url: url.href });
3481
+ throw error;
3482
+ }
3483
+
3484
+ await states.blockletExtras.setSettings(blocklet.appPid, {
3457
3485
  federated: {
3458
3486
  config: {
3459
3487
  appId: blocklet.appDid,
3460
- appPid: blocklet.appPid || blocklet.appDid,
3488
+ appPid: blocklet.appPid,
3461
3489
  isMaster: false,
3462
3490
  },
3463
3491
  sites: data.sites,
3464
3492
  },
3465
3493
  });
3466
3494
 
3495
+ const newState = await this.getBlocklet(did);
3496
+ this.emit(BlockletEvents.updated, {
3497
+ masterAppUrl: appUrl,
3498
+ });
3499
+ return newState;
3500
+ }
3501
+
3502
+ async quitFederatedLogin({ did }) {
3503
+ const blocklet = await this.getBlocklet(did);
3504
+ const federated = defaults(cloneDeep(blocklet.settings.federated || {}), {
3505
+ config: {},
3506
+ sites: [],
3507
+ });
3508
+ const masterSite = federated.sites[0];
3509
+ if (masterSite && masterSite.isMaster !== false) {
3510
+ const nodeInfo = await states.node.read();
3511
+ const blockletInfo = getBlockletInfo(blocklet, nodeInfo.sk);
3512
+ const { permanentWallet } = blockletInfo;
3513
+ logger.info('Quit federated login', {
3514
+ memberSite: {
3515
+ appId: blocklet.appDid,
3516
+ appPid: blocklet.appPid,
3517
+ appName: blockletInfo.name,
3518
+ appDescription: blockletInfo.description,
3519
+ appUrl: blockletInfo.appUrl,
3520
+ },
3521
+ masterAppUrl: masterSite.appUrl,
3522
+ });
3523
+ const url = new URL(masterSite.appUrl);
3524
+ url.pathname = `${WELLKNOWN_SERVICE_PATH_PREFIX}/api/federated/quit`;
3525
+ try {
3526
+ await request.post(url.href, {
3527
+ signer: permanentWallet.address,
3528
+ data: signV2(permanentWallet.address, permanentWallet.secretKey, {
3529
+ memberPid: blocklet.appPid,
3530
+ }),
3531
+ });
3532
+ } catch (error) {
3533
+ logger.error('Failed to quit blocklet', { error, did, url: url.href });
3534
+ throw error;
3535
+ }
3536
+ }
3537
+
3538
+ await states.blockletExtras.setSettings(blocklet.appPid, {
3539
+ federated: null,
3540
+ });
3467
3541
  const newState = await this.getBlocklet(did);
3468
3542
  this.emit(BlockletEvents.updated, newState);
3469
3543
  return newState;
3470
3544
  }
3471
3545
 
3546
+ /**
3547
+ * 更改 federated 配置
3548
+ * @param {object} param
3549
+ * @param {string} param.did blocklet pid
3550
+ * @param {object} param.config federated 配置内容
3551
+ * @returns {Promise<any>} 更新后的 blocklet 数据
3552
+ */
3472
3553
  async setFederated({ did, config }) {
3473
3554
  await states.blockletExtras.setSettings(did, { federated: config });
3474
3555
 
@@ -3477,6 +3558,13 @@ class FederatedBlockletManager extends DiskBlockletManager {
3477
3558
  return newState;
3478
3559
  }
3479
3560
 
3561
+ /**
3562
+ * 配置 federated 设置
3563
+ * @param {object} param
3564
+ * @param {string} param.did blocklet pid
3565
+ * @param {boolean} param.autoLogin 是否自动登录
3566
+ * @returns {Promise<any>} 更新后的 blocklet 数据
3567
+ */
3480
3568
  async configFederated({ did, autoLogin = false }) {
3481
3569
  const blocklet = await this.getBlocklet(did);
3482
3570
  const federated = cloneDeep(blocklet.settings.federated || {});
@@ -3488,23 +3576,40 @@ class FederatedBlockletManager extends DiskBlockletManager {
3488
3576
  return newState;
3489
3577
  }
3490
3578
 
3491
- async auditFederatedLogin({ appId, did, status }) {
3579
+ /**
3580
+ * 审核 federated 申请
3581
+ * @param {object} param
3582
+ * @param {string} param.did master blocklet pid
3583
+ * @param {string} param.memberPid member blocklet pid
3584
+ * @param {boolean} param.autoLogin 是否自动登录
3585
+ * @returns {Promise<any>} 更新后的 blocklet 数据
3586
+ */
3587
+ async auditFederatedLogin({ memberPid, did, status }) {
3492
3588
  const blocklet = await this.getBlocklet(did);
3493
3589
 
3494
- const federated = cloneDeep(blocklet.settings.federated || {});
3495
- const memberSite = federated.sites.find((item) => item.appId === appId);
3590
+ const federated = defaults(cloneDeep(blocklet.settings.federated || {}), {
3591
+ config: {},
3592
+ sites: [],
3593
+ });
3594
+ const memberSite = federated.sites.find((item) => item.appPid === memberPid);
3496
3595
  memberSite.status = status;
3497
3596
  if ([null, undefined].includes(federated.config.isMaster)) {
3498
- const masterSite = federated.sites.find((item) => item.appId === blocklet.meta.did);
3597
+ const { sites, config } = federated;
3598
+ const masterSite = sites.find((item) => item.appPid === blocklet.appPid);
3499
3599
 
3500
3600
  masterSite.isMaster = true;
3501
- federated.config.isMaster = true;
3601
+ config.isMaster = true;
3502
3602
  }
3503
3603
  // 有审批操作的一方,自动成为 master
3504
3604
  const newState = await this.setFederated({
3505
- did: blocklet.meta.did,
3605
+ did: blocklet.appPid,
3506
3606
  config: federated,
3507
3607
  });
3608
+ logger.info('Audit member join federated login', {
3609
+ memberSite: pick(memberSite, ['appId', 'appPid', 'appName', 'appDescription', 'appUrl']),
3610
+ status,
3611
+ });
3612
+
3508
3613
  const nodeInfo = await states.node.read();
3509
3614
  const { permanentWallet } = getBlockletInfo(blocklet, nodeInfo.sk);
3510
3615
  let delegation;
@@ -3530,18 +3635,30 @@ class FederatedBlockletManager extends DiskBlockletManager {
3530
3635
  ],
3531
3636
  exp: Math.floor(new Date().getTime() / 1000) + 86400 * 365 * 100, // valid for 100 year
3532
3637
  });
3533
- roles = await this.teamManager.getRoles(blocklet.meta.did);
3638
+ roles = await this.teamManager.getRoles(blocklet.appPid);
3534
3639
  }
3535
3640
 
3536
- await request.post(`${memberSite.appUrl}/${WELLKNOWN_SERVICE_PATH_PREFIX}/api/federated/audit-res`, {
3537
- signer: permanentWallet.address,
3538
- data: signV2(permanentWallet.address, permanentWallet.secretKey, {
3539
- appId: blocklet.meta.did,
3540
- status,
3541
- delegation,
3542
- roles: roles.map((item) => pick(item, ['name', 'title', 'description'])),
3543
- }),
3641
+ const postUrl = `${memberSite.appUrl}/${WELLKNOWN_SERVICE_PATH_PREFIX}/api/federated/audit-res`;
3642
+
3643
+ logger.info('Audit member join federated login', {
3644
+ status,
3645
+ postUrl,
3544
3646
  });
3647
+ try {
3648
+ const roleList = roles.map((item) => pick(item, ['name', 'title', 'description']));
3649
+ await request.post(postUrl, {
3650
+ signer: permanentWallet.address,
3651
+ data: signV2(permanentWallet.address, permanentWallet.secretKey, {
3652
+ masterPid: blocklet.appPid,
3653
+ status,
3654
+ delegation,
3655
+ roles: roleList,
3656
+ }),
3657
+ });
3658
+ } catch (error) {
3659
+ logger.error('Failed to post audit res to member-site', { error, did, url: postUrl });
3660
+ throw error;
3661
+ }
3545
3662
  const waitingList = federated.sites
3546
3663
  .filter((item) => item.appId !== federated.config.appId)
3547
3664
  .map((item) => {
package/lib/index.js CHANGED
@@ -259,6 +259,7 @@ function ABTNode(options) {
259
259
  configNavigations: blockletManager.configNavigations.bind(blockletManager),
260
260
  configOAuth: blockletManager.configOAuth.bind(blockletManager),
261
261
  joinFederatedLogin: blockletManager.joinFederatedLogin.bind(blockletManager),
262
+ quitFederatedLogin: blockletManager.quitFederatedLogin.bind(blockletManager),
262
263
  auditFederatedLogin: blockletManager.auditFederatedLogin.bind(blockletManager),
263
264
  configFederated: blockletManager.configFederated.bind(blockletManager),
264
265
  setFederated: blockletManager.setFederated.bind(blockletManager),
@@ -108,7 +108,7 @@ const getLogContent = async (action, args, context, result, info, node) => {
108
108
  case 'deleteBlocklet':
109
109
  return `removed application ${result.meta.title}`; // prettier-ignore
110
110
  case 'backupBlocklet':
111
- return `backup application ${result.meta.title}`; // prettier-ignore
111
+ return `backup application ${result.meta.title} to ${args.to}`; // prettier-ignore
112
112
  case 'startBlocklet':
113
113
  return `started ${componentOrApplicationInfo(result, args.componentDids)}`;
114
114
  case 'restartBlocklet':
@@ -138,16 +138,21 @@ const getLogContent = async (action, args, context, result, info, node) => {
138
138
  return `set publicToStore to ${args.publicToStore ? 'true' : 'false'}`;
139
139
  case 'configNavigations':
140
140
  // eslint-disable-next-line prettier/prettier
141
- return `updated following navigations:\n${args.navigations.map(
142
- (x) => `- ${x.title}: ${x.link}\n`
143
- )}`;
141
+ return `updated following navigations:\n${args.navigations.map((x) => `- ${x.title}: ${x.link}\n`)}`;
144
142
  case 'configOAuth':
145
143
  return `updated following OAuth for blocklet ${getBlockletInfo(result, info)}:\n${args.oauth}`;
146
- // TODO: @zhanghan 配置审计日志
147
144
  case 'joinFederatedLogin':
148
- return `updated following OAuth for blocklet ${getBlockletInfo(result, info)}:\n${args.oauth}`;
145
+ return `blocklet ${getBlockletInfo(result, info)} join federated login to ${args.appUrl}`;
146
+ case 'quitFederatedLogin':
147
+ return `blocklet ${getBlockletInfo(result, info)} quit federated login`;
149
148
  case 'auditFederatedLogin':
150
- return `updated following OAuth:\n${args.oauth}`;
149
+ return `blocklet ${getBlockletInfo(result, info)} audit federated login member ${args.memberPid} with status: ${
150
+ args.status
151
+ }`;
152
+ case 'configFederated':
153
+ return `blocklet ${getBlockletInfo(result, info)} config federated login settings with autoLogin: ${
154
+ args.autoLogin
155
+ }`;
151
156
  case 'configNotification':
152
157
  return `updated following notification setting: ${args.notification}`;
153
158
  case 'updateComponentTitle':
@@ -315,6 +320,10 @@ const getLogCategory = (action) => {
315
320
  case 'updateComponentTitle':
316
321
  case 'updateComponentMountPoint':
317
322
  case 'backupToSpaces':
323
+ case 'joinFederatedLogin':
324
+ case 'quitFederatedLogin':
325
+ case 'auditFederatedLogin':
326
+ case 'configFederated':
318
327
  return 'blocklet';
319
328
 
320
329
  // store,此处应该返回 server
@@ -124,7 +124,7 @@ class BackupState extends BaseState {
124
124
  * @return {Promise<Array<import('@abtnode/models').BackupState>>}
125
125
  */
126
126
  getBlockletBackups({ did }) {
127
- return this.find({ appPid: did }, {}, { updatedAt: -1 });
127
+ return this.find({ appPid: did }, {}, { createdAt: -1 });
128
128
  }
129
129
  }
130
130
 
@@ -1229,6 +1229,7 @@ const getBlocklet = async ({
1229
1229
  }
1230
1230
 
1231
1231
  // app settings
1232
+ // FIXME: @zhanghan 在 server 开发模式下,使用 `node /workspace/arcblock/blocklet-server/core/cli/tools/dev.js` 运行的 blocklet,blocklet.meta.did 和 blocklet.appPid 是不一致的
1232
1233
  const settings = await states.blockletExtras.getSettings(blocklet.meta.did);
1233
1234
  blocklet.trustedPassports = get(settings, 'trustedPassports') || [];
1234
1235
  blocklet.trustedFactories = (get(settings, 'trustedFactories') || []).map((x) => {
@@ -8,6 +8,8 @@ const validateBackupStart = Joi.object({
8
8
  sourceUrl: Joi.string().required(),
9
9
  target: Joi.string().valid('Spaces', 'Local').optional().default('Spaces'),
10
10
  targetName: Joi.string().required(),
11
+
12
+ updatedAt: Joi.string().optional().allow(null).default(null),
11
13
  });
12
14
 
13
15
  const validateBackupSuccess = Joi.object({
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.16.14-beta-dc99d0a2",
6
+ "version": "1.16.14-beta-a90ba909",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,19 +19,19 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "Apache-2.0",
21
21
  "dependencies": {
22
- "@abtnode/analytics": "1.16.14-beta-dc99d0a2",
23
- "@abtnode/auth": "1.16.14-beta-dc99d0a2",
24
- "@abtnode/certificate-manager": "1.16.14-beta-dc99d0a2",
25
- "@abtnode/constant": "1.16.14-beta-dc99d0a2",
26
- "@abtnode/cron": "1.16.14-beta-dc99d0a2",
27
- "@abtnode/logger": "1.16.14-beta-dc99d0a2",
28
- "@abtnode/models": "1.16.14-beta-dc99d0a2",
29
- "@abtnode/queue": "1.16.14-beta-dc99d0a2",
30
- "@abtnode/rbac": "1.16.14-beta-dc99d0a2",
31
- "@abtnode/router-provider": "1.16.14-beta-dc99d0a2",
32
- "@abtnode/static-server": "1.16.14-beta-dc99d0a2",
33
- "@abtnode/timemachine": "1.16.14-beta-dc99d0a2",
34
- "@abtnode/util": "1.16.14-beta-dc99d0a2",
22
+ "@abtnode/analytics": "1.16.14-beta-a90ba909",
23
+ "@abtnode/auth": "1.16.14-beta-a90ba909",
24
+ "@abtnode/certificate-manager": "1.16.14-beta-a90ba909",
25
+ "@abtnode/constant": "1.16.14-beta-a90ba909",
26
+ "@abtnode/cron": "1.16.14-beta-a90ba909",
27
+ "@abtnode/logger": "1.16.14-beta-a90ba909",
28
+ "@abtnode/models": "1.16.14-beta-a90ba909",
29
+ "@abtnode/queue": "1.16.14-beta-a90ba909",
30
+ "@abtnode/rbac": "1.16.14-beta-a90ba909",
31
+ "@abtnode/router-provider": "1.16.14-beta-a90ba909",
32
+ "@abtnode/static-server": "1.16.14-beta-a90ba909",
33
+ "@abtnode/timemachine": "1.16.14-beta-a90ba909",
34
+ "@abtnode/util": "1.16.14-beta-a90ba909",
35
35
  "@arcblock/did": "1.18.87",
36
36
  "@arcblock/did-auth": "1.18.87",
37
37
  "@arcblock/did-ext": "^1.18.87",
@@ -42,11 +42,11 @@
42
42
  "@arcblock/pm2-events": "^0.0.5",
43
43
  "@arcblock/validator": "^1.18.87",
44
44
  "@arcblock/vc": "1.18.87",
45
- "@blocklet/constant": "1.16.14-beta-dc99d0a2",
46
- "@blocklet/meta": "1.16.14-beta-dc99d0a2",
47
- "@blocklet/resolver": "1.16.14-beta-dc99d0a2",
48
- "@blocklet/sdk": "1.16.14-beta-dc99d0a2",
49
- "@did-space/client": "^0.2.129",
45
+ "@blocklet/constant": "1.16.14-beta-a90ba909",
46
+ "@blocklet/meta": "1.16.14-beta-a90ba909",
47
+ "@blocklet/resolver": "1.16.14-beta-a90ba909",
48
+ "@blocklet/sdk": "1.16.14-beta-a90ba909",
49
+ "@did-space/client": "^0.2.141",
50
50
  "@fidm/x509": "^1.2.1",
51
51
  "@ocap/mcrypto": "1.18.87",
52
52
  "@ocap/util": "1.18.87",
@@ -99,5 +99,5 @@
99
99
  "jest": "^27.5.1",
100
100
  "unzipper": "^0.10.11"
101
101
  },
102
- "gitHead": "a00766d660ede97e2036f3a785f4f5cfb2e6d870"
102
+ "gitHead": "a59c9970f447462db0ccfee75b277e98bb11a6fa"
103
103
  }