@abtnode/core 1.16.5-beta-1472da21 → 1.16.6-beta-8be2fe37

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.
package/lib/api/team.js CHANGED
@@ -12,6 +12,7 @@ const {
12
12
  WELLKNOWN_SERVICE_PATH_PREFIX,
13
13
  MAX_USER_PAGE_SIZE,
14
14
  STORE_DETAIL_PAGE_PATH_PREFIX,
15
+ MAIN_CHAIN_ENDPOINT,
15
16
  } = require('@abtnode/constant');
16
17
  const { isValid: isValidDid } = require('@arcblock/did');
17
18
  const { BlockletEvents } = require('@blocklet/constant');
@@ -25,8 +26,10 @@ const {
25
26
  const { getPassportStatusEndpoint } = require('@abtnode/auth/lib/auth');
26
27
  const getBlockletInfo = require('@blocklet/meta/lib/info');
27
28
  const { parseUserAvatar } = require('@abtnode/util/lib/user-avatar');
29
+ const { getChainClient } = require('@abtnode/util/lib/get-chain-client');
28
30
 
29
31
  const { validateTrustedPassportIssuers } = require('../validators/trusted-passport');
32
+ const { validateTrustedFactories } = require('../validators/trusted-factory');
30
33
  const { validateCreateRole, validateUpdateRole } = require('../validators/role');
31
34
  const { validateCreatePermission, validateUpdatePermission } = require('../validators/permission');
32
35
 
@@ -80,6 +83,14 @@ const sendPassportVcNotification = ({ userDid, appWallet: wallet, locale, vc })
80
83
  }
81
84
  };
82
85
 
86
+ const formatTransferData = (data) => ({
87
+ transferId: data._id,
88
+ remark: data.remark || '',
89
+ expireDate: new Date(data.expireDate).toString(),
90
+ appDid: data.appDid,
91
+ status: data.status || '',
92
+ });
93
+
83
94
  class TeamAPI extends EventEmitter {
84
95
  /**
85
96
  *
@@ -92,7 +103,7 @@ class TeamAPI extends EventEmitter {
92
103
  this.node = states.node;
93
104
  this.states = states;
94
105
  this.memberInviteExpireTime = 1000 * 3600 * 24 * 30; // 30 days
95
- this.serverInviteExpireTime = 1000 * 3600; // 1 hour
106
+ this.transferOwnerExpireTime = 1000 * 3600; // 1 hour
96
107
  this.teamManager = teamManager;
97
108
  this.dataDirs = dataDirs;
98
109
  }
@@ -489,13 +500,6 @@ class TeamAPI extends EventEmitter {
489
500
  };
490
501
  }
491
502
 
492
- async createTransferInvitation({ teamDid, remark }, context) {
493
- return this.createMemberInvitation(
494
- { teamDid, expireTime: this.serverInviteExpireTime, remark, role: 'owner' },
495
- context
496
- );
497
- }
498
-
499
503
  async getInvitation({ teamDid, inviteId }) {
500
504
  if (!teamDid || !inviteId) {
501
505
  return null;
@@ -561,7 +565,7 @@ class TeamAPI extends EventEmitter {
561
565
  throw new Error(`The invitation does not exist: ${inviteId}`);
562
566
  }
563
567
 
564
- const { role, expireDate, remark } = await state.read(inviteId);
568
+ const { role, expireDate, remark } = invitation;
565
569
 
566
570
  if (Date.now() > expireDate) {
567
571
  logger.error('Invite id has expired', { inviteId, expireAt: new Date(expireDate) });
@@ -601,6 +605,106 @@ class TeamAPI extends EventEmitter {
601
605
  }, timeout);
602
606
  }
603
607
 
608
+ // transfer
609
+
610
+ /**
611
+ * this function is only used to create server owner transfer invitation
612
+ */
613
+ async createTransferInvitation({ teamDid, remark }, context = {}) {
614
+ return this.createMemberInvitation(
615
+ { teamDid, expireTime: this.transferOwnerExpireTime, remark, role: 'owner' },
616
+ context
617
+ );
618
+ }
619
+
620
+ /**
621
+ * this function is only used to create application owner transfer
622
+ */
623
+ async createTransferAppOwnerSession({ appDid, remark = '' }) {
624
+ const expireTime = this.transferOwnerExpireTime;
625
+
626
+ await this.teamManager.checkEnableTransferAppOwner(appDid);
627
+
628
+ if (remark && remark.length > 50) {
629
+ throw new Error('Remark length should NOT be more than 50 characters');
630
+ }
631
+
632
+ const expireDate = Date.now() + expireTime;
633
+ const state = await this.getSessionState(appDid);
634
+ const { id: transferId } = await state.start({
635
+ type: 'transfer-app-owner',
636
+ remark,
637
+ expireDate,
638
+ appDid,
639
+ });
640
+
641
+ logger.info('createTransferAppOwnerSession', { appDid, transferId });
642
+
643
+ return {
644
+ transferId,
645
+ remark,
646
+ expireDate: new Date(expireDate).toString(),
647
+ appDid,
648
+ status: 'created',
649
+ };
650
+ }
651
+
652
+ async getTransferAppOwnerSession({ appDid, transferId }) {
653
+ if (!appDid || !transferId) {
654
+ return null;
655
+ }
656
+
657
+ const state = await this.getSessionState(appDid);
658
+
659
+ const transfer = await state.findOne({ _id: transferId, type: 'transfer-app-owner' });
660
+ if (!transfer) {
661
+ return null;
662
+ }
663
+
664
+ return formatTransferData(transfer);
665
+ }
666
+
667
+ async checkTransferAppOwnerSession({ appDid, transferId }) {
668
+ const state = await this.getSessionState(appDid);
669
+
670
+ const transfer = await state.read(transferId);
671
+
672
+ if (!transfer) {
673
+ throw new Error(`The transfer session does not exist: ${transferId}`);
674
+ }
675
+
676
+ const { expireDate } = transfer;
677
+
678
+ if (Date.now() > expireDate) {
679
+ logger.error('Transfer session has expired', { transferId, expireAt: new Date(expireDate) });
680
+
681
+ throw new Error(`The transfer session has expired: ${transferId}`);
682
+ }
683
+
684
+ return formatTransferData(transfer);
685
+ }
686
+
687
+ async closeTransferAppOwnerSession({ appPid, transferId, status, timeout = 30 * 1000 }) {
688
+ const state = await this.getSessionState(appPid);
689
+
690
+ const session = await state.read(transferId);
691
+
692
+ if (!session) {
693
+ throw new Error(`The transfer app owner session does not exist: ${transferId}`);
694
+ }
695
+
696
+ await state.update(transferId, { status });
697
+
698
+ setTimeout(async () => {
699
+ try {
700
+ await state.end(transferId);
701
+ logger.info('Transfer session closed', { transferId });
702
+ } catch (error) {
703
+ logger.error('close transfer session failed', { transferId, error });
704
+ }
705
+ }, timeout);
706
+ }
707
+
604
708
  // Issue Passport
605
709
 
606
710
  /**
@@ -772,10 +876,27 @@ class TeamAPI extends EventEmitter {
772
876
  }
773
877
 
774
878
  async configTrustedPassports({ teamDid, trustedPassports }) {
775
- await validateTrustedPassportIssuers(trustedPassports);
879
+ const value = await validateTrustedPassportIssuers(trustedPassports);
880
+ await this.teamManager.configTrustedPassports(teamDid, value);
881
+ if (!this.teamManager.isNodeTeam(teamDid)) {
882
+ this.emit(BlockletEvents.updated, { meta: { did: teamDid } });
883
+ }
884
+ }
885
+
886
+ async configTrustedFactories({ teamDid, trustedFactories }) {
887
+ const value = await validateTrustedFactories(trustedFactories);
776
888
 
777
- await this.teamManager.configTrustedPassports(teamDid, trustedPassports);
889
+ const client = getChainClient(MAIN_CHAIN_ENDPOINT);
890
+ await Promise.all(
891
+ value.map(async (x) => {
892
+ const { state } = await client.getFactoryState({ address: x.factoryAddress });
893
+ if (!state) {
894
+ throw new Error(`NFT Collection ${x.factoryAddress} not found on ${MAIN_CHAIN_ENDPOINT}`);
895
+ }
896
+ })
897
+ );
778
898
 
899
+ await this.teamManager.configTrustedFactories(teamDid, value);
779
900
  if (!this.teamManager.isNodeTeam(teamDid)) {
780
901
  this.emit(BlockletEvents.updated, { meta: { did: teamDid } });
781
902
  }
@@ -1007,8 +1007,11 @@ class BlockletManager extends BaseBlockletManager {
1007
1007
  throw new Error('configs list is not an array');
1008
1008
  }
1009
1009
 
1010
- const dids = Array.isArray(did) ? uniq(did) : [did];
1011
- const [rootDid, ...childDids] = dids;
1010
+ const tmpDids = Array.isArray(did) ? uniq(did) : [did];
1011
+ const [rootDid, ...childDids] = tmpDids;
1012
+ const rootMetaDid = await states.blocklet.getBlockletMetaDid(rootDid);
1013
+ const dids = [rootMetaDid, ...childDids];
1014
+
1012
1015
  logger.info('config blocklet', { dids });
1013
1016
 
1014
1017
  const ancestors = [];
@@ -1044,6 +1047,14 @@ class BlockletManager extends BaseBlockletManager {
1044
1047
  configObj[x.key] = x.value;
1045
1048
  }
1046
1049
 
1050
+ const willAppSkChange = isRotatingAppSk(newConfigs, blocklet.configs, blocklet.externalSk);
1051
+ const willAppDidChange = isRotatingAppDid(newConfigs, blocklet.configs, blocklet.externalSk);
1052
+
1053
+ // NOTICE: cannot use appDid as did param because appDid will become old appDid in alsoKnownAs and cannot get blocklet by the old appDid
1054
+ if (willAppSkChange && rootDid !== rootMetaDid) {
1055
+ throw new Error(`Please use app meta did (${rootMetaDid}) as did param when config appSk`);
1056
+ }
1057
+
1047
1058
  // run hook
1048
1059
  if (!skipHook) {
1049
1060
  const nodeEnvironments = await states.node.getEnvironments();
@@ -1060,9 +1071,6 @@ class BlockletManager extends BaseBlockletManager {
1060
1071
 
1061
1072
  Object.assign(blocklet.configObj, configObj);
1062
1073
 
1063
- const willAppSkChange = isRotatingAppSk(newConfigs, blocklet.configs, blocklet.externalSk);
1064
- const willAppDidChange = isRotatingAppDid(newConfigs, blocklet.configs, blocklet.externalSk);
1065
-
1066
1074
  // update db
1067
1075
  await states.blockletExtras.setConfigs(dids, newConfigs);
1068
1076
 
@@ -1300,6 +1308,20 @@ class BlockletManager extends BaseBlockletManager {
1300
1308
  return this.getBlocklet(did);
1301
1309
  }
1302
1310
 
1311
+ async updateOwner({ did, owner }) {
1312
+ if (!validateOwner(owner)) {
1313
+ throw new Error('owner is invalid');
1314
+ }
1315
+
1316
+ const blocklet = await states.blocklet.getBlocklet(did);
1317
+ await states.blockletExtras.setSettings(blocklet.meta.did, { owner });
1318
+ logger.info('update blocklet owner', { did, owner });
1319
+
1320
+ this.emit(BlockletEvents.updated, { meta: { did: blocklet.meta.did } });
1321
+
1322
+ return this.getBlocklet(did);
1323
+ }
1324
+
1303
1325
  async status(did, { forceSync = false } = {}) {
1304
1326
  const fastReturnOnForceSync = async (blocklet = {}) => {
1305
1327
  const { status } = blocklet;
@@ -2,10 +2,10 @@ const path = require('path');
2
2
  const fs = require('fs-extra');
3
3
  const pick = require('lodash/pick');
4
4
  const pRetry = require('p-retry');
5
- const Client = require('@ocap/client');
6
5
  const urlPathFriendly = require('@blocklet/meta/lib/url-path-friendly').default;
7
6
  const { slugify } = require('transliteration');
8
7
  const Lock = require('@abtnode/util/lib/lock');
8
+ const { getChainClient } = require('@abtnode/util/lib/get-chain-client');
9
9
 
10
10
  const logger = require('@abtnode/logger')('@abtnode/core:migrate-application-to-struct-v2');
11
11
 
@@ -106,7 +106,7 @@ const getChainHost = (blocklet) => {
106
106
 
107
107
  const ensureAccountOnMainChain = async (blocklet, newWallet) => {
108
108
  // ensure new account on main chain
109
- const mainChainClient = new Client(MAIN_CHAIN_ENDPOINT);
109
+ const mainChainClient = getChainClient(MAIN_CHAIN_ENDPOINT);
110
110
  const newResultOnMainChain = await mainChainClient.getAccountState({ address: newWallet.address });
111
111
  if (!newResultOnMainChain.state) {
112
112
  logger.info('declare account on main chain', { address: newWallet.address, did: blocklet.meta.did });
@@ -157,7 +157,7 @@ const migrateAppOnChain = async (blocklet, oldSk, newSk) => {
157
157
 
158
158
  // migrate on chain
159
159
  logger.info('on-chain migration for chain ', { did: blocklet.meta.did, host: chainHost });
160
- const client = new Client(chainHost);
160
+ const client = getChainClient(chainHost);
161
161
  const oldResult = await client.getAccountState({ address: oldWallet.address });
162
162
  const newResult = await client.getAccountState({ address: newWallet.address });
163
163
 
package/lib/index.js CHANGED
@@ -250,6 +250,7 @@ function ABTNode(options) {
250
250
  hasBlocklet: blockletManager.hasBlocklet.bind(blockletManager),
251
251
  updateAllBlockletEnvironment: blockletManager.updateAllBlockletEnvironment.bind(blockletManager),
252
252
  setBlockletInitialized: blockletManager.setInitialized.bind(blockletManager),
253
+ updateBlockletOwner: blockletManager.updateOwner.bind(blockletManager),
253
254
  getBlockletRuntimeHistory: blockletManager.getRuntimeHistory.bind(blockletManager),
254
255
 
255
256
  // Store
@@ -278,13 +279,19 @@ function ABTNode(options) {
278
279
 
279
280
  // Invitation
280
281
  createMemberInvitation: teamAPI.createMemberInvitation.bind(teamAPI),
281
- createTransferInvitation: teamAPI.createTransferInvitation.bind(teamAPI),
282
282
  getInvitation: teamAPI.getInvitation.bind(teamAPI),
283
283
  getInvitations: teamAPI.getInvitations.bind(teamAPI),
284
284
  checkInvitation: teamAPI.checkInvitation.bind(teamAPI),
285
285
  deleteInvitation: teamAPI.deleteInvitation.bind(teamAPI),
286
286
  closeInvitation: teamAPI.closeInvitation.bind(teamAPI),
287
287
 
288
+ // transfer
289
+ createTransferAppOwnerSession: teamAPI.createTransferAppOwnerSession.bind(teamAPI),
290
+ getTransferAppOwnerSession: teamAPI.getTransferAppOwnerSession.bind(teamAPI),
291
+ checkTransferAppOwnerSession: teamAPI.checkTransferAppOwnerSession.bind(teamAPI),
292
+ closeTransferAppOwnerSession: teamAPI.closeTransferAppOwnerSession.bind(teamAPI),
293
+ createTransferInvitation: teamAPI.createTransferInvitation.bind(teamAPI),
294
+
288
295
  // Account
289
296
  getUsers: teamAPI.getUsers.bind(teamAPI),
290
297
  getUsersCount: teamAPI.getUsersCount.bind(teamAPI),
@@ -329,6 +336,7 @@ function ABTNode(options) {
329
336
  deletePassportIssuance: teamAPI.deletePassportIssuance.bind(teamAPI),
330
337
  processPassportIssuance: teamAPI.processPassportIssuance.bind(teamAPI),
331
338
  configTrustedPassports: teamAPI.configTrustedPassports.bind(teamAPI),
339
+ configTrustedFactories: teamAPI.configTrustedFactories.bind(teamAPI),
332
340
  configPassportIssuance: teamAPI.configPassportIssuance.bind(teamAPI),
333
341
 
334
342
  // Team Settings
@@ -69,6 +69,8 @@ const states = require('../states');
69
69
  const { getBlockletDomainGroupName, getDidFromDomainGroupName } = require('../util/router');
70
70
  const { getBlockletKnownAs } = require('../util/blocklet');
71
71
 
72
+ const isServiceFeDevelopment = process.env.ABT_NODE_SERVICE_FE_PORT;
73
+
72
74
  /**
73
75
  * replace 888-888-888-888 with accessible ip for domain
74
76
  */
@@ -327,7 +329,7 @@ const ensureWellknownRule = async (sites = []) => {
327
329
  type: 'blocklet',
328
330
  did: rule.to.did,
329
331
  componentId: rule.to.componentId,
330
- cacheGroup: 'blockletProxy',
332
+ cacheGroup: isServiceFeDevelopment ? '' : 'blockletProxy',
331
333
  target: avatarPathPrefix,
332
334
  },
333
335
  isProtected: true,
@@ -431,7 +433,7 @@ const ensureBlockletCache = async (sites = [], blocklets) => {
431
433
  cacheable.forEach((cachePrefix) => {
432
434
  const clone = cloneDeep(rule);
433
435
  clone.from.pathPrefix = joinUrl(rule.from.pathPrefix, cachePrefix);
434
- clone.to.cacheGroup = 'blockletProxy';
436
+ clone.to.cacheGroup = isServiceFeDevelopment ? '' : 'blockletProxy';
435
437
  clone.to.targetPrefix = cachePrefix;
436
438
  clone.dynamic = true; // mark as dynamic to avoid redundant generated rules
437
439
  cacheRules.push(clone);
@@ -17,6 +17,8 @@ const logger = require('@abtnode/logger')('@abtnode/core:router');
17
17
 
18
18
  const { isGatewayCacheEnabled, isBlockletSite } = require('../util');
19
19
 
20
+ const isServiceFeDevelopment = process.env.ABT_NODE_SERVICE_FE_PORT;
21
+
20
22
  const expandSites = (sites = []) => {
21
23
  const result = [];
22
24
 
@@ -284,7 +286,7 @@ Router.formatSites = (sites = []) => {
284
286
  port: daemonRule.to.port,
285
287
  type: ROUTING_RULE_TYPES.DAEMON,
286
288
  target: BLOCKLET_PROXY_PATH_PREFIX,
287
- cacheGroup: site.mode === BLOCKLET_MODES.PRODUCTION ? 'blockletProxy' : '',
289
+ cacheGroup: !isServiceFeDevelopment && site.mode === BLOCKLET_MODES.PRODUCTION ? 'blockletProxy' : '',
288
290
  did: rule.to.did,
289
291
  },
290
292
  });
@@ -1,3 +1,4 @@
1
+ /* eslint-disable no-case-declarations */
1
2
  /* eslint-disable no-async-promise-executor */
2
3
  const pick = require('lodash/pick');
3
4
  const get = require('lodash/get');
@@ -182,10 +183,17 @@ const getLogContent = async (action, args, context, result, info, node) => {
182
183
  case 'updatePermissionsForRole':
183
184
  return `granted following permissions to passport ${args.roleName} for ${team}: \n${args.grantNames.map(x => `- ${x}`).join('\n')}`; // prettier-ignore
184
185
  case 'configTrustedPassports':
185
- if (args.trustedPassports.length === 0) {
186
+ const trustedPassports = args.trustedPassports || [];
187
+ if (trustedPassports.length === 0) {
186
188
  return `removed all trusted passport issuers for ${team}`;
187
189
  }
188
- return `updated trusted passport issuers to following for ${team}: \n${args.trustedPassports.map(x => `- ${x.remark}: ${x.issuerDid}`).join('\n')}`; // prettier-ignore
190
+ return `updated trusted passport issuers to following for ${team}: \n${trustedPassports.map(x => `- ${x.remark}: ${x.issuerDid}`).join('\n')}`; // prettier-ignore
191
+ case 'configTrustedFactories':
192
+ const trustedFactories = args.trustedFactories || [];
193
+ if (trustedFactories.length === 0) {
194
+ return `removed all trusted factories for ${team}`;
195
+ }
196
+ return `updated trusted factories to following for ${team}: \n${trustedFactories.map(x => `- ${x.remark}: ${x.factoryAddress}`).join('\n')}`; // prettier-ignore
189
197
  case 'delegateTransferNFT':
190
198
  return `${args.owner} ${args.reason}`;
191
199
  case 'issuePassportToUser':
@@ -304,6 +312,7 @@ const getLogCategory = (action) => {
304
312
  case 'updateRole':
305
313
  case 'updatePermissionsForRole':
306
314
  case 'configTrustedPassports':
315
+ case 'configTrustedFactories':
307
316
  case 'delegateTransferNFT':
308
317
  case 'createTransferInvitation':
309
318
  return 'team';
@@ -28,6 +28,7 @@ const noop = (k) => (v) => v[k];
28
28
  // }>; // 在 blocklet dashboard 添加组件时的商店列表
29
29
  // navigations: any;
30
30
  // trustedPassports: any;
31
+ // trustedFactories: any;
31
32
  // enablePassportIssuance: boolean;
32
33
  // children: Array<any>; // deleted children
33
34
  // publicToStore: boolean;
@@ -111,14 +111,16 @@ class TeamManager extends EventEmitter {
111
111
  // user state
112
112
 
113
113
  async getUserState(did) {
114
+ const pid = await this.getPid(did);
115
+
114
116
  // validate exist
115
- if (!this.isNodeTeam(did) && !(await this.states.blocklet.hasBlocklet(did))) {
117
+ if (!pid) {
116
118
  logger.error('Did does not exist', { action: 'getUserState', did });
117
119
  throw new Error(`Did does not exist: ${did}`);
118
120
  }
119
121
 
120
- if (!this.cache[did]) {
121
- this.cache[did] = {
122
+ if (!this.cache[pid]) {
123
+ this.cache[pid] = {
122
124
  rbac: null,
123
125
  user: null,
124
126
  session: null,
@@ -126,15 +128,15 @@ class TeamManager extends EventEmitter {
126
128
  }
127
129
 
128
130
  // first get userState after blocklet added
129
- if (!this.cache[did].user) {
131
+ if (!this.cache[pid].user) {
130
132
  const user = await this.createUserState(did);
131
- logger.info('user state created', { teamDid: did });
132
- this.cache[did].user = user;
133
+ logger.info('Team state created', { teamDid: did });
134
+ this.cache[pid].user = user;
133
135
  return user;
134
136
  }
135
137
 
136
138
  // use cache
137
- return this.cache[did].user;
139
+ return this.cache[pid].user;
138
140
  }
139
141
 
140
142
  async createUserState(did) {
@@ -150,14 +152,16 @@ class TeamManager extends EventEmitter {
150
152
  // session state
151
153
 
152
154
  async getSessionState(did) {
155
+ const pid = await this.getPid(did);
156
+
153
157
  // validate exist
154
- if (!this.isNodeTeam(did) && !(await this.states.blocklet.hasBlocklet(did))) {
158
+ if (!pid) {
155
159
  logger.error('Did does not exist', { action: 'getSessionState', did });
156
160
  throw new Error(`Did does not exist: ${did}`);
157
161
  }
158
162
 
159
- if (!this.cache[did]) {
160
- this.cache[did] = {
163
+ if (!this.cache[pid]) {
164
+ this.cache[pid] = {
161
165
  rbac: null,
162
166
  user: null,
163
167
  session: null,
@@ -165,15 +169,15 @@ class TeamManager extends EventEmitter {
165
169
  }
166
170
 
167
171
  // first get userState after blocklet added
168
- if (!this.cache[did].session) {
169
- const session = await this.createSessionState(did);
170
- logger.info('session state created', { teamDid: did });
171
- this.cache[did].session = session;
172
+ if (!this.cache[pid].session) {
173
+ const session = await this.createSessionState(pid);
174
+ logger.info('session state created', { did, pid });
175
+ this.cache[pid].session = session;
172
176
  return session;
173
177
  }
174
178
 
175
179
  // use cache
176
- return this.cache[did].session;
180
+ return this.cache[pid].session;
177
181
  }
178
182
 
179
183
  async createSessionState(did) {
@@ -189,14 +193,16 @@ class TeamManager extends EventEmitter {
189
193
  async getRBAC(did) {
190
194
  logger.info('get rbac', { did });
191
195
 
196
+ const pid = await this.getPid(did);
197
+
192
198
  // validate exist
193
- if (!this.isNodeTeam(did) && !(await this.states.blocklet.hasBlocklet(did))) {
199
+ if (!pid) {
194
200
  logger.error('Did does not exist', { action: 'getRBAC', did });
195
201
  throw new Error(`Did does not exist: ${did}`);
196
202
  }
197
203
 
198
- if (!this.cache[did]) {
199
- this.cache[did] = {
204
+ if (!this.cache[pid]) {
205
+ this.cache[pid] = {
200
206
  rbac: null,
201
207
  user: null,
202
208
  session: null,
@@ -204,8 +210,8 @@ class TeamManager extends EventEmitter {
204
210
  }
205
211
 
206
212
  // first getRBAC after blocklet added
207
- if (!this.cache[did].rbac) {
208
- if (this.isNodeTeam(did)) {
213
+ if (!this.cache[pid].rbac) {
214
+ if (this.isNodeTeam(pid)) {
209
215
  throw new Error('Blocklet Server rbac instance has not been initialized');
210
216
  }
211
217
 
@@ -213,9 +219,9 @@ class TeamManager extends EventEmitter {
213
219
  await rbacCreationLock.acquire();
214
220
  try {
215
221
  logger.info('create rbac', { did });
216
- const file = await this.getRbacFileByDid(did);
222
+ const file = await this.getRbacFileByDid(pid);
217
223
  const rbac = await createRBAC({ storage: new NedbStorage({ file }) });
218
- this.cache[did].rbac = rbac;
224
+ this.cache[pid].rbac = rbac;
219
225
 
220
226
  const roles = await rbac.getRoles();
221
227
  // 按照顺序创建, 后创建的会排在前面
@@ -235,7 +241,7 @@ class TeamManager extends EventEmitter {
235
241
  }
236
242
 
237
243
  // use cache
238
- return this.cache[did].rbac;
244
+ return this.cache[pid].rbac;
239
245
  }
240
246
 
241
247
  isNodeTeam(did) {
@@ -247,7 +253,16 @@ class TeamManager extends EventEmitter {
247
253
  return this.states.node.updateNodeInfo({ trustedPassports });
248
254
  }
249
255
 
250
- return this.states.blockletExtras.setSettings(did, { trustedPassports });
256
+ const metaDid = await this.states.blocklet.getBlockletMetaDid(did);
257
+ return this.states.blockletExtras.setSettings(metaDid, { trustedPassports });
258
+ }
259
+
260
+ async configTrustedFactories(did, trustedFactories) {
261
+ if (this.isNodeTeam(did)) {
262
+ return this.states.node.updateNodeInfo({ trustedFactories });
263
+ }
264
+
265
+ return this.states.blockletExtras.setSettings(did, { trustedFactories });
251
266
  }
252
267
 
253
268
  async configWhoCanAccess(did, value) {
@@ -255,7 +270,8 @@ class TeamManager extends EventEmitter {
255
270
  throw new Error('Cannot be node did');
256
271
  }
257
272
 
258
- return this.states.blockletExtras.setSettings(did, { whoCanAccess: value });
273
+ const metaDid = await this.states.blocklet.getBlockletMetaDid(did);
274
+ return this.states.blockletExtras.setSettings(metaDid, { whoCanAccess: value });
259
275
  }
260
276
 
261
277
  async configPassportIssuance(did, enable) {
@@ -264,7 +280,8 @@ class TeamManager extends EventEmitter {
264
280
  return this.states.node.updateNodeInfo({ enablePassportIssuance });
265
281
  }
266
282
 
267
- return this.states.blockletExtras.setSettings(did, { enablePassportIssuance });
283
+ const metaDid = await this.states.blocklet.getBlockletMetaDid(did);
284
+ return this.states.blockletExtras.setSettings(metaDid, { enablePassportIssuance });
268
285
  }
269
286
 
270
287
  async checkEnablePassportIssuance(did) {
@@ -273,7 +290,8 @@ class TeamManager extends EventEmitter {
273
290
  const nodeInfo = await this.states.node.read();
274
291
  enable = get(nodeInfo, 'enablePassportIssuance', true);
275
292
  } else {
276
- const settings = this.states.blockletExtras.getSettings(did);
293
+ const metaDid = await this.states.blocklet.getBlockletMetaDid(did);
294
+ const settings = await this.states.blockletExtras.getSettings(metaDid);
277
295
  enable = get(settings, 'enablePassportIssuance', true);
278
296
  }
279
297
 
@@ -283,13 +301,26 @@ class TeamManager extends EventEmitter {
283
301
  }
284
302
  }
285
303
 
304
+ async checkEnableTransferAppOwner(did) {
305
+ if (this.isNodeTeam(did)) {
306
+ throw new Error('server owner cannot be transfer by this workflow');
307
+ }
308
+
309
+ const exist = await this.states.blocklet.hasBlocklet(did);
310
+
311
+ if (!exist) {
312
+ throw new Error(`Blocklet ${did} does not exist`);
313
+ }
314
+ }
315
+
286
316
  async getStoreList(did) {
287
317
  if (this.isNodeTeam(did)) {
288
318
  const nodeInfo = await this.states.node.read();
289
319
  return nodeInfo.blockletRegistryList || [];
290
320
  }
291
321
 
292
- const settings = await this.states.blockletExtras.getSettings(did);
322
+ const metaDid = await this.states.blocklet.getBlockletMetaDid(did);
323
+ const settings = await this.states.blockletExtras.getSettings(metaDid);
293
324
  return get(settings, 'storeList', []) || [];
294
325
  }
295
326
 
@@ -299,8 +330,9 @@ class TeamManager extends EventEmitter {
299
330
  return;
300
331
  }
301
332
 
302
- await this.states.blockletExtras.setSettings(did, { storeList: list });
303
- this.emit(BlockletEvents.storeChange, { meta: { did } });
333
+ const metaDid = await this.states.blocklet.getBlockletMetaDid(did);
334
+ await this.states.blockletExtras.setSettings(metaDid, { storeList: list });
335
+ this.emit(BlockletEvents.storeChange, { meta: { did: metaDid } });
304
336
  }
305
337
 
306
338
  async getOwner(did) {
@@ -309,7 +341,8 @@ class TeamManager extends EventEmitter {
309
341
  const nodeInfo = await this.states.node.read();
310
342
  owner = get(nodeInfo, 'nodeOwner');
311
343
  } else {
312
- const settings = await this.states.blockletExtras.getSettings(did);
344
+ const metaDid = await this.states.blocklet.getBlockletMetaDid(did);
345
+ const settings = await this.states.blockletExtras.getSettings(metaDid);
313
346
  owner = get(settings, 'owner');
314
347
  }
315
348
 
@@ -351,18 +384,20 @@ class TeamManager extends EventEmitter {
351
384
 
352
385
  logger.info('deleteTeam', { did, closeDB });
353
386
 
354
- if (closeDB && this.cache[did]) {
387
+ const pid = await this.getPid(did);
388
+
389
+ if (closeDB && this.cache[pid]) {
355
390
  try {
356
- if (this.cache[did].rbac) {
357
- await closeDatabase(this.cache[did].rbac.storage.db);
391
+ if (this.cache[pid].rbac) {
392
+ await closeDatabase(this.cache[pid].rbac.storage.db);
358
393
  }
359
394
 
360
- if (this.cache[did].user) {
361
- await closeDatabase(this.cache[did].user.db);
395
+ if (this.cache[pid].user) {
396
+ await closeDatabase(this.cache[pid].user.db);
362
397
  }
363
398
 
364
- if (this.cache[did].session) {
365
- await closeDatabase(this.cache[did].session.db);
399
+ if (this.cache[pid].session) {
400
+ await closeDatabase(this.cache[pid].session.db);
366
401
  }
367
402
 
368
403
  // NOTICE: wait for nedb to finish closeDatabase
@@ -374,6 +409,7 @@ class TeamManager extends EventEmitter {
374
409
  }
375
410
 
376
411
  this.cache[did] = null;
412
+ this.cache[pid] = null;
377
413
  }
378
414
 
379
415
  // =======
@@ -393,6 +429,14 @@ class TeamManager extends EventEmitter {
393
429
  const blocklet = await this.states.blocklet.getBlocklet(did);
394
430
  return path.join(this.dataDirs.data, blocklet.meta.name);
395
431
  }
432
+
433
+ async getPid(did) {
434
+ if (this.isNodeTeam(did)) {
435
+ return did;
436
+ }
437
+
438
+ return this.states.blocklet.getBlockletMetaDid(did);
439
+ }
396
440
  }
397
441
 
398
442
  module.exports = TeamManager;
@@ -1388,6 +1388,7 @@ const getBlocklet = async ({
1388
1388
  // app settings
1389
1389
  const settings = await states.blockletExtras.getSettings(blocklet.meta.did);
1390
1390
  blocklet.trustedPassports = get(settings, 'trustedPassports') || [];
1391
+ blocklet.trustedFactories = get(settings, 'trustedFactories') || [];
1391
1392
  blocklet.enablePassportIssuance = get(settings, 'enablePassportIssuance', true);
1392
1393
  blocklet.settings = settings || {};
1393
1394
 
@@ -0,0 +1,27 @@
1
+ /* eslint-disable newline-per-chained-call */
2
+ const JOI = require('joi');
3
+ const { didExtension } = require('@blocklet/meta/lib/extension');
4
+ const { getMultipleLangParams } = require('./util');
5
+
6
+ const Joi = JOI.extend(didExtension);
7
+
8
+ const trustedFactoriesSchema = Joi.array()
9
+ .items(
10
+ Joi.object({
11
+ issuerDid: Joi.DID().optional().allow('').default(''),
12
+ holderDid: Joi.DID().optional().allow('').default(''),
13
+ factoryAddress: Joi.DID().required(),
14
+ remark: Joi.string().trim().required(),
15
+ passport: Joi.object({
16
+ role: Joi.string().required(),
17
+ ttl: Joi.number().integer().min(0).default(0),
18
+ }).required(),
19
+ })
20
+ )
21
+ .unique((a, b) => a.factoryAddress === b.factoryAddress)
22
+ .options({ stripUnknown: true, noDefaults: false });
23
+
24
+ module.exports = {
25
+ validateTrustedFactories: (entity, context) =>
26
+ trustedFactoriesSchema.validateAsync(entity, getMultipleLangParams(context)),
27
+ };
@@ -5,22 +5,26 @@ const { getMultipleLangParams } = require('./util');
5
5
 
6
6
  const Joi = JOI.extend(didExtension);
7
7
 
8
- const trustedPassportsSchema = Joi.array().items(
9
- Joi.object({
10
- issuerDid: Joi.DID().required(),
11
- remark: Joi.string().trim(),
12
- mappings: Joi.array().items(
13
- Joi.object({
14
- from: Joi.object({
15
- passport: Joi.string().required(),
16
- }),
17
- to: Joi.object({
18
- role: Joi.string().required(),
19
- }),
20
- })
21
- ),
22
- })
23
- );
8
+ const trustedPassportsSchema = Joi.array()
9
+ .items(
10
+ Joi.object({
11
+ issuerDid: Joi.DID().required(),
12
+ remark: Joi.string().trim(),
13
+ mappings: Joi.array().items(
14
+ Joi.object({
15
+ from: Joi.object({
16
+ passport: Joi.string().required(),
17
+ }),
18
+ to: Joi.object({
19
+ role: Joi.string().required(),
20
+ ttl: Joi.number().integer().min(0).default(0),
21
+ }),
22
+ })
23
+ ),
24
+ })
25
+ )
26
+ .unique((a, b) => a.issuerDid === b.issuerDid)
27
+ .options({ stripUnknown: true, noDefaults: false });
24
28
 
25
29
  module.exports = {
26
30
  validateTrustedPassportIssuers: (entity, context) =>
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.16.5-beta-1472da21",
6
+ "version": "1.16.6-beta-8be2fe37",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,34 +19,34 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@abtnode/auth": "1.16.5-beta-1472da21",
23
- "@abtnode/certificate-manager": "1.16.5-beta-1472da21",
24
- "@abtnode/constant": "1.16.5-beta-1472da21",
25
- "@abtnode/cron": "1.16.5-beta-1472da21",
26
- "@abtnode/db": "1.16.5-beta-1472da21",
27
- "@abtnode/logger": "1.16.5-beta-1472da21",
28
- "@abtnode/queue": "1.16.5-beta-1472da21",
29
- "@abtnode/rbac": "1.16.5-beta-1472da21",
30
- "@abtnode/router-provider": "1.16.5-beta-1472da21",
31
- "@abtnode/static-server": "1.16.5-beta-1472da21",
32
- "@abtnode/timemachine": "1.16.5-beta-1472da21",
33
- "@abtnode/util": "1.16.5-beta-1472da21",
34
- "@arcblock/did": "1.18.68",
22
+ "@abtnode/auth": "1.16.6-beta-8be2fe37",
23
+ "@abtnode/certificate-manager": "1.16.6-beta-8be2fe37",
24
+ "@abtnode/constant": "1.16.6-beta-8be2fe37",
25
+ "@abtnode/cron": "1.16.6-beta-8be2fe37",
26
+ "@abtnode/db": "1.16.6-beta-8be2fe37",
27
+ "@abtnode/logger": "1.16.6-beta-8be2fe37",
28
+ "@abtnode/queue": "1.16.6-beta-8be2fe37",
29
+ "@abtnode/rbac": "1.16.6-beta-8be2fe37",
30
+ "@abtnode/router-provider": "1.16.6-beta-8be2fe37",
31
+ "@abtnode/static-server": "1.16.6-beta-8be2fe37",
32
+ "@abtnode/timemachine": "1.16.6-beta-8be2fe37",
33
+ "@abtnode/util": "1.16.6-beta-8be2fe37",
34
+ "@arcblock/did": "1.18.71",
35
35
  "@arcblock/did-motif": "^1.1.10",
36
- "@arcblock/did-util": "1.18.68",
37
- "@arcblock/event-hub": "1.18.68",
38
- "@arcblock/jwt": "^1.18.68",
36
+ "@arcblock/did-util": "1.18.71",
37
+ "@arcblock/event-hub": "1.18.71",
38
+ "@arcblock/jwt": "^1.18.71",
39
39
  "@arcblock/pm2-events": "^0.0.5",
40
- "@arcblock/vc": "1.18.68",
41
- "@blocklet/constant": "1.16.5-beta-1472da21",
42
- "@blocklet/meta": "1.16.5-beta-1472da21",
43
- "@blocklet/sdk": "1.16.5-beta-1472da21",
44
- "@did-space/client": "^0.2.72",
40
+ "@arcblock/vc": "1.18.71",
41
+ "@blocklet/constant": "1.16.6-beta-8be2fe37",
42
+ "@blocklet/meta": "1.16.6-beta-8be2fe37",
43
+ "@blocklet/sdk": "1.16.6-beta-8be2fe37",
44
+ "@did-space/client": "^0.2.74",
45
45
  "@fidm/x509": "^1.2.1",
46
- "@ocap/client": "1.18.68",
47
- "@ocap/mcrypto": "1.18.68",
48
- "@ocap/util": "1.18.68",
49
- "@ocap/wallet": "1.18.68",
46
+ "@ocap/client": "1.18.71",
47
+ "@ocap/mcrypto": "1.18.71",
48
+ "@ocap/util": "1.18.71",
49
+ "@ocap/wallet": "1.18.71",
50
50
  "@slack/webhook": "^5.0.4",
51
51
  "archiver": "^5.3.1",
52
52
  "axios": "^0.27.2",
@@ -93,5 +93,5 @@
93
93
  "express": "^4.18.2",
94
94
  "jest": "^27.5.1"
95
95
  },
96
- "gitHead": "98f7daa18747660f044ef1c736b1b58bdefa6925"
96
+ "gitHead": "27229a1a62850e95907b7a53e0259a809d99377b"
97
97
  }