@abtnode/blocklet-services 1.16.11-next-069c3537 → 1.16.11-next-3d2b39f7
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/index.js +8 -1
- package/api/libs/auth/utils.js +1 -40
- package/api/middlewares/check-running.js +23 -5
- package/api/routes/blocklet.js +94 -58
- package/api/routes/user.js +1 -1
- package/api/services/auth/session.js +8 -1
- package/api/services/notification/index.js +7 -3
- package/api/socket/channel/did.js +26 -7
- package/api/socket/util.js +7 -0
- package/api/util/index.js +1 -0
- package/build/asset-manifest.json +19 -19
- package/build/index.html +1 -1
- package/build/static/js/158.ca656ebd.chunk.js +2 -0
- package/build/static/js/{189.70043381.chunk.js → 189.f876739c.chunk.js} +3 -3
- package/build/static/js/343.da2b2075.chunk.js +2 -0
- package/build/static/js/{359.c47779c2.chunk.js → 359.d6450ee2.chunk.js} +2 -2
- package/build/static/js/387.55ad5515.chunk.js +3 -0
- package/build/static/js/{573.b071429e.chunk.js → 573.be050716.chunk.js} +2 -2
- package/build/static/js/{716.0d2a2d32.chunk.js → 716.b48e64d9.chunk.js} +2 -2
- package/build/static/js/737.ef64812c.chunk.js +2 -0
- package/build/static/js/main.748b0f19.js +3 -0
- package/package.json +22 -23
- package/build/static/js/158.4e4fac79.chunk.js +0 -2
- package/build/static/js/343.5944a507.chunk.js +0 -2
- package/build/static/js/387.cbcd76fa.chunk.js +0 -3
- package/build/static/js/737.38028d6a.chunk.js +0 -2
- package/build/static/js/main.badcc6cc.js +0 -3
- /package/build/static/js/{189.70043381.chunk.js.LICENSE.txt → 189.f876739c.chunk.js.LICENSE.txt} +0 -0
- /package/build/static/js/{387.cbcd76fa.chunk.js.LICENSE.txt → 387.55ad5515.chunk.js.LICENSE.txt} +0 -0
- /package/build/static/js/{main.badcc6cc.js.LICENSE.txt → main.748b0f19.js.LICENSE.txt} +0 -0
package/api/index.js
CHANGED
|
@@ -13,7 +13,7 @@ const minimatch = require('minimatch');
|
|
|
13
13
|
|
|
14
14
|
const { getAccessLogStream } = require('@abtnode/logger');
|
|
15
15
|
const { WELLKNOWN_SERVICE_PATH_PREFIX, NODE_SERVICES_PREFIX, EVENTS } = require('@abtnode/constant');
|
|
16
|
-
const { BlockletEvents } = require('@blocklet/constant');
|
|
16
|
+
const { BlockletEvents, BlockletInternalEvents } = require('@blocklet/constant');
|
|
17
17
|
const normalizePathPrefix = require('@abtnode/util/lib/normalize-path-prefix');
|
|
18
18
|
const createInvite = require('@abtnode/auth/lib/invitation');
|
|
19
19
|
const eventHub =
|
|
@@ -145,6 +145,13 @@ module.exports = function createServer(node, serverOptions = {}) {
|
|
|
145
145
|
cache.del(cache.keyFns.node());
|
|
146
146
|
});
|
|
147
147
|
|
|
148
|
+
[BlockletInternalEvents.componentsUpdated, BlockletInternalEvents.appConfigChanged].forEach((name) => {
|
|
149
|
+
eventHub.on(name, (data) => {
|
|
150
|
+
const { appDid } = data;
|
|
151
|
+
notificationService.sendToApp.exec({ event: name, appDid, data });
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
148
155
|
// Http server
|
|
149
156
|
const server = express();
|
|
150
157
|
|
package/api/libs/auth/utils.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
const md5 = require('md5');
|
|
2
|
-
const axios = require('axios');
|
|
3
|
-
const logger = require('@abtnode/auth/lib/logger');
|
|
4
1
|
const { getPassportStatusEndpoint, getApplicationInfo } = require('@abtnode/auth/lib/auth');
|
|
5
2
|
const { createPassportVC } = require('@abtnode/auth/lib/passport');
|
|
6
3
|
const { VC_TYPE_NODE_PASSPORT, PASSPORT_STATUS } = require('@abtnode/constant');
|
|
7
|
-
const { parseUserAvatar } = require('@abtnode/util/lib/user');
|
|
4
|
+
const { parseUserAvatar, getAvatarByEmail, getAvatarByUrl } = require('@abtnode/util/lib/user');
|
|
8
5
|
const { getBlockletAppIdList } = require('@blocklet/meta/lib/util');
|
|
9
6
|
const pick = require('lodash/pick');
|
|
10
7
|
const uniq = require('lodash/uniq');
|
|
@@ -12,41 +9,6 @@ const uniqBy = require('lodash/uniqBy');
|
|
|
12
9
|
|
|
13
10
|
const { sendToUser } = require('../notification');
|
|
14
11
|
|
|
15
|
-
function getEmailHash(email = '') {
|
|
16
|
-
const cleanEmail = email.trim().toLowerCase();
|
|
17
|
-
return md5(cleanEmail);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async function getAvatarByUrl(url, options = {}) {
|
|
21
|
-
const { verbose = true } = options || {};
|
|
22
|
-
try {
|
|
23
|
-
const { data } = await axios.get(url, {
|
|
24
|
-
responseType: 'arraybuffer',
|
|
25
|
-
});
|
|
26
|
-
const base64Content = Buffer.from(data, 'binary').toString('base64');
|
|
27
|
-
|
|
28
|
-
return `data:image/png;base64,${base64Content}`;
|
|
29
|
-
} catch (error) {
|
|
30
|
-
if (verbose) {
|
|
31
|
-
logger.error(`Fetch avatar failed: ${url}`, { error });
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
throw error;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async function getAvatarByEmail(email = '') {
|
|
39
|
-
try {
|
|
40
|
-
const emailHash = getEmailHash(email);
|
|
41
|
-
const gravatarUrl = `https://www.gravatar.com/avatar/${emailHash}`;
|
|
42
|
-
const avatarBase64 = await getAvatarByUrl(gravatarUrl, { verbose: false });
|
|
43
|
-
return avatarBase64;
|
|
44
|
-
} catch (error) {
|
|
45
|
-
logger.error(`Fetch gravatar failed: ${email}`, { error });
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
12
|
// FIXME: @zhanghan 转移通行证目前只能颁发新的,会导致用户数据中产生多余的通行证
|
|
51
13
|
async function transferPassport(fromUser, toUser, { req, teamDid, node, nodeInfo }) {
|
|
52
14
|
if (!fromUser || !toUser) {
|
|
@@ -129,7 +91,6 @@ async function transferPassport(fromUser, toUser, { req, teamDid, node, nodeInfo
|
|
|
129
91
|
}
|
|
130
92
|
|
|
131
93
|
module.exports = {
|
|
132
|
-
getEmailHash,
|
|
133
94
|
getAvatarByUrl,
|
|
134
95
|
getAvatarByEmail,
|
|
135
96
|
transferPassport,
|
|
@@ -1,20 +1,31 @@
|
|
|
1
1
|
const { BlockletStatus } = require('@blocklet/constant');
|
|
2
2
|
const getBlockletMaintenanceTemplate = require('@abtnode/router-templates/lib/blocklet-maintenance');
|
|
3
|
+
const { findComponentByIdV2 } = require('@blocklet/meta/lib/util');
|
|
3
4
|
|
|
4
5
|
const { shouldGotoStartPage, getRedirectUrl } = require('../util');
|
|
5
6
|
|
|
6
7
|
const checkRunning = async (req, res, next) => {
|
|
7
|
-
const
|
|
8
|
+
const app = await req.getBlocklet();
|
|
9
|
+
const componentId = req.getBlockletComponentId();
|
|
10
|
+
let component = findComponentByIdV2(app, componentId);
|
|
11
|
+
|
|
12
|
+
// for backward compatibility
|
|
13
|
+
component = component || app;
|
|
14
|
+
|
|
8
15
|
if (
|
|
9
16
|
![
|
|
10
17
|
BlockletStatus.running,
|
|
11
18
|
// Waiting, Downloading should be allowed because blocklet is currently being upgrading
|
|
12
19
|
BlockletStatus.waiting,
|
|
13
20
|
BlockletStatus.downloading,
|
|
14
|
-
].includes(
|
|
21
|
+
].includes(component.status)
|
|
15
22
|
) {
|
|
16
|
-
if (shouldGotoStartPage(req,
|
|
17
|
-
|
|
23
|
+
if (shouldGotoStartPage(req, component)) {
|
|
24
|
+
// FIXME: @wangshijun how to validate this token or generate token here?
|
|
25
|
+
if (req.query.setupToken) {
|
|
26
|
+
res.cookie('login_token', req.query.setupToken, { maxAge: 24 * 60 * 60 * 1000 });
|
|
27
|
+
}
|
|
28
|
+
if (app.settings.initialized) {
|
|
18
29
|
res.redirect(getRedirectUrl({ req, pagePath: '/start' }));
|
|
19
30
|
} else {
|
|
20
31
|
res.redirect(getRedirectUrl({ req, pagePath: '/setup' }));
|
|
@@ -28,11 +39,18 @@ const checkRunning = async (req, res, next) => {
|
|
|
28
39
|
if (req.accepts(['html', 'json']) === 'json') {
|
|
29
40
|
res.json({ code: 'error', error: 'blocklet is under maintenance' });
|
|
30
41
|
} else {
|
|
31
|
-
res.send(getBlockletMaintenanceTemplate(
|
|
42
|
+
res.send(getBlockletMaintenanceTemplate(app, nodeInfo, component));
|
|
32
43
|
}
|
|
33
44
|
return;
|
|
34
45
|
}
|
|
35
46
|
|
|
47
|
+
const url = new URL(`http://localhost${req.url}`);
|
|
48
|
+
if (url.searchParams.get('__start__')) {
|
|
49
|
+
url.searchParams.delete('__start__');
|
|
50
|
+
res.redirect(`${url.pathname}${url.search}`);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
36
54
|
next();
|
|
37
55
|
};
|
|
38
56
|
|
package/api/routes/blocklet.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const cloneDeep = require('lodash/cloneDeep');
|
|
4
|
-
const joinUrl = require('url-join');
|
|
5
4
|
const dayjs = require('dayjs');
|
|
6
5
|
const JWT = require('@arcblock/jwt');
|
|
6
|
+
const joinUrl = require('url-join');
|
|
7
7
|
const handleInstanceInStore = require('@abtnode/core/lib/util/public-to-store');
|
|
8
|
+
const { getPassportStatusEndpoint } = require('@abtnode/auth/lib/auth');
|
|
9
|
+
const { createPassportVC, createPassport, createUserPassport } = require('@abtnode/auth/lib/passport');
|
|
8
10
|
|
|
9
11
|
const formatContext = require('@abtnode/util/lib/format-context');
|
|
10
12
|
const { parseUserAvatar, getAvatarFile } = require('@abtnode/util/lib/user');
|
|
@@ -19,18 +21,15 @@ const {
|
|
|
19
21
|
cacheError,
|
|
20
22
|
} = require('@abtnode/util/lib/logo-middleware');
|
|
21
23
|
const formatName = require('@abtnode/util/lib/format-name');
|
|
22
|
-
const {
|
|
23
|
-
|
|
24
|
+
const {
|
|
25
|
+
fixBlockletStatus,
|
|
26
|
+
wipeSensitiveData,
|
|
27
|
+
findComponentByIdV2,
|
|
28
|
+
forEachComponentV2Sync,
|
|
29
|
+
} = require('@blocklet/meta/lib/util');
|
|
30
|
+
const { WELLKNOWN_SERVICE_PATH_PREFIX, USER_AVATAR_PATH_PREFIX, ROLES } = require('@abtnode/constant');
|
|
24
31
|
const logger = require('@abtnode/logger')(require('../../package.json').name);
|
|
25
32
|
|
|
26
|
-
const { getPassportStatusEndpoint } = require('@abtnode/auth/lib/auth');
|
|
27
|
-
|
|
28
|
-
const {
|
|
29
|
-
createPassportVC,
|
|
30
|
-
createPassport,
|
|
31
|
-
upsertToPassports,
|
|
32
|
-
createUserPassport,
|
|
33
|
-
} = require('@abtnode/auth/lib/passport');
|
|
34
33
|
const { createDownloadLogStream } = require('@abtnode/util/lib/log');
|
|
35
34
|
|
|
36
35
|
const { BlockletStatus } = require('@blocklet/constant');
|
|
@@ -94,7 +93,7 @@ module.exports = {
|
|
|
94
93
|
onGetBlocklet: async ({ req }) => {
|
|
95
94
|
const blocklet = await req.getBlocklet();
|
|
96
95
|
const dids = req.url.split('?')[0].replace(`${prefix}/blocklet/logo-bundle`, '').split('/').filter(Boolean);
|
|
97
|
-
const component =
|
|
96
|
+
const component = findComponentByIdV2(blocklet, [blocklet.meta.did].concat(dids));
|
|
98
97
|
return component;
|
|
99
98
|
},
|
|
100
99
|
}),
|
|
@@ -137,7 +136,7 @@ module.exports = {
|
|
|
137
136
|
const blocklet = await req.getBlocklet({ useCache: false });
|
|
138
137
|
|
|
139
138
|
const { fromSetup } = req.body;
|
|
140
|
-
const { did: userDid
|
|
139
|
+
const { did: userDid } = req.user;
|
|
141
140
|
|
|
142
141
|
// eslint-disable-next-line no-unreachable
|
|
143
142
|
|
|
@@ -176,8 +175,7 @@ module.exports = {
|
|
|
176
175
|
const user = await node.getUser({ teamDid, user: { did: userDid } });
|
|
177
176
|
user.avatar = await parseUserAvatar(user.avatar, { dataDir: blocklet.env.dataDir });
|
|
178
177
|
|
|
179
|
-
const { pk, locale = 'en'
|
|
180
|
-
const { baseUrl } = extra;
|
|
178
|
+
const { pk, locale = 'en' } = user;
|
|
181
179
|
|
|
182
180
|
await node.setBlockletInitialized({ did: blocklet.meta.did, owner: { did: userDid, pk } });
|
|
183
181
|
|
|
@@ -193,52 +191,57 @@ module.exports = {
|
|
|
193
191
|
}
|
|
194
192
|
}
|
|
195
193
|
|
|
196
|
-
// create vc
|
|
197
|
-
const vc = createPassportVC({
|
|
198
|
-
issuerName: name,
|
|
199
|
-
issuerWallet: wallet,
|
|
200
|
-
ownerDid: userDid,
|
|
201
|
-
passport: await createPassport({
|
|
202
|
-
name: role,
|
|
203
|
-
node,
|
|
204
|
-
teamDid,
|
|
205
|
-
locale,
|
|
206
|
-
endpoint: baseUrl,
|
|
207
|
-
}),
|
|
208
|
-
endpoint: getPassportStatusEndpoint({
|
|
209
|
-
baseUrl: joinUrl(baseUrl, WELLKNOWN_SERVICE_PATH_PREFIX),
|
|
210
|
-
userDid,
|
|
211
|
-
teamDid,
|
|
212
|
-
}),
|
|
213
|
-
ownerProfile: user,
|
|
214
|
-
preferredColor: passportColor,
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
// write passport to db
|
|
218
|
-
const passport = createUserPassport(vc, { role });
|
|
219
|
-
const result = await node.updateUser({
|
|
220
|
-
teamDid,
|
|
221
|
-
user: {
|
|
222
|
-
did: userDid,
|
|
223
|
-
pk,
|
|
224
|
-
passports: upsertToPassports(user.passports || [], passport),
|
|
225
|
-
},
|
|
226
|
-
});
|
|
227
|
-
await node.createAuditLog(
|
|
228
|
-
{
|
|
229
|
-
action: 'updateUser',
|
|
230
|
-
args: { teamDid, passport, reason: 'setup blocklet' },
|
|
231
|
-
context: formatContext(req),
|
|
232
|
-
result,
|
|
233
|
-
},
|
|
234
|
-
node
|
|
235
|
-
);
|
|
236
|
-
|
|
237
194
|
// send notification to wallet
|
|
238
195
|
const receiver = userDid;
|
|
239
196
|
const token = JWT.sign(wallet.address, wallet.secretKey);
|
|
240
197
|
|
|
241
|
-
if
|
|
198
|
+
// send passport to wallet if no passport for this user
|
|
199
|
+
const role = ROLES.OWNER;
|
|
200
|
+
const hasOwnerPassport = (user.passports || []).some((x) => x.name === role);
|
|
201
|
+
if (hasOwnerPassport === false) {
|
|
202
|
+
const appUrl = blocklet.environments.find((item) => item.key === 'BLOCKLET_APP_URL').value;
|
|
203
|
+
|
|
204
|
+
// create vc
|
|
205
|
+
const vc = createPassportVC({
|
|
206
|
+
issuerName: name,
|
|
207
|
+
issuerWallet: wallet,
|
|
208
|
+
ownerDid: userDid,
|
|
209
|
+
passport: await createPassport({
|
|
210
|
+
name: role,
|
|
211
|
+
node,
|
|
212
|
+
teamDid,
|
|
213
|
+
locale,
|
|
214
|
+
endpoint: appUrl,
|
|
215
|
+
}),
|
|
216
|
+
endpoint: getPassportStatusEndpoint({
|
|
217
|
+
baseUrl: joinUrl(appUrl, WELLKNOWN_SERVICE_PATH_PREFIX),
|
|
218
|
+
userDid,
|
|
219
|
+
teamDid,
|
|
220
|
+
}),
|
|
221
|
+
ownerProfile: user,
|
|
222
|
+
preferredColor: passportColor,
|
|
223
|
+
expirationDate: undefined,
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
// write passport to db
|
|
227
|
+
const passport = createUserPassport(vc, { role });
|
|
228
|
+
const result = await node.updateUser({
|
|
229
|
+
teamDid,
|
|
230
|
+
user: {
|
|
231
|
+
did: userDid,
|
|
232
|
+
passports: [passport],
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
await node.createAuditLog(
|
|
236
|
+
{
|
|
237
|
+
action: 'updateUser',
|
|
238
|
+
args: { teamDid, passport, reason: 'setup blocklet' },
|
|
239
|
+
context: formatContext(req),
|
|
240
|
+
result,
|
|
241
|
+
},
|
|
242
|
+
node
|
|
243
|
+
);
|
|
244
|
+
|
|
242
245
|
// send owner vc
|
|
243
246
|
const notificationText = {
|
|
244
247
|
title: {
|
|
@@ -261,7 +264,7 @@ module.exports = {
|
|
|
261
264
|
type: 'vc',
|
|
262
265
|
data: {
|
|
263
266
|
credential: vc,
|
|
264
|
-
tag:
|
|
267
|
+
tag: ROLES.OWNER,
|
|
265
268
|
},
|
|
266
269
|
},
|
|
267
270
|
],
|
|
@@ -320,10 +323,43 @@ module.exports = {
|
|
|
320
323
|
server.get(`${prefix}/health`, async (req, res) => {
|
|
321
324
|
const blocklet = await req.getBlocklet();
|
|
322
325
|
|
|
326
|
+
if (!blocklet) {
|
|
327
|
+
return res.status(404).json({ message: 'blocklet not found' });
|
|
328
|
+
}
|
|
329
|
+
|
|
323
330
|
if (blocklet.status !== BlockletStatus.running) {
|
|
324
331
|
return res.status(503).json({ message: 'not running' });
|
|
325
332
|
}
|
|
326
333
|
|
|
334
|
+
const components = {};
|
|
335
|
+
forEachComponentV2Sync(blocklet, (component) => {
|
|
336
|
+
components[component.meta.did] = {
|
|
337
|
+
running: component.status === BlockletStatus.running,
|
|
338
|
+
};
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
return res.json({ message: 'ok', components });
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
server.get(`${prefix}/health/:componentId`, async (req, res) => {
|
|
345
|
+
const { componentId } = req.params;
|
|
346
|
+
|
|
347
|
+
const blocklet = await req.getBlocklet();
|
|
348
|
+
|
|
349
|
+
if (!blocklet) {
|
|
350
|
+
return res.status(404).json({ message: 'blocklet not found' });
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const component = findComponentByIdV2(blocklet, componentId);
|
|
354
|
+
|
|
355
|
+
if (!component) {
|
|
356
|
+
return res.status(404).json({ message: 'component not found' });
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (component.status !== BlockletStatus.running) {
|
|
360
|
+
return res.status(503).json({ message: 'not running' });
|
|
361
|
+
}
|
|
362
|
+
|
|
327
363
|
return res.json({ message: 'ok' });
|
|
328
364
|
});
|
|
329
365
|
|
package/api/routes/user.js
CHANGED
|
@@ -62,7 +62,7 @@ async function composeProfileData({ avatar, fullName, email }, { node, req, team
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
if (avatar) {
|
|
65
|
-
avatarLocal = await getAvatarByUrl(avatar);
|
|
65
|
+
avatarLocal = avatar.startsWith('data:') ? avatar : await getAvatarByUrl(avatar);
|
|
66
66
|
}
|
|
67
67
|
if (avatarLocal) {
|
|
68
68
|
const nodeInfo = await req.getNodeInfo();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const nocache = require('nocache');
|
|
2
|
+
const joinUrl = require('url-join');
|
|
2
3
|
const SealedBox = require('tweetnacl-sealedbox-js');
|
|
3
4
|
const { decodeEncryptionKey } = require('@abtnode/util/lib/security');
|
|
4
5
|
const { WELLKNOWN_SERVICE_PATH_PREFIX, USER_AVATAR_URL_PREFIX, USER_AVATAR_PATH_PREFIX } = require('@abtnode/constant');
|
|
@@ -17,9 +18,9 @@ module.exports = {
|
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
const teamDid = req.getBlockletDid();
|
|
21
|
+
// FIXME: this code have performance issue
|
|
20
22
|
const user = await node.getUser({ teamDid, user: { did: req.user.did } });
|
|
21
23
|
if (req.user.role) {
|
|
22
|
-
// FIXME: this code may have performance issue
|
|
23
24
|
const rbac = await node.getRBAC(teamDid);
|
|
24
25
|
user.permissions = await rbac.getScope(req.user.role);
|
|
25
26
|
user.role = req.user.role;
|
|
@@ -29,6 +30,12 @@ module.exports = {
|
|
|
29
30
|
user.avatar = `${WELLKNOWN_SERVICE_PATH_PREFIX}${USER_AVATAR_PATH_PREFIX}/${
|
|
30
31
|
user.avatar.split('/').slice(-1)[0]
|
|
31
32
|
}`;
|
|
33
|
+
|
|
34
|
+
if (req.headers['x-avatar-host'] === '1') {
|
|
35
|
+
const blocklet = await req.getBlocklet();
|
|
36
|
+
const appUrl = blocklet.environmentObj.BLOCKLET_APP_URL;
|
|
37
|
+
user.avatar = joinUrl(appUrl, user.avatar);
|
|
38
|
+
}
|
|
32
39
|
}
|
|
33
40
|
|
|
34
41
|
const encKey = '_ek_';
|
|
@@ -10,7 +10,7 @@ const states = require('../../state');
|
|
|
10
10
|
const { PREFIXES } = require('../../util/constants');
|
|
11
11
|
|
|
12
12
|
const { sendToAppChannel } = require('../../socket/channel/app');
|
|
13
|
-
const {
|
|
13
|
+
const { sendToUserDid, sendToAppDid } = require('../../socket/channel/did');
|
|
14
14
|
const getHooksByChannel = require('../../socket/channel/hooks');
|
|
15
15
|
const { getTokenInfo } = require('../../socket/util');
|
|
16
16
|
|
|
@@ -113,7 +113,7 @@ const init = ({ node }) => {
|
|
|
113
113
|
|
|
114
114
|
const onSendToUser = async (req, res) => {
|
|
115
115
|
try {
|
|
116
|
-
await
|
|
116
|
+
await sendToUserDid({ ...req.body.data, node, wsServer });
|
|
117
117
|
res.status(200).send('');
|
|
118
118
|
} catch (error) {
|
|
119
119
|
logger.error('Send message to user channel failed', { error });
|
|
@@ -144,7 +144,11 @@ const init = ({ node }) => {
|
|
|
144
144
|
app.post(`${prefix}/api/sendToUser`, onSendToUser);
|
|
145
145
|
});
|
|
146
146
|
},
|
|
147
|
-
exec: (data) =>
|
|
147
|
+
exec: (data) => sendToUserDid({ ...data, node, wsServer }),
|
|
148
|
+
},
|
|
149
|
+
|
|
150
|
+
sendToApp: {
|
|
151
|
+
exec: ({ event, appDid, data }) => sendToAppDid({ event, appDid, data, node, wsServer }),
|
|
148
152
|
},
|
|
149
153
|
|
|
150
154
|
sendToAppChannel: {
|
|
@@ -6,16 +6,17 @@ const {
|
|
|
6
6
|
} = require('@blocklet/sdk/lib/validators/notification');
|
|
7
7
|
const { NODE_MODES } = require('@abtnode/constant');
|
|
8
8
|
const { getWalletDid } = require('@blocklet/sdk/lib/did');
|
|
9
|
+
const JWT = require('@arcblock/jwt');
|
|
9
10
|
const pMap = require('p-map');
|
|
10
11
|
|
|
11
12
|
// eslint-disable-next-line global-require
|
|
12
13
|
const logger = require('@abtnode/logger')(`${require('../../../package.json').name}:notification`);
|
|
13
|
-
const { ensureSenderApp, parseNotification, broadcast, EVENTS } = require('../util');
|
|
14
|
+
const { ensureSenderApp, getSenderServer, parseNotification, broadcast, EVENTS } = require('../util');
|
|
14
15
|
const states = require('../../state');
|
|
15
16
|
const { validateEmail, sendEmail } = require('../../libs/email');
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
|
-
*
|
|
19
|
+
* app send notification to user
|
|
19
20
|
* @param {{
|
|
20
21
|
* {{
|
|
21
22
|
* did: String
|
|
@@ -29,7 +30,7 @@ const { validateEmail, sendEmail } = require('../../libs/email');
|
|
|
29
30
|
* }}
|
|
30
31
|
* @returns
|
|
31
32
|
*/
|
|
32
|
-
const
|
|
33
|
+
const sendToUserDid = async ({ sender, receiver: rawDid, notification, options, node, wsServer }) => {
|
|
33
34
|
const { keepForOfflineUser = true } = options || {};
|
|
34
35
|
const receiver = Array.isArray(rawDid) ? rawDid : [rawDid];
|
|
35
36
|
|
|
@@ -72,7 +73,7 @@ const sendToDid = async ({ sender, receiver: rawDid, notification, options, node
|
|
|
72
73
|
throw new Error('Invalid receiver');
|
|
73
74
|
}
|
|
74
75
|
|
|
75
|
-
const nodeInfo = await node.getNodeInfo();
|
|
76
|
+
const nodeInfo = await node.getNodeInfo({ useCache: true });
|
|
76
77
|
|
|
77
78
|
if (nodeInfo.mode !== NODE_MODES.DEBUG) {
|
|
78
79
|
await validateNotification(notification);
|
|
@@ -107,6 +108,24 @@ const sendToDid = async ({ sender, receiver: rawDid, notification, options, node
|
|
|
107
108
|
});
|
|
108
109
|
};
|
|
109
110
|
|
|
111
|
+
// server send notification to app
|
|
112
|
+
const sendToAppDid = async ({ event, appDid, data, node, wsServer }) => {
|
|
113
|
+
const senderInfo = await getSenderServer({ node });
|
|
114
|
+
|
|
115
|
+
const notification = {
|
|
116
|
+
data,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
notification.sender = {
|
|
120
|
+
did: senderInfo.wallet.address,
|
|
121
|
+
pk: senderInfo.wallet.publicKey,
|
|
122
|
+
token: JWT.sign(senderInfo.wallet.address, senderInfo.wallet.secretKey),
|
|
123
|
+
name: senderInfo.name,
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
wsServer.broadcast(appDid, event, notification, { noCluster: true });
|
|
127
|
+
};
|
|
128
|
+
|
|
110
129
|
const sendCachedMessages = async (wsServer, did) => {
|
|
111
130
|
try {
|
|
112
131
|
const messages = await states.message.find({ did });
|
|
@@ -145,9 +164,9 @@ const onMessage = async ({ channel: from, event = EVENTS.MESSAGE, payload: messa
|
|
|
145
164
|
// validate receiver
|
|
146
165
|
const { receiver, ...data } = message;
|
|
147
166
|
|
|
148
|
-
const blocklet = await node.getBlocklet({ did: receiver.did, attachConfig: false });
|
|
167
|
+
const blocklet = await node.getBlocklet({ did: receiver.did, attachConfig: false, useCache: true });
|
|
149
168
|
if (!blocklet) {
|
|
150
|
-
const nodeInfo = await node.getNodeInfo();
|
|
169
|
+
const nodeInfo = await node.getNodeInfo({ useCache: true });
|
|
151
170
|
|
|
152
171
|
// only throw error if receiver is a blocklet (not server)
|
|
153
172
|
if (nodeInfo.did !== receiver.did) {
|
|
@@ -187,4 +206,4 @@ const onAuthenticate = async ({ channel, did, payload }) => {
|
|
|
187
206
|
}
|
|
188
207
|
};
|
|
189
208
|
|
|
190
|
-
module.exports = { onAuthenticate, onJoin, onMessage,
|
|
209
|
+
module.exports = { onAuthenticate, onJoin, onMessage, sendToUserDid, sendToAppDid };
|
package/api/socket/util.js
CHANGED
|
@@ -66,6 +66,12 @@ const ensureSenderApp = async ({ sender, node, nodeInfo }) => {
|
|
|
66
66
|
return appInfo;
|
|
67
67
|
};
|
|
68
68
|
|
|
69
|
+
const getSenderServer = async ({ node }) => {
|
|
70
|
+
const nodeInfo = await node.getNodeInfo({ useCache: true });
|
|
71
|
+
const senderInfo = await getApplicationInfo({ node, nodeInfo, teamDid: nodeInfo.did });
|
|
72
|
+
return senderInfo;
|
|
73
|
+
};
|
|
74
|
+
|
|
69
75
|
const getTokenInfo = (decoded) => ({
|
|
70
76
|
did: decoded.iss.replace(/^did:abt:/, ''),
|
|
71
77
|
});
|
|
@@ -78,6 +84,7 @@ module.exports = {
|
|
|
78
84
|
parseNotification,
|
|
79
85
|
broadcast,
|
|
80
86
|
ensureSenderApp,
|
|
87
|
+
getSenderServer,
|
|
81
88
|
getTokenInfo,
|
|
82
89
|
EVENTS,
|
|
83
90
|
};
|
package/api/util/index.js
CHANGED
|
@@ -133,6 +133,7 @@ const getRedirectUrl = ({ req, pagePath }) => {
|
|
|
133
133
|
redirectUrlObj.searchParams.delete('__start__');
|
|
134
134
|
redirectUrlObj.searchParams.delete('serverUrl');
|
|
135
135
|
redirectUrlObj.searchParams.delete('fromLauncher');
|
|
136
|
+
redirectUrlObj.searchParams.delete('setupToken');
|
|
136
137
|
redirectUrlObj.searchParams.delete('launchType');
|
|
137
138
|
redirectUrlObj.searchParams.delete('nftId');
|
|
138
139
|
redirectUrlObj.searchParams.delete('chainHost');
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": {
|
|
3
3
|
"main.css": "/.blocklet/proxy/blocklet-service/static/css/main.632501d5.css",
|
|
4
|
-
"main.js": "/.blocklet/proxy/blocklet-service/static/js/main.
|
|
5
|
-
"static/js/716.
|
|
6
|
-
"static/js/359.
|
|
4
|
+
"main.js": "/.blocklet/proxy/blocklet-service/static/js/main.748b0f19.js",
|
|
5
|
+
"static/js/716.b48e64d9.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/716.b48e64d9.chunk.js",
|
|
6
|
+
"static/js/359.d6450ee2.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/359.d6450ee2.chunk.js",
|
|
7
7
|
"static/js/255.279b1bca.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/255.279b1bca.chunk.js",
|
|
8
8
|
"static/js/371.f67a06b4.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/371.f67a06b4.chunk.js",
|
|
9
|
-
"static/js/737.
|
|
10
|
-
"static/js/158.
|
|
9
|
+
"static/js/737.ef64812c.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/737.ef64812c.chunk.js",
|
|
10
|
+
"static/js/158.ca656ebd.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/158.ca656ebd.chunk.js",
|
|
11
11
|
"static/js/868.ac8df3a0.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/868.ac8df3a0.chunk.js",
|
|
12
12
|
"static/js/547.03d5d719.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/547.03d5d719.chunk.js",
|
|
13
|
-
"static/js/343.
|
|
13
|
+
"static/js/343.da2b2075.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/343.da2b2075.chunk.js",
|
|
14
14
|
"static/js/682.a8bf723a.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/682.a8bf723a.chunk.js",
|
|
15
15
|
"static/js/711.56427a24.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/711.56427a24.chunk.js",
|
|
16
16
|
"static/js/437.075e8453.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/437.075e8453.chunk.js",
|
|
17
17
|
"static/js/690.afb99ee7.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/690.afb99ee7.chunk.js",
|
|
18
18
|
"static/js/42.c390a3f4.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/42.c390a3f4.chunk.js",
|
|
19
|
-
"static/js/189.
|
|
19
|
+
"static/js/189.f876739c.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/189.f876739c.chunk.js",
|
|
20
20
|
"static/js/162.8c29e450.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/162.8c29e450.chunk.js",
|
|
21
21
|
"static/js/610.40349d57.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/610.40349d57.chunk.js",
|
|
22
22
|
"static/css/387.bcbdad69.chunk.css": "/.blocklet/proxy/blocklet-service/static/css/387.bcbdad69.chunk.css",
|
|
23
|
-
"static/js/387.
|
|
23
|
+
"static/js/387.55ad5515.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/387.55ad5515.chunk.js",
|
|
24
24
|
"static/js/199.3d76c24b.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/199.3d76c24b.chunk.js",
|
|
25
|
-
"static/js/573.
|
|
25
|
+
"static/js/573.be050716.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/573.be050716.chunk.js",
|
|
26
26
|
"static/media/ubuntu-mono-all-400-normal.woff": "/.blocklet/proxy/blocklet-service/static/media/ubuntu-mono-all-400-normal.c879328bc62e9c68268f.woff",
|
|
27
27
|
"static/media/lato-all-400-normal.woff": "/.blocklet/proxy/blocklet-service/static/media/lato-all-400-normal.3dc1eff492ab1f598560.woff",
|
|
28
28
|
"static/media/iconify.cjs": "/.blocklet/proxy/blocklet-service/static/media/iconify.212917dd32288c600255.cjs",
|
|
@@ -45,31 +45,31 @@
|
|
|
45
45
|
"router-template-styles/styles.css": "/.blocklet/proxy/blocklet-service/router-template-styles/styles.css",
|
|
46
46
|
"index.html": "/.blocklet/proxy/blocklet-service/index.html",
|
|
47
47
|
"main.632501d5.css.map": "/.blocklet/proxy/blocklet-service/static/css/main.632501d5.css.map",
|
|
48
|
-
"main.
|
|
49
|
-
"716.
|
|
50
|
-
"359.
|
|
48
|
+
"main.748b0f19.js.map": "/.blocklet/proxy/blocklet-service/static/js/main.748b0f19.js.map",
|
|
49
|
+
"716.b48e64d9.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/716.b48e64d9.chunk.js.map",
|
|
50
|
+
"359.d6450ee2.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/359.d6450ee2.chunk.js.map",
|
|
51
51
|
"255.279b1bca.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/255.279b1bca.chunk.js.map",
|
|
52
52
|
"371.f67a06b4.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/371.f67a06b4.chunk.js.map",
|
|
53
|
-
"737.
|
|
54
|
-
"158.
|
|
53
|
+
"737.ef64812c.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/737.ef64812c.chunk.js.map",
|
|
54
|
+
"158.ca656ebd.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/158.ca656ebd.chunk.js.map",
|
|
55
55
|
"868.ac8df3a0.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/868.ac8df3a0.chunk.js.map",
|
|
56
56
|
"547.03d5d719.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/547.03d5d719.chunk.js.map",
|
|
57
|
-
"343.
|
|
57
|
+
"343.da2b2075.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/343.da2b2075.chunk.js.map",
|
|
58
58
|
"682.a8bf723a.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/682.a8bf723a.chunk.js.map",
|
|
59
59
|
"711.56427a24.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/711.56427a24.chunk.js.map",
|
|
60
60
|
"437.075e8453.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/437.075e8453.chunk.js.map",
|
|
61
61
|
"690.afb99ee7.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/690.afb99ee7.chunk.js.map",
|
|
62
62
|
"42.c390a3f4.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/42.c390a3f4.chunk.js.map",
|
|
63
|
-
"189.
|
|
63
|
+
"189.f876739c.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/189.f876739c.chunk.js.map",
|
|
64
64
|
"162.8c29e450.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/162.8c29e450.chunk.js.map",
|
|
65
65
|
"610.40349d57.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/610.40349d57.chunk.js.map",
|
|
66
66
|
"387.bcbdad69.chunk.css.map": "/.blocklet/proxy/blocklet-service/static/css/387.bcbdad69.chunk.css.map",
|
|
67
|
-
"387.
|
|
67
|
+
"387.55ad5515.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/387.55ad5515.chunk.js.map",
|
|
68
68
|
"199.3d76c24b.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/199.3d76c24b.chunk.js.map",
|
|
69
|
-
"573.
|
|
69
|
+
"573.be050716.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/573.be050716.chunk.js.map"
|
|
70
70
|
},
|
|
71
71
|
"entrypoints": [
|
|
72
72
|
"static/css/main.632501d5.css",
|
|
73
|
-
"static/js/main.
|
|
73
|
+
"static/js/main.748b0f19.js"
|
|
74
74
|
]
|
|
75
75
|
}
|
package/build/index.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0"/><meta name="theme-color" content="#000000"/><title>Blocklet Service</title><script src=".well-known/service/api/env"></script><script src="/__blocklet__.js"></script><script defer="defer" src="/.blocklet/proxy/blocklet-service/static/js/main.
|
|
1
|
+
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0"/><meta name="theme-color" content="#000000"/><title>Blocklet Service</title><script src=".well-known/service/api/env"></script><script src="/__blocklet__.js"></script><script defer="defer" src="/.blocklet/proxy/blocklet-service/static/js/main.748b0f19.js"></script><link href="/.blocklet/proxy/blocklet-service/static/css/main.632501d5.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|