@abtnode/auth 1.7.20 → 1.7.21
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 -1
- package/lib/invitation.js +15 -8
- package/lib/server.js +2 -2
- package/package.json +6 -6
package/lib/auth.js
CHANGED
|
@@ -5,10 +5,12 @@ const get = require('lodash/get');
|
|
|
5
5
|
const { verifyPresentation, createCredentialList } = require('@arcblock/vc');
|
|
6
6
|
const formatContext = require('@abtnode/util/lib/format-context');
|
|
7
7
|
const Mcrypto = require('@ocap/mcrypto');
|
|
8
|
+
const Client = require('@ocap/client');
|
|
8
9
|
const { fromSecretKey, WalletType } = require('@ocap/wallet');
|
|
9
10
|
const getBlockletInfo = require('@blocklet/meta/lib/info');
|
|
10
11
|
const { PASSPORT_STATUS, VC_TYPE_NODE_PASSPORT, ROLES } = require('@abtnode/constant');
|
|
11
12
|
const axios = require('@abtnode/util/lib/axios');
|
|
13
|
+
|
|
12
14
|
const logger = require('./logger');
|
|
13
15
|
const verifySignature = require('./util/verify-signature');
|
|
14
16
|
const {
|
|
@@ -199,6 +201,18 @@ const messages = {
|
|
|
199
201
|
en: 'chainHost not found from server launcher info',
|
|
200
202
|
zh: '节点初始化信息异常:缺少链地址',
|
|
201
203
|
},
|
|
204
|
+
alreadyTransferred: {
|
|
205
|
+
en: 'The Blocklet Server already belongs to {owner}',
|
|
206
|
+
zh: '该节点已经属于 {owner}',
|
|
207
|
+
},
|
|
208
|
+
delegateTransferOwnerNFT: {
|
|
209
|
+
en: 'Sign the delegation transaction to authorize blocklet server to transfer your ownership NFT to new owner when he/she claims the transfer.',
|
|
210
|
+
zh: '签名下面的交易以授权节点转移所有权以及代表所有权的 NFT。',
|
|
211
|
+
},
|
|
212
|
+
notAllowedTransferToSelf: {
|
|
213
|
+
en: 'Not allowed to transfer the Server to yourself',
|
|
214
|
+
zh: '不能将节点转移给自己',
|
|
215
|
+
},
|
|
202
216
|
};
|
|
203
217
|
|
|
204
218
|
const PASSPORT_STATUS_KEY = 'passport-status';
|
|
@@ -372,11 +386,38 @@ const handleInvitationResponse = async ({
|
|
|
372
386
|
claims,
|
|
373
387
|
statusEndpointBaseUrl,
|
|
374
388
|
endpoint,
|
|
389
|
+
newNftOwner,
|
|
375
390
|
}) => {
|
|
376
391
|
if (!nodeInfo.nodeOwner) {
|
|
377
392
|
throw new Error(messages.notInitialized[locale]);
|
|
378
393
|
}
|
|
379
394
|
|
|
395
|
+
const tmpInvitation = await node.getInvitation({ teamDid, inviteId });
|
|
396
|
+
|
|
397
|
+
if (tmpInvitation.role === 'owner' && userDid === nodeInfo.nodeOwner.did) {
|
|
398
|
+
throw new Error(messages.notAllowedTransferToSelf[locale]);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
const inviteInfo = await node.processInvitation({ teamDid, inviteId });
|
|
402
|
+
if (inviteInfo.role === 'owner' && get(nodeInfo, 'ownerNft.holder')) {
|
|
403
|
+
// 这种情况下是 Transfer 有 Owner NFT 的 Blocklet Server
|
|
404
|
+
const client = new Client(nodeInfo.launcher.chainHost);
|
|
405
|
+
|
|
406
|
+
const { state: assetState } = await client.getAssetState({ address: nodeInfo.ownerNft.did });
|
|
407
|
+
if (assetState.owner !== newNftOwner) {
|
|
408
|
+
const hash = await client.transfer({
|
|
409
|
+
delegator: nodeInfo.ownerNft.holder,
|
|
410
|
+
to: newNftOwner,
|
|
411
|
+
assets: [nodeInfo.ownerNft.did],
|
|
412
|
+
wallet: getNodeWallet(nodeInfo.sk),
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
logger.info('transferred nft', { hash, nft: nodeInfo.ownerNft.did });
|
|
416
|
+
await node.updateNftHolder(newNftOwner);
|
|
417
|
+
logger.info('updated owner nft holder', { holder: newNftOwner, nft: nodeInfo.ownerNft.did });
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
380
421
|
const claim = claims.find((x) => x.type === 'signature');
|
|
381
422
|
verifySignature(claim, userDid, userPk, locale);
|
|
382
423
|
|
|
@@ -387,7 +428,6 @@ const handleInvitationResponse = async ({
|
|
|
387
428
|
passportColor,
|
|
388
429
|
} = await getTeamInfo({ node, nodeInfo, teamDid });
|
|
389
430
|
|
|
390
|
-
const inviteInfo = await node.processInvitation({ teamDid, inviteId });
|
|
391
431
|
const { remark } = inviteInfo;
|
|
392
432
|
|
|
393
433
|
const profile = claims.find((x) => x.type === 'profile');
|
|
@@ -424,6 +464,25 @@ const handleInvitationResponse = async ({
|
|
|
424
464
|
|
|
425
465
|
const user = await getUser(node, teamDid, userDid);
|
|
426
466
|
|
|
467
|
+
if (role === 'owner') {
|
|
468
|
+
if (user && user.role === 'owner') {
|
|
469
|
+
throw new Error(messages.alreadyTransferred[locale](userDid));
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
await node.updateNodeOwner({ nodeOwner: { did: userDid, pk: userPk } });
|
|
473
|
+
|
|
474
|
+
const originalOwner = await getUser(node, teamDid, nodeInfo.nodeOwner.did);
|
|
475
|
+
const originalOwnerPassport = (originalOwner.passports || []).find((p) => p.role === 'owner');
|
|
476
|
+
if (originalOwnerPassport) {
|
|
477
|
+
await node.revokeUserPassport({ teamDid, userDid: nodeInfo.nodeOwner.did, passportId: originalOwnerPassport.id });
|
|
478
|
+
logger.info('passport revoked on server transfer claiming', {
|
|
479
|
+
teamDid,
|
|
480
|
+
userDid: nodeInfo.nodeOwner.did,
|
|
481
|
+
passportId: originalOwnerPassport.id,
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
427
486
|
if (user) {
|
|
428
487
|
const doc = await node.updateUser({
|
|
429
488
|
teamDid,
|
package/lib/invitation.js
CHANGED
|
@@ -10,6 +10,7 @@ module.exports = {
|
|
|
10
10
|
const { inviteId } = req.query;
|
|
11
11
|
const groupPathPrefix = req.headers['x-group-path-prefix'] || '/';
|
|
12
12
|
|
|
13
|
+
const nodeInfo = await node.getNodeInfo();
|
|
13
14
|
try {
|
|
14
15
|
let info;
|
|
15
16
|
if (type === 'blocklet') {
|
|
@@ -24,22 +25,23 @@ module.exports = {
|
|
|
24
25
|
// TODO: 需要将 CHAIN_HOST 纳入标准
|
|
25
26
|
chainHost: blockletInfo.configObj.CHAIN_HOST,
|
|
26
27
|
passportColor: blockletInfo.configObj[BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_PASSPORT_COLOR],
|
|
28
|
+
description: blockletInfo.meta.description,
|
|
27
29
|
};
|
|
28
30
|
} else {
|
|
29
|
-
const nodeInfo = await node.getNodeInfo();
|
|
30
31
|
info = {
|
|
31
32
|
did: nodeInfo.did,
|
|
32
33
|
appDid: nodeInfo.did,
|
|
33
34
|
url: '/',
|
|
34
35
|
name: nodeInfo.name,
|
|
35
36
|
version: nodeInfo.version,
|
|
37
|
+
description: nodeInfo.description,
|
|
36
38
|
};
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
const teamDid = info.did;
|
|
40
42
|
const invitations = await node.getInvitations({ teamDid });
|
|
41
43
|
const invitation = invitations.find((v) => v.inviteId === inviteId);
|
|
42
|
-
if (!invitation) {
|
|
44
|
+
if (!invitation || Date.now() > new Date(invitation.expireDate).getTime()) {
|
|
43
45
|
res.status(404).send('Invitation not found or invitation has been used');
|
|
44
46
|
return;
|
|
45
47
|
}
|
|
@@ -55,16 +57,21 @@ module.exports = {
|
|
|
55
57
|
logger.error('failed to get role permission', { teamDid, role: role.name, error: err });
|
|
56
58
|
role.permissions = [];
|
|
57
59
|
}
|
|
60
|
+
const user = await node.getUser({ teamDid: nodeInfo.did, user: { did: invitation.inviter.did } });
|
|
61
|
+
|
|
62
|
+
const inviter = {
|
|
63
|
+
did: invitation.inviter.did,
|
|
64
|
+
email: invitation.inviter.email,
|
|
65
|
+
fullName: invitation.inviter.fullName,
|
|
66
|
+
role: invitation.inviter.role,
|
|
67
|
+
avatar: user && user.avatar,
|
|
68
|
+
};
|
|
58
69
|
|
|
59
70
|
res.json({
|
|
60
71
|
...invitation,
|
|
61
72
|
info,
|
|
62
|
-
inviter
|
|
63
|
-
|
|
64
|
-
email: invitation.inviter.email,
|
|
65
|
-
fullName: invitation.inviter.fullName,
|
|
66
|
-
role: invitation.inviter.role,
|
|
67
|
-
},
|
|
73
|
+
inviter,
|
|
74
|
+
inviterRaw: invitation.inviter,
|
|
68
75
|
role: role || {},
|
|
69
76
|
});
|
|
70
77
|
} catch (err) {
|
package/lib/server.js
CHANGED
|
@@ -160,12 +160,12 @@ const authenticateByNFT = async ({ node, claims, userDid, challenge, locale }) =
|
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
const user = await getUser(node, info.did, userDid);
|
|
163
|
-
return { role: ROLES.OWNER, teamDid: info.did, nft: state, user, passport: null };
|
|
163
|
+
return { role: ROLES.OWNER, teamDid: info.did, nft: state, user, passport: null, ownerDid, ownerNFT: address };
|
|
164
164
|
};
|
|
165
165
|
|
|
166
166
|
const getAuthVcClaim =
|
|
167
167
|
(node) =>
|
|
168
|
-
async ({ extraParams: { locale, passportId
|
|
168
|
+
async ({ extraParams: { locale, passportId }, context: { didwallet } }) => {
|
|
169
169
|
checkWalletVersion({ didwallet, locale });
|
|
170
170
|
const info = await node.getNodeInfo();
|
|
171
171
|
const trustedPassports = (info.trustedPassports || []).map((x) => x.issuerDid);
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.7.
|
|
6
|
+
"version": "1.7.21",
|
|
7
7
|
"description": "Simple lib to manage auth in ABT Node",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
"author": "linchen <linchen1987@foxmail.com> (http://github.com/linchen1987)",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@abtnode/constant": "1.7.
|
|
24
|
-
"@abtnode/logger": "1.7.
|
|
25
|
-
"@abtnode/util": "1.7.
|
|
23
|
+
"@abtnode/constant": "1.7.21",
|
|
24
|
+
"@abtnode/logger": "1.7.21",
|
|
25
|
+
"@abtnode/util": "1.7.21",
|
|
26
26
|
"@arcblock/did": "^1.16.15",
|
|
27
27
|
"@arcblock/vc": "^1.16.15",
|
|
28
|
-
"@blocklet/meta": "1.7.
|
|
28
|
+
"@blocklet/meta": "1.7.21",
|
|
29
29
|
"@ocap/client": "1.16.15",
|
|
30
30
|
"@ocap/mcrypto": "^1.16.15",
|
|
31
31
|
"@ocap/util": "^1.16.15",
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"jest": "^27.4.5"
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "e7b99d9b3f878cc47e54ddfead2ac5284145b6ae"
|
|
44
44
|
}
|