@abtnode/auth 1.8.37 → 1.8.39
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/auth.js +60 -16
- package/lib/server.js +29 -31
- package/package.json +14 -14
package/lib/auth.js
CHANGED
|
@@ -15,6 +15,7 @@ const {
|
|
|
15
15
|
ROLES,
|
|
16
16
|
NODE_DATA_DIR_NAME,
|
|
17
17
|
AUTH_CERT_TYPE,
|
|
18
|
+
WELLKNOWN_BLOCKLET_ADMIN_PATH,
|
|
18
19
|
} = require('@abtnode/constant');
|
|
19
20
|
const axios = require('@abtnode/util/lib/axios');
|
|
20
21
|
const { extractUserAvatar, parseUserAvatar } = require('@abtnode/util/lib/user-avatar');
|
|
@@ -201,6 +202,22 @@ const messages = {
|
|
|
201
202
|
en: 'Please provide server ownership NFT',
|
|
202
203
|
zh: '请提供节点所有权 NFT',
|
|
203
204
|
},
|
|
205
|
+
requestServerlessNFT: {
|
|
206
|
+
en: 'Please provide serverless NFT',
|
|
207
|
+
zh: '请提供无服务 NFT',
|
|
208
|
+
},
|
|
209
|
+
serverlessNftIdRequired: {
|
|
210
|
+
en: 'Serverless NFT ID is required',
|
|
211
|
+
zh: '无服务 NFT ID 是必须的',
|
|
212
|
+
},
|
|
213
|
+
nftAlreadyConsume: {
|
|
214
|
+
en: 'This NFT has already been used',
|
|
215
|
+
zh: '该 NFT 已经被使用过了',
|
|
216
|
+
},
|
|
217
|
+
nftAlreadyExpired: {
|
|
218
|
+
en: 'This NFT has expired',
|
|
219
|
+
zh: '该 NFT 已经过期',
|
|
220
|
+
},
|
|
204
221
|
missingNftClaim: {
|
|
205
222
|
en: 'Ownership NFT not provided',
|
|
206
223
|
zh: '节点所有权 NFT 必须提供',
|
|
@@ -237,6 +254,11 @@ const messages = {
|
|
|
237
254
|
|
|
238
255
|
const PASSPORT_STATUS_KEY = 'passport-status';
|
|
239
256
|
|
|
257
|
+
const TEAM_TYPE = {
|
|
258
|
+
NODE: 'node',
|
|
259
|
+
BLOCKLET: 'blocklet',
|
|
260
|
+
};
|
|
261
|
+
|
|
240
262
|
const getPassportStatusEndpoint = ({ baseUrl, userDid, teamDid }) => {
|
|
241
263
|
if (!baseUrl) {
|
|
242
264
|
return null;
|
|
@@ -279,7 +301,7 @@ const getTeamInfo = async ({ node, nodeInfo, teamDid }) => {
|
|
|
279
301
|
name = nodeInfo.name;
|
|
280
302
|
description = nodeInfo.description;
|
|
281
303
|
wallet = getNodeWallet(nodeInfo.sk);
|
|
282
|
-
type =
|
|
304
|
+
type = TEAM_TYPE.NODE;
|
|
283
305
|
passportColor = 'default';
|
|
284
306
|
owner = nodeInfo.nodeOwner;
|
|
285
307
|
dataDir = path.join(node.dataDirs.data, NODE_DATA_DIR_NAME);
|
|
@@ -290,7 +312,7 @@ const getTeamInfo = async ({ node, nodeInfo, teamDid }) => {
|
|
|
290
312
|
description = blockletInfo.description;
|
|
291
313
|
wallet = blockletInfo.wallet;
|
|
292
314
|
passportColor = blockletInfo.passportColor;
|
|
293
|
-
type =
|
|
315
|
+
type = TEAM_TYPE.BLOCKLET;
|
|
294
316
|
owner = get(blocklet, 'settings.owner');
|
|
295
317
|
dataDir = blocklet.env.dataDir;
|
|
296
318
|
}
|
|
@@ -493,7 +515,7 @@ const handleInvitationResponse = async ({
|
|
|
493
515
|
preferredColor: passportColor,
|
|
494
516
|
};
|
|
495
517
|
|
|
496
|
-
if (issuerType ===
|
|
518
|
+
if (issuerType === TEAM_TYPE.NODE) {
|
|
497
519
|
vcParams.tag = nodeInfo.did;
|
|
498
520
|
}
|
|
499
521
|
|
|
@@ -731,7 +753,7 @@ const handleIssuePassportResponse = async ({
|
|
|
731
753
|
preferredColor: passportColor,
|
|
732
754
|
};
|
|
733
755
|
|
|
734
|
-
if (issuerType ===
|
|
756
|
+
if (issuerType === TEAM_TYPE.NODE) {
|
|
735
757
|
vcParams.tag = nodeInfo.did;
|
|
736
758
|
}
|
|
737
759
|
|
|
@@ -763,7 +785,7 @@ const handleIssuePassportResponse = async ({
|
|
|
763
785
|
node
|
|
764
786
|
);
|
|
765
787
|
|
|
766
|
-
if (name === ROLES.OWNER && issuerType ===
|
|
788
|
+
if (name === ROLES.OWNER && issuerType === TEAM_TYPE.BLOCKLET) {
|
|
767
789
|
logger.info('Bind owner for blocklet', { teamDid, userDid });
|
|
768
790
|
await node.setBlockletInitialized({ did: teamDid, owner: { did: userDid, pk: userPk } });
|
|
769
791
|
}
|
|
@@ -846,8 +868,14 @@ const getPassportStatus = async ({ node, teamDid, userDid, vcId, locale = 'en' }
|
|
|
846
868
|
const { wallet: issuerWallet, name: issuerName, type: issuerType } = await getTeamInfo({ node, nodeInfo, teamDid });
|
|
847
869
|
|
|
848
870
|
const actionLabel = {
|
|
849
|
-
|
|
850
|
-
|
|
871
|
+
open: {
|
|
872
|
+
zh: `${issuerType === TEAM_TYPE.NODE ? '管理节点' : '查看 Blocklet'}`,
|
|
873
|
+
en: `${issuerType === TEAM_TYPE.NODE ? 'Manage Node' : 'View Blocklet'}`,
|
|
874
|
+
},
|
|
875
|
+
manage: {
|
|
876
|
+
zh: '管理 Blocklet',
|
|
877
|
+
en: 'Manage Blocklet',
|
|
878
|
+
},
|
|
851
879
|
};
|
|
852
880
|
|
|
853
881
|
const user = await node.getUser({ teamDid, user: { did: userDid } });
|
|
@@ -875,18 +903,33 @@ const getPassportStatus = async ({ node, teamDid, userDid, vcId, locale = 'en' }
|
|
|
875
903
|
|
|
876
904
|
const actionList = [];
|
|
877
905
|
if (passport.endpoint) {
|
|
906
|
+
const claims = [];
|
|
907
|
+
|
|
908
|
+
// open blocklet
|
|
909
|
+
claims.push({
|
|
910
|
+
id: passport.endpoint,
|
|
911
|
+
type: 'navigate',
|
|
912
|
+
name: issuerType === TEAM_TYPE.NODE ? 'open-node' : 'open-blocklet',
|
|
913
|
+
scope: 'public',
|
|
914
|
+
label: actionLabel.open[locale],
|
|
915
|
+
});
|
|
916
|
+
|
|
917
|
+
// manage blocklet
|
|
918
|
+
const { name } = passport;
|
|
919
|
+
if ([ROLES.OWNER, ROLES.ADMIN].includes(name) && issuerType === TEAM_TYPE.BLOCKLET) {
|
|
920
|
+
claims.push({
|
|
921
|
+
id: joinUrl(passport.endpoint, WELLKNOWN_BLOCKLET_ADMIN_PATH),
|
|
922
|
+
type: 'navigate',
|
|
923
|
+
name: 'open-blocklet-admin',
|
|
924
|
+
scope: 'public',
|
|
925
|
+
label: actionLabel.manage[locale],
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
|
|
878
929
|
actionList.push(
|
|
879
930
|
...createCredentialList({
|
|
880
931
|
issuer,
|
|
881
|
-
claims
|
|
882
|
-
{
|
|
883
|
-
id: passport.endpoint,
|
|
884
|
-
type: 'navigate',
|
|
885
|
-
name: issuerType === 'node' ? 'open-node' : 'open-blocklet',
|
|
886
|
-
scope: 'public',
|
|
887
|
-
label: actionLabel[locale],
|
|
888
|
-
},
|
|
889
|
-
],
|
|
932
|
+
claims,
|
|
890
933
|
})
|
|
891
934
|
);
|
|
892
935
|
}
|
|
@@ -976,4 +1019,5 @@ module.exports = {
|
|
|
976
1019
|
validatePassportStatus,
|
|
977
1020
|
setUserInfoHeaders,
|
|
978
1021
|
createBlockletControllerAuthToken,
|
|
1022
|
+
TEAM_TYPE,
|
|
979
1023
|
};
|
package/lib/server.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const get = require('lodash/get');
|
|
2
2
|
const isEmpty = require('lodash/isEmpty');
|
|
3
3
|
const last = require('lodash/last');
|
|
4
|
+
const { isNFTExpired, isNFTConsumed } = require('@abtnode/util/lib/nft');
|
|
4
5
|
const Client = require('@ocap/client');
|
|
5
6
|
const { fromPublicKey } = require('@ocap/wallet');
|
|
6
7
|
const { fromBase58, toAddress } = require('@ocap/util');
|
|
@@ -12,7 +13,7 @@ const {
|
|
|
12
13
|
VC_TYPE_NODE_PASSPORT,
|
|
13
14
|
NFT_TYPE_SERVER_OWNERSHIP,
|
|
14
15
|
SERVER_ROLES,
|
|
15
|
-
|
|
16
|
+
NFT_TYPE_SERVERLESS,
|
|
16
17
|
} = require('@abtnode/constant');
|
|
17
18
|
const { toExternalBlocklet } = require('@blocklet/meta/lib/did');
|
|
18
19
|
const {
|
|
@@ -55,16 +56,6 @@ const getTrustedIssuers = (nodeInfo) => {
|
|
|
55
56
|
return [nodeInfo.did, ...trustedPassports].filter(Boolean);
|
|
56
57
|
};
|
|
57
58
|
|
|
58
|
-
const getExternalPassport = async (nft) => {
|
|
59
|
-
const data = JSON.parse(nft.data.value);
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
name: SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER,
|
|
63
|
-
appMaxCount: data.appMaxCount || 1,
|
|
64
|
-
expireDate: last(data.expirationDate),
|
|
65
|
-
};
|
|
66
|
-
};
|
|
67
|
-
|
|
68
59
|
const authenticateByVc = async ({
|
|
69
60
|
node,
|
|
70
61
|
locale,
|
|
@@ -153,7 +144,7 @@ const authenticateByVc = async ({
|
|
|
153
144
|
return { role, user, teamDid, passport };
|
|
154
145
|
};
|
|
155
146
|
|
|
156
|
-
const authenticateByNFT = async ({ node, claims, userDid, challenge, locale }) => {
|
|
147
|
+
const authenticateByNFT = async ({ node, claims, userDid, challenge, locale, isAuth }) => {
|
|
157
148
|
const info = await node.getNodeInfo();
|
|
158
149
|
const client = new Client(info.launcher.chainHost);
|
|
159
150
|
|
|
@@ -193,8 +184,16 @@ const authenticateByNFT = async ({ node, claims, userDid, challenge, locale }) =
|
|
|
193
184
|
throw new Error(messages.invalidNftIssuer[locale]);
|
|
194
185
|
}
|
|
195
186
|
|
|
196
|
-
if (state.tags.includes(
|
|
197
|
-
|
|
187
|
+
if (state.tags.includes(NFT_TYPE_SERVERLESS)) {
|
|
188
|
+
state.data.value = JSON.parse(state.data.value);
|
|
189
|
+
|
|
190
|
+
if (!isAuth && isNFTConsumed(state)) {
|
|
191
|
+
throw new Error(messages.nftAlreadyConsume[locale]);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (!isAuth && isNFTExpired(state)) {
|
|
195
|
+
throw new Error(messages.nftAlreadyExpired[locale]);
|
|
196
|
+
}
|
|
198
197
|
|
|
199
198
|
return {
|
|
200
199
|
role: SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER,
|
|
@@ -202,8 +201,7 @@ const authenticateByNFT = async ({ node, claims, userDid, challenge, locale }) =
|
|
|
202
201
|
controller: {
|
|
203
202
|
nftId: address,
|
|
204
203
|
nftOwner: state.owner,
|
|
205
|
-
appMaxCount:
|
|
206
|
-
expireDate: passport.expireDate,
|
|
204
|
+
appMaxCount: state.data.value.appMaxCount || 1,
|
|
207
205
|
},
|
|
208
206
|
},
|
|
209
207
|
user: {
|
|
@@ -263,10 +261,14 @@ const getAuthVcClaim =
|
|
|
263
261
|
|
|
264
262
|
const getAuthNFTClaim =
|
|
265
263
|
({ node }) =>
|
|
266
|
-
async ({ extraParams: { locale, launchType }, context: { didwallet } }) => {
|
|
264
|
+
async ({ extraParams: { locale, launchType, nftId }, context: { didwallet } }) => {
|
|
267
265
|
checkWalletVersion({ didwallet, locale });
|
|
268
266
|
if (launchType === 'serverless') {
|
|
269
|
-
|
|
267
|
+
if (!nftId) {
|
|
268
|
+
throw new Error(messages.serverlessNftIdRequired[locale]);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return getServerlessNFTClaim(node, nftId, locale);
|
|
270
272
|
}
|
|
271
273
|
|
|
272
274
|
return getOwnershipNFTClaim(node, locale);
|
|
@@ -318,7 +320,7 @@ const getOwnershipNFTClaim = async (node, locale) => {
|
|
|
318
320
|
};
|
|
319
321
|
};
|
|
320
322
|
|
|
321
|
-
const
|
|
323
|
+
const getServerlessNFTClaim = async (node, nftId, locale) => {
|
|
322
324
|
const info = await node.getNodeInfo();
|
|
323
325
|
if (!info.ownerNft || !info.ownerNft.issuer) {
|
|
324
326
|
throw new Error(messages.noNft[locale]);
|
|
@@ -331,13 +333,13 @@ const getUsageCredentialNFTClaim = async (node, locale) => {
|
|
|
331
333
|
}
|
|
332
334
|
|
|
333
335
|
return {
|
|
334
|
-
description: messages.
|
|
336
|
+
description: messages.requestServerlessNFT[locale],
|
|
335
337
|
trustedIssuers: [info.ownerNft.issuer],
|
|
336
|
-
|
|
338
|
+
address: nftId,
|
|
337
339
|
};
|
|
338
340
|
};
|
|
339
341
|
|
|
340
|
-
const ensureBlockletPermission = async ({ authMethod, node, userDid, claims, challenge, locale, blocklet }) => {
|
|
342
|
+
const ensureBlockletPermission = async ({ authMethod, node, userDid, claims, challenge, locale, blocklet, isAuth }) => {
|
|
341
343
|
let result;
|
|
342
344
|
if (authMethod === 'vc') {
|
|
343
345
|
result = await authenticateByVc({
|
|
@@ -357,6 +359,7 @@ const ensureBlockletPermission = async ({ authMethod, node, userDid, claims, cha
|
|
|
357
359
|
userDid,
|
|
358
360
|
claims,
|
|
359
361
|
challenge,
|
|
362
|
+
isAuth,
|
|
360
363
|
});
|
|
361
364
|
}
|
|
362
365
|
const { teamDid, role } = result;
|
|
@@ -387,6 +390,7 @@ const createLaunchBlockletHandler =
|
|
|
387
390
|
claims,
|
|
388
391
|
challenge,
|
|
389
392
|
locale,
|
|
393
|
+
isAuth: false,
|
|
390
394
|
});
|
|
391
395
|
|
|
392
396
|
const blocklet = await node.getBlockletMetaFromUrl({ url: blockletMetaUrl, checkPrice: true });
|
|
@@ -436,7 +440,7 @@ const createLaunchBlockletHandler =
|
|
|
436
440
|
|
|
437
441
|
const blockletDid =
|
|
438
442
|
role === SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER
|
|
439
|
-
? toExternalBlocklet(blocklet.meta.name,
|
|
443
|
+
? toExternalBlocklet(blocklet.meta.name, controller.nftId, { didOnly: true })
|
|
440
444
|
: blocklet.meta.did;
|
|
441
445
|
|
|
442
446
|
await updateSession({
|
|
@@ -456,13 +460,7 @@ const createLaunchBlockletHandler =
|
|
|
456
460
|
url: blockletMetaUrl,
|
|
457
461
|
delay: 1000 * 4, // delay 4 seconds to download, wait for ws connection from frontend
|
|
458
462
|
downloadTokenList: extraParams?.previousWorkflowData?.downloadTokenList,
|
|
459
|
-
controller:
|
|
460
|
-
role === SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER
|
|
461
|
-
? {
|
|
462
|
-
...controller,
|
|
463
|
-
id: userDid,
|
|
464
|
-
}
|
|
465
|
-
: null,
|
|
463
|
+
controller: role === SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER ? controller : null,
|
|
466
464
|
});
|
|
467
465
|
|
|
468
466
|
await node.createAuditLog(
|
|
@@ -487,5 +485,5 @@ module.exports = {
|
|
|
487
485
|
ensureBlockletPermission,
|
|
488
486
|
getSetupBlockletClaims,
|
|
489
487
|
getTrustedIssuers,
|
|
490
|
-
|
|
488
|
+
getServerlessNFTClaim,
|
|
491
489
|
};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.8.
|
|
6
|
+
"version": "1.8.39",
|
|
7
7
|
"description": "Simple lib to manage auth in ABT Node",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -20,18 +20,18 @@
|
|
|
20
20
|
"author": "linchen <linchen1987@foxmail.com> (http://github.com/linchen1987)",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@abtnode/constant": "1.8.
|
|
24
|
-
"@abtnode/logger": "1.8.
|
|
25
|
-
"@abtnode/util": "1.8.
|
|
26
|
-
"@arcblock/did": "1.18.
|
|
27
|
-
"@arcblock/jwt": "^1.18.
|
|
28
|
-
"@arcblock/vc": "1.18.
|
|
29
|
-
"@blocklet/constant": "1.8.
|
|
30
|
-
"@blocklet/meta": "1.8.
|
|
31
|
-
"@ocap/client": "1.18.
|
|
32
|
-
"@ocap/mcrypto": "1.18.
|
|
33
|
-
"@ocap/util": "1.18.
|
|
34
|
-
"@ocap/wallet": "1.18.
|
|
23
|
+
"@abtnode/constant": "1.8.39",
|
|
24
|
+
"@abtnode/logger": "1.8.39",
|
|
25
|
+
"@abtnode/util": "1.8.39",
|
|
26
|
+
"@arcblock/did": "1.18.18",
|
|
27
|
+
"@arcblock/jwt": "^1.18.18",
|
|
28
|
+
"@arcblock/vc": "1.18.18",
|
|
29
|
+
"@blocklet/constant": "1.8.39",
|
|
30
|
+
"@blocklet/meta": "1.8.39",
|
|
31
|
+
"@ocap/client": "1.18.18",
|
|
32
|
+
"@ocap/mcrypto": "1.18.18",
|
|
33
|
+
"@ocap/util": "1.18.18",
|
|
34
|
+
"@ocap/wallet": "1.18.18",
|
|
35
35
|
"axios": "^0.27.2",
|
|
36
36
|
"joi": "17.6.3",
|
|
37
37
|
"jsonwebtoken": "^8.5.1",
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"jest": "^27.5.1"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "cf2223c4d9a999993b2be1c943dd75b4221593c3"
|
|
46
46
|
}
|