@abtnode/webapp 1.8.63-beta-a36b5e1a → 1.8.63

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 (198) hide show
  1. package/blocklet.yml +6 -3
  2. package/build/asset-manifest.json +93 -0
  3. package/build/favicon.ico +0 -0
  4. package/build/icons/css/all.css +5919 -0
  5. package/build/icons/css/brands.css +14 -0
  6. package/build/icons/css/brands.min.css +12 -0
  7. package/build/icons/css/fontawesome.css +7816 -0
  8. package/build/icons/css/fontawesome.min.css +5864 -0
  9. package/build/icons/css/light.css +15 -0
  10. package/build/icons/css/light.min.css +13 -0
  11. package/build/icons/webfonts/fa-brands-400.eot +0 -0
  12. package/build/icons/webfonts/fa-brands-400.svg +1256 -0
  13. package/build/icons/webfonts/fa-brands-400.ttf +0 -0
  14. package/build/icons/webfonts/fa-brands-400.woff +0 -0
  15. package/build/icons/webfonts/fa-brands-400.woff2 +0 -0
  16. package/build/icons/webfonts/fa-light-300.eot +0 -0
  17. package/build/icons/webfonts/fa-light-300.svg +4445 -0
  18. package/build/icons/webfonts/fa-light-300.ttf +0 -0
  19. package/build/icons/webfonts/fa-light-300.woff +0 -0
  20. package/build/icons/webfonts/fa-light-300.woff2 +0 -0
  21. package/build/images/blocklet.png +0 -0
  22. package/build/images/blocklets-00c2c4.png +0 -0
  23. package/build/images/blocklets-222222.png +0 -0
  24. package/build/images/celebrate.png +0 -0
  25. package/build/images/community.svg +6 -0
  26. package/build/images/console-00c2c4.png +0 -0
  27. package/build/images/console-222222.png +0 -0
  28. package/build/images/dashboard-00c2c4.png +0 -0
  29. package/build/images/dashboard-222222.png +0 -0
  30. package/build/images/doc-222222.png +0 -0
  31. package/build/images/hourglass-222222.png +0 -0
  32. package/build/images/https-certificate-icon.png +0 -0
  33. package/build/images/labs-00c2c4.png +0 -0
  34. package/build/images/labs-222222.png +0 -0
  35. package/build/images/log-00c2c4.png +0 -0
  36. package/build/images/log-222222.png +0 -0
  37. package/build/images/member-222222.png +0 -0
  38. package/build/images/node.png +0 -0
  39. package/build/images/official.svg +1 -0
  40. package/build/images/private-222222.png +0 -0
  41. package/build/images/public-222222.png +0 -0
  42. package/build/images/public_avatar.png +0 -0
  43. package/build/images/router-00c2c4.png +0 -0
  44. package/build/images/router-222222.png +0 -0
  45. package/build/images/settings-00c2c4.png +0 -0
  46. package/build/images/settings-222222.png +0 -0
  47. package/build/images/slack.png +0 -0
  48. package/build/images/storage-222222.png +0 -0
  49. package/build/images/store-00c2c4.png +0 -0
  50. package/build/images/store-222222.png +0 -0
  51. package/build/images/team-00c2c4.png +0 -0
  52. package/build/images/team-222222.png +0 -0
  53. package/build/images/time-222222.png +0 -0
  54. package/build/images/upgrade.png +0 -0
  55. package/build/index.html +1 -0
  56. package/build/manifest.json +15 -0
  57. package/build/static/css/4381.5ade355d.chunk.css +1 -0
  58. package/build/static/css/4691.56c2f951.chunk.css +1 -0
  59. package/build/static/css/5245.5d6e9197.chunk.css +1 -0
  60. package/build/static/css/8213.f696fdbf.chunk.css +1 -0
  61. package/build/static/css/9779.f696fdbf.chunk.css +1 -0
  62. package/build/static/css/main.c9e90622.css +1 -0
  63. package/build/static/images/logo.png +0 -0
  64. package/build/static/js/1057.8280393f.chunk.js +1 -0
  65. package/build/static/js/1361.85e46159.chunk.js +1 -0
  66. package/build/static/js/1366.2f174c9b.chunk.js +2 -0
  67. package/build/static/js/1366.2f174c9b.chunk.js.LICENSE.txt +37 -0
  68. package/build/static/js/154.94956824.chunk.js +1 -0
  69. package/build/static/js/1826.07c285de.chunk.js +1 -0
  70. package/build/static/js/2129.120e36ae.chunk.js +1 -0
  71. package/build/static/js/2308.b65bc299.chunk.js +1 -0
  72. package/build/static/js/2564.eef717f3.chunk.js +1 -0
  73. package/build/static/js/2657.d3c62d57.chunk.js +1 -0
  74. package/build/static/js/2720.26eb1788.chunk.js +1 -0
  75. package/build/static/js/2828.4f318970.chunk.js +1 -0
  76. package/build/static/js/2878.5626558d.chunk.js +1 -0
  77. package/build/static/js/3111.84e02823.chunk.js +1 -0
  78. package/build/static/js/3476.c0b3411b.chunk.js +1 -0
  79. package/build/static/js/3633.8c7cf02d.chunk.js +1 -0
  80. package/build/static/js/3732.f5d8b39b.chunk.js +1 -0
  81. package/build/static/js/3776.1490b0f7.chunk.js +1 -0
  82. package/build/static/js/3829.b6d6cf45.chunk.js +1 -0
  83. package/build/static/js/4074.19db40ec.chunk.js +1 -0
  84. package/build/static/js/4104.b47ae0e1.chunk.js +1 -0
  85. package/build/static/js/4241.83e4f741.chunk.js +1 -0
  86. package/build/static/js/4274.e18ffddd.chunk.js +1 -0
  87. package/build/static/js/4349.7c2f6507.chunk.js +1 -0
  88. package/build/static/js/4381.631ef61d.chunk.js +2 -0
  89. package/build/static/js/4381.631ef61d.chunk.js.LICENSE.txt +22 -0
  90. package/build/static/js/4557.3907550e.chunk.js +1 -0
  91. package/build/static/js/4590.5a14012c.chunk.js +1 -0
  92. package/build/static/js/4633.9f946ed5.chunk.js +1 -0
  93. package/build/static/js/4691.550fcb40.chunk.js +2 -0
  94. package/build/static/js/4691.550fcb40.chunk.js.LICENSE.txt +8 -0
  95. package/build/static/js/5074.9ea094a9.chunk.js +1 -0
  96. package/build/static/js/5082.18d16cb9.chunk.js +1 -0
  97. package/build/static/js/519.adae6e43.chunk.js +1 -0
  98. package/build/static/js/556.381dcbd8.chunk.js +1 -0
  99. package/build/static/js/5984.25af6288.chunk.js +1 -0
  100. package/build/static/js/6158.8a43296d.chunk.js +1 -0
  101. package/build/static/js/6189.d6d74d14.chunk.js +1 -0
  102. package/build/static/js/6239.5a873a03.chunk.js +2 -0
  103. package/build/static/js/6239.5a873a03.chunk.js.LICENSE.txt +14 -0
  104. package/build/static/js/629.1a7f2553.chunk.js +1 -0
  105. package/build/static/js/6413.ab4a8e01.chunk.js +1 -0
  106. package/build/static/js/6602.c417a217.chunk.js +1 -0
  107. package/build/static/js/6780.64314507.chunk.js +1 -0
  108. package/build/static/js/6830.88b993a0.chunk.js +1 -0
  109. package/build/static/js/6866.2131ea60.chunk.js +2 -0
  110. package/build/static/js/6866.2131ea60.chunk.js.LICENSE.txt +8 -0
  111. package/build/static/js/6898.6fe0c32d.chunk.js +2 -0
  112. package/build/static/js/6898.6fe0c32d.chunk.js.LICENSE.txt +5 -0
  113. package/build/static/js/7016.835958ef.chunk.js +1 -0
  114. package/build/static/js/7298.a7286c09.chunk.js +1 -0
  115. package/build/static/js/7327.56a5e016.chunk.js +1 -0
  116. package/build/static/js/744.8b656dd2.chunk.js +1 -0
  117. package/build/static/js/7652.722b9180.chunk.js +1 -0
  118. package/build/static/js/8034.c4dcdeff.chunk.js +1 -0
  119. package/build/static/js/8058.0b2d4727.chunk.js +1 -0
  120. package/build/static/js/8213.09f25083.chunk.js +1 -0
  121. package/build/static/js/8235.add24931.chunk.js +1 -0
  122. package/build/static/js/8249.63c55b3a.chunk.js +1 -0
  123. package/build/static/js/8262.869cc799.chunk.js +1 -0
  124. package/build/static/js/8352.b57b0e44.chunk.js +1 -0
  125. package/build/static/js/8464.b4b82828.chunk.js +1 -0
  126. package/build/static/js/8606.66db67e2.chunk.js +1 -0
  127. package/build/static/js/9038.2908c176.chunk.js +1 -0
  128. package/build/static/js/9076.c77366bc.chunk.js +1 -0
  129. package/build/static/js/9301.a65db324.chunk.js +2 -0
  130. package/build/static/js/9301.a65db324.chunk.js.LICENSE.txt +8 -0
  131. package/build/static/js/9575.36f3de5b.chunk.js +2 -0
  132. package/build/static/js/9575.36f3de5b.chunk.js.LICENSE.txt +194 -0
  133. package/build/static/js/9779.bbf0dd81.chunk.js +1 -0
  134. package/build/static/js/main.cb5d8d67.js +2 -0
  135. package/build/static/js/main.cb5d8d67.js.LICENSE.txt +159 -0
  136. package/build/static/media/iconify.32b54549e843e448ee9b.cjs +2 -0
  137. package/build/static/media/iconify.32b54549e843e448ee9b.cjs.LICENSE.txt +13 -0
  138. package/build/static/media/lato-all-400-normal.3dc1eff492ab1f598560.woff +0 -0
  139. package/build/static/media/lato-all-700-normal.1e7707c9ec98d9b97e7f.woff +0 -0
  140. package/build/static/media/lato-latin-400-normal.be36596da218e1eec01c.woff2 +0 -0
  141. package/build/static/media/lato-latin-700-normal.8f28e0e1fdb195149f1c.woff2 +0 -0
  142. package/build/static/media/lato-latin-ext-400-normal.361f3dbb9db6a5980326.woff2 +0 -0
  143. package/build/static/media/lato-latin-ext-700-normal.9c8812eaec45956201e1.woff2 +0 -0
  144. package/build/static/media/logo.60f66bbe1ce9674a4df4e374c9d97fc4.svg +16 -0
  145. package/build/static/media/ubuntu-mono-all-400-normal.c879328bc62e9c68268f.woff +0 -0
  146. package/build/static/media/ubuntu-mono-cyrillic-400-normal.c367f416832eb8f1b846.woff2 +0 -0
  147. package/build/static/media/ubuntu-mono-cyrillic-ext-400-normal.eda1c4946b1f7bf58386.woff2 +0 -0
  148. package/build/static/media/ubuntu-mono-greek-400-normal.22f3bfc91f79c342bdf4.woff2 +0 -0
  149. package/build/static/media/ubuntu-mono-greek-ext-400-normal.b3459900ea8a25d1f7c2.woff2 +0 -0
  150. package/build/static/media/ubuntu-mono-latin-400-normal.18e32d9d743af28f913e.woff2 +0 -0
  151. package/build/static/media/ubuntu-mono-latin-ext-400-normal.b56e2315611d10838ad5.woff2 +0 -0
  152. package/package.json +1 -1
  153. package/api/gql/config.js +0 -392
  154. package/api/gql/index.js +0 -102
  155. package/api/gql/middlewares/create-audit-log.js +0 -3
  156. package/api/gql/middlewares/get-blocklet-list.js +0 -14
  157. package/api/gql/middlewares/install-blocklet.js +0 -13
  158. package/api/gql/middlewares/verify-blocklet.js +0 -21
  159. package/api/gql/middlewares/verify-team.js +0 -9
  160. package/api/index.js +0 -249
  161. package/api/libs/auth.js +0 -78
  162. package/api/libs/env.js +0 -3
  163. package/api/libs/login.js +0 -212
  164. package/api/libs/security.js +0 -90
  165. package/api/libs/storage.js +0 -69
  166. package/api/middlewares/mutate-blocklet-permission.js +0 -18
  167. package/api/routes/auth/accept-server.js +0 -28
  168. package/api/routes/auth/connect-owner.js +0 -143
  169. package/api/routes/auth/delegate-transfer-owner-nft.js +0 -86
  170. package/api/routes/auth/invite.js +0 -93
  171. package/api/routes/auth/issue-passport.js +0 -61
  172. package/api/routes/auth/launch-free-blocklet-by-nft.js +0 -9
  173. package/api/routes/auth/launch-free-blocklet.js +0 -9
  174. package/api/routes/auth/launch-paid-blocklet-by-nft.js +0 -9
  175. package/api/routes/auth/launch-paid-blocklet.js +0 -9
  176. package/api/routes/auth/login.js +0 -63
  177. package/api/routes/auth/lost-passport-issue.js +0 -5
  178. package/api/routes/auth/lost-passport-list.js +0 -5
  179. package/api/routes/auth/switch-passport.js +0 -47
  180. package/api/routes/auth/switch-profile.js +0 -69
  181. package/api/routes/auth/util.js +0 -135
  182. package/api/routes/auth/verify-owner.js +0 -39
  183. package/api/routes/auth/verify-purchase.js +0 -185
  184. package/api/routes/blocklet-info.js +0 -246
  185. package/api/routes/blocklet-preference.js +0 -161
  186. package/api/routes/blocklet-proxy.js +0 -220
  187. package/api/routes/did-resolver.js +0 -38
  188. package/api/routes/dns-resolver.js +0 -73
  189. package/api/routes/log.js +0 -31
  190. package/api/routes/passport.js +0 -19
  191. package/api/routes/session.js +0 -61
  192. package/api/routes/user.js +0 -38
  193. package/api/util/find-routing-rule.js +0 -95
  194. package/api/util/get-configs.js +0 -31
  195. package/api/util/index.js +0 -5
  196. package/api/util/navigation.js +0 -84
  197. package/api/webpack.blocklet.js +0 -43
  198. package/api/ws/index.js +0 -146
@@ -1,161 +0,0 @@
1
- const fs = require('fs-extra');
2
- const qs = require('querystring');
3
- const get = require('lodash/get');
4
- const joinUrl = require('url-join');
5
- const express = require('express');
6
- const multer = require('multer');
7
- const serveStatic = require('serve-static');
8
- const path = require('path');
9
- const { BLOCKLET_PREFERENCE_FILE, BLOCKLET_PREFERENCE_PREFIX, BLOCKLET_UPLOADS_DIR } = require('@blocklet/constant');
10
- const { WELLKNOWN_SERVICE_PATH_PREFIX } = require('@abtnode/constant');
11
-
12
- const mutateBlockletPermission = require('../middlewares/mutate-blocklet-permission');
13
- const DiskStorage = require('../libs/storage');
14
-
15
- // For reading and updating blocklet preferences
16
- module.exports = {
17
- init(app, node) {
18
- // find a component from the dependency tree
19
- const findComponent = (parent, id) => {
20
- if (parent.env.id === id) {
21
- return parent;
22
- }
23
-
24
- const possible = parent.children.find(x => id.startsWith(x.env.id));
25
- return possible ? findComponent(possible, id) : null;
26
- };
27
-
28
- const mergeConfigToSchema = (properties, configs, uploadAction) => {
29
- Object.keys(properties).forEach(key => {
30
- const prop = properties[key];
31
- if (prop.properties) {
32
- mergeConfigToSchema(prop.properties, configs, uploadAction);
33
- }
34
- if (prop['x-decorator'] === 'FormItem') {
35
- const prefixedKey = `${BLOCKLET_PREFERENCE_PREFIX}${key}`;
36
- if (typeof configs[prefixedKey] !== 'undefined') {
37
- prop.default = configs[prefixedKey];
38
- }
39
- if (prop['x-component'].startsWith('Upload') && !prop['x-component-props'].action) {
40
- prop['x-component-props'].action = uploadAction;
41
- }
42
- }
43
- });
44
- };
45
-
46
- const ensurePermission = mutateBlockletPermission(node);
47
-
48
- const ensureBlocklet = async (req, res, next) => {
49
- if (!req.query.id) {
50
- return res.status(400).json({ code: 'bad_request', error: 'no blocklet did' });
51
- }
52
-
53
- const [did] = req.query.id.split('/');
54
- req.blocklet = await node.getBlocklet({ did, attachRuntimeInfo: false });
55
- if (!req.blocklet) {
56
- return res.status(400).json({ code: 'bad_request', error: 'blocklet not found' });
57
- }
58
-
59
- return next();
60
- };
61
-
62
- const ensureComponent = (req, res, next) => {
63
- req.component = findComponent(req.blocklet, req.query.id);
64
- if (!req.component) {
65
- return res.status(400).json({ code: 'bad_request', error: 'component not found' });
66
- }
67
-
68
- return next();
69
- };
70
-
71
- const uploadApi = '/api/uploads';
72
-
73
- // load preferences schema
74
- app.get('/api/preferences', ensurePermission, ensureBlocklet, ensureComponent, async (req, res) => {
75
- const schemaFile = path.join(req.component.env.appDir, BLOCKLET_PREFERENCE_FILE);
76
- if (fs.existsSync(schemaFile)) {
77
- try {
78
- const info = await node.getNodeInfo();
79
- const isFromService = req.get('source') === 'blocklet-service';
80
- const uploadAction = joinUrl(
81
- // eslint-disable-next-line no-nested-ternary
82
- isFromService
83
- ? joinUrl(WELLKNOWN_SERVICE_PATH_PREFIX, uploadApi)
84
- : process.env.NODE_ENV === 'production'
85
- ? joinUrl(info.routing.adminPath, uploadApi)
86
- : uploadApi,
87
- `?${qs.stringify(req.query)}`
88
- );
89
-
90
- const schema = JSON.parse(fs.readFileSync(schemaFile, 'utf8'));
91
- mergeConfigToSchema(get(schema, 'schema.properties', {}), req.component.configObj, uploadAction);
92
- return res.json(schema);
93
- } catch (err) {
94
- console.error(err);
95
- return res.json({});
96
- }
97
- }
98
-
99
- return res.json({});
100
- });
101
-
102
- // save preferences data
103
- app.post('/api/preferences', ensurePermission, ensureBlocklet, ensureComponent, async (req, res) => {
104
- const configs = Object.keys(req.body).reduce((acc, key) => {
105
- const value = req.body[key];
106
- acc.push({ key: `${BLOCKLET_PREFERENCE_PREFIX}${key}`, value });
107
- return acc;
108
- }, []);
109
- await node.configBlocklet({ did: req.query.id.split('/'), configs }, { user: req.user });
110
- res.json(req.body);
111
- });
112
-
113
- // download dataDir
114
- // FIXME: we should limit this feature when dataDir is too large
115
- app.get('/api/export', ensurePermission, ensureBlocklet, async (req, res) => {
116
- const timestamp = new Date().toISOString().split('.')[0].split(':').join('-').replaceAll('-', '');
117
- const fileName = `blocklet-${req.blocklet.env.appId}-${timestamp}.zip`;
118
- const filePath = await node.createBlockletDataArchive(req.blocklet.env.dataDir, fileName);
119
- res.download(filePath, err => err && console.error(err));
120
- });
121
-
122
- const upload = multer({
123
- storage: new DiskStorage({
124
- destination: (req, file, cb) => {
125
- const uploadDir = path.join(req.blocklet.env.dataDir, BLOCKLET_UPLOADS_DIR);
126
- if (fs.existsSync(uploadDir) === false) {
127
- fs.mkdirSync(uploadDir, { recursive: true });
128
- }
129
- cb(null, uploadDir);
130
- },
131
- }),
132
- });
133
-
134
- // handle upload for blocklet prefs
135
- // FIXME: should also ensurePermission here
136
- app.post(uploadApi, ensureBlocklet, ensureComponent, upload.single('file'), async (req, res) => {
137
- res.json({
138
- url: joinUrl(
139
- req.blocklet.environmentObj.BLOCKLET_APP_URL,
140
- WELLKNOWN_SERVICE_PATH_PREFIX,
141
- BLOCKLET_UPLOADS_DIR,
142
- req.file.filename
143
- ),
144
- });
145
- });
146
-
147
- const staticOptions = {
148
- maxAge: '30d',
149
- extensions: ['html', 'htm'],
150
- index: ['index.html', 'index.htm'],
151
- setHeaders: (res, file) => {
152
- if (serveStatic.mime.lookup(file) === 'text/html') {
153
- res.setHeader('Cache-Control', 'public, max-age=0');
154
- }
155
- },
156
- };
157
-
158
- // serve hosted version
159
- app.use('/hosted/form-collector', express.static(node.collectorPath, staticOptions));
160
- },
161
- };
@@ -1,220 +0,0 @@
1
- /* eslint-disable no-underscore-dangle, global-require */
2
- /* eslint-disable no-console */
3
- const httpProxy = require('http-proxy');
4
- const LRU = require('lru-cache');
5
- const { isValid } = require('@arcblock/did');
6
- const { BlockletEvents } = require('@blocklet/constant');
7
- const md5 = require('@abtnode/util/lib/md5');
8
- const { BLOCKLET_PROXY_PATH_PREFIX, WELLKNOWN_SERVICE_PATH_PREFIX, EVENTS } = require('@abtnode/constant');
9
- const { forEachBlocklet } = require('@blocklet/meta/lib/util');
10
-
11
- const get = require('lodash/get');
12
-
13
- const logger = require('@abtnode/logger')(`${require('../../package.json').name}:blockletProxy`);
14
-
15
- const findRoutingRule = require('../util/find-routing-rule');
16
-
17
- const createLRU = opts => new LRU(opts);
18
-
19
- const GENERIC_GROUP = 'GENERIC';
20
-
21
- const createProxyCache = opts => {
22
- const groups = {};
23
-
24
- const resetGroup = did => {
25
- logger.info('Reset cache group', { did });
26
- groups[did] = createLRU(opts);
27
- };
28
-
29
- resetGroup(GENERIC_GROUP);
30
-
31
- return {
32
- set(did, key, value) {
33
- if (!groups[did]) {
34
- resetGroup(did);
35
- }
36
- groups[did].set(key, value);
37
- },
38
- get(did, key) {
39
- return groups[did] ? groups[did].get(key) : undefined;
40
- },
41
- resetGroup,
42
- deleteGroup(did) {
43
- logger.info('Delete cache group', { did });
44
- delete groups[did];
45
- },
46
- };
47
- };
48
-
49
- const ensureUrl = (req, urlPrefix) => {
50
- req.url = req.url.slice(urlPrefix.length);
51
-
52
- // convert all faviconXXX to favicon to ensure file exists in root blocklet
53
- if (req.url.startsWith('/favicon')) {
54
- req.url = '/favicon.ico';
55
- }
56
- };
57
-
58
- module.exports = {
59
- createProxyCache,
60
- init(app, node, proxy, proxyCache) {
61
- if (process.env.NODE_ENV !== 'test' && (proxy || proxyCache)) {
62
- throw new Error('proxy or proxyCache should only be invoked in test environment');
63
- }
64
-
65
- if (!proxy) {
66
- // eslint-disable-next-line no-param-reassign
67
- proxy = httpProxy.createProxyServer({
68
- timeout: 3600 * 1000,
69
- proxyTimeout: 3600 * 1000,
70
- });
71
- }
72
-
73
- if (!proxyCache) {
74
- // eslint-disable-next-line no-param-reassign
75
- proxyCache = createProxyCache({
76
- // FIXME: 如果 css 文件加载后, css文件中的 font 文件没有被立即加载, 期间加载了超过 50 个其他的文件, 再加载 css 文件中的 font 文件, 则 font 文件会无法加载. 这种情况可能会在 abt web wallet 中出现
77
- max: 50, // cache at most 50
78
- maxAge: 1 * 60 * 1000, // cache for 1 minute
79
- });
80
- }
81
-
82
- const refreshSites = async () => {
83
- try {
84
- const sites = await node.getSitesFromSnapshot();
85
- proxyCache.set(GENERIC_GROUP, 'SITES', sites);
86
- return sites;
87
- } catch (err) {
88
- logger.error('refreshSites failed', { error: err });
89
- return [];
90
- }
91
- };
92
-
93
- [BlockletEvents.started, BlockletEvents.reloaded].forEach(event => {
94
- node.on(event, blocklet => {
95
- forEachBlocklet(
96
- blocklet,
97
- b => {
98
- proxyCache.resetGroup(get(b, 'meta.did'));
99
- },
100
- { sync: true }
101
- );
102
- });
103
- });
104
-
105
- node.on(BlockletEvents.removed, blocklet => {
106
- forEachBlocklet(
107
- blocklet,
108
- b => {
109
- proxyCache.deleteGroup(get(b, 'meta.did'));
110
- },
111
- { sync: true }
112
- );
113
- });
114
-
115
- node.on(EVENTS.ROUTING_UPDATED, refreshSites);
116
-
117
- /**
118
- * match request
119
- * e.g.
120
- * /.blocklet/proxy/<did>/a.css
121
- * /.blocklet/proxy/path/a.css
122
- */
123
- app.get(`${BLOCKLET_PROXY_PATH_PREFIX}/:did/**`, async (req, res, next) => {
124
- const { did } = req.params;
125
-
126
- // proxy to blocklet service
127
- if (did === 'blocklet-service') {
128
- req.url = req.url.replace(`${BLOCKLET_PROXY_PATH_PREFIX}/${did}`, `${WELLKNOWN_SERVICE_PATH_PREFIX}/static`);
129
- const target = `http://127.0.0.1:${process.env.ABT_NODE_SERVICE_PORT}`;
130
- proxy.web(req, res, { target }, error => {
131
- if (error) {
132
- logger.error('http proxy error', { error });
133
- res.status(502).send(`Can not proxy to blocklet service: ${target}`);
134
- }
135
- });
136
- return;
137
- }
138
-
139
- if (isValid(did)) {
140
- req.PROXY_PATH_PREFIX_DID = did;
141
- req.PROXY_PATH_PREFIX = `${BLOCKLET_PROXY_PATH_PREFIX}/${did}`;
142
- }
143
- next();
144
- });
145
-
146
- /**
147
- * match request
148
- * e.g.
149
- * /.blocklet/proxy/<did>/a.css
150
- * /.blocklet/proxy/path/a.css
151
- * /.blocklet/proxy/a.css
152
- */
153
- app.get(`${BLOCKLET_PROXY_PATH_PREFIX}/**`, async (req, res) => {
154
- if (!req.headers.referer) {
155
- res.status(400).send('Referer was not found in headers');
156
- return;
157
- }
158
-
159
- const urlPrefix = req.PROXY_PATH_PREFIX || BLOCKLET_PROXY_PATH_PREFIX;
160
-
161
- const group = req.PROXY_PATH_PREFIX_DID || GENERIC_GROUP;
162
-
163
- // get origin by referer because the origin of referer of css resource and font resource are same
164
- // e.g. https://a.b.c:8080/.blocklet/proxy/style.css | referer: https://a.b.c:8080/ | origin: https://a.b.c:8080
165
- // https://a.b.c:8080/.blocklet/proxy/font.woff | referer: https://a.b.c:8080/.blocklet/proxy/style.css | origin: https://a.b.c:8080
166
- const cacheUrl = md5(`${new URL(req.headers.referer).origin}${req.url}${req.search || ''}`);
167
-
168
- const cacheKey = md5(`${cacheUrl}${req.headers.referer}`);
169
- const cacheReferer = md5(req.headers.referer);
170
-
171
- // use cache target if exist
172
- const cachedTarget = proxyCache.get(group, cacheKey) || proxyCache.get(group, cacheReferer);
173
- if (cachedTarget) {
174
- ensureUrl(req, urlPrefix);
175
-
176
- proxy.web(req, res, { target: cachedTarget }, error => {
177
- if (error) {
178
- logger.error('http proxy error', { error });
179
- res.status(502).send(`Can not proxy to upstream blocklet: ${cachedTarget}`);
180
- }
181
- });
182
- return;
183
- }
184
-
185
- // get sites
186
- let sites = proxyCache.get(GENERIC_GROUP, 'SITES');
187
- if (!sites) {
188
- sites = await refreshSites();
189
- }
190
-
191
- // find routing rule
192
- const rule = findRoutingRule(sites, req, urlPrefix);
193
-
194
- // proxy to target is matched rule was founded
195
- if (rule) {
196
- const target = `http://127.0.0.1:${rule.to.port}`;
197
-
198
- // cache the target for subsequent requests with the same url and referer
199
- proxyCache.set(group, cacheKey, target);
200
-
201
- // cache the target for subsequent requests request which referer is this url
202
- // e.g. current request: http://a.com/.blocklet/proxy/a.css
203
- // follow-up request: http://a.com/.blocklet/proxy/font.woff (referer is http://a.com/.blocklet/proxy/a.css)
204
- proxyCache.set(group, cacheUrl, target);
205
-
206
- ensureUrl(req, urlPrefix);
207
-
208
- proxy.web(req, res, { target }, error => {
209
- if (error) {
210
- logger.error('http proxy error', { error });
211
- res.status(502).send(`Can not proxy to upstream blocklet: ${target}`);
212
- }
213
- });
214
- return;
215
- }
216
-
217
- res.status(400).send(`Cannot find blocklet served at ${req.hostname}`);
218
- });
219
- },
220
- };
@@ -1,38 +0,0 @@
1
- const { WELLKNOWN_DID_RESOLVER_PREFIX } = require('@abtnode/constant');
2
-
3
- const getDidDocumentMiddleware = node => async (req, res) => {
4
- const blockletDid = req.get('x-blocklet-did');
5
- if (!blockletDid) {
6
- return res.status(404).json({ message: 'Service can not be found' });
7
- }
8
-
9
- const { did: serverDid } = await node.getNodeInfo();
10
- let appId = serverDid;
11
- let did = serverDid;
12
-
13
- if (blockletDid !== serverDid) {
14
- const blocklet = await node.getBlocklet({ did: blockletDid, attachRuntimeInfo: false });
15
- if (!blocklet) {
16
- return res.status(404).json({ message: 'Service can not be found' });
17
- }
18
-
19
- appId = blocklet.appDid;
20
- did = blockletDid;
21
- }
22
-
23
- const document = {
24
- id: `did:abt:${appId}`,
25
- alsoKnownAs: [`did:abt:${did}`],
26
- controller: `did:abt:${serverDid}`,
27
- services: [],
28
- };
29
-
30
- return res.json(document);
31
- };
32
-
33
- module.exports = {
34
- init(app, node) {
35
- app.get(WELLKNOWN_DID_RESOLVER_PREFIX, getDidDocumentMiddleware(node));
36
- },
37
- getDidDocumentMiddleware,
38
- };
@@ -1,73 +0,0 @@
1
- const dns = require('dns');
2
- const LRU = require('lru-cache');
3
- const joinUrl = require('url-join');
4
- const axios = require('@abtnode/util/lib/axios');
5
- const { DEFAULT_IP_DOMAIN, DEFAULT_ADMIN_PATH } = require('@abtnode/constant');
6
-
7
- const getNodeDomain = ip => (ip ? DEFAULT_IP_DOMAIN.replace(/^\*/, ip.replace(/\./g, '-')) : '');
8
-
9
- const timeout = process.env.NODE_ENV === 'test' ? 500 : 2000;
10
-
11
- // check if node dashboard https endpoint return 2xx
12
- const checkConnected = async ({ ip, nodeInfo }) => {
13
- const { adminPath = DEFAULT_ADMIN_PATH } = nodeInfo.routing || {};
14
- const origin = `https://${getNodeDomain(ip)}`;
15
- const endpoint = joinUrl(origin, adminPath);
16
- await axios.get(endpoint, { timeout });
17
- };
18
-
19
- module.exports = {
20
- init(router, node) {
21
- const cache = new LRU({
22
- max: 50, // cache at most 50
23
- maxAge: 5 * 60 * 1000, // cache for 5 minute
24
- });
25
-
26
- const accessibleCache = new LRU({
27
- max: 50, // cache at most 50
28
- maxAge: 5 * 60 * 1000, // cache for 5 minute
29
- });
30
-
31
- router.get('/api/dns-resolve/', async (req, res) => {
32
- const hostname = req.query.hostname || req.hostname;
33
- const accessible = !!req.query.accessible;
34
-
35
- const _cache = accessible ? accessibleCache : cache;
36
-
37
- const cachedAddress = _cache.get(hostname);
38
-
39
- if (cachedAddress) {
40
- res.json({ address: cachedAddress });
41
- return;
42
- }
43
-
44
- dns.lookup(hostname, async (err, address, family) => {
45
- if (err) {
46
- _cache.del(hostname);
47
- res.json({ address: null, error: err.message });
48
- return;
49
- }
50
-
51
- if (family !== 4) {
52
- _cache.del(hostname);
53
- res.json({ address: null, error: 'address is not IPv4 format' });
54
- }
55
-
56
- if (accessible) {
57
- const nodeInfo = await node.getNodeInfo();
58
- try {
59
- await checkConnected({ ip: address, nodeInfo });
60
- _cache.set(hostname, address);
61
- res.json({ address });
62
- } catch {
63
- _cache.del(hostname);
64
- res.json({ address: null, error: 'address is not accessible' });
65
- }
66
- } else {
67
- _cache.set(hostname, address);
68
- res.json({ address });
69
- }
70
- });
71
- });
72
- },
73
- };
package/api/routes/log.js DELETED
@@ -1,31 +0,0 @@
1
- const dayjs = require('dayjs');
2
- const { createDownloadLogStream } = require('@abtnode/util/lib/log');
3
-
4
- const mutateBlockletPermission = require('../middlewares/mutate-blocklet-permission');
5
-
6
- module.exports = {
7
- init(app, node) {
8
- const ensurePermission = mutateBlockletPermission(node);
9
-
10
- app.get('/api/download/log/:did', ensurePermission, async (req, res) => {
11
- const { did } = req.params;
12
- const { days } = req.query;
13
-
14
- if (days > 7) {
15
- res.status(400).send('Interval should not > 1 week');
16
- return;
17
- }
18
-
19
- try {
20
- const stream = await createDownloadLogStream({ node, did, days });
21
-
22
- res.setHeader('Content-Type', 'application/octet-stream');
23
- res.setHeader('Content-Disposition', `attachment;filename=${did}.${dayjs().format('YYYYMMDDHHmmss')}.log.zip`);
24
-
25
- stream.pipe(res);
26
- } catch (error) {
27
- res.status(500).send(error.message);
28
- }
29
- });
30
- },
31
- };
@@ -1,19 +0,0 @@
1
- const { getPassportStatus } = require('@abtnode/auth/lib/auth');
2
-
3
- module.exports = {
4
- init(router, node) {
5
- router.get('/api/passport/status', async (req, res) => {
6
- const { vcId, userDid, locale } = req.query;
7
- const nodeInfo = await node.getNodeInfo();
8
- const teamDid = nodeInfo.did;
9
-
10
- if (teamDid !== req.query.teamDid) {
11
- throw new Error('teamDid is invalid');
12
- }
13
-
14
- const status = await getPassportStatus({ node, teamDid, userDid, vcId, locale });
15
-
16
- res.json(status);
17
- });
18
- },
19
- };
@@ -1,61 +0,0 @@
1
- const url = require('url');
2
- const SealedBox = require('tweetnacl-sealedbox-js');
3
- const { getBaseUrl } = require('@abtnode/router-adapter');
4
- const { decodeEncryptionKey } = require('@abtnode/util/lib/security');
5
-
6
- const env = require('../libs/env');
7
- const { createSessionToken } = require('../libs/login');
8
-
9
- module.exports = {
10
- init(app, node) {
11
- // eslint-disable-next-line consistent-return
12
- app.get('/api/did/session', async (req, res) => {
13
- // Must be some one try to trick daemon with a blocklet token
14
- if (req.user && req.user.bid) {
15
- return res.status(403).send('Forbidden');
16
- }
17
-
18
- if (!req.user) {
19
- return res.json({});
20
- }
21
-
22
- // Authentication request from dashboard
23
- const user = { ...req.user };
24
- const rbac = await node.getRBAC();
25
- user.permissions = await rbac.getScope(user.role);
26
-
27
- const encKey = '_ek_';
28
- let nextToken = '';
29
- if (req.query[encKey]) {
30
- try {
31
- const encryptionKey = decodeEncryptionKey(req.query[encKey]);
32
- nextToken = JSON.stringify(await createSessionToken(user.did, { passport: user.passport, role: user.role }));
33
- nextToken = Buffer.from(SealedBox.seal(Buffer.from(nextToken), encryptionKey)).toString('base64');
34
- } catch {
35
- // Do nothing
36
- }
37
- }
38
-
39
- res.json({ user, nextToken });
40
- });
41
-
42
- app.get('/api/env', async (req, res) => {
43
- res.type('js');
44
-
45
- const info = await node.getNodeInfo();
46
- const baseUrl = url.format({
47
- protocol: req.protocol,
48
- host: req.get('host'),
49
- pathname: '',
50
- });
51
-
52
- res.send(`window.env = {
53
- appId: "${info.did}",
54
- appName: "${info.name}",
55
- appDescription: "${info.description}",
56
- apiPrefix: "${getBaseUrl(req)}",
57
- baseUrl: "${env.baseUrl || baseUrl}",
58
- }`);
59
- });
60
- },
61
- };
@@ -1,38 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
-
4
- const { NODE_DATA_DIR_NAME, USER_AVATAR_PATH_PREFIX } = require('@abtnode/constant');
5
- const { getAvatarFile } = require('@abtnode/util/lib/user-avatar');
6
-
7
- module.exports = {
8
- init(app, node) {
9
- // eslint-disable-next-line consistent-return
10
- app.get(`${USER_AVATAR_PATH_PREFIX}/:did/:fileName`, async (req, res) => {
11
- const sendOptions = { maxAge: '1y' };
12
- const info = await node.getNodeInfo();
13
- const { did, fileName } = req.params;
14
-
15
- let dataDir;
16
- if (did === info.did) {
17
- dataDir = path.join(node.dataDirs.data, NODE_DATA_DIR_NAME);
18
- } else {
19
- const blocklet = await node.getBlocklet({ did, attachConfig: false });
20
- if (!blocklet) {
21
- res.status(404).send('Blocklet Not Found');
22
- return;
23
- }
24
-
25
- dataDir = path.join(node.dataDirs.data, blocklet.meta.name);
26
- }
27
-
28
- const avatarFile = getAvatarFile(dataDir, fileName);
29
-
30
- if (!fs.existsSync(avatarFile)) {
31
- res.status(404).send('Avatar Not Found');
32
- return;
33
- }
34
-
35
- res.sendFile(avatarFile, sendOptions);
36
- });
37
- },
38
- };