@abtnode/core 1.16.8-beta-186fd5aa → 1.16.8-next-d1e52353
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 +24 -64
- package/lib/blocklet/manager/disk.js +2 -8
- package/lib/blocklet/manager/helper/migrate-application-to-struct-v2.js +5 -5
- package/lib/blocklet/storage/backup/blocklet-extras.js +2 -2
- package/lib/blocklet/storage/backup/blocklet.js +2 -2
- package/lib/index.js +14 -16
- package/lib/migrations/1.16.8-component-title.js +1 -1
- package/lib/migrations/1.6.9-update-node-info-and-certificate.js +1 -1
- package/lib/migrations/index.js +190 -40
- package/lib/monitor/node-runtime-monitor.js +2 -29
- package/lib/router/helper.js +6 -6
- package/lib/router/manager.js +35 -36
- package/lib/states/access-key.js +3 -20
- package/lib/states/audit-log.js +7 -8
- package/lib/states/backup.js +11 -59
- package/lib/states/base.js +13 -5
- package/lib/states/blocklet-extras.js +11 -8
- package/lib/states/blocklet.js +136 -225
- package/lib/states/cache.js +3 -21
- package/lib/states/connect-account.js +8 -0
- package/lib/states/index.js +28 -18
- package/lib/states/job.js +8 -0
- package/lib/states/migration.js +3 -4
- package/lib/states/node.js +104 -145
- package/lib/states/notification.js +18 -40
- package/lib/states/passport.js +8 -0
- package/lib/states/session.js +28 -44
- package/lib/states/site.js +32 -39
- package/lib/states/user.js +187 -374
- package/lib/states/webhook.js +5 -7
- package/lib/team/manager.js +108 -116
- package/lib/util/blocklet.js +0 -1
- package/lib/util/index.js +3 -0
- package/lib/util/queue.js +14 -20
- package/lib/util/ready.js +1 -1
- package/lib/webhook/index.js +6 -4
- package/package.json +19 -18
- package/lib/states/challenge.js +0 -58
package/lib/states/user.js
CHANGED
|
@@ -1,34 +1,18 @@
|
|
|
1
1
|
const pickBy = require('lodash/pickBy');
|
|
2
|
-
const
|
|
2
|
+
const get = require('lodash/get');
|
|
3
3
|
const pick = require('lodash/pick');
|
|
4
|
-
const cloneDeep = require('lodash/cloneDeep');
|
|
5
|
-
const logger = require('@abtnode/logger')('@abtnode/core:states:user');
|
|
6
4
|
const { isValid } = require('@arcblock/did');
|
|
7
5
|
const { PASSPORT_STATUS } = require('@abtnode/constant');
|
|
8
|
-
const {
|
|
9
|
-
const {
|
|
6
|
+
const { BaseState } = require('@abtnode/models');
|
|
7
|
+
const { Sequelize, Op } = require('sequelize');
|
|
8
|
+
const { updateConnectedAccount } = require('@abtnode/util/lib/user');
|
|
10
9
|
|
|
11
|
-
const BaseState = require('./base');
|
|
12
10
|
const { validateOwner } = require('../util');
|
|
13
11
|
const { loginSchema } = require('../validators/user');
|
|
12
|
+
const ExtendBase = require('./base');
|
|
14
13
|
|
|
15
14
|
const isNullOrUndefined = (x) => x === undefined || x === null;
|
|
16
15
|
|
|
17
|
-
/**
|
|
18
|
-
* UserPassport
|
|
19
|
-
* @typedef {Object} UserPassport
|
|
20
|
-
* @property {string} id - id
|
|
21
|
-
* @property {string[]} [type] - passport's type
|
|
22
|
-
* @property {string[]} [issuer] - passport's issuer
|
|
23
|
-
* @property {Date} [issuanceDate] - passport's issuanceDate
|
|
24
|
-
* @property {string} [specVersion] - passport's specVersion
|
|
25
|
-
* @property {string} name - passport's name
|
|
26
|
-
* @property {string} [title] - passport's title
|
|
27
|
-
* @property {string} [endpoint] - passport's endpoint
|
|
28
|
-
* @property {string} [status] - passport's status
|
|
29
|
-
* @property {string} role - passport's role
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
16
|
/**
|
|
33
17
|
* Auth0Account
|
|
34
18
|
* @typedef {Object} Auth0Account
|
|
@@ -66,126 +50,76 @@ const isNullOrUndefined = (x) => x === undefined || x === null;
|
|
|
66
50
|
*/
|
|
67
51
|
|
|
68
52
|
/**
|
|
69
|
-
*
|
|
70
|
-
* @typedef {Object} BlockletUser - Blocklet Service User Table
|
|
71
|
-
* @property {string} _id - id
|
|
72
|
-
* @property {('profile')} type - type of user
|
|
73
|
-
* @property {string} fullName - user profile's name
|
|
74
|
-
* @property {string} avatar - url of user's avatar, eg: bn://avatar/7f8848569405f8cdf8b1b2788ebf7d0f.jpg
|
|
75
|
-
* @property {string} did - user's did -> 实际上变为 uid, 是不可变的;真正的 wallet-did 转移到 extraConfigs 中去了
|
|
76
|
-
* @property {string} pk - user's publicKey
|
|
77
|
-
* @property {UserPassport[]} passports - user's passport list
|
|
78
|
-
* @property {boolean} approved - enable user to login
|
|
79
|
-
* @property {string} locale - locale
|
|
80
|
-
* @property {Object} [extra] - extra data of user
|
|
81
|
-
* @property {Object} [extraConfigs] - extra data of user
|
|
82
|
-
* @property {ConnectedAccount[]} [extraConfigs.connectedAccounts] - connectedAccounts
|
|
83
|
-
* @property {('wallet'|'auth0')} [extraConfigs.sourceProvider] - sourceProvider, the main account provider
|
|
84
|
-
* @property {Date} firstLoginAt - firstLoginAt
|
|
85
|
-
* @property {Date} lastLoginAt - lastLoginAt
|
|
86
|
-
* @property {string} lastLoginIp - lastLoginIp
|
|
87
|
-
* @property {Date} createdAt - createdAt
|
|
88
|
-
* @property {Date} updatedAt - updatedAt
|
|
89
|
-
* @property {('owner'|'admin'|'member'|'guest'|string)} role - user's role deprecated
|
|
53
|
+
* @extends ExtendBase<import('@abtnode/models').UserState>
|
|
90
54
|
*/
|
|
55
|
+
class User extends ExtendBase {
|
|
56
|
+
constructor(model, config, models) {
|
|
57
|
+
super(model, config);
|
|
91
58
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const updated = cloneDeep(filterAccounts);
|
|
96
|
-
const updates = Array.isArray(connectedAccount) ? connectedAccount : [connectedAccount];
|
|
97
|
-
updates.filter(Boolean).forEach((x) => {
|
|
98
|
-
if (x.provider && x.did) {
|
|
99
|
-
const findAccountIndex = updated.findIndex((item) => item.provider === x.provider && item.did === x.did);
|
|
100
|
-
if (findAccountIndex > -1) {
|
|
101
|
-
updated[findAccountIndex] = {
|
|
102
|
-
...filterAccounts[findAccountIndex],
|
|
103
|
-
...x,
|
|
104
|
-
lastLoginAt: now,
|
|
105
|
-
};
|
|
106
|
-
} else {
|
|
107
|
-
updated.push({
|
|
108
|
-
...x,
|
|
109
|
-
firstLoginAt: now,
|
|
110
|
-
lastLoginAt: now,
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
return updated;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
class User extends BaseState {
|
|
120
|
-
constructor(baseDir, config = {}) {
|
|
121
|
-
super(baseDir, { filename: 'user.db', ...config });
|
|
122
|
-
|
|
123
|
-
this.onReady(() => {
|
|
124
|
-
this.ensureIndex({ fieldName: 'did', unique: true }, (error) => {
|
|
125
|
-
if (error) {
|
|
126
|
-
logger.error('ensure index failed', { error });
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
});
|
|
59
|
+
this.models = models;
|
|
60
|
+
this.passport = new BaseState(models.Passport, config);
|
|
61
|
+
this.connectedAccount = new BaseState(models.ConnectedAccount, config);
|
|
130
62
|
}
|
|
131
63
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
* @param {BlockletUser} user - user data
|
|
135
|
-
* @returns {Promise<number>}
|
|
136
|
-
*/
|
|
137
|
-
async add(user) {
|
|
64
|
+
// FIXME: @wangshijun wrap these in a transaction
|
|
65
|
+
async addUser(user) {
|
|
138
66
|
if (!validateOwner(user)) {
|
|
139
67
|
throw new Error('user is invalid');
|
|
140
68
|
}
|
|
141
69
|
|
|
142
|
-
|
|
70
|
+
// create user
|
|
71
|
+
await this.insert({
|
|
143
72
|
...user,
|
|
73
|
+
sourceProvider: user.sourceProvider || 'wallet',
|
|
144
74
|
approved: !!user.approved,
|
|
145
75
|
});
|
|
146
|
-
}
|
|
147
76
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
async update(user) {
|
|
154
|
-
if (!validateOwner(user)) {
|
|
155
|
-
throw new Error('user is invalid');
|
|
156
|
-
}
|
|
77
|
+
// create passports and connectedAccounts
|
|
78
|
+
await Promise.all((get(user, 'passports') || []).map((x) => this.passport.insert({ ...x, userDid: user.did })));
|
|
79
|
+
await Promise.all(
|
|
80
|
+
(get(user, 'connectedAccounts') || []).map((x) => this.connectedAccount.insert({ ...x, userDid: user.did }))
|
|
81
|
+
);
|
|
157
82
|
|
|
158
|
-
|
|
83
|
+
return this.getUser(user.did);
|
|
84
|
+
}
|
|
159
85
|
|
|
160
|
-
|
|
161
|
-
|
|
86
|
+
// FIXME: @wangshijun wrap these in a transaction
|
|
87
|
+
async updateUser(did, updates) {
|
|
88
|
+
const exist = await super.count({ did });
|
|
89
|
+
if (!exist) {
|
|
90
|
+
throw new Error(`user does not exist: ${did}`);
|
|
162
91
|
}
|
|
163
92
|
|
|
164
|
-
|
|
93
|
+
await super.update({ did }, { $set: updates });
|
|
94
|
+
await Promise.all(
|
|
95
|
+
(get(updates, 'passports') || []).map((x) => this.passport.upsert({ id: x.id }, { ...x, userDid: did }))
|
|
96
|
+
);
|
|
97
|
+
await Promise.all(
|
|
98
|
+
(get(updates, 'connectedAccounts') || []).map((x) =>
|
|
99
|
+
this.connectedAccount.upsert({ did: x.did }, { ...x, userDid: did })
|
|
100
|
+
)
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
return this.getUser(did);
|
|
165
104
|
}
|
|
166
105
|
|
|
167
|
-
|
|
168
|
-
* @param {string} did user did
|
|
169
|
-
* @param {string} id passport id
|
|
170
|
-
*/
|
|
171
|
-
async revokePassportById({ did, id } = {}) {
|
|
106
|
+
async revokePassportById({ did, id }) {
|
|
172
107
|
return this._setPassportStatusById({ did, id, status: PASSPORT_STATUS.REVOKED });
|
|
173
108
|
}
|
|
174
109
|
|
|
175
|
-
async enablePassportById({ did, id }
|
|
110
|
+
async enablePassportById({ did, id }) {
|
|
176
111
|
return this._setPassportStatusById({ did, id, status: PASSPORT_STATUS.VALID });
|
|
177
112
|
}
|
|
178
113
|
|
|
179
114
|
/**
|
|
180
115
|
* remove a user by user's did
|
|
181
|
-
* @param {
|
|
182
|
-
* @
|
|
116
|
+
* @param {object} params
|
|
117
|
+
* @param {string} params.did - the did of user
|
|
183
118
|
*/
|
|
184
119
|
async remove({ did }) {
|
|
185
120
|
const num = await super.remove({ did });
|
|
186
|
-
|
|
187
121
|
if (num === 0) {
|
|
188
|
-
throw new Error(
|
|
122
|
+
throw new Error(`user does not exist: ${did}`);
|
|
189
123
|
}
|
|
190
124
|
|
|
191
125
|
return num;
|
|
@@ -193,13 +127,12 @@ class User extends BaseState {
|
|
|
193
127
|
|
|
194
128
|
/**
|
|
195
129
|
* enable/disable user login
|
|
196
|
-
* @param {
|
|
197
|
-
* @param {
|
|
198
|
-
* @
|
|
130
|
+
* @param {object} params
|
|
131
|
+
* @param {string} params.did user's did
|
|
132
|
+
* @param {boolean} params.approved enable/disable user login
|
|
199
133
|
*/
|
|
200
134
|
async updateApproved({ did, approved }) {
|
|
201
|
-
const [num, doc] = await super.update({ did }, { $set: { approved } });
|
|
202
|
-
|
|
135
|
+
const [num, [doc]] = await super.update({ did }, { $set: { approved } });
|
|
203
136
|
if (num === 0) {
|
|
204
137
|
throw new Error(`user does not exist: ${did}`);
|
|
205
138
|
}
|
|
@@ -209,13 +142,12 @@ class User extends BaseState {
|
|
|
209
142
|
|
|
210
143
|
/**
|
|
211
144
|
* update user's role
|
|
212
|
-
* @param {
|
|
213
|
-
* @param {
|
|
214
|
-
* @
|
|
145
|
+
* @param {object} params
|
|
146
|
+
* @param {string} params.did user's did
|
|
147
|
+
* @param {string} params.role user's role
|
|
215
148
|
*/
|
|
216
149
|
async updateRole({ did, role }) {
|
|
217
|
-
const [num, doc] = await super.update({ did }, { $set: { role } });
|
|
218
|
-
|
|
150
|
+
const [num, [doc]] = await super.update({ did }, { $set: { role } });
|
|
219
151
|
if (num === 0) {
|
|
220
152
|
throw new Error(`user does not exist: ${did}`);
|
|
221
153
|
}
|
|
@@ -225,267 +157,175 @@ class User extends BaseState {
|
|
|
225
157
|
|
|
226
158
|
/**
|
|
227
159
|
* Get blocklet service user list
|
|
228
|
-
* @param {Object} query query params
|
|
229
|
-
* @param {('asc'|'desc')} sort query sort
|
|
230
|
-
* @param {any} paging query paging
|
|
231
|
-
* @returns {{list: BlockletUser[]; paging: any;}}
|
|
232
160
|
*/
|
|
233
|
-
async getUsers({ query, sort, paging
|
|
161
|
+
async getUsers({ query, sort, paging } = {}) {
|
|
234
162
|
const { approved, role, search, connectedDid } = query || {};
|
|
235
|
-
const queryParamList = [];
|
|
236
163
|
|
|
237
|
-
|
|
238
|
-
const
|
|
164
|
+
const where = {};
|
|
165
|
+
const include = [
|
|
166
|
+
{
|
|
167
|
+
model: this.models.Passport,
|
|
168
|
+
as: 'passports',
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
model: this.models.ConnectedAccount,
|
|
172
|
+
as: 'connectedAccounts',
|
|
173
|
+
},
|
|
174
|
+
];
|
|
239
175
|
|
|
240
|
-
if (
|
|
241
|
-
|
|
176
|
+
if (isNullOrUndefined(approved) === false) {
|
|
177
|
+
where.approved = approved;
|
|
242
178
|
}
|
|
243
179
|
|
|
244
180
|
if (search) {
|
|
245
181
|
if (search.length > 50) {
|
|
246
182
|
throw new Error('the length of search text should not more than 50');
|
|
247
183
|
}
|
|
248
|
-
|
|
249
184
|
if (isValid(search)) {
|
|
250
|
-
|
|
185
|
+
where.did = search;
|
|
251
186
|
} else {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
queryParam.fullName = { $regex: reg };
|
|
187
|
+
where[Op.or] = [{ fullName: { [Op.like]: `%${search}%` } }, { email: { [Op.like]: `%${search}%` } }];
|
|
255
188
|
}
|
|
256
189
|
}
|
|
257
190
|
|
|
258
191
|
if (role && role !== '$all') {
|
|
259
192
|
if (role === '$none') {
|
|
260
|
-
|
|
193
|
+
include[0].required = false;
|
|
194
|
+
include[0].where = {
|
|
195
|
+
[Op.or]: [{ name: null }, { id: null }],
|
|
196
|
+
};
|
|
261
197
|
} else {
|
|
262
|
-
|
|
198
|
+
include[0].where = { name: role };
|
|
199
|
+
include[0].required = true;
|
|
263
200
|
}
|
|
264
201
|
}
|
|
265
202
|
|
|
266
|
-
// 根据 connectedDid 查询 user 信息(wallet 账户绑定 oauth 账户后,会有该字段)
|
|
267
203
|
if (connectedDid) {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
'extraConfigs.connectedAccounts.did': connectedDid,
|
|
271
|
-
});
|
|
272
|
-
// HACK: 在某些情况下,查询的条件可能是 version2 版本的用户 did,并且查村的 did 是派生出来的,没有实际的用户记录,只能通过这个条件查询出来
|
|
273
|
-
// version 1 的用户不需要通过这个条件来查询
|
|
274
|
-
queryParamList.push({
|
|
275
|
-
...queryParam,
|
|
276
|
-
'extraConfigs.derivedAccount.did': connectedDid,
|
|
277
|
-
});
|
|
204
|
+
include[1].where = { did: connectedDid };
|
|
205
|
+
include[1].required = true;
|
|
278
206
|
}
|
|
279
207
|
|
|
280
|
-
const
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
sortParam.createdAt = -1;
|
|
208
|
+
const sorting = pickBy(sort, (x) => !isNullOrUndefined(x));
|
|
209
|
+
if (!Object.keys(sorting).length) {
|
|
210
|
+
sorting.createdAt = -1;
|
|
284
211
|
}
|
|
285
212
|
|
|
286
|
-
|
|
287
|
-
const { list, paging } = await this.paginate(
|
|
288
|
-
queryParamList.length > 0 ? { $or: queryParamList } : queryParam,
|
|
289
|
-
sortParam,
|
|
290
|
-
inputPaging
|
|
291
|
-
);
|
|
292
|
-
|
|
293
|
-
return {
|
|
294
|
-
list,
|
|
295
|
-
paging,
|
|
296
|
-
};
|
|
213
|
+
return this.paginate({ where, include }, sorting, paging);
|
|
297
214
|
}
|
|
298
215
|
|
|
299
|
-
|
|
300
|
-
* get user list by did list
|
|
301
|
-
* @param {string[]} dids user did list
|
|
302
|
-
* @returns {BlockletUser[]}
|
|
303
|
-
*/
|
|
304
|
-
async getUsersByDids({ dids, query } = {}) {
|
|
216
|
+
async getUsersByDids({ dids, query }) {
|
|
305
217
|
const { approved } = query || {};
|
|
306
|
-
const
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
did: { $in: didList },
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
if (!isNullOrUndefined(approved)) {
|
|
313
|
-
queryParam.approved = !!approved;
|
|
218
|
+
const condition = { did: dids };
|
|
219
|
+
if (isNullOrUndefined(approved) === false) {
|
|
220
|
+
condition.approved = !!approved;
|
|
314
221
|
}
|
|
315
222
|
|
|
316
|
-
|
|
317
|
-
|
|
223
|
+
return this.find({
|
|
224
|
+
where: condition,
|
|
225
|
+
include: [
|
|
226
|
+
{
|
|
227
|
+
model: this.models.ConnectedAccount,
|
|
228
|
+
as: 'connectedAccounts',
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
model: this.models.Passport,
|
|
232
|
+
as: 'passports',
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
});
|
|
318
236
|
}
|
|
319
237
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
'extraConfigs.sourceId': { $in: sourceIdList },
|
|
331
|
-
};
|
|
238
|
+
async countByPassport({ name, status = PASSPORT_STATUS.VALID }) {
|
|
239
|
+
if (name === '$none') {
|
|
240
|
+
return this.count({
|
|
241
|
+
where: {
|
|
242
|
+
did: {
|
|
243
|
+
[Op.notIn]: Sequelize.literal('(SELECT DISTINCT userDid FROM passports)'),
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
}
|
|
332
248
|
|
|
333
|
-
if (
|
|
334
|
-
|
|
249
|
+
if (name === '$all') {
|
|
250
|
+
return this.count({});
|
|
335
251
|
}
|
|
336
252
|
|
|
337
|
-
|
|
338
|
-
|
|
253
|
+
return this.count({
|
|
254
|
+
distinct: true,
|
|
255
|
+
col: 'did',
|
|
256
|
+
include: [
|
|
257
|
+
{
|
|
258
|
+
model: this.models.Passport,
|
|
259
|
+
as: 'passports',
|
|
260
|
+
attributes: [],
|
|
261
|
+
where: { name, status },
|
|
262
|
+
},
|
|
263
|
+
],
|
|
264
|
+
});
|
|
339
265
|
}
|
|
340
266
|
|
|
341
267
|
/**
|
|
342
|
-
*
|
|
268
|
+
* get user by did
|
|
269
|
+
* @param {string} did user's did
|
|
343
270
|
*/
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
version = 3;
|
|
359
|
-
}
|
|
360
|
-
}
|
|
271
|
+
async getUser(did, { enableConnectedAccount = false } = {}) {
|
|
272
|
+
let user = await this.findOne({
|
|
273
|
+
where: { did },
|
|
274
|
+
include: [
|
|
275
|
+
{
|
|
276
|
+
model: this.models.ConnectedAccount,
|
|
277
|
+
as: 'connectedAccounts',
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
model: this.models.Passport,
|
|
281
|
+
as: 'passports',
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
});
|
|
361
285
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
286
|
+
if (enableConnectedAccount && !user) {
|
|
287
|
+
user = await this.findOne({
|
|
288
|
+
include: [
|
|
365
289
|
{
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
lastLoginAt: user.lastLoginAt,
|
|
290
|
+
model: this.models.ConnectedAccount,
|
|
291
|
+
as: 'connectedAccounts',
|
|
292
|
+
where: { did },
|
|
293
|
+
required: true,
|
|
371
294
|
},
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
did: user.did,
|
|
376
|
-
pk: user.pk,
|
|
377
|
-
extraConfigs: {
|
|
378
|
-
sourceProvider,
|
|
379
|
-
connectedAccounts,
|
|
380
|
-
},
|
|
381
|
-
});
|
|
382
|
-
return updatedUser;
|
|
383
|
-
},
|
|
384
|
-
2: async () => {
|
|
385
|
-
// eslint-disable-next-line prefer-const
|
|
386
|
-
let { sourceId, sourceProvider, connectedAccounts = [] } = user.extraConfigs || {};
|
|
387
|
-
if (sourceId && sourceProvider) {
|
|
388
|
-
connectedAccounts = [
|
|
389
|
-
{
|
|
390
|
-
provider: sourceProvider,
|
|
391
|
-
id: sourceId,
|
|
392
|
-
did: user.did,
|
|
393
|
-
pk: user.pk,
|
|
394
|
-
firstLoginAt: user.firstLoginAt,
|
|
395
|
-
lastLoginAt: user.lastLoginAt,
|
|
396
|
-
},
|
|
397
|
-
];
|
|
398
|
-
} else {
|
|
399
|
-
sourceProvider = 'wallet';
|
|
400
|
-
connectedAccounts.forEach((account) => {
|
|
401
|
-
if (account.id && blockletSk) {
|
|
402
|
-
const accountWallet = fromAppDid(account.id, blockletSk);
|
|
403
|
-
account.did = accountWallet.address;
|
|
404
|
-
account.pk = accountWallet.publicKey;
|
|
405
|
-
account.firstLoginAt = account.firstLoginAt || new Date().toISOString();
|
|
406
|
-
account.lastLoginAt = account.lastLoginAt || new Date().toISOString();
|
|
407
|
-
}
|
|
408
|
-
});
|
|
409
|
-
connectedAccounts.unshift({
|
|
410
|
-
provider: 'wallet',
|
|
411
|
-
did: user.did,
|
|
412
|
-
pk: user.pk,
|
|
413
|
-
firstLoginAt: user.firstLoginAt,
|
|
414
|
-
lastLoginAt: user.lastLoginAt,
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
const updatedUser = await this.update({
|
|
418
|
-
did: user.did,
|
|
419
|
-
pk: user.pk,
|
|
420
|
-
extraConfigs: {
|
|
421
|
-
sourceProvider,
|
|
422
|
-
connectedAccounts,
|
|
295
|
+
{
|
|
296
|
+
model: this.models.Passport,
|
|
297
|
+
as: 'passports',
|
|
423
298
|
},
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
return updatedUser;
|
|
427
|
-
},
|
|
428
|
-
3: () => {
|
|
429
|
-
return user;
|
|
430
|
-
},
|
|
431
|
-
};
|
|
432
|
-
return versionMap[version]();
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
/**
|
|
436
|
-
* get user by did
|
|
437
|
-
* @param {string} did user's did
|
|
438
|
-
* @returns {BlockletUser}
|
|
439
|
-
*/
|
|
440
|
-
async getUser(did, { enableConnectedAccount = false, enableNormalize = false, blockletSk } = {}) {
|
|
441
|
-
let user = await this.findOne({ did });
|
|
442
|
-
if (enableConnectedAccount) {
|
|
443
|
-
if (!user) {
|
|
444
|
-
user = await this.findOne({
|
|
445
|
-
'extraConfigs.connectedAccounts.did': did,
|
|
446
|
-
});
|
|
447
|
-
} else if (user.extraConfig?.bindDid) {
|
|
448
|
-
// @deprecated 已经不存在 bindDid 字段
|
|
449
|
-
({ user } = await this.findOne({ did: user.extraConfig.bindDid }));
|
|
450
|
-
}
|
|
299
|
+
],
|
|
300
|
+
});
|
|
451
301
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
return this.normalize(user, { blockletSk });
|
|
302
|
+
|
|
303
|
+
// Normalize
|
|
304
|
+
if (user && !user.passports) {
|
|
305
|
+
user.passports = [];
|
|
457
306
|
}
|
|
307
|
+
|
|
458
308
|
return user;
|
|
459
309
|
}
|
|
460
310
|
|
|
461
311
|
/**
|
|
462
|
-
* @param {
|
|
463
|
-
* @param {string}
|
|
464
|
-
* @param {string}
|
|
312
|
+
* @param {object} params
|
|
313
|
+
* @param {string} params.did user did
|
|
314
|
+
* @param {string} params.id passport id
|
|
315
|
+
* @param {string} params.status passport status
|
|
465
316
|
*/
|
|
466
|
-
async _setPassportStatusById({ did, id, status }
|
|
467
|
-
const exist =
|
|
468
|
-
|
|
317
|
+
async _setPassportStatusById({ did, id, status }) {
|
|
318
|
+
const exist = this.passport.count({ id });
|
|
469
319
|
if (!exist) {
|
|
470
|
-
throw new Error('did does not exist');
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
const passports = exist.passports || [];
|
|
474
|
-
const passport = passports.find((x) => x.id === id);
|
|
475
|
-
|
|
476
|
-
if (!passport) {
|
|
477
320
|
throw new Error(`cannot find passport by id ${id}`);
|
|
478
321
|
}
|
|
479
322
|
|
|
480
|
-
passport.status
|
|
481
|
-
|
|
482
|
-
const [num, doc] = await super.update({ did }, { $set: { passports } });
|
|
483
|
-
|
|
323
|
+
const [num] = await this.passport.update({ id }, { $set: { status } });
|
|
484
324
|
if (num === 0) {
|
|
485
|
-
throw new Error('user does not exist');
|
|
325
|
+
throw new Error('user passport does not exist');
|
|
486
326
|
}
|
|
487
327
|
|
|
488
|
-
return
|
|
328
|
+
return this.getUser(did);
|
|
489
329
|
}
|
|
490
330
|
|
|
491
331
|
/**
|
|
@@ -502,66 +342,39 @@ class User extends BaseState {
|
|
|
502
342
|
* @param {string} user.lastLoginIp - lastLoginIp
|
|
503
343
|
* @param {('owner'|'admin'|'member'|'guest'|string)} user.role - deprecated user's role
|
|
504
344
|
*/
|
|
505
|
-
async
|
|
506
|
-
const { error, value: user } = loginSchema.validate(
|
|
345
|
+
async loginUser(raw) {
|
|
346
|
+
const { error, value: user } = loginSchema.validate(raw);
|
|
507
347
|
if (error) {
|
|
508
348
|
throw new Error(error);
|
|
509
349
|
}
|
|
510
350
|
|
|
511
|
-
let
|
|
512
|
-
|
|
351
|
+
let updated;
|
|
352
|
+
|
|
513
353
|
const now = new Date().toISOString();
|
|
514
|
-
const
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
const passports = upsertToPassports(
|
|
519
|
-
oldUser?.passports || [],
|
|
520
|
-
cloneData.passport && {
|
|
521
|
-
...cloneData.passport,
|
|
522
|
-
lastLoginAt: now,
|
|
523
|
-
}
|
|
524
|
-
);
|
|
525
|
-
const mergeData = {
|
|
526
|
-
...pick(cloneData, ['type', 'fullName', 'email', 'avatar', 'role', 'locale', 'extra', 'lastLoginIp', 'remark']),
|
|
527
|
-
did: user.did,
|
|
528
|
-
pk: user.pk,
|
|
529
|
-
passports,
|
|
354
|
+
const exist = await this.getUser(user.did, { enableConnectedAccount: true });
|
|
355
|
+
|
|
356
|
+
const updates = {
|
|
357
|
+
...pick(user, ['fullName', 'email', 'avatar', 'role', 'locale', 'extra', 'lastLoginIp', 'remark']),
|
|
530
358
|
lastLoginAt: now,
|
|
531
|
-
|
|
532
|
-
sourceProvider: 'wallet',
|
|
533
|
-
connectedAccounts: [],
|
|
534
|
-
},
|
|
359
|
+
passports: user.passport ? [{ ...user.passport, lastLoginAt: now }] : [],
|
|
535
360
|
};
|
|
536
361
|
|
|
537
|
-
if (
|
|
538
|
-
// update
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
sourceProvider: oldUser?.extraConfigs?.sourceProvider || 'wallet',
|
|
542
|
-
connectedAccounts: updateConnectedAccount(
|
|
543
|
-
oldUser?.extraConfigs?.connectedAccounts || [],
|
|
544
|
-
cloneData.connectedAccount
|
|
545
|
-
),
|
|
546
|
-
};
|
|
547
|
-
mergeData.extraConfigs = extraConfigs;
|
|
548
|
-
updatedUser = await this.update(mergeData);
|
|
362
|
+
if (exist) {
|
|
363
|
+
// update user, connectedAccount, passport
|
|
364
|
+
updates.connectedAccounts = updateConnectedAccount(exist.connectedAccounts, user.connectedAccount);
|
|
365
|
+
updated = await this.updateUser(user.did, updates);
|
|
549
366
|
} else {
|
|
550
|
-
//
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
mergeData.extraConfigs = {
|
|
559
|
-
sourceProvider: connectedAccount.provider,
|
|
560
|
-
connectedAccounts: updateConnectedAccount([], cloneData.connectedAccount),
|
|
561
|
-
};
|
|
562
|
-
updatedUser = await this.add(mergeData);
|
|
367
|
+
// create user, connectedAccount, passport
|
|
368
|
+
updates.did = user.did;
|
|
369
|
+
updates.pk = user.pk;
|
|
370
|
+
updates.firstLoginAt = now;
|
|
371
|
+
updates.approved = true;
|
|
372
|
+
updates.connectedAccounts = updateConnectedAccount([], user.connectedAccount);
|
|
373
|
+
updates.sourceProvider = updates.connectedAccounts[0].provider;
|
|
374
|
+
updated = await this.addUser(updates);
|
|
563
375
|
}
|
|
564
|
-
|
|
376
|
+
|
|
377
|
+
return { ...updated, _action: exist ? 'update' : 'add' };
|
|
565
378
|
}
|
|
566
379
|
}
|
|
567
380
|
|