@abtnode/core 1.17.8-beta-20260109-075740-5f484e08 → 1.17.8-beta-20260113-015027-32a1cec4
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/access-key-manager.js +104 -0
- package/lib/api/team/invitation-manager.js +461 -0
- package/lib/api/team/notification-manager.js +189 -0
- package/lib/api/team/oauth-manager.js +60 -0
- package/lib/api/team/org-crud-manager.js +202 -0
- package/lib/api/team/org-manager.js +56 -0
- package/lib/api/team/org-member-manager.js +403 -0
- package/lib/api/team/org-query-manager.js +126 -0
- package/lib/api/team/org-resource-manager.js +186 -0
- package/lib/api/team/passport-manager.js +670 -0
- package/lib/api/team/rbac-manager.js +335 -0
- package/lib/api/team/session-manager.js +540 -0
- package/lib/api/team/store-manager.js +198 -0
- package/lib/api/team/tag-manager.js +230 -0
- package/lib/api/team/user-auth-manager.js +132 -0
- package/lib/api/team/user-manager.js +78 -0
- package/lib/api/team/user-query-manager.js +299 -0
- package/lib/api/team/user-social-manager.js +354 -0
- package/lib/api/team/user-update-manager.js +224 -0
- package/lib/api/team/verify-code-manager.js +161 -0
- package/lib/api/team.js +439 -3287
- package/lib/blocklet/manager/disk/auth-manager.js +68 -0
- package/lib/blocklet/manager/disk/backup-manager.js +288 -0
- package/lib/blocklet/manager/disk/cleanup-manager.js +157 -0
- package/lib/blocklet/manager/disk/component-manager.js +83 -0
- package/lib/blocklet/manager/disk/config-manager.js +191 -0
- package/lib/blocklet/manager/disk/controller-manager.js +64 -0
- package/lib/blocklet/manager/disk/delete-reset-manager.js +328 -0
- package/lib/blocklet/manager/disk/download-manager.js +96 -0
- package/lib/blocklet/manager/disk/env-config-manager.js +311 -0
- package/lib/blocklet/manager/disk/federated-manager.js +651 -0
- package/lib/blocklet/manager/disk/hook-manager.js +124 -0
- package/lib/blocklet/manager/disk/install-component-manager.js +95 -0
- package/lib/blocklet/manager/disk/install-core-manager.js +448 -0
- package/lib/blocklet/manager/disk/install-download-manager.js +313 -0
- package/lib/blocklet/manager/disk/install-manager.js +36 -0
- package/lib/blocklet/manager/disk/install-upgrade-manager.js +340 -0
- package/lib/blocklet/manager/disk/job-manager.js +467 -0
- package/lib/blocklet/manager/disk/lifecycle-manager.js +26 -0
- package/lib/blocklet/manager/disk/notification-manager.js +343 -0
- package/lib/blocklet/manager/disk/query-manager.js +562 -0
- package/lib/blocklet/manager/disk/settings-manager.js +507 -0
- package/lib/blocklet/manager/disk/start-manager.js +611 -0
- package/lib/blocklet/manager/disk/stop-restart-manager.js +292 -0
- package/lib/blocklet/manager/disk/update-manager.js +153 -0
- package/lib/blocklet/manager/disk.js +669 -5796
- package/lib/blocklet/manager/helper/blue-green-start-blocklet.js +5 -0
- package/lib/blocklet/manager/lock.js +18 -0
- package/lib/event/index.js +28 -24
- package/lib/util/blocklet/app-utils.js +192 -0
- package/lib/util/blocklet/blocklet-loader.js +258 -0
- package/lib/util/blocklet/config-manager.js +232 -0
- package/lib/util/blocklet/did-document.js +240 -0
- package/lib/util/blocklet/environment.js +555 -0
- package/lib/util/blocklet/health-check.js +449 -0
- package/lib/util/blocklet/install-utils.js +365 -0
- package/lib/util/blocklet/logo.js +57 -0
- package/lib/util/blocklet/meta-utils.js +269 -0
- package/lib/util/blocklet/port-manager.js +141 -0
- package/lib/util/blocklet/process-manager.js +504 -0
- package/lib/util/blocklet/runtime-info.js +105 -0
- package/lib/util/blocklet/validation.js +418 -0
- package/lib/util/blocklet.js +98 -3066
- package/lib/util/wallet-app-notification.js +40 -0
- package/package.json +22 -22
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
const defaults = require('lodash/defaults');
|
|
2
|
+
const logger = require('@abtnode/logger')('@abtnode/core:api:team:session');
|
|
3
|
+
const { Op } = require('sequelize');
|
|
4
|
+
const { USER_SESSION_STATUS, SESSION_TTL } = require('@abtnode/constant');
|
|
5
|
+
const { BlockletEvents } = require('@blocklet/constant');
|
|
6
|
+
const { getBlockletInfo } = require('@blocklet/meta/lib/info');
|
|
7
|
+
const { callFederated, getFederatedMaster, findFederatedSite } = require('@abtnode/auth/lib/util/federated');
|
|
8
|
+
|
|
9
|
+
const { getBlocklet } = require('../../util/blocklet');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Get user session where clause
|
|
13
|
+
* @param {Object} params
|
|
14
|
+
* @param {string} params.status - Session status
|
|
15
|
+
* @param {Object} params.blocklet - Blocklet
|
|
16
|
+
* @returns {Object}
|
|
17
|
+
*/
|
|
18
|
+
const getUserSessionWhere = ({ status, blocklet }) => {
|
|
19
|
+
const now = Date.now();
|
|
20
|
+
const sessionTtl = blocklet.settings?.session?.ttl || SESSION_TTL;
|
|
21
|
+
if (status === USER_SESSION_STATUS.ONLINE) {
|
|
22
|
+
return {
|
|
23
|
+
updatedAt: {
|
|
24
|
+
[Op.gt]: new Date(now - sessionTtl * 1000),
|
|
25
|
+
},
|
|
26
|
+
status: {
|
|
27
|
+
[Op.ne]: USER_SESSION_STATUS.OFFLINE,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
if (status === USER_SESSION_STATUS.EXPIRED) {
|
|
32
|
+
return {
|
|
33
|
+
updatedAt: {
|
|
34
|
+
[Op.lt]: new Date(now - sessionTtl * 1000),
|
|
35
|
+
},
|
|
36
|
+
status: {
|
|
37
|
+
[Op.ne]: USER_SESSION_STATUS.OFFLINE,
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (status === USER_SESSION_STATUS.OFFLINE) {
|
|
42
|
+
return {
|
|
43
|
+
status: USER_SESSION_STATUS.OFFLINE,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return {};
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get user session
|
|
51
|
+
* @param {Object} api - TeamAPI instance
|
|
52
|
+
* @param {Object} params
|
|
53
|
+
* @param {string} params.teamDid - Team DID
|
|
54
|
+
* @param {string} params.id - Session ID
|
|
55
|
+
* @param {boolean} params.includeUser - Include user data
|
|
56
|
+
* @returns {Promise<Object>}
|
|
57
|
+
*/
|
|
58
|
+
async function getUserSession(api, { teamDid, id, includeUser = false }) {
|
|
59
|
+
const state = await api.getUserSessionState(teamDid);
|
|
60
|
+
const userState = await api.getUserState(teamDid);
|
|
61
|
+
|
|
62
|
+
const where = {
|
|
63
|
+
status: USER_SESSION_STATUS.ONLINE,
|
|
64
|
+
id,
|
|
65
|
+
};
|
|
66
|
+
const include = [];
|
|
67
|
+
if (includeUser) {
|
|
68
|
+
include.push({
|
|
69
|
+
model: userState.model,
|
|
70
|
+
as: 'user',
|
|
71
|
+
attributes: ['did', 'pk', 'sourceProvider', 'fullName', 'email', 'avatar', 'remark', 'sourceAppPid', 'approved'],
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const userSession = await state.model.findOne({
|
|
76
|
+
where,
|
|
77
|
+
attributes: [
|
|
78
|
+
'id',
|
|
79
|
+
'appPid',
|
|
80
|
+
'userDid',
|
|
81
|
+
'visitorId',
|
|
82
|
+
'passportId',
|
|
83
|
+
'createdAt',
|
|
84
|
+
'updatedAt',
|
|
85
|
+
'extra',
|
|
86
|
+
'ua',
|
|
87
|
+
'lastLoginIp',
|
|
88
|
+
'status',
|
|
89
|
+
],
|
|
90
|
+
include,
|
|
91
|
+
});
|
|
92
|
+
return userSession?.toJSON?.();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get user sessions
|
|
97
|
+
* @param {Object} api - TeamAPI instance
|
|
98
|
+
* @param {Object} params
|
|
99
|
+
* @param {string} params.teamDid - Team DID
|
|
100
|
+
* @param {Object} params.query - Query options
|
|
101
|
+
* @param {Object} params.paging - Paging options
|
|
102
|
+
* @param {Object} params.sort - Sort options
|
|
103
|
+
* @returns {Promise<Object>}
|
|
104
|
+
*/
|
|
105
|
+
async function getUserSessions(api, { teamDid, query = {}, paging, sort }) {
|
|
106
|
+
const nodeInfo = await api.node.read({ useCache: true });
|
|
107
|
+
if (teamDid === nodeInfo.did) {
|
|
108
|
+
return {
|
|
109
|
+
list: [],
|
|
110
|
+
paging: {
|
|
111
|
+
page: 1,
|
|
112
|
+
pageCount: 0,
|
|
113
|
+
pageSize: 10,
|
|
114
|
+
total: 0,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const { userDid, visitorId, appPid, includeUser = false, status = USER_SESSION_STATUS.ONLINE } = query;
|
|
120
|
+
const state = await api.getUserSessionState(teamDid);
|
|
121
|
+
const userState = await api.getUserState(teamDid);
|
|
122
|
+
const where = {};
|
|
123
|
+
if (userDid) where.userDid = userDid;
|
|
124
|
+
if (visitorId) where.visitorId = visitorId;
|
|
125
|
+
if (appPid) where.appPid = appPid;
|
|
126
|
+
|
|
127
|
+
const blocklet = await getBlocklet({ did: teamDid, states: api.states, dataDirs: api.dataDirs, useCache: true });
|
|
128
|
+
const whereStatus = getUserSessionWhere({ status, blocklet });
|
|
129
|
+
Object.assign(where, whereStatus);
|
|
130
|
+
const include = [];
|
|
131
|
+
if (includeUser) {
|
|
132
|
+
include.push({
|
|
133
|
+
model: userState.model,
|
|
134
|
+
as: 'user',
|
|
135
|
+
attributes: ['did', 'pk', 'sourceProvider', 'fullName', 'email', 'avatar', 'remark', 'sourceAppPid', 'approved'],
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const result = await state.paginate(
|
|
140
|
+
{
|
|
141
|
+
where,
|
|
142
|
+
attributes: [
|
|
143
|
+
'id',
|
|
144
|
+
'appPid',
|
|
145
|
+
'userDid',
|
|
146
|
+
'visitorId',
|
|
147
|
+
'passportId',
|
|
148
|
+
'createdAt',
|
|
149
|
+
'updatedAt',
|
|
150
|
+
'extra',
|
|
151
|
+
'ua',
|
|
152
|
+
'lastLoginIp',
|
|
153
|
+
'status',
|
|
154
|
+
],
|
|
155
|
+
include,
|
|
156
|
+
},
|
|
157
|
+
{ updatedAt: -1, ...sort },
|
|
158
|
+
{ pageSize: 10, ...paging }
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
// NOTICE: 保留结构,方便理解
|
|
162
|
+
return {
|
|
163
|
+
list: result.list,
|
|
164
|
+
paging: result.paging,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Get user sessions count
|
|
170
|
+
* @param {Object} api - TeamAPI instance
|
|
171
|
+
* @param {Object} params
|
|
172
|
+
* @param {string} params.teamDid - Team DID
|
|
173
|
+
* @param {Object} params.query - Query options
|
|
174
|
+
* @returns {Promise<Object>}
|
|
175
|
+
*/
|
|
176
|
+
async function getUserSessionsCount(api, { teamDid, query = {} }) {
|
|
177
|
+
const nodeInfo = await api.node.read();
|
|
178
|
+
if (teamDid === nodeInfo.did) {
|
|
179
|
+
return {
|
|
180
|
+
count: 0,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
const { userDid, visitorId, appPid, status = USER_SESSION_STATUS.ONLINE } = query;
|
|
184
|
+
const state = await api.getUserSessionState(teamDid);
|
|
185
|
+
const where = {};
|
|
186
|
+
if (userDid) where.userDid = userDid;
|
|
187
|
+
if (visitorId) where.visitorId = visitorId;
|
|
188
|
+
if (appPid) where.appPid = appPid;
|
|
189
|
+
|
|
190
|
+
const blocklet = await getBlocklet({ did: teamDid, states: api.states, dataDirs: api.dataDirs, useCache: true });
|
|
191
|
+
const whereStatus = getUserSessionWhere({ status, blocklet });
|
|
192
|
+
Object.assign(where, whereStatus);
|
|
193
|
+
|
|
194
|
+
// HACK: 使用 state.count 并不能按预期工作,先改为使用 state.model.count 来实现
|
|
195
|
+
const result = await state.model.count({ where });
|
|
196
|
+
return {
|
|
197
|
+
count: result,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Get passport by ID
|
|
203
|
+
* @param {Object} api - TeamAPI instance
|
|
204
|
+
* @param {Object} params
|
|
205
|
+
* @param {string} params.teamDid - Team DID
|
|
206
|
+
* @param {string} params.passportId - Passport ID
|
|
207
|
+
* @returns {Promise<Object>}
|
|
208
|
+
*/
|
|
209
|
+
async function getPassportById(api, { teamDid, passportId }) {
|
|
210
|
+
const userState = await api.getUserState(teamDid);
|
|
211
|
+
const passport = await userState.getPassportById(passportId);
|
|
212
|
+
return passport;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Get passport from federated
|
|
217
|
+
* @param {Object} api - TeamAPI instance
|
|
218
|
+
* @param {Object} params
|
|
219
|
+
* @param {Object} params.site - Site
|
|
220
|
+
* @param {string} params.passportId - Passport ID
|
|
221
|
+
* @param {string} params.teamDid - Team DID
|
|
222
|
+
* @returns {Promise<Object>}
|
|
223
|
+
*/
|
|
224
|
+
async function getPassportFromFederated(api, { site, passportId, teamDid }) {
|
|
225
|
+
try {
|
|
226
|
+
const blocklet = await getBlocklet({
|
|
227
|
+
did: teamDid,
|
|
228
|
+
states: api.states,
|
|
229
|
+
dataDirs: api.dataDirs,
|
|
230
|
+
useCache: true,
|
|
231
|
+
});
|
|
232
|
+
const nodeInfo = await api.node.read();
|
|
233
|
+
const { permanentWallet } = getBlockletInfo(blocklet, nodeInfo.sk);
|
|
234
|
+
|
|
235
|
+
const result = await callFederated({
|
|
236
|
+
action: 'getPassport',
|
|
237
|
+
data: {
|
|
238
|
+
passportId,
|
|
239
|
+
},
|
|
240
|
+
permanentWallet,
|
|
241
|
+
site,
|
|
242
|
+
requestOptions: {
|
|
243
|
+
// 缩短查询通行证的请求时间,这个请求不会很复杂
|
|
244
|
+
timeout: 3 * 1000,
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
return result;
|
|
249
|
+
} catch (error) {
|
|
250
|
+
// 吞没错误,查询失败也不会影响整个快捷登录流程
|
|
251
|
+
logger.error('Failed to getPassportFromFederated', { site, passportId, teamDid, error });
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Upsert user session
|
|
258
|
+
* @param {Object} api - TeamAPI instance
|
|
259
|
+
* @param {Object} params
|
|
260
|
+
* @param {string} params.teamDid - Team DID
|
|
261
|
+
* @param {string} params.appPid - App PID
|
|
262
|
+
* @param {string} params.userDid - User DID
|
|
263
|
+
* @param {string} params.visitorId - Visitor ID
|
|
264
|
+
* @param {string} params.ua - User agent
|
|
265
|
+
* @param {string} params.lastLoginIp - Last login IP
|
|
266
|
+
* @param {string} params.passportId - Passport ID
|
|
267
|
+
* @param {string} params.status - Status
|
|
268
|
+
* @param {Object} params.extra - Extra data
|
|
269
|
+
* @param {string} params.locale - Locale
|
|
270
|
+
* @param {string} params.origin - Origin
|
|
271
|
+
* @param {Object} options
|
|
272
|
+
* @param {boolean} options.skipNotification - Skip notification
|
|
273
|
+
* @returns {Promise<Object>}
|
|
274
|
+
*/
|
|
275
|
+
async function upsertUserSession(
|
|
276
|
+
api,
|
|
277
|
+
{ teamDid, appPid, userDid, visitorId, ua, lastLoginIp, passportId, status, extra, locale, origin },
|
|
278
|
+
{ skipNotification = false } = {}
|
|
279
|
+
) {
|
|
280
|
+
if (!userDid) {
|
|
281
|
+
throw new Error('userDid is required');
|
|
282
|
+
}
|
|
283
|
+
if (visitorId) {
|
|
284
|
+
if (visitorId.length > 80) {
|
|
285
|
+
throw new Error('visitorId should be less than 80 characters');
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const state = await api.getUserSessionState(teamDid);
|
|
290
|
+
let data;
|
|
291
|
+
if (!visitorId) {
|
|
292
|
+
data = await state.insert({
|
|
293
|
+
userDid,
|
|
294
|
+
ua,
|
|
295
|
+
lastLoginIp,
|
|
296
|
+
appPid,
|
|
297
|
+
passportId,
|
|
298
|
+
extra,
|
|
299
|
+
});
|
|
300
|
+
logger.info('insert userSession successfully', { userDid, ua, lastLoginIp, appPid, passportId, extra });
|
|
301
|
+
api.emit(BlockletEvents.addUserSession, {
|
|
302
|
+
userSession: data,
|
|
303
|
+
teamDid,
|
|
304
|
+
userDid,
|
|
305
|
+
locale,
|
|
306
|
+
skipNotification,
|
|
307
|
+
origin,
|
|
308
|
+
});
|
|
309
|
+
} else {
|
|
310
|
+
const exist = await state.findOne({ userDid, visitorId, appPid });
|
|
311
|
+
if (exist) {
|
|
312
|
+
const mergeExtra = defaults({}, extra || {}, exist.extra || {});
|
|
313
|
+
[, [data]] = await state.update(exist.id, {
|
|
314
|
+
passportId,
|
|
315
|
+
lastLoginIp,
|
|
316
|
+
ua,
|
|
317
|
+
status,
|
|
318
|
+
extra: mergeExtra,
|
|
319
|
+
});
|
|
320
|
+
logger.info('update userSession successfully', {
|
|
321
|
+
id: exist.id,
|
|
322
|
+
ua,
|
|
323
|
+
lastLoginIp,
|
|
324
|
+
passportId,
|
|
325
|
+
status,
|
|
326
|
+
extra: mergeExtra,
|
|
327
|
+
});
|
|
328
|
+
if (Date.now() - new Date(exist.createdAt).getTime() < 1000 * 10) {
|
|
329
|
+
// HACK: 此处是为了矫正首次创建 userSession 没有 ua 的情况,会通过 /api/did/session 接口来更新 ua 信息,这个时候才能当成新增 userSession 来发送通知
|
|
330
|
+
api.emit(BlockletEvents.addUserSession, {
|
|
331
|
+
userSession: data,
|
|
332
|
+
teamDid,
|
|
333
|
+
userDid,
|
|
334
|
+
locale,
|
|
335
|
+
skipNotification,
|
|
336
|
+
origin,
|
|
337
|
+
});
|
|
338
|
+
} else {
|
|
339
|
+
api.emit(BlockletEvents.updateUserSession, {
|
|
340
|
+
userSession: data,
|
|
341
|
+
teamDid,
|
|
342
|
+
userDid,
|
|
343
|
+
skipNotification,
|
|
344
|
+
origin,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
} else {
|
|
348
|
+
data = await state.insert({
|
|
349
|
+
visitorId,
|
|
350
|
+
userDid,
|
|
351
|
+
ua,
|
|
352
|
+
lastLoginIp,
|
|
353
|
+
appPid,
|
|
354
|
+
passportId,
|
|
355
|
+
extra,
|
|
356
|
+
});
|
|
357
|
+
logger.info('insert userSession successfully', {
|
|
358
|
+
visitorId,
|
|
359
|
+
userDid,
|
|
360
|
+
ua,
|
|
361
|
+
lastLoginIp,
|
|
362
|
+
appPid,
|
|
363
|
+
passportId,
|
|
364
|
+
extra,
|
|
365
|
+
});
|
|
366
|
+
api.emit(BlockletEvents.addUserSession, {
|
|
367
|
+
userSession: data,
|
|
368
|
+
teamDid,
|
|
369
|
+
userDid,
|
|
370
|
+
locale,
|
|
371
|
+
skipNotification,
|
|
372
|
+
origin,
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return data;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Sync user session
|
|
382
|
+
* @param {Object} api - TeamAPI instance
|
|
383
|
+
* @param {Object} params
|
|
384
|
+
* @param {string} params.teamDid - Team DID
|
|
385
|
+
* @param {string} params.targetAppPid - Target app PID
|
|
386
|
+
* @param {string} params.userDid - User DID
|
|
387
|
+
* @param {string} params.visitorId - Visitor ID
|
|
388
|
+
* @param {string} params.ua - User agent
|
|
389
|
+
* @param {string} params.lastLoginIp - Last login IP
|
|
390
|
+
* @param {string} params.passportId - Passport ID
|
|
391
|
+
* @param {Object} params.extra - Extra data
|
|
392
|
+
* @returns {Promise<void>}
|
|
393
|
+
*/
|
|
394
|
+
async function syncUserSession(api, { teamDid, targetAppPid, userDid, visitorId, ua, lastLoginIp, passportId, extra }) {
|
|
395
|
+
if (!targetAppPid) return;
|
|
396
|
+
|
|
397
|
+
const blocklet = await getBlocklet({ did: teamDid, states: api.states, dataDirs: api.dataDirs, useCache: true });
|
|
398
|
+
const nodeInfo = await api.node.read();
|
|
399
|
+
const { permanentWallet } = getBlockletInfo(blocklet, nodeInfo.sk);
|
|
400
|
+
|
|
401
|
+
const targetSite = findFederatedSite(blocklet, targetAppPid);
|
|
402
|
+
const masterSite = getFederatedMaster(blocklet);
|
|
403
|
+
|
|
404
|
+
let syncSite = null;
|
|
405
|
+
let appPid;
|
|
406
|
+
if (masterSite && targetSite) {
|
|
407
|
+
if (targetSite.appPid === masterSite.appPid) {
|
|
408
|
+
if (teamDid !== masterSite.appPid) {
|
|
409
|
+
syncSite = masterSite;
|
|
410
|
+
appPid = teamDid;
|
|
411
|
+
}
|
|
412
|
+
} else if (teamDid === masterSite.appPid) {
|
|
413
|
+
syncSite = targetSite;
|
|
414
|
+
appPid = targetAppPid;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (syncSite) {
|
|
418
|
+
try {
|
|
419
|
+
const userSession = {
|
|
420
|
+
action: 'login',
|
|
421
|
+
userDid,
|
|
422
|
+
visitorId,
|
|
423
|
+
ua,
|
|
424
|
+
lastLoginIp,
|
|
425
|
+
appPid,
|
|
426
|
+
passportId,
|
|
427
|
+
extra,
|
|
428
|
+
};
|
|
429
|
+
await callFederated({
|
|
430
|
+
action: 'sync',
|
|
431
|
+
permanentWallet,
|
|
432
|
+
site: targetSite,
|
|
433
|
+
data: {
|
|
434
|
+
userSessions: [userSession],
|
|
435
|
+
},
|
|
436
|
+
});
|
|
437
|
+
logger.debug('Sync userSession to federated site successfully', {
|
|
438
|
+
userDid,
|
|
439
|
+
visitorId,
|
|
440
|
+
ua,
|
|
441
|
+
lastLoginIp,
|
|
442
|
+
appPid,
|
|
443
|
+
passportId,
|
|
444
|
+
targetSite,
|
|
445
|
+
extra,
|
|
446
|
+
});
|
|
447
|
+
} catch (err) {
|
|
448
|
+
logger.error(
|
|
449
|
+
'Sync userSession to federated site failed',
|
|
450
|
+
{
|
|
451
|
+
userDid,
|
|
452
|
+
visitorId,
|
|
453
|
+
ua,
|
|
454
|
+
lastLoginIp,
|
|
455
|
+
appPid,
|
|
456
|
+
passportId,
|
|
457
|
+
targetSite,
|
|
458
|
+
extra,
|
|
459
|
+
},
|
|
460
|
+
err
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Logout user
|
|
469
|
+
* @param {Object} api - TeamAPI instance
|
|
470
|
+
* @param {Object} params
|
|
471
|
+
* @param {string} params.teamDid - Team DID
|
|
472
|
+
* @param {string} params.userDid - User DID
|
|
473
|
+
* @param {string} params.visitorId - Visitor ID
|
|
474
|
+
* @param {string} params.appPid - App PID
|
|
475
|
+
* @param {string} params.status - Status
|
|
476
|
+
* @param {boolean} params.remove - Remove session
|
|
477
|
+
* @returns {Promise<number>}
|
|
478
|
+
*/
|
|
479
|
+
async function logoutUser(api, { teamDid, userDid, visitorId = '', appPid = '', status = '', remove = false }) {
|
|
480
|
+
if (!userDid) {
|
|
481
|
+
throw new Error('userDid is required');
|
|
482
|
+
}
|
|
483
|
+
if (!teamDid) {
|
|
484
|
+
throw new Error('teamDid is required');
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
const nodeInfo = await api.node.read();
|
|
488
|
+
if (nodeInfo.did === teamDid) {
|
|
489
|
+
return 0;
|
|
490
|
+
}
|
|
491
|
+
const userSessionState = await api.getUserSessionState(teamDid);
|
|
492
|
+
const where = { userDid };
|
|
493
|
+
if (visitorId) where.visitorId = visitorId;
|
|
494
|
+
if (appPid) where.appPid = appPid;
|
|
495
|
+
|
|
496
|
+
const blocklet = await getBlocklet({ did: teamDid, states: api.states, dataDirs: api.dataDirs, useCache: true });
|
|
497
|
+
const whereStatus = getUserSessionWhere({ status, blocklet });
|
|
498
|
+
Object.assign(where, whereStatus);
|
|
499
|
+
let result;
|
|
500
|
+
if (remove) {
|
|
501
|
+
result = await userSessionState.remove(where);
|
|
502
|
+
} else {
|
|
503
|
+
result = await userSessionState.update(where, { $set: { status: USER_SESSION_STATUS.OFFLINE } });
|
|
504
|
+
}
|
|
505
|
+
const { permanentWallet } = getBlockletInfo(blocklet, nodeInfo.sk);
|
|
506
|
+
const masterSite = getFederatedMaster(blocklet);
|
|
507
|
+
if (masterSite && masterSite.isMaster !== false && masterSite.appPid !== teamDid) {
|
|
508
|
+
callFederated({
|
|
509
|
+
action: 'sync',
|
|
510
|
+
permanentWallet,
|
|
511
|
+
// FIXME: @zhanghan 是否还需要通知其他 Member 站点,执行退出登录的操作
|
|
512
|
+
site: masterSite,
|
|
513
|
+
data: {
|
|
514
|
+
userSessions: [
|
|
515
|
+
{
|
|
516
|
+
action: 'logout',
|
|
517
|
+
userDid,
|
|
518
|
+
visitorId,
|
|
519
|
+
// HACK: 如果未传入 appPid,代表要注销当前用户在 master 中所有登录状态,所以传入 undefined;否则就只注销 master 中记录的当前 member 的登录状态
|
|
520
|
+
appPid: appPid ? teamDid : undefined,
|
|
521
|
+
remove,
|
|
522
|
+
},
|
|
523
|
+
],
|
|
524
|
+
},
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
return result;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
module.exports = {
|
|
531
|
+
getUserSessionWhere,
|
|
532
|
+
getUserSession,
|
|
533
|
+
getUserSessions,
|
|
534
|
+
getUserSessionsCount,
|
|
535
|
+
getPassportById,
|
|
536
|
+
getPassportFromFederated,
|
|
537
|
+
upsertUserSession,
|
|
538
|
+
syncUserSession,
|
|
539
|
+
logoutUser,
|
|
540
|
+
};
|