@abtnode/blocklet-services 1.16.19-beta-e6aac665 → 1.16.19-beta-710018ca
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/api/libs/connect/v1.js +1 -5
- package/api/libs/connect/v2.js +1 -5
- package/api/libs/image.js +62 -62
- package/api/libs/open-graph/emoji.js +2 -2
- package/api/libs/open-graph/index.js +1 -0
- package/api/routes/oauth.js +5 -1
- package/api/routes/user.js +42 -25
- package/api/validators/login.js +3 -1
- package/build/asset-manifest.json +59 -61
- package/build/index.html +1 -1
- package/build/service-worker.js +1 -1
- package/build/service-worker.js.map +1 -1
- package/build/static/css/5547.75913953.chunk.css +12 -0
- package/build/static/js/{1148.5ccba08e.chunk.js → 1148.67f53e43.chunk.js} +2 -2
- package/build/static/js/{1233.276cf2d0.chunk.js → 1233.43c6131b.chunk.js} +3 -3
- package/build/static/js/1905.656cb960.chunk.js +2 -0
- package/build/static/js/2838.bc235457.chunk.js +3 -0
- package/build/static/js/2940.5fc76234.chunk.js +2 -0
- package/build/static/js/3033.f950a32b.chunk.js +2 -0
- package/build/static/js/3430.28c5bd04.chunk.js +2 -0
- package/build/static/js/3708.937e3176.chunk.js +3 -0
- package/build/static/js/{4023.5fe8180a.chunk.js → 4023.623d31df.chunk.js} +2 -2
- package/build/static/js/4461.2e764a6b.chunk.js +2 -0
- package/build/static/js/{4587.9a042d46.chunk.js → 4587.0d0fd3ae.chunk.js} +2 -2
- package/build/static/js/5070.267c5f25.chunk.js +2 -0
- package/build/static/js/5547.1bea60f5.chunk.js +3 -0
- package/build/static/js/{5683.051a03c1.chunk.js → 5683.b87f7ca2.chunk.js} +2 -2
- package/build/static/js/6032.406db269.chunk.js +2 -0
- package/build/static/js/716.8cd88d8c.chunk.js +3 -0
- package/build/static/js/7419.4eabaec0.chunk.js +2 -0
- package/build/static/js/779.21153e82.chunk.js +2 -0
- package/build/static/js/7858.b08b86e5.chunk.js +2 -0
- package/build/static/js/{8181.6c2a7dcb.chunk.js → 8181.bc510ea3.chunk.js} +2 -2
- package/build/static/js/8393.c6c4c762.chunk.js +2 -0
- package/build/static/js/{8622.6aa0a4d4.chunk.js → 8622.c87f0f5b.chunk.js} +2 -2
- package/build/static/js/{8944.939de854.chunk.js → 8944.d3a98445.chunk.js} +2 -2
- package/build/static/js/{8641.bec13444.chunk.js → 8983.6213f391.chunk.js} +2 -2
- package/build/static/js/9017.369db632.chunk.js +2 -0
- package/build/static/js/{9314.f0add972.chunk.js → 9314.2073578f.chunk.js} +2 -2
- package/build/static/js/main.43cea647.js +3 -0
- package/build/static/js/{main.6f748ae5.js.LICENSE.txt → main.43cea647.js.LICENSE.txt} +1 -1
- package/package.json +23 -23
- package/build/static/css/5547.e016de4c.chunk.css +0 -12
- package/build/static/js/2801.33d2f238.chunk.js +0 -2
- package/build/static/js/2838.ec459fda.chunk.js +0 -3
- package/build/static/js/2940.ce32ab3f.chunk.js +0 -2
- package/build/static/js/3033.9fe46d7f.chunk.js +0 -2
- package/build/static/js/3430.dc830483.chunk.js +0 -2
- package/build/static/js/3708.7e2ad66b.chunk.js +0 -3
- package/build/static/js/4461.f9a883d3.chunk.js +0 -2
- package/build/static/js/5070.31a74ba7.chunk.js +0 -2
- package/build/static/js/5434.523d071d.chunk.js +0 -2
- package/build/static/js/5547.42b98889.chunk.js +0 -3
- package/build/static/js/6032.1001afd3.chunk.js +0 -2
- package/build/static/js/716.e68425d7.chunk.js +0 -3
- package/build/static/js/779.73350f02.chunk.js +0 -2
- package/build/static/js/7858.52930f63.chunk.js +0 -2
- package/build/static/js/8393.ea7ef05d.chunk.js +0 -2
- package/build/static/js/840.5bc210dd.chunk.js +0 -2
- package/build/static/js/9017.56c20b17.chunk.js +0 -2
- package/build/static/js/main.6f748ae5.js +0 -3
- /package/build/static/js/{1233.276cf2d0.chunk.js.LICENSE.txt → 1233.43c6131b.chunk.js.LICENSE.txt} +0 -0
- /package/build/static/js/{2838.ec459fda.chunk.js.LICENSE.txt → 2838.bc235457.chunk.js.LICENSE.txt} +0 -0
- /package/build/static/js/{3708.7e2ad66b.chunk.js.LICENSE.txt → 3708.937e3176.chunk.js.LICENSE.txt} +0 -0
- /package/build/static/js/{5547.42b98889.chunk.js.LICENSE.txt → 5547.1bea60f5.chunk.js.LICENSE.txt} +0 -0
- /package/build/static/js/{716.e68425d7.chunk.js.LICENSE.txt → 716.8cd88d8c.chunk.js.LICENSE.txt} +0 -0
package/api/libs/connect/v1.js
CHANGED
|
@@ -66,11 +66,7 @@ module.exports = (node, opts) => {
|
|
|
66
66
|
|
|
67
67
|
const handlerOpts = {
|
|
68
68
|
authenticator,
|
|
69
|
-
tokenStorage: new DynamicStorage({
|
|
70
|
-
dbPath: path.join(opts.dataDir, 'connections.db'),
|
|
71
|
-
model: 'Connection',
|
|
72
|
-
primaryKey: 'token',
|
|
73
|
-
}),
|
|
69
|
+
tokenStorage: new DynamicStorage({ dbPath: path.join(opts.dataDir, 'connections.db') }),
|
|
74
70
|
sendNotificationFn: async (connectedDid, message, { req }) => {
|
|
75
71
|
const { wallet } = await req.getBlockletInfo();
|
|
76
72
|
return sendToUser(
|
package/api/libs/connect/v2.js
CHANGED
|
@@ -22,11 +22,7 @@ module.exports = (node, opts) => {
|
|
|
22
22
|
const handlers = createHandlers({
|
|
23
23
|
logger,
|
|
24
24
|
authenticator,
|
|
25
|
-
storage: new DynamicStorage({
|
|
26
|
-
dbPath: path.join(opts.dataDir, 'connections.db'),
|
|
27
|
-
model: 'ConnectionV2',
|
|
28
|
-
primaryKey: 'sessionId',
|
|
29
|
-
}),
|
|
25
|
+
storage: new DynamicStorage({ dbPath: path.join(opts.dataDir, 'connections.db'), v2: true }),
|
|
30
26
|
socketPathname: `${WELLKNOWN_SERVICE_PATH_PREFIX}/api/connect/relay/websocket`,
|
|
31
27
|
sendNotificationFn: async (connectedDid, message, { request }) => {
|
|
32
28
|
const { wallet } = await request.getBlockletInfo();
|
package/api/libs/image.js
CHANGED
|
@@ -130,68 +130,6 @@ const isImageRequest = (req) => {
|
|
|
130
130
|
|
|
131
131
|
const getImageContentType = (extension) => (extension === 'svg' ? 'image/svg+xml' : `image/${extension}`);
|
|
132
132
|
|
|
133
|
-
const tasks = {};
|
|
134
|
-
const processAndRespond = (req, res, cacheDir, getSrc, ext, sendOptions = { maxAge: '356d', immutable: true }) => {
|
|
135
|
-
if (fs.existsSync(cacheDir) === false) {
|
|
136
|
-
fs.mkdirSync(cacheDir, { recursive: true });
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const params = req.imageFilter;
|
|
140
|
-
const extension = toLower(ext || path.extname(req.path).slice(1));
|
|
141
|
-
|
|
142
|
-
// NOTE: 不要使用 `req.accepts('image/webp')`,这里需要排除掉 `Accept: */*` 和 `Accept: image/*` 的情况
|
|
143
|
-
const acceptWebp = req.accepts().includes('image/webp');
|
|
144
|
-
if (!acceptWebp) {
|
|
145
|
-
if (params.f === 'webp') {
|
|
146
|
-
params.f = undefined;
|
|
147
|
-
}
|
|
148
|
-
if ((!extension || extension === 'webp') && !params.f) {
|
|
149
|
-
params.f = 'png';
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
if (!extension && !params.f) {
|
|
153
|
-
params.f = 'png';
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (!extension && !params.f) {
|
|
157
|
-
res.status(400).send('Image filter failed: either extension or format must be specified');
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const cacheKey = md5(stringify({ target: req.target, path: req.originalUrl, params }));
|
|
162
|
-
const destPath = getCacheFilePath(cacheDir, `${cacheKey}.${params.f || extension}`);
|
|
163
|
-
if (fs.existsSync(destPath)) {
|
|
164
|
-
res.header('Content-Type', getImageContentType(params.f || extension));
|
|
165
|
-
res.sendFile(destPath, sendOptions);
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// do the convert
|
|
170
|
-
tasks[cacheKey] ??= getSrc(req)
|
|
171
|
-
.then(([src, _extension]) => processImage(src, toLower(_extension), destPath, params))
|
|
172
|
-
.finally(() => {
|
|
173
|
-
setTimeout(() => {
|
|
174
|
-
delete tasks[cacheKey];
|
|
175
|
-
}, 1000);
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
tasks[cacheKey]
|
|
179
|
-
.then(() => {
|
|
180
|
-
logger.info('image filter succeed', { params, url: req.originalUrl, destPath });
|
|
181
|
-
res.header('Content-Type', getImageContentType(params.f || extension));
|
|
182
|
-
res.sendFile(destPath, sendOptions);
|
|
183
|
-
})
|
|
184
|
-
.catch((err) => {
|
|
185
|
-
logger.error('image filter failed', { error: err, params, url: req.url });
|
|
186
|
-
if (params.e) {
|
|
187
|
-
res.status(500).send(`Image service error: ${err.message}`);
|
|
188
|
-
} else {
|
|
189
|
-
res.status(500);
|
|
190
|
-
res.sendFile(errorImage, { maxAge: 0 });
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
};
|
|
194
|
-
|
|
195
133
|
const processImage = (src, extension, dest, params) => {
|
|
196
134
|
return new Promise((resolve, reject) => {
|
|
197
135
|
// output stream
|
|
@@ -282,6 +220,68 @@ const processImage = (src, extension, dest, params) => {
|
|
|
282
220
|
});
|
|
283
221
|
};
|
|
284
222
|
|
|
223
|
+
const tasks = {};
|
|
224
|
+
const processAndRespond = (req, res, cacheDir, getSrc, ext, sendOptions = { maxAge: '356d', immutable: true }) => {
|
|
225
|
+
if (fs.existsSync(cacheDir) === false) {
|
|
226
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const params = req.imageFilter;
|
|
230
|
+
const extension = toLower(ext || path.extname(req.path).slice(1));
|
|
231
|
+
|
|
232
|
+
// NOTE: 不要使用 `req.accepts('image/webp')`,这里需要排除掉 `Accept: */*` 和 `Accept: image/*` 的情况
|
|
233
|
+
const acceptWebp = req.accepts().includes('image/webp');
|
|
234
|
+
if (!acceptWebp) {
|
|
235
|
+
if (params.f === 'webp') {
|
|
236
|
+
params.f = undefined;
|
|
237
|
+
}
|
|
238
|
+
if ((!extension || extension === 'webp') && !params.f) {
|
|
239
|
+
params.f = 'png';
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (!extension && !params.f) {
|
|
243
|
+
params.f = 'png';
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (!extension && !params.f) {
|
|
247
|
+
res.status(400).send('Image filter failed: either extension or format must be specified');
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const cacheKey = md5(stringify({ target: req.target, path: req.originalUrl, params }));
|
|
252
|
+
const destPath = getCacheFilePath(cacheDir, `${cacheKey}.${params.f || extension}`);
|
|
253
|
+
if (fs.existsSync(destPath)) {
|
|
254
|
+
res.header('Content-Type', getImageContentType(params.f || extension));
|
|
255
|
+
res.sendFile(destPath, sendOptions);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// do the convert
|
|
260
|
+
tasks[cacheKey] ??= getSrc(req)
|
|
261
|
+
.then(([src, _extension]) => processImage(src, toLower(_extension), destPath, params))
|
|
262
|
+
.finally(() => {
|
|
263
|
+
setTimeout(() => {
|
|
264
|
+
delete tasks[cacheKey];
|
|
265
|
+
}, 1000);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
tasks[cacheKey]
|
|
269
|
+
.then(() => {
|
|
270
|
+
logger.info('image filter succeed', { params, url: req.originalUrl, destPath });
|
|
271
|
+
res.header('Content-Type', getImageContentType(params.f || extension));
|
|
272
|
+
res.sendFile(destPath, sendOptions);
|
|
273
|
+
})
|
|
274
|
+
.catch((err) => {
|
|
275
|
+
logger.error('image filter failed', { error: err, params, url: req.url });
|
|
276
|
+
if (params.e) {
|
|
277
|
+
res.status(500).send(`Image service error: ${err.message}`);
|
|
278
|
+
} else {
|
|
279
|
+
res.status(500);
|
|
280
|
+
res.sendFile(errorImage, { maxAge: 0 });
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
};
|
|
284
|
+
|
|
285
285
|
module.exports = {
|
|
286
286
|
isImageAccepted,
|
|
287
287
|
isImageRequest,
|
|
@@ -5,8 +5,6 @@ const fetch = require('node-fetch').default;
|
|
|
5
5
|
const U200D = String.fromCharCode(8205); // zero-width joiner
|
|
6
6
|
const UFE0Fg = /\uFE0F/g; // variation selector regex
|
|
7
7
|
|
|
8
|
-
const getIconCode = (char) => toCodePoint(char.indexOf(U200D) < 0 ? char.replace(UFE0Fg, '') : char);
|
|
9
|
-
|
|
10
8
|
const toCodePoint = (unicodeSurrogates) => {
|
|
11
9
|
const r = [];
|
|
12
10
|
let c = 0;
|
|
@@ -26,6 +24,8 @@ const toCodePoint = (unicodeSurrogates) => {
|
|
|
26
24
|
return r.join('-');
|
|
27
25
|
};
|
|
28
26
|
|
|
27
|
+
const getIconCode = (char) => toCodePoint(char.indexOf(U200D) < 0 ? char.replace(UFE0Fg, '') : char);
|
|
28
|
+
|
|
29
29
|
const apis = {
|
|
30
30
|
twemoji: (code) => `https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/svg/${code.toLowerCase()}.svg`,
|
|
31
31
|
openmoji: 'https://cdn.jsdelivr.net/npm/@svgmoji/openmoji@2.0.0/svg/',
|
|
@@ -107,6 +107,7 @@ const getOgImage = ({ input, info, cacheDir, format, tmpDir }) => {
|
|
|
107
107
|
return destPath;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
// eslint-disable-next-line no-use-before-define
|
|
110
111
|
generateTasks[cacheKey] ??= generateOgImage(params, tmpDir).finally(() => {
|
|
111
112
|
setTimeout(() => {
|
|
112
113
|
delete generateTasks[cacheKey];
|
package/api/routes/oauth.js
CHANGED
|
@@ -75,6 +75,7 @@ async function login(req, node, options) {
|
|
|
75
75
|
throw new ApiError(400, t('oauthCantBeOwner', locale));
|
|
76
76
|
}
|
|
77
77
|
const { did: teamDid, wallet: blockletWallet, secret, appUrl } = await req.getBlockletInfo();
|
|
78
|
+
|
|
78
79
|
let userWallet;
|
|
79
80
|
let oauthInfo;
|
|
80
81
|
|
|
@@ -94,6 +95,7 @@ async function login(req, node, options) {
|
|
|
94
95
|
oauthInfo = await authClient.getProfile(token);
|
|
95
96
|
userWallet = fromAppDid(oauthInfo.sub, blockletWallet.secretKey);
|
|
96
97
|
}
|
|
98
|
+
|
|
97
99
|
const userDid = userWallet.address;
|
|
98
100
|
const userPk = userWallet.publicKey;
|
|
99
101
|
|
|
@@ -275,6 +277,8 @@ async function invite(req, node, options) {
|
|
|
275
277
|
let userWallet;
|
|
276
278
|
let oauthInfo;
|
|
277
279
|
|
|
280
|
+
const { did: teamDid, wallet: blockletWallet, secret } = await req.getBlockletInfo();
|
|
281
|
+
|
|
278
282
|
// NOTICE: 如果是统一登录,则向 master 站点发起 oauth 登录请求,auth0 的账户信息必须由 master 来生成
|
|
279
283
|
if (sourceAppPid) {
|
|
280
284
|
const data = await getOAuthUserInfo({
|
|
@@ -292,7 +296,7 @@ async function invite(req, node, options) {
|
|
|
292
296
|
oauthInfo = await authClient.getProfile(token);
|
|
293
297
|
userWallet = fromAppDid(oauthInfo.sub, blockletWallet.secretKey);
|
|
294
298
|
}
|
|
295
|
-
|
|
299
|
+
|
|
296
300
|
const nodeInfo = await req.getNodeInfo();
|
|
297
301
|
let userDid = userWallet.address;
|
|
298
302
|
let userPk = userWallet.publicKey;
|
package/api/routes/user.js
CHANGED
|
@@ -7,9 +7,9 @@ const createTranslator = require('@abtnode/util/lib/translate');
|
|
|
7
7
|
const logger = require('@abtnode/logger')('blocklet-services:user');
|
|
8
8
|
const { isFromPublicKey } = require('@arcblock/did');
|
|
9
9
|
const { LOGIN_PROVIDER } = require('@blocklet/constant');
|
|
10
|
-
const { fromPublicKey } = require('@ocap/wallet');
|
|
11
10
|
const sortBy = require('lodash/sortBy');
|
|
12
11
|
const head = require('lodash/head');
|
|
12
|
+
const { verify } = require('@arcblock/jwt');
|
|
13
13
|
|
|
14
14
|
const { isInvitedUserOnly, createTokenFn, getDidConnectVersion } = require('../util');
|
|
15
15
|
const initJwt = require('../libs/jwt');
|
|
@@ -19,6 +19,7 @@ const { loginWalletSchema, loginOAuthSchema, loginUserWalletSchema } = require('
|
|
|
19
19
|
const verifySig = require('../middlewares/verify-sig');
|
|
20
20
|
const { getAvatarByEmail } = require('../libs/auth/utils');
|
|
21
21
|
const ensureBlocklet = require('../middlewares/ensure-blocklet');
|
|
22
|
+
const { getUserWithinFederated } = require('../util/federated');
|
|
22
23
|
|
|
23
24
|
const validateUser = (user) => {
|
|
24
25
|
try {
|
|
@@ -38,12 +39,14 @@ const translations = {
|
|
|
38
39
|
notAllowed: '你没有权限登录该节点',
|
|
39
40
|
needComponentId: '缺少登录参数: componentId',
|
|
40
41
|
userInfoError: '登录用户信息有误',
|
|
42
|
+
notExist: '用户不存在',
|
|
41
43
|
},
|
|
42
44
|
en: {
|
|
43
45
|
needInviteToLogin: 'You need to be invited to sign in to this app',
|
|
44
46
|
notAllowed: 'You are not allowed to login to this node',
|
|
45
47
|
needComponentId: 'componentId is required when login user',
|
|
46
48
|
userInfoError: 'Login user info is invalid',
|
|
49
|
+
notExist: 'User is not exist',
|
|
47
50
|
},
|
|
48
51
|
};
|
|
49
52
|
|
|
@@ -57,7 +60,13 @@ async function checkNeedInvite({ req, node, teamDid, componentId, locale }) {
|
|
|
57
60
|
}
|
|
58
61
|
}
|
|
59
62
|
|
|
60
|
-
function
|
|
63
|
+
function ensureUserExist(user, { locale }) {
|
|
64
|
+
if (!user) {
|
|
65
|
+
throw new ApiError(404, t('notExist', locale));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function ensureUserEnable(user, { locale }) {
|
|
61
70
|
if (!user.approved) {
|
|
62
71
|
throw new ApiError(403, t('notAllowed', locale));
|
|
63
72
|
}
|
|
@@ -130,7 +139,7 @@ async function loginWallet(
|
|
|
130
139
|
let profile = {};
|
|
131
140
|
if (currentUser) {
|
|
132
141
|
if (updateInfo) {
|
|
133
|
-
|
|
142
|
+
ensureUserEnable(currentUser, { locale });
|
|
134
143
|
profile = await composeProfileData({ avatar, email, fullName }, { node, req, teamDid });
|
|
135
144
|
}
|
|
136
145
|
} else {
|
|
@@ -192,7 +201,7 @@ async function loginOAuth(
|
|
|
192
201
|
let profile = {};
|
|
193
202
|
if (currentUser) {
|
|
194
203
|
if (updateInfo) {
|
|
195
|
-
|
|
204
|
+
ensureUserEnable(currentUser, { locale });
|
|
196
205
|
profile = await composeProfileData({ avatar, email, fullName }, { node, req, teamDid });
|
|
197
206
|
}
|
|
198
207
|
} else {
|
|
@@ -313,21 +322,12 @@ async function login(req, node, options) {
|
|
|
313
322
|
};
|
|
314
323
|
}
|
|
315
324
|
|
|
316
|
-
async function verifyUserSig({ userDid, signature, teamDid,
|
|
317
|
-
const currentUser = await
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
options: {
|
|
323
|
-
enableConnectedAccount: true,
|
|
324
|
-
},
|
|
325
|
-
});
|
|
326
|
-
if (!currentUser) {
|
|
327
|
-
throw new Error('user is not exist');
|
|
328
|
-
}
|
|
329
|
-
const userWallet = fromPublicKey(currentUser.pk);
|
|
330
|
-
const valid = userWallet.verify(data, signature);
|
|
325
|
+
async function verifyUserSig({ userDid, signature, teamDid, sourceAppPid, userPk }, { node, locale, blocklet }) {
|
|
326
|
+
const currentUser = await getUserWithinFederated({ sourceAppPid, teamDid, userDid, userPk }, { node, blocklet });
|
|
327
|
+
ensureUserExist(currentUser, { locale });
|
|
328
|
+
ensureUserEnable(currentUser, { locale });
|
|
329
|
+
|
|
330
|
+
const valid = verify(signature, currentUser.pk);
|
|
331
331
|
if (!valid) {
|
|
332
332
|
throw new Error('invalid signature');
|
|
333
333
|
}
|
|
@@ -357,31 +357,48 @@ module.exports = {
|
|
|
357
357
|
* @summary 暂时不允许用户注册,只允许登录
|
|
358
358
|
*/
|
|
359
359
|
server.post(`${prefixApi}/loginByWallet`, async (req, res) => {
|
|
360
|
-
const {
|
|
360
|
+
const {
|
|
361
|
+
userDid,
|
|
362
|
+
userPk,
|
|
363
|
+
signature,
|
|
364
|
+
walletOS,
|
|
365
|
+
challenge,
|
|
366
|
+
visitorId,
|
|
367
|
+
passportId,
|
|
368
|
+
sourceAppPid = null,
|
|
369
|
+
locale,
|
|
370
|
+
componentId,
|
|
371
|
+
} = req.body;
|
|
361
372
|
const { error } = loginUserWalletSchema.validate({
|
|
362
373
|
userDid,
|
|
374
|
+
userPk,
|
|
363
375
|
signature,
|
|
364
376
|
walletOS,
|
|
365
|
-
|
|
377
|
+
challenge,
|
|
366
378
|
visitorId,
|
|
367
379
|
passportId,
|
|
368
380
|
sourceAppPid,
|
|
369
381
|
locale,
|
|
382
|
+
componentId,
|
|
370
383
|
});
|
|
371
384
|
if (error) {
|
|
372
385
|
throw new ApiError(400, error.message);
|
|
373
386
|
}
|
|
387
|
+
// FIXME: @zhanghan 需要根据 componentId 来判断当前 component 设置的访问权限,来看当前要登录的用户是否有登录的权限
|
|
388
|
+
const blocklet = await req.getBlocklet();
|
|
374
389
|
const { did: teamDid, secret } = await req.getBlockletInfo();
|
|
375
|
-
const currentUser = await verifyUserSig(
|
|
390
|
+
const currentUser = await verifyUserSig(
|
|
391
|
+
{ userDid, signature, teamDid, sourceAppPid, userPk },
|
|
392
|
+
{ node, locale, blocklet }
|
|
393
|
+
);
|
|
376
394
|
const { createSessionToken } = initJwt(node, options);
|
|
377
395
|
const createToken = createTokenFn(createSessionToken);
|
|
378
|
-
const blocklet = await req.getBlocklet();
|
|
379
396
|
const sessionConfig = blocklet.settings?.session || {};
|
|
380
397
|
const passports = currentUser?.passports || [];
|
|
381
398
|
|
|
382
399
|
let passport = null;
|
|
383
400
|
if (passportId) {
|
|
384
|
-
passport = passports.find((x) => x.passportId === passportId);
|
|
401
|
+
passport = passports.find((x) => x.status === 'valid' && x.passportId === passportId);
|
|
385
402
|
}
|
|
386
403
|
if (!passport) {
|
|
387
404
|
const now = new Date().getTime();
|
|
@@ -452,7 +469,7 @@ module.exports = {
|
|
|
452
469
|
res.json({
|
|
453
470
|
sessionToken,
|
|
454
471
|
refreshToken,
|
|
455
|
-
|
|
472
|
+
challenge,
|
|
456
473
|
visitorId: userSession.visitorId,
|
|
457
474
|
});
|
|
458
475
|
});
|
package/api/validators/login.js
CHANGED
|
@@ -20,13 +20,15 @@ const loginOAuthSchema = Joi.object({
|
|
|
20
20
|
|
|
21
21
|
const loginUserWalletSchema = Joi.object({
|
|
22
22
|
userDid: Joi.DID().trim().required(),
|
|
23
|
+
userPk: Joi.string().required(),
|
|
23
24
|
signature: Joi.string().required(),
|
|
24
25
|
walletOS: Joi.string().required(),
|
|
25
|
-
|
|
26
|
+
challenge: Joi.string().required(),
|
|
26
27
|
visitorId: Joi.string().optional(),
|
|
27
28
|
passportId: Joi.string().optional(),
|
|
28
29
|
sourceAppPid: Joi.DID().trim().empty(null),
|
|
29
30
|
locale: Joi.string().optional(),
|
|
31
|
+
componentId: Joi.string().required(),
|
|
30
32
|
}).empty(null);
|
|
31
33
|
|
|
32
34
|
exports.loginWalletSchema = loginWalletSchema;
|