@abtnode/core 1.16.31-beta-52250475 → 1.16.31-beta-4246ab25
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 +3 -1
- package/lib/blocklet/manager/disk.js +16 -0
- package/lib/index.js +3 -3
- package/lib/states/user.js +123 -4
- package/package.json +35 -35
package/lib/api/team.js
CHANGED
|
@@ -282,7 +282,7 @@ class TeamAPI extends EventEmitter {
|
|
|
282
282
|
const now = Date.now();
|
|
283
283
|
let sessionTtl = SESSION_TTL;
|
|
284
284
|
let blocklet;
|
|
285
|
-
if (teamDid !== nodeInfo.did) {
|
|
285
|
+
if (teamDid !== nodeInfo.did && query?.includeUserSessions) {
|
|
286
286
|
blocklet = await getBlocklet({ did: teamDid, states: this.states, dataDirs: this.dataDirs });
|
|
287
287
|
sessionTtl = blocklet.settings?.session?.ttl || SESSION_TTL;
|
|
288
288
|
}
|
|
@@ -310,6 +310,8 @@ class TeamAPI extends EventEmitter {
|
|
|
310
310
|
'locale',
|
|
311
311
|
'tags',
|
|
312
312
|
'url',
|
|
313
|
+
'inviter',
|
|
314
|
+
'generation',
|
|
313
315
|
'userSessions',
|
|
314
316
|
// oauth relate fields
|
|
315
317
|
'sourceProvider',
|
|
@@ -2372,6 +2372,20 @@ class DiskBlockletManager extends BaseBlockletManager {
|
|
|
2372
2372
|
return states.backup.getBlockletBackups({ did });
|
|
2373
2373
|
}
|
|
2374
2374
|
|
|
2375
|
+
async updateInviteSettings({ did, invite }, context) {
|
|
2376
|
+
await states.blockletExtras.setSettings(did, { invite });
|
|
2377
|
+
|
|
2378
|
+
const newState = await this.getBlocklet(did);
|
|
2379
|
+
this.emit(BlockletInternalEvents.appSettingChanged, { appDid: did });
|
|
2380
|
+
this.emit(BlockletEvents.updated, { ...newState, context });
|
|
2381
|
+
|
|
2382
|
+
return newState;
|
|
2383
|
+
}
|
|
2384
|
+
|
|
2385
|
+
getInviteSettings({ did }) {
|
|
2386
|
+
return states.blockletExtras.getSettings(did, 'invite', { enabled: false });
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2375
2389
|
deleteCache(did) {
|
|
2376
2390
|
const cache = this.cachedBlocklets.get(did);
|
|
2377
2391
|
if (cache) {
|
|
@@ -4854,6 +4868,8 @@ class FederatedBlockletManager extends DiskBlockletManager {
|
|
|
4854
4868
|
'disconnectedAccount',
|
|
4855
4869
|
'action',
|
|
4856
4870
|
'sourceAppPid',
|
|
4871
|
+
'inviter',
|
|
4872
|
+
'generation',
|
|
4857
4873
|
])
|
|
4858
4874
|
);
|
|
4859
4875
|
}
|
package/lib/index.js
CHANGED
|
@@ -377,15 +377,15 @@ function ABTNode(options) {
|
|
|
377
377
|
updateBlockletSpaceGateway: blockletManager.updateBlockletSpaceGateway.bind(blockletManager),
|
|
378
378
|
getBlockletSpaceGateways: blockletManager.getBlockletSpaceGateways.bind(blockletManager),
|
|
379
379
|
|
|
380
|
-
// auto backup
|
|
380
|
+
// auto backup related
|
|
381
381
|
updateAutoBackup: blockletManager.updateAutoBackup.bind(blockletManager),
|
|
382
|
-
|
|
383
|
-
// blocklet backup record
|
|
384
382
|
getBlockletBackups: blockletManager.getBlockletBackups.bind(blockletManager),
|
|
385
383
|
|
|
386
384
|
// check update
|
|
387
385
|
updateAutoCheckUpdate: blockletManager.updateAutoCheckUpdate.bind(blockletManager),
|
|
388
386
|
|
|
387
|
+
updateInviteSettings: blockletManager.updateInviteSettings.bind(blockletManager),
|
|
388
|
+
|
|
389
389
|
// Store
|
|
390
390
|
getBlockletMeta: StoreUtil.getBlockletMeta,
|
|
391
391
|
getStoreMeta: StoreUtil.getStoreMeta,
|
package/lib/states/user.js
CHANGED
|
@@ -3,11 +3,12 @@ const get = require('lodash/get');
|
|
|
3
3
|
const pick = require('lodash/pick');
|
|
4
4
|
const uniq = require('lodash/uniq');
|
|
5
5
|
const { isValid, toAddress } = require('@arcblock/did');
|
|
6
|
-
const { PASSPORT_STATUS } = require('@abtnode/constant');
|
|
6
|
+
const { PASSPORT_STATUS, USER_MAX_INVITE_DEPTH } = require('@abtnode/constant');
|
|
7
7
|
const { BaseState } = require('@abtnode/models');
|
|
8
8
|
const { Sequelize, Op } = require('sequelize');
|
|
9
9
|
const { updateConnectedAccount } = require('@abtnode/util/lib/user');
|
|
10
10
|
const { LOGIN_PROVIDER } = require('@blocklet/constant');
|
|
11
|
+
const logger = require('@abtnode/logger')('@abtnode/core:states:user');
|
|
11
12
|
|
|
12
13
|
const { validateOwner } = require('../util');
|
|
13
14
|
const { loginSchema, disconnectAccountSchema } = require('../validators/user');
|
|
@@ -72,6 +73,7 @@ class User extends ExtendBase {
|
|
|
72
73
|
// create user
|
|
73
74
|
await this.insert({
|
|
74
75
|
...user,
|
|
76
|
+
...(await this._prepareInviteInfo(user)),
|
|
75
77
|
sourceProvider: user.sourceProvider || LOGIN_PROVIDER.WALLET,
|
|
76
78
|
approved: !!user.approved,
|
|
77
79
|
});
|
|
@@ -188,7 +190,18 @@ class User extends ExtendBase {
|
|
|
188
190
|
// eslint-disable-next-line require-await
|
|
189
191
|
async getUsers({ query, sort, paging } = {}) {
|
|
190
192
|
const where = {};
|
|
191
|
-
const {
|
|
193
|
+
const {
|
|
194
|
+
approved,
|
|
195
|
+
role,
|
|
196
|
+
search,
|
|
197
|
+
tags,
|
|
198
|
+
invitee,
|
|
199
|
+
inviter,
|
|
200
|
+
generation, // 0 - unlimited, 1 - invited by inviter, 2 - invited by another
|
|
201
|
+
includeTags,
|
|
202
|
+
includePassports,
|
|
203
|
+
includeUserSessions,
|
|
204
|
+
} = query || {};
|
|
192
205
|
const shouldIncludeTag = (tags && tags.length) || includeTags;
|
|
193
206
|
|
|
194
207
|
if (isNullOrUndefined(approved) === false) {
|
|
@@ -206,6 +219,68 @@ class User extends ExtendBase {
|
|
|
206
219
|
}
|
|
207
220
|
}
|
|
208
221
|
|
|
222
|
+
if (inviter && invitee) {
|
|
223
|
+
throw new Error('You can not query by inviter and invitee at the same time');
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// handle descendant query
|
|
227
|
+
if (inviter) {
|
|
228
|
+
if (isValid(inviter) === false) {
|
|
229
|
+
throw new Error('inviter did invalid');
|
|
230
|
+
}
|
|
231
|
+
const exist = await this.model.findByPk(toAddress(inviter), { attributes: ['did', 'generation'] });
|
|
232
|
+
if (!exist) {
|
|
233
|
+
throw new Error(`inviter not found: ${inviter}`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
try {
|
|
237
|
+
const subQuery = `
|
|
238
|
+
WITH RECURSIVE UserTree(did,inviter,generation) AS (
|
|
239
|
+
SELECT did,inviter,generation FROM users WHERE inviter="${exist.did}"
|
|
240
|
+
UNION ALL
|
|
241
|
+
SELECT child.did,child.inviter,child.generation FROM users AS child INNER JOIN UserTree AS parent ON (child.inviter=parent.did)
|
|
242
|
+
)
|
|
243
|
+
SELECT did,inviter,generation FROM UserTree ${generation > 0 ? `WHERE generation=${(exist.generation > 0 ? exist.generation : 0) + generation}` : ''} LIMIT ${USER_MAX_INVITE_DEPTH}`.trim();
|
|
244
|
+
const children = await this.query(subQuery);
|
|
245
|
+
where.did = children.map((x) => x.did);
|
|
246
|
+
} catch (err) {
|
|
247
|
+
console.error('Failed to get descendants', err);
|
|
248
|
+
where.did = [];
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// handle ancestor query
|
|
253
|
+
if (invitee) {
|
|
254
|
+
if (isValid(invitee) === false) {
|
|
255
|
+
throw new Error('invitee did invalid');
|
|
256
|
+
}
|
|
257
|
+
const exist = await this.model.findByPk(toAddress(invitee), { attributes: ['did', 'generation'] });
|
|
258
|
+
if (!exist) {
|
|
259
|
+
throw new Error(`invitee not found: ${invitee}`);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
try {
|
|
263
|
+
const subQuery = `
|
|
264
|
+
WITH RECURSIVE UserTree(did,inviter,generation) AS (
|
|
265
|
+
SELECT did,inviter,generation FROM users WHERE did="${exist.did}"
|
|
266
|
+
UNION ALL
|
|
267
|
+
SELECT
|
|
268
|
+
inviter,
|
|
269
|
+
(SELECT inviter FROM users AS parent WHERE parent.did=child.inviter),
|
|
270
|
+
(SELECT generation FROM users AS parent WHERE parent.did=child.inviter)
|
|
271
|
+
FROM UserTree AS child
|
|
272
|
+
WHERE inviter IS NOT NULL
|
|
273
|
+
LIMIT ${USER_MAX_INVITE_DEPTH}
|
|
274
|
+
)
|
|
275
|
+
SELECT did,inviter,generation FROM UserTree`.trim();
|
|
276
|
+
const children = await this.query(subQuery);
|
|
277
|
+
where.did = children.map((x) => x.did).filter((x) => x !== exist.did);
|
|
278
|
+
} catch (err) {
|
|
279
|
+
console.error('Failed to get ancestors', err);
|
|
280
|
+
where.did = [];
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
209
284
|
const replacements = {};
|
|
210
285
|
|
|
211
286
|
if (role && role !== '$all' && !where.did) {
|
|
@@ -371,10 +446,10 @@ class User extends ExtendBase {
|
|
|
371
446
|
* @param {string} user.did
|
|
372
447
|
* @param {string} user.pk
|
|
373
448
|
* @param {ConnectedAccount} user.connectedAccount
|
|
374
|
-
* @param {passport} user.passport
|
|
375
449
|
* @param {string} user.fullName - user profile's name
|
|
376
450
|
* @param {string} user.avatar - url of user's avatar, eg: bn://avatar/7f8848569405f8cdf8b1b2788ebf7d0f.jpg
|
|
377
451
|
* @param {string} user.locale - locale
|
|
452
|
+
* @param {string} user.inviter - inviter
|
|
378
453
|
* @param {Object} [user.extra] - extra data of user
|
|
379
454
|
* @param {string} user.lastLoginIp - lastLoginIp
|
|
380
455
|
* @param {('owner'|'admin'|'member'|'guest'|string)} user.role - deprecated user's role
|
|
@@ -402,6 +477,8 @@ class User extends ExtendBase {
|
|
|
402
477
|
'extra',
|
|
403
478
|
'lastLoginIp',
|
|
404
479
|
'remark',
|
|
480
|
+
'inviter',
|
|
481
|
+
'generation',
|
|
405
482
|
'sourceAppPid',
|
|
406
483
|
]),
|
|
407
484
|
lastLoginAt: now,
|
|
@@ -413,11 +490,17 @@ class User extends ExtendBase {
|
|
|
413
490
|
updates.sourceAppPid = null;
|
|
414
491
|
}
|
|
415
492
|
|
|
493
|
+
Object.assign(updates, await this._prepareInviteInfo(raw));
|
|
494
|
+
|
|
416
495
|
if (exist) {
|
|
417
|
-
//
|
|
496
|
+
// immutable
|
|
418
497
|
if (updates.sourceAppPid) {
|
|
419
498
|
delete updates.sourceAppPid;
|
|
420
499
|
}
|
|
500
|
+
if (updates.inviter) {
|
|
501
|
+
delete updates.inviter;
|
|
502
|
+
delete updates.generation;
|
|
503
|
+
}
|
|
421
504
|
// 登录不再更新 locale
|
|
422
505
|
delete updates.locale;
|
|
423
506
|
// update user, connectedAccount, passport
|
|
@@ -437,6 +520,42 @@ class User extends ExtendBase {
|
|
|
437
520
|
return { ...updated, _action: exist ? 'update' : 'add' };
|
|
438
521
|
}
|
|
439
522
|
|
|
523
|
+
async _prepareInviteInfo(raw) {
|
|
524
|
+
const info = {};
|
|
525
|
+
|
|
526
|
+
// set inviter and generation
|
|
527
|
+
if (raw.inviter) {
|
|
528
|
+
// sybil-attack
|
|
529
|
+
if (isValid(raw.inviter)) {
|
|
530
|
+
const inviterId = toAddress(raw.inviter);
|
|
531
|
+
const inviter = await this.model.findByPk(inviterId, { attributes: ['did', 'generation'] });
|
|
532
|
+
if (inviter) {
|
|
533
|
+
info.inviter = inviterId;
|
|
534
|
+
info.generation = inviter.generation + 1;
|
|
535
|
+
} else {
|
|
536
|
+
logger.warn('Set inviter to non-exist user is not allowed', raw);
|
|
537
|
+
}
|
|
538
|
+
} else {
|
|
539
|
+
logger.warn('Set inviter to invalid did is not allowed', raw);
|
|
540
|
+
info.inviter = null;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// anti-land-attack
|
|
544
|
+
if (info.inviter === raw.did) {
|
|
545
|
+
logger.warn('Set inviter to self is not allowed', raw);
|
|
546
|
+
info.inviter = null;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
if (!info.inviter) {
|
|
550
|
+
info.generation = 0;
|
|
551
|
+
}
|
|
552
|
+
if (info.generation > USER_MAX_INVITE_DEPTH) {
|
|
553
|
+
throw new Error('You have exceeded max user invite chain length');
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
return info;
|
|
557
|
+
}
|
|
558
|
+
|
|
440
559
|
async disconnectUserAccount(raw) {
|
|
441
560
|
const { error, value: connectedAccount } = disconnectAccountSchema.validate(raw);
|
|
442
561
|
if (error) {
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.16.31-beta-
|
|
6
|
+
"version": "1.16.31-beta-4246ab25",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,43 +19,43 @@
|
|
|
19
19
|
"author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
|
|
20
20
|
"license": "Apache-2.0",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@abtnode/analytics": "1.16.31-beta-
|
|
23
|
-
"@abtnode/auth": "1.16.31-beta-
|
|
24
|
-
"@abtnode/certificate-manager": "1.16.31-beta-
|
|
25
|
-
"@abtnode/constant": "1.16.31-beta-
|
|
26
|
-
"@abtnode/cron": "1.16.31-beta-
|
|
27
|
-
"@abtnode/logger": "1.16.31-beta-
|
|
28
|
-
"@abtnode/models": "1.16.31-beta-
|
|
29
|
-
"@abtnode/queue": "1.16.31-beta-
|
|
30
|
-
"@abtnode/rbac": "1.16.31-beta-
|
|
31
|
-
"@abtnode/router-provider": "1.16.31-beta-
|
|
32
|
-
"@abtnode/static-server": "1.16.31-beta-
|
|
33
|
-
"@abtnode/timemachine": "1.16.31-beta-
|
|
34
|
-
"@abtnode/util": "1.16.31-beta-
|
|
35
|
-
"@arcblock/did": "1.18.
|
|
36
|
-
"@arcblock/did-auth": "1.18.
|
|
37
|
-
"@arcblock/did-ext": "^1.18.
|
|
22
|
+
"@abtnode/analytics": "1.16.31-beta-4246ab25",
|
|
23
|
+
"@abtnode/auth": "1.16.31-beta-4246ab25",
|
|
24
|
+
"@abtnode/certificate-manager": "1.16.31-beta-4246ab25",
|
|
25
|
+
"@abtnode/constant": "1.16.31-beta-4246ab25",
|
|
26
|
+
"@abtnode/cron": "1.16.31-beta-4246ab25",
|
|
27
|
+
"@abtnode/logger": "1.16.31-beta-4246ab25",
|
|
28
|
+
"@abtnode/models": "1.16.31-beta-4246ab25",
|
|
29
|
+
"@abtnode/queue": "1.16.31-beta-4246ab25",
|
|
30
|
+
"@abtnode/rbac": "1.16.31-beta-4246ab25",
|
|
31
|
+
"@abtnode/router-provider": "1.16.31-beta-4246ab25",
|
|
32
|
+
"@abtnode/static-server": "1.16.31-beta-4246ab25",
|
|
33
|
+
"@abtnode/timemachine": "1.16.31-beta-4246ab25",
|
|
34
|
+
"@abtnode/util": "1.16.31-beta-4246ab25",
|
|
35
|
+
"@arcblock/did": "1.18.135",
|
|
36
|
+
"@arcblock/did-auth": "1.18.135",
|
|
37
|
+
"@arcblock/did-ext": "^1.18.135",
|
|
38
38
|
"@arcblock/did-motif": "^1.1.13",
|
|
39
|
-
"@arcblock/did-util": "1.18.
|
|
40
|
-
"@arcblock/event-hub": "1.18.
|
|
41
|
-
"@arcblock/jwt": "^1.18.
|
|
39
|
+
"@arcblock/did-util": "1.18.135",
|
|
40
|
+
"@arcblock/event-hub": "1.18.135",
|
|
41
|
+
"@arcblock/jwt": "^1.18.135",
|
|
42
42
|
"@arcblock/pm2-events": "^0.0.5",
|
|
43
|
-
"@arcblock/validator": "^1.18.
|
|
44
|
-
"@arcblock/vc": "1.18.
|
|
45
|
-
"@blocklet/constant": "1.16.31-beta-
|
|
46
|
-
"@blocklet/env": "1.16.31-beta-
|
|
47
|
-
"@blocklet/meta": "1.16.31-beta-
|
|
48
|
-
"@blocklet/resolver": "1.16.31-beta-
|
|
49
|
-
"@blocklet/sdk": "1.16.31-beta-
|
|
50
|
-
"@blocklet/store": "1.16.31-beta-
|
|
51
|
-
"@did-space/client": "^0.5.
|
|
43
|
+
"@arcblock/validator": "^1.18.135",
|
|
44
|
+
"@arcblock/vc": "1.18.135",
|
|
45
|
+
"@blocklet/constant": "1.16.31-beta-4246ab25",
|
|
46
|
+
"@blocklet/env": "1.16.31-beta-4246ab25",
|
|
47
|
+
"@blocklet/meta": "1.16.31-beta-4246ab25",
|
|
48
|
+
"@blocklet/resolver": "1.16.31-beta-4246ab25",
|
|
49
|
+
"@blocklet/sdk": "1.16.31-beta-4246ab25",
|
|
50
|
+
"@blocklet/store": "1.16.31-beta-4246ab25",
|
|
51
|
+
"@did-space/client": "^0.5.31",
|
|
52
52
|
"@fidm/x509": "^1.2.1",
|
|
53
|
-
"@ocap/mcrypto": "1.18.
|
|
54
|
-
"@ocap/util": "1.18.
|
|
55
|
-
"@ocap/wallet": "1.18.
|
|
53
|
+
"@ocap/mcrypto": "1.18.135",
|
|
54
|
+
"@ocap/util": "1.18.135",
|
|
55
|
+
"@ocap/wallet": "1.18.135",
|
|
56
56
|
"@slack/webhook": "^5.0.4",
|
|
57
57
|
"archiver": "^7.0.1",
|
|
58
|
-
"axios": "^1.7.
|
|
58
|
+
"axios": "^1.7.5",
|
|
59
59
|
"axon": "^2.0.3",
|
|
60
60
|
"chalk": "^4.1.2",
|
|
61
61
|
"cross-spawn": "^7.0.3",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"p-limit": "^3.1.0",
|
|
82
82
|
"p-retry": "4.6.1",
|
|
83
83
|
"read-last-lines": "^1.8.0",
|
|
84
|
-
"semver": "^7.3
|
|
84
|
+
"semver": "^7.6.3",
|
|
85
85
|
"sequelize": "^6.35.0",
|
|
86
86
|
"shelljs": "^0.8.5",
|
|
87
87
|
"ssri": "^8.0.1",
|
|
@@ -103,5 +103,5 @@
|
|
|
103
103
|
"jest": "^29.7.0",
|
|
104
104
|
"unzipper": "^0.10.11"
|
|
105
105
|
},
|
|
106
|
-
"gitHead": "
|
|
106
|
+
"gitHead": "ef93705b89033e4cd5fed458b64521d0a994a1d0"
|
|
107
107
|
}
|