@abtnode/blocklet-services 1.6.26 → 1.6.29

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.
Files changed (81) hide show
  1. package/README.md +1 -5
  2. package/{lib → api}/cache.js +0 -0
  3. package/api/index.js +296 -0
  4. package/{services/auth → api}/libs/auth.js +24 -8
  5. package/api/libs/env.js +7 -0
  6. package/{services/auth → api}/libs/jwt.js +1 -0
  7. package/api/middlewares/check-admin-permission.js +15 -0
  8. package/api/middlewares/check-running.js +46 -0
  9. package/api/routes/blocklet.js +98 -0
  10. package/api/routes/env.js +27 -0
  11. package/{services/auth/routes → api/services/auth/connect}/invite.js +5 -4
  12. package/{services/auth/routes → api/services/auth/connect}/issue-passport.js +6 -2
  13. package/{services/auth/routes → api/services/auth/connect}/login.js +18 -10
  14. package/api/services/auth/connect/lost-passport-issue.js +10 -0
  15. package/{services/auth/routes → api/services/auth/connect}/lost-passport-list.js +1 -1
  16. package/api/services/auth/index.js +189 -0
  17. package/api/services/auth/passport.js +22 -0
  18. package/api/services/auth/session.js +31 -0
  19. package/{services/auth/routes/notification.js → api/services/notification/index.js} +25 -9
  20. package/api/services/static.js +76 -0
  21. package/{services/auth → api}/state/index.js +0 -0
  22. package/{services/auth → api}/state/message.js +0 -0
  23. package/api/util/attach-shared-utils.js +149 -0
  24. package/api/util/constants.js +10 -0
  25. package/api/util/format-context.js +24 -0
  26. package/{services/auth → api}/util/index.js +31 -1
  27. package/build/asset-manifest.json +32 -30
  28. package/build/index.html +1 -1
  29. package/build/precache-manifest.f8d516b676d205d1f6e2c4e869fbf297.js +154 -0
  30. package/build/service-worker.js +2 -2
  31. package/build/static/css/2.d49e994f.chunk.css +2 -0
  32. package/build/static/css/{2.cc9dc85c.chunk.css.map → 2.d49e994f.chunk.css.map} +1 -1
  33. package/build/static/js/2.ca22e0d7.chunk.js +3 -0
  34. package/build/static/js/{2.90523f87.chunk.js.LICENSE.txt → 2.ca22e0d7.chunk.js.LICENSE.txt} +0 -0
  35. package/build/static/js/2.ca22e0d7.chunk.js.map +1 -0
  36. package/build/static/js/3.38949d38.chunk.js +3 -0
  37. package/build/static/js/{3.e6540184.chunk.js.LICENSE.txt → 3.38949d38.chunk.js.LICENSE.txt} +0 -0
  38. package/build/static/js/3.38949d38.chunk.js.map +1 -0
  39. package/build/static/js/4.97f8d423.chunk.js +2 -0
  40. package/build/static/js/4.97f8d423.chunk.js.map +1 -0
  41. package/build/static/js/5.8149df59.chunk.js +2 -0
  42. package/build/static/js/5.8149df59.chunk.js.map +1 -0
  43. package/build/static/js/6.001b8434.chunk.js +2 -0
  44. package/build/static/js/6.001b8434.chunk.js.map +1 -0
  45. package/build/static/js/7.f30a5254.chunk.js +2 -0
  46. package/build/static/js/7.f30a5254.chunk.js.map +1 -0
  47. package/build/static/js/8.e354cbf1.chunk.js +2 -0
  48. package/build/static/js/8.e354cbf1.chunk.js.map +1 -0
  49. package/build/static/js/main.561b39e2.chunk.js +2 -0
  50. package/build/static/js/main.561b39e2.chunk.js.map +1 -0
  51. package/build/static/js/runtime-main.8ddd5828.js +2 -0
  52. package/build/static/js/runtime-main.8ddd5828.js.map +1 -0
  53. package/{services/auth/meta.json → configs/auth.json} +2 -2
  54. package/package.json +27 -24
  55. package/build/precache-manifest.f3419eb785f255da7655fa425fc775a1.js +0 -150
  56. package/build/static/css/2.cc9dc85c.chunk.css +0 -2
  57. package/build/static/js/2.90523f87.chunk.js +0 -3
  58. package/build/static/js/2.90523f87.chunk.js.map +0 -1
  59. package/build/static/js/3.e6540184.chunk.js +0 -3
  60. package/build/static/js/3.e6540184.chunk.js.map +0 -1
  61. package/build/static/js/4.4410aa8a.chunk.js +0 -2
  62. package/build/static/js/4.4410aa8a.chunk.js.map +0 -1
  63. package/build/static/js/5.967448ae.chunk.js +0 -2
  64. package/build/static/js/5.967448ae.chunk.js.map +0 -1
  65. package/build/static/js/6.1de827ed.chunk.js +0 -2
  66. package/build/static/js/6.1de827ed.chunk.js.map +0 -1
  67. package/build/static/js/7.cb386b54.chunk.js +0 -2
  68. package/build/static/js/7.cb386b54.chunk.js.map +0 -1
  69. package/build/static/js/main.c51a8d5b.chunk.js +0 -2
  70. package/build/static/js/main.c51a8d5b.chunk.js.map +0 -1
  71. package/build/static/js/runtime-main.24dfe4a3.js +0 -2
  72. package/build/static/js/runtime-main.24dfe4a3.js.map +0 -1
  73. package/lib/index.js +0 -443
  74. package/lib/mount.js +0 -52
  75. package/lib/util.js +0 -17
  76. package/services/auth/index.js +0 -290
  77. package/services/auth/routes/blocklet-info.js +0 -33
  78. package/services/auth/routes/env.js +0 -33
  79. package/services/auth/routes/lost-passport-issue.js +0 -5
  80. package/services/auth/routes/passport.js +0 -18
  81. package/services/auth/routes/session.js +0 -27
@@ -1,290 +0,0 @@
1
- /* eslint-disable arrow-parens */
2
- const path = require('path');
3
- const get = require('lodash/get');
4
- const minimatch = require('minimatch');
5
- const bearerToken = require('express-bearer-token');
6
- const validators = require('@blocklet/sdk/lib/validators');
7
- const {
8
- genPermissionName,
9
- NODE_SERVICES,
10
- NODE_SERVICES_PREFIX,
11
- WELLKNOWN_AUTH_PATH_PREFIX,
12
- } = require('@abtnode/constant');
13
- const { BLOCKLET_MODES, BlockletStatus } = require('@blocklet/meta/lib/constants');
14
-
15
- const getBlockletNotRunningTemplate = require('@abtnode/router-templates/lib/blocklet-not-running');
16
- const getBlockletMaintenanceTemplate = require('@abtnode/router-templates/lib/blocklet-maintenance');
17
- const { getBaseUrl } = require('@abtnode/router-adapter');
18
- const { setUserInfoHeaders } = require('@abtnode/auth/lib/auth');
19
- const logger = require('@abtnode/logger')(require('./meta.json').name);
20
-
21
- const { name, description, version } = require('./meta.json');
22
-
23
- const initJwt = require('./libs/jwt');
24
- const initAuth = require('./libs/auth');
25
- const createLoginRoutes = require('./routes/login');
26
- const createInviteRoutes = require('./routes/invite');
27
- const createIssuePassportAuth = require('./routes/issue-passport');
28
- const createLostPassportListAuth = require('./routes/lost-passport-list');
29
- const createLostPassportIssueAuth = require('./routes/lost-passport-issue');
30
- const createSessionRoutes = require('./routes/session');
31
- const createEnvRoutes = require('./routes/env');
32
- const createBlockletRoutes = require('./routes/blocklet-info');
33
- const createPassportRoutes = require('./routes/passport');
34
- const { init: initNotification } = require('./routes/notification');
35
- const { init: initStates } = require('./state/index');
36
-
37
- const defaultOptions = {
38
- dataDir: '',
39
- sessionSecret: 'your_should_change_this',
40
- sessionTtl: '7d',
41
- webWalletUrl: 'https://web.abtwallet.io',
42
- loginTokenKey: 'login_token',
43
- };
44
-
45
- const init = ({ node, httpRouter, serviceHttpRouter, wsRouter, options }) => {
46
- if (!options.dataDir) {
47
- throw new Error('Auth service requires dataDir to start');
48
- }
49
- if (!options.sessionSecret) {
50
- throw new Error('Auth service requires sessionSecret to start');
51
- }
52
-
53
- const isProduction = process.env.NODE_ENV === 'production' || process.env.ABT_NODE_SERVICE_ENV === 'production';
54
- const isE2E = process.env.NODE_ENV === 'e2e';
55
- const distDir = path.resolve(__dirname, '../../build');
56
-
57
- logger.info('init params', { isProduction, distDir });
58
-
59
- const opts = { ...defaultOptions, ...options, name, description, version, prefix: NODE_SERVICES_PREFIX.AUTH_SERVICE };
60
- if (opts.sessionSecret === defaultOptions.sessionSecret) {
61
- logger.warn('session secret should be set to make things secure');
62
- }
63
-
64
- /**
65
- * set user info to req.user
66
- */
67
- const ensureUser = async ({ req, token } = {}) => {
68
- try {
69
- if (token) {
70
- const teamDid = req.getBlockletDid();
71
- const result = await verify(token, teamDid);
72
- req.user = result;
73
- }
74
- } catch {
75
- // Do nothing
76
- }
77
- };
78
-
79
- /**
80
- * @returns {object} res
81
- * {boolean} res.blocked
82
- * {boolean} res.authenticated
83
- * {boolean} res.authorized
84
- */
85
- const checkAuth = async ({ req } = {}) => {
86
- if (!isProduction && !isE2E) {
87
- return {};
88
- }
89
-
90
- const config = (await req.getServiceConfig(NODE_SERVICES.AUTH_SERVICE)) || {};
91
-
92
- const ignoreUrls = (get(config, 'ignoreUrls') || []).filter(Boolean);
93
-
94
- const shouldIgnore = ignoreUrls.some((s) => minimatch(req.url, s)) || req.url.startsWith(`${opts.prefix}/api`);
95
- if (shouldIgnore) {
96
- return {};
97
- }
98
-
99
- if (config.blockUnauthenticated === false) {
100
- return {};
101
- }
102
-
103
- if (!req.user) {
104
- return { blocked: true, authenticated: false };
105
- }
106
-
107
- if (!config.blockUnauthorized) {
108
- return {};
109
- }
110
-
111
- const rule = await req.getRoutingRule();
112
- if (rule.to && rule.to.interfaceName) {
113
- const permissionName = genPermissionName(rule.to.interfaceName);
114
- const teamDid = req.getBlockletDid();
115
- const rbac = await node.getRBAC(teamDid);
116
-
117
- if (await rbac.can(req.user.role, ...permissionName.split('_'))) {
118
- return {};
119
- }
120
-
121
- return { blocked: true, authenticated: true, authorized: false };
122
- }
123
-
124
- return {};
125
- };
126
-
127
- initStates(opts.dataDir);
128
-
129
- initNotification(node, httpRouter, wsRouter, opts);
130
-
131
- const { login, verify } = initJwt(node, opts);
132
- const { authenticator, handlers } = initAuth(node, opts);
133
-
134
- // auth middleware for http request
135
- serviceHttpRouter.use(
136
- bearerToken({
137
- queryKey: opts.loginTokenKey,
138
- bodyKey: opts.loginTokenKey,
139
- headerKey: 'Bearer',
140
- cookie: {
141
- signed: true,
142
- secret: opts.sessionSecret,
143
- key: opts.loginTokenKey,
144
- },
145
- })
146
- );
147
-
148
- // set user info to req.user
149
- serviceHttpRouter.use(async (req, res, next) => {
150
- const { token } = req;
151
- await ensureUser({ req, token });
152
- next();
153
- });
154
-
155
- // set user info to req.headers
156
- serviceHttpRouter.use(async (req, res, next) => {
157
- setUserInfoHeaders(req);
158
- next();
159
- });
160
-
161
- // public did-auth api
162
- handlers.attach(Object.assign({ app: serviceHttpRouter }, createLoginRoutes(node, authenticator, login, opts)));
163
- handlers.attach(Object.assign({ app: serviceHttpRouter }, createInviteRoutes(node, authenticator, login, opts)));
164
- handlers.attach(Object.assign({ app: serviceHttpRouter }, createIssuePassportAuth(node, authenticator, login, opts)));
165
- handlers.attach(
166
- Object.assign({ app: serviceHttpRouter }, createLostPassportListAuth(node, authenticator, login, opts))
167
- );
168
- handlers.attach(
169
- Object.assign({ app: serviceHttpRouter }, createLostPassportIssueAuth(node, authenticator, login, opts))
170
- );
171
-
172
- // public page
173
- [`${WELLKNOWN_AUTH_PATH_PREFIX}/issue-passport`, `${WELLKNOWN_AUTH_PATH_PREFIX}/lost-passport`].forEach((x) => {
174
- serviceHttpRouter.get(x, (req, res) => {
175
- res.sendFile(path.join(distDir, 'index.html'));
176
- });
177
- });
178
-
179
- // public http api
180
- createEnvRoutes.init(httpRouter, node, opts);
181
- createBlockletRoutes.init(httpRouter, node, opts);
182
- createPassportRoutes.init(httpRouter, node, opts);
183
-
184
- // check blocklet running
185
- // Request would not arrive here before blocklet is installed, because there is no config in router provider(nginx)
186
- serviceHttpRouter.use(async (req, res, next) => {
187
- const blocklet = await req.getBlocklet();
188
- if (
189
- ![
190
- BlockletStatus.running,
191
- // Waiting, Downloading should be allowed because blocklet is currently being upgrading
192
- BlockletStatus.waiting,
193
- BlockletStatus.downloading,
194
- ].includes(blocklet.status)
195
- ) {
196
- const nodeInfo = await req.getNodeInfo();
197
- res.status(500);
198
- // return json if json has high priority, e.g. "*/*,application/json"
199
- if (req.accepts(['html', 'json']) === 'json') {
200
- res.json({ code: 'error', error: 'blocklet is not running' });
201
- } else if (blocklet.status === BlockletStatus.starting) {
202
- res.send(getBlockletMaintenanceTemplate(blocklet, nodeInfo));
203
- } else {
204
- res.send(getBlockletNotRunningTemplate(blocklet, nodeInfo));
205
- }
206
- return;
207
- }
208
-
209
- next();
210
- });
211
-
212
- // auth middleware for websocket connect
213
- wsRouter.use('**', async (req, socket, head, next) => {
214
- const { searchParams } = new URL(req.url, `http://${req.headers.host || 'unknown'}`);
215
- const token = searchParams.get('token');
216
-
217
- // ignore some dev path in dev mode
218
- const blocklet = await req.getBlocklet();
219
- const devUrls = ['/sockjs-node'];
220
- const mode = get(blocklet, 'mode');
221
- if (mode === BLOCKLET_MODES.DEVELOPMENT && devUrls.includes(req.url)) {
222
- next();
223
- return;
224
- }
225
-
226
- await ensureUser({ req, token });
227
-
228
- setUserInfoHeaders(req);
229
-
230
- const { blocked, authenticated, authorized } = await checkAuth({ req });
231
- if (blocked) {
232
- let message = '401 Unauthorized';
233
- if (authenticated && !authorized) {
234
- message = '403 Forbidden';
235
- }
236
- socket.write(`HTTP/1.1 ${message}\r\n\r\n`);
237
- socket.destroy();
238
- return;
239
- }
240
-
241
- next();
242
- });
243
-
244
- serviceHttpRouter.use(async (req, res, next) => {
245
- const { blocked, authenticated, authorized } = await checkAuth({ req });
246
-
247
- if (blocked) {
248
- if (!authenticated) {
249
- if (req.path !== '/') {
250
- // redirect to root path for login
251
- // redirect to target path after login
252
- const baseUrl = getBaseUrl(req);
253
- const redirect = encodeURIComponent(`${baseUrl.replace(/\/+$/, '')}/${req.url.replace(/^\/+/, '')}`);
254
- res.redirect(`${baseUrl.replace(/\/+$/, '')}/?redirect=${redirect}`);
255
- } else {
256
- res.sendFile(path.join(distDir, 'index.html'));
257
- }
258
- return;
259
- }
260
-
261
- if (!authorized) {
262
- res.status(403).json({ code: 'forbidden', error: 'not allowed' });
263
- return;
264
- }
265
- }
266
-
267
- next();
268
- });
269
-
270
- // Note: this api depends on the user decoding logic
271
- createSessionRoutes.init(serviceHttpRouter, node, opts);
272
-
273
- // Block /.service/@abtnode/auth-service/<invalid_path>
274
- serviceHttpRouter.use((req, res, next) => {
275
- if (req.path.startsWith(opts.prefix)) {
276
- res.status(400).send('Bad request');
277
- return;
278
- }
279
-
280
- next();
281
- });
282
- };
283
-
284
- module.exports = {
285
- name,
286
- description,
287
- version,
288
- init,
289
- validators,
290
- };
@@ -1,33 +0,0 @@
1
- /* eslint-disable no-console */
2
- const fs = require('fs');
3
- const path = require('path');
4
- const get = require('lodash/get');
5
- const logger = require('@abtnode/logger')(require('../meta.json').name);
6
-
7
- module.exports = {
8
- init(server, node, opts) {
9
- server.get(`${opts.prefix}/blocklet/logo/:did`, async (req, res) => {
10
- const staticDir = path.resolve(__dirname, './build');
11
- const sendOptions = { maxAge: '1d' };
12
-
13
- let blocklet = null;
14
- try {
15
- blocklet = await node.ensureBlockletIntegrity(req.params.did);
16
-
17
- if (blocklet && get(blocklet, 'env.appDir') && blocklet.meta.logo) {
18
- const logoFile = path.join(get(blocklet, 'env.appDir'), blocklet.meta.logo);
19
-
20
- if (fs.existsSync(logoFile)) {
21
- res.sendFile(logoFile, sendOptions);
22
- return;
23
- }
24
- }
25
-
26
- res.sendFile('/images/blocklet.png', { root: staticDir, ...sendOptions });
27
- } catch (err) {
28
- logger.error('failed to send blocklet logo', { did: req.params.did, error: err });
29
- res.sendFile('/images/blocklet.png', { root: staticDir, ...sendOptions });
30
- }
31
- });
32
- },
33
- };
@@ -1,33 +0,0 @@
1
- const { WELLKNOWN_AUTH_PATH_PREFIX } = require('@abtnode/constant');
2
-
3
- module.exports = {
4
- init(server, node, opts) {
5
- server.get(`**${opts.prefix}/api/env`, async (req, res) => {
6
- res.type('js');
7
-
8
- const [blocklet, config, info] = await Promise.all([
9
- req.getBlockletInfo(),
10
- req.getServiceConfig(opts.name),
11
- req.getNodeInfo(),
12
- ]);
13
- let pathPrefix = req.headers['x-path-prefix'] || '/';
14
- let groupPathPrefix = req.headers['x-group-path-prefix'];
15
-
16
- // fix pathPrefix && groupPathPrefix
17
- // FIXME: pathPrefix and groupPathPrefix should be correct in service gateway
18
- pathPrefix = pathPrefix.replace(WELLKNOWN_AUTH_PATH_PREFIX, '') || '/';
19
- if (groupPathPrefix) {
20
- groupPathPrefix = groupPathPrefix.replace(WELLKNOWN_AUTH_PATH_PREFIX, '') || '/';
21
- }
22
-
23
- res.send(`window.env = {
24
- appId: "${blocklet.did}",
25
- appName: "${blocklet.name}",
26
- pathPrefix: "${pathPrefix}",
27
- apiPrefix: "${pathPrefix.replace(/\/+$/, '')}${opts.prefix}",
28
- ${groupPathPrefix ? `groupPathPrefix: "${groupPathPrefix}",` : ''}
29
- webWalletUrl: "${info.webWalletUrl || config.webWalletUrl || opts.webWalletUrl}",
30
- }`);
31
- });
32
- },
33
- };
@@ -1,5 +0,0 @@
1
- const { createLostPassportIssueRoute, TEAM_TYPES } = require('@abtnode/auth/lib/lost-passport');
2
-
3
- module.exports = function createRoutes(node, authenticator, login, opts) {
4
- return createLostPassportIssueRoute({ node, type: TEAM_TYPES.BLOCKLET, authServicePrefix: opts.prefix });
5
- };
@@ -1,18 +0,0 @@
1
- const { getPassportStatus } = require('@abtnode/auth/lib/auth');
2
-
3
- module.exports = {
4
- init(server, node, opts) {
5
- server.get(`${opts.prefix}/api/passport/status`, async (req, res) => {
6
- const { vcId, userDid, locale } = req.query;
7
- const teamDid = req.headers['x-blocklet-did'];
8
-
9
- if (teamDid !== req.query.teamDid) {
10
- throw new Error('teamDid is invalid');
11
- }
12
-
13
- const status = await getPassportStatus({ node, teamDid, userDid, vcId, locale });
14
-
15
- res.json(status);
16
- });
17
- },
18
- };
@@ -1,27 +0,0 @@
1
- const nocache = require('nocache');
2
-
3
- module.exports = {
4
- init(server, node, opts) {
5
- const prefix = `${opts.prefix}/api/did/session`;
6
-
7
- const handler = async (req, res) => {
8
- if (!req.user) {
9
- res.json({ user: null });
10
- return;
11
- }
12
-
13
- const user = { ...req.user };
14
- if (user.role) {
15
- const teamDid = req.getBlockletDid();
16
- // FIXME: this code may have performance issue
17
- const rbac = await node.getRBAC(teamDid);
18
- user.permissions = await rbac.getScope(req.user.role);
19
- }
20
-
21
- res.json({ user });
22
- };
23
-
24
- server.get(prefix, nocache(), handler);
25
- server.post(prefix, nocache(), handler);
26
- },
27
- };