@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 +132 -11
- package/lib/blocklet/manager/disk.js +27 -5
- package/lib/blocklet/manager/helper/migrate-application-to-struct-v2.js +3 -3
- package/lib/index.js +9 -1
- package/lib/router/helper.js +4 -2
- package/lib/router/index.js +3 -1
- package/lib/states/audit-log.js +11 -2
- package/lib/states/blocklet-extras.js +1 -0
- package/lib/team/manager.js +82 -38
- package/lib/util/blocklet.js +1 -0
- package/lib/validators/trusted-factory.js +27 -0
- package/lib/validators/trusted-passport.js +20 -16
- package/package.json +27 -27
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.
|
|
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 } =
|
|
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
|
-
|
|
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
|
|
1011
|
-
const [rootDid, ...childDids] =
|
|
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 =
|
|
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 =
|
|
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
|
package/lib/router/helper.js
CHANGED
|
@@ -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);
|
package/lib/router/index.js
CHANGED
|
@@ -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
|
});
|
package/lib/states/audit-log.js
CHANGED
|
@@ -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
|
-
|
|
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${
|
|
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;
|
package/lib/team/manager.js
CHANGED
|
@@ -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 (!
|
|
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[
|
|
121
|
-
this.cache[
|
|
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[
|
|
131
|
+
if (!this.cache[pid].user) {
|
|
130
132
|
const user = await this.createUserState(did);
|
|
131
|
-
logger.info('
|
|
132
|
-
this.cache[
|
|
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[
|
|
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 (!
|
|
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[
|
|
160
|
-
this.cache[
|
|
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[
|
|
169
|
-
const session = await this.createSessionState(
|
|
170
|
-
logger.info('session state created', {
|
|
171
|
-
this.cache[
|
|
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[
|
|
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 (!
|
|
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[
|
|
199
|
-
this.cache[
|
|
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[
|
|
208
|
-
if (this.isNodeTeam(
|
|
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(
|
|
222
|
+
const file = await this.getRbacFileByDid(pid);
|
|
217
223
|
const rbac = await createRBAC({ storage: new NedbStorage({ file }) });
|
|
218
|
-
this.cache[
|
|
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[
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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.
|
|
303
|
-
this.
|
|
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
|
|
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
|
-
|
|
387
|
+
const pid = await this.getPid(did);
|
|
388
|
+
|
|
389
|
+
if (closeDB && this.cache[pid]) {
|
|
355
390
|
try {
|
|
356
|
-
if (this.cache[
|
|
357
|
-
await closeDatabase(this.cache[
|
|
391
|
+
if (this.cache[pid].rbac) {
|
|
392
|
+
await closeDatabase(this.cache[pid].rbac.storage.db);
|
|
358
393
|
}
|
|
359
394
|
|
|
360
|
-
if (this.cache[
|
|
361
|
-
await closeDatabase(this.cache[
|
|
395
|
+
if (this.cache[pid].user) {
|
|
396
|
+
await closeDatabase(this.cache[pid].user.db);
|
|
362
397
|
}
|
|
363
398
|
|
|
364
|
-
if (this.cache[
|
|
365
|
-
await closeDatabase(this.cache[
|
|
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;
|
package/lib/util/blocklet.js
CHANGED
|
@@ -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()
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Joi.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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.
|
|
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.
|
|
23
|
-
"@abtnode/certificate-manager": "1.16.
|
|
24
|
-
"@abtnode/constant": "1.16.
|
|
25
|
-
"@abtnode/cron": "1.16.
|
|
26
|
-
"@abtnode/db": "1.16.
|
|
27
|
-
"@abtnode/logger": "1.16.
|
|
28
|
-
"@abtnode/queue": "1.16.
|
|
29
|
-
"@abtnode/rbac": "1.16.
|
|
30
|
-
"@abtnode/router-provider": "1.16.
|
|
31
|
-
"@abtnode/static-server": "1.16.
|
|
32
|
-
"@abtnode/timemachine": "1.16.
|
|
33
|
-
"@abtnode/util": "1.16.
|
|
34
|
-
"@arcblock/did": "1.18.
|
|
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.
|
|
37
|
-
"@arcblock/event-hub": "1.18.
|
|
38
|
-
"@arcblock/jwt": "^1.18.
|
|
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.
|
|
41
|
-
"@blocklet/constant": "1.16.
|
|
42
|
-
"@blocklet/meta": "1.16.
|
|
43
|
-
"@blocklet/sdk": "1.16.
|
|
44
|
-
"@did-space/client": "^0.2.
|
|
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.
|
|
47
|
-
"@ocap/mcrypto": "1.18.
|
|
48
|
-
"@ocap/util": "1.18.
|
|
49
|
-
"@ocap/wallet": "1.18.
|
|
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": "
|
|
96
|
+
"gitHead": "27229a1a62850e95907b7a53e0259a809d99377b"
|
|
97
97
|
}
|