@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
package/api/index.js DELETED
@@ -1,249 +0,0 @@
1
- const path = require('path');
2
- const cors = require('cors');
3
- const compression = require('compression');
4
- const morgan = require('morgan');
5
- const express = require('express');
6
- require('express-async-errors');
7
- const cookieParser = require('cookie-parser');
8
- const bodyParser = require('body-parser');
9
- const bearerToken = require('express-bearer-token');
10
- const fallback = require('express-history-api-fallback');
11
- const graphqlUploadExpress = require('graphql-upload/graphqlUploadExpress.js');
12
- const joinUrl = require('url-join');
13
- const getRouterAdapter = require('@abtnode/router-adapter');
14
- const get502Template = require('@abtnode/router-templates/lib/502');
15
- const getBlockletNotRunningTemplate = require('@abtnode/router-templates/lib/blocklet-not-running');
16
- const {
17
- MAX_UPLOAD_FILE_SIZE,
18
- DEFAULT_ADMIN_PATH,
19
- USER_AVATAR_URL_PREFIX,
20
- USER_AVATAR_PATH_PREFIX,
21
- } = require('@abtnode/constant');
22
- const http = require('http');
23
- const { setUserInfoHeaders } = require('@abtnode/auth/lib/auth');
24
- const log = require('@abtnode/logger');
25
- const certificateManager = require('@abtnode/certificate-manager');
26
- const createInvite = require('@abtnode/auth/lib/invitation');
27
-
28
- const { authWithJwt, authWithAccessKey, authWithVcPresentation } = require('./libs/login');
29
- const { context, handlers } = require('./libs/auth');
30
- const { protectGQL } = require('./libs/security');
31
- const gql = require('./gql');
32
- const createWebSocketServer = require('./ws');
33
-
34
- const logger = log('webapp:index');
35
-
36
- const createLoginAuth = require('./routes/auth/login');
37
- const createSwitchProfileAuth = require('./routes/auth/switch-profile');
38
- const createSwitchPassportAuth = require('./routes/auth/switch-passport');
39
- const createConnectOwnerAuth = require('./routes/auth/connect-owner');
40
- const createVerifyOwnerAuth = require('./routes/auth/verify-owner');
41
- const createAcceptServerAuth = require('./routes/auth/accept-server');
42
- const createVerifyPurchaseAuth = require('./routes/auth/verify-purchase');
43
- const createIssuePassportAuth = require('./routes/auth/issue-passport');
44
- const createLostPassportListAuth = require('./routes/auth/lost-passport-list');
45
- const createLostPassportIssueAuth = require('./routes/auth/lost-passport-issue');
46
- const createInviteAuth = require('./routes/auth/invite');
47
- const createLaunchFreeBlockletAuth = require('./routes/auth/launch-free-blocklet');
48
- const createLaunchPaidBlockletAuth = require('./routes/auth/launch-paid-blocklet');
49
- const createLaunchFreeBlockletByNFTAuth = require('./routes/auth/launch-free-blocklet-by-nft');
50
- const createLaunchPaidBlockletByNFTAuth = require('./routes/auth/launch-paid-blocklet-by-nft');
51
- const createDelegateTransferOwnerNFTAuth = require('./routes/auth/delegate-transfer-owner-nft');
52
- const sessionRoutes = require('./routes/session');
53
- const blockletInfoRoutes = require('./routes/blocklet-info');
54
- const blockletPreferenceRoutes = require('./routes/blocklet-preference');
55
- const blockletProxyRoutes = require('./routes/blocklet-proxy');
56
- const passportRoutes = require('./routes/passport');
57
- const didResolverRoutes = require('./routes/did-resolver');
58
- const dnsResolverRoutes = require('./routes/dns-resolver');
59
- const userRoutes = require('./routes/user');
60
- const logRoutes = require('./routes/log');
61
-
62
- const MAX_FILE_SIZE = Number(process.env.MAX_UPLOAD_FILE_SIZE || MAX_UPLOAD_FILE_SIZE) * 1024 * 1024;
63
-
64
- module.exports = function createServer(node) {
65
- const isTestBuild = process.env.TEST_BUILD && JSON.parse(process.env.TEST_BUILD);
66
- const isProduction = process.env.NODE_ENV === 'production' || isTestBuild;
67
-
68
- if (!process.env.ABT_NODE_DATA_DIR) {
69
- throw new Error('Cannot start application without process.env.ABT_NODE_DATA_DIR');
70
- }
71
-
72
- context.set('node', node);
73
-
74
- // Create and config express application
75
- const app = express();
76
-
77
- app.set('trust proxy', 'loopback');
78
- app.disable('x-powered-by');
79
-
80
- app.use(compression());
81
- app.use(cookieParser());
82
- app.use(bodyParser.json({ limit: '4mb' }));
83
- app.use(bodyParser.urlencoded({ extended: true, limit: '2mb' }));
84
- app.use(cors());
85
-
86
- app.get('/error/502', async (req, res) => {
87
- try {
88
- res.type('html');
89
- res.status(502);
90
-
91
- const blockletDid = req.get('x-did');
92
- const nodeInfo = await node.getNodeInfo();
93
- const info = { version: nodeInfo.version, mode: nodeInfo.mode };
94
-
95
- if (blockletDid) {
96
- const blocklet = await node.getBlocklet({ did: blockletDid, attachConfig: false });
97
- if (!blocklet) {
98
- return res.send(get502Template(info));
99
- }
100
-
101
- return res.send(getBlockletNotRunningTemplate(blocklet, nodeInfo));
102
- }
103
-
104
- return res.send(get502Template(info));
105
- } catch (error) {
106
- logger.error('render 502 page failed', { error });
107
- return res.send('502 Error');
108
- }
109
- });
110
-
111
- if (isProduction) {
112
- // format:
113
- // :remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"
114
- app.use(morgan('combined', { stream: log.getAccessLogStream(process.env.ABT_NODE_LOG_DIR) }));
115
- } else {
116
- app.use(
117
- morgan((tokens, req, res) => {
118
- const format = [
119
- tokens.method(req, res),
120
- tokens.url(req, res),
121
- tokens.status(req, res),
122
- tokens.res(req, res, 'content-length'),
123
- '-',
124
- tokens['response-time'](req, res),
125
- 'ms',
126
- ].join(' ');
127
-
128
- return format;
129
- })
130
- );
131
- }
132
-
133
- app.use(bearerToken());
134
- app.use(async (req, res, next) => {
135
- try {
136
- const { token, headers, body } = req;
137
- if (token) {
138
- // request by login user
139
- const user = await authWithJwt(token, node);
140
-
141
- // parse user avatar
142
- if (user && user.avatar && user.avatar.startsWith(USER_AVATAR_URL_PREFIX)) {
143
- const nodeInfo = await node.getNodeInfo();
144
-
145
- const adminPath =
146
- process.env.NODE_ENV === 'development' ? '' : nodeInfo.routing?.adminPath || DEFAULT_ADMIN_PATH;
147
-
148
- user.avatar = joinUrl(adminPath, USER_AVATAR_PATH_PREFIX, nodeInfo.did, user.avatar.split('/').slice(-1)[0]);
149
- }
150
-
151
- req.user = user;
152
- } else if (headers['x-access-key-id'] && headers['x-access-stamp'] && headers['x-access-signature']) {
153
- // request by accessKey
154
- const user = await authWithAccessKey({
155
- keyId: headers['x-access-key-id'],
156
- stamp: headers['x-access-stamp'],
157
- signature: headers['x-access-signature'],
158
- node,
159
- blockletDid: headers['x-access-blocklet'],
160
- });
161
- req.user = user;
162
- } else if (body['x-authenticate'] && body['x-authenticate'].vcPresentation) {
163
- req.user = await authWithVcPresentation({
164
- node,
165
- vcPresentation: body['x-authenticate'].vcPresentation,
166
- challenge: body['x-authenticate'].challenge,
167
- });
168
- }
169
- } catch (error) {
170
- // Do nothing
171
- }
172
- next();
173
- });
174
-
175
- app.use(async (req, res, next) => {
176
- setUserInfoHeaders(req);
177
- next();
178
- });
179
- app.use(certificateManager.createRoutes(node.dataDirs.certManagerModule));
180
-
181
- const router = express.Router();
182
-
183
- handlers.attach(Object.assign({ app: router }, createLoginAuth(node)));
184
- handlers.attach(Object.assign({ app: router }, createSwitchProfileAuth(node)));
185
- handlers.attach(Object.assign({ app: router }, createSwitchPassportAuth(node)));
186
- handlers.attach(Object.assign({ app: router }, createConnectOwnerAuth(node)));
187
- handlers.attach(Object.assign({ app: router }, createVerifyOwnerAuth(node)));
188
- handlers.attach(Object.assign({ app: router }, createAcceptServerAuth(node)));
189
- handlers.attach(Object.assign({ app: router }, createVerifyPurchaseAuth(node)));
190
- handlers.attach(Object.assign({ app: router }, createIssuePassportAuth(node)));
191
- handlers.attach(Object.assign({ app: router }, createLostPassportListAuth(node)));
192
- handlers.attach(Object.assign({ app: router }, createLostPassportIssueAuth(node)));
193
- handlers.attach(Object.assign({ app: router }, createInviteAuth(node)));
194
- handlers.attach(Object.assign({ app: router }, createLaunchFreeBlockletAuth(node)));
195
- handlers.attach(Object.assign({ app: router }, createLaunchPaidBlockletAuth(node)));
196
- handlers.attach(Object.assign({ app: router }, createLaunchFreeBlockletByNFTAuth(node)));
197
- handlers.attach(Object.assign({ app: router }, createLaunchPaidBlockletByNFTAuth(node)));
198
- handlers.attach(Object.assign({ app: router }, createDelegateTransferOwnerNFTAuth(node)));
199
-
200
- sessionRoutes.init(router, node);
201
- blockletInfoRoutes.init(router, node);
202
- blockletPreferenceRoutes.init(router, node);
203
- blockletProxyRoutes.init(router, node);
204
- passportRoutes.init(router, node);
205
- didResolverRoutes.init(router, node);
206
- dnsResolverRoutes.init(router, node);
207
- createInvite.init(app, node, { prefix: '/api' });
208
- userRoutes.init(router, node);
209
- logRoutes.init(router, node);
210
-
211
- // serve abt node gql
212
- const gqlConfig = gql.genConfig(node);
213
- app.use(
214
- '/api/gql',
215
- graphqlUploadExpress({ maxFileSize: MAX_FILE_SIZE, maxFiles: 10 }),
216
- protectGQL(node, gqlConfig),
217
- gql(gqlConfig, !isProduction)
218
- );
219
-
220
- if (isProduction) {
221
- app.use(router);
222
-
223
- const staticDir = path.resolve(__dirname, './build');
224
-
225
- app.use(getRouterAdapter());
226
- app.use(express.static(staticDir, { maxAge: '365d', index: false }));
227
- app.use(fallback('index.html', { root: staticDir }));
228
-
229
- app.use((req, res) => {
230
- res.status(404).send('404 NOT FOUND');
231
- });
232
-
233
- // eslint-disable-next-line no-unused-vars
234
- app.use((err, req, res, next) => {
235
- logger.error('Something broke', { error: err });
236
- res.status(500).send(`Daemon: Something broke! ${err.message}`);
237
- });
238
- } else {
239
- app.use(router);
240
- }
241
-
242
- const httpServer = http.createServer(app);
243
- const wsServer = createWebSocketServer(node);
244
- wsServer.attach(httpServer);
245
-
246
- httpServer.app = app;
247
-
248
- return httpServer;
249
- };
package/api/libs/auth.js DELETED
@@ -1,78 +0,0 @@
1
- const path = require('path');
2
- const joinUrl = require('url-join');
3
- const Mcrypto = require('@ocap/mcrypto');
4
- const DiskStorage = require('@arcblock/did-auth-storage-nedb');
5
- const { fromSecretKey, WalletType } = require('@ocap/wallet');
6
- const { WalletAuthenticator } = require('@arcblock/did-auth');
7
- const { DEFAULT_SERVICE_PATH, WELLKNOWN_SERVICE_PATH_PREFIX } = require('@abtnode/constant');
8
- const WalletHandlers = require('@blocklet/sdk/lib/wallet-handler');
9
- const { sendToUser } = require('@blocklet/sdk/lib/util/send-notification');
10
-
11
- const env = require('./env');
12
-
13
- const type = WalletType({
14
- role: Mcrypto.types.RoleType.ROLE_APPLICATION,
15
- pk: Mcrypto.types.KeyType.ED25519,
16
- hash: Mcrypto.types.HashType.SHA3,
17
- });
18
-
19
- const wallet = fromSecretKey(process.env.ABT_NODE_SK, type);
20
-
21
- const context = (() => {
22
- const store = {};
23
- return {
24
- get: key => store[key],
25
- set: (key, value) => {
26
- store[key] = value;
27
- },
28
- };
29
- })();
30
-
31
- const authenticator = new WalletAuthenticator({
32
- wallet,
33
- baseUrl: env.baseUrl,
34
- appInfo: async ({ baseUrl }) => {
35
- const info = await context.get('node').getNodeInfo();
36
- return {
37
- name: info.name,
38
- description: info.description,
39
- icon: `${env.baseUrl || baseUrl}/images/node.png?version=${info.version}`,
40
- link: env.baseUrl || baseUrl,
41
- updateSubEndpoint: true,
42
- subscriptionEndpoint: joinUrl(DEFAULT_SERVICE_PATH, WELLKNOWN_SERVICE_PATH_PREFIX, 'websocket'),
43
- nodeDid: info.did,
44
- };
45
- },
46
- chainInfo: {
47
- host: 'none',
48
- id: 'none',
49
- },
50
- });
51
-
52
- const handlers = new WalletHandlers({
53
- authenticator,
54
- tokenStorage: new DiskStorage({
55
- dbPath: path.join(process.env.ABT_NODE_DATA_DIR, 'auth.db'),
56
- dbPort: process.env.NODE_ENV === 'test' ? null : Number(process.env.NEDB_MULTI_PORT),
57
- onload: err => {
58
- if (err) {
59
- // eslint-disable-next-line no-console
60
- console.error(`Failed to load database from ${path.join(process.env.ABT_NODE_DATA_DIR, 'auth.db')}`, err);
61
- }
62
- },
63
- }),
64
- sendNotificationFn: (connectedDid, message) => {
65
- const sender = {
66
- appDid: wallet.address,
67
- appSk: wallet.secretKey,
68
- };
69
- return sendToUser(connectedDid, message, sender, process.env.ABT_NODE_SERVICE_PORT);
70
- },
71
- });
72
-
73
- module.exports = {
74
- authenticator,
75
- handlers,
76
- wallet,
77
- context,
78
- };
package/api/libs/env.js DELETED
@@ -1,3 +0,0 @@
1
- module.exports = {
2
- baseUrl: process.env.ABT_NODE_BASE_URL,
3
- };
package/api/libs/login.js DELETED
@@ -1,212 +0,0 @@
1
- /* eslint-disable implicit-arrow-linebreak */
2
- /* eslint-disable no-underscore-dangle */
3
- const jwt = require('jsonwebtoken');
4
- const get = require('lodash/get');
5
- const { fromPublicKey } = require('@ocap/wallet');
6
- const getBlockletInfo = require('@blocklet/meta/lib/info');
7
- const { VC_TYPE_NODE_PASSPORT, SERVER_ROLES, AUTH_CERT_TYPE } = require('@abtnode/constant');
8
- const { createAuthToken } = require('@abtnode/auth/lib/auth');
9
- const { isUserPassportRevoked, getRoleFromLocalPassport, isPassportAvailable } = require('@abtnode/auth/lib/passport');
10
- const { getVcFromPresentation } = require('@abtnode/util/lib/vc');
11
- const { verifyPresentation } = require('@arcblock/vc');
12
-
13
- const logger = require('../../../auth/lib/logger');
14
-
15
- if (!process.env.ABT_NODE_SESSION_SECRET) {
16
- throw new Error('ABT_NODE_SESSION_SECRET must be set to start the node');
17
- }
18
-
19
- const secret = process.env.ABT_NODE_SESSION_SECRET;
20
- // @link checkout https://github.com/auth0/node-jsonwebtoken#usage for ttl syntax
21
- const ttl = Number(process.env.ABT_NODE_SESSION_TTL) ? Number(process.env.ABT_NODE_SESSION_TTL) : '1d';
22
-
23
- async function getUser(node, did) {
24
- const user = await node.getNodeUser({ did });
25
- if (user && user.approved) {
26
- return user;
27
- }
28
- return null;
29
- }
30
-
31
- const createSessionToken = async (did, { passport, role } = {}) =>
32
- createAuthToken({
33
- did,
34
- passport,
35
- role,
36
- secret,
37
- expiresIn: ttl,
38
- });
39
-
40
- const parseUserByDecodedJwtToken = async ({ data = {}, node } = {}) => {
41
- const { did } = data;
42
- if (!did) {
43
- throw new Error('Invalid jwt token: invalid did');
44
- }
45
-
46
- if (data.type === AUTH_CERT_TYPE.OWNERSHIP_NFT) {
47
- return { role: data.role, did: data.did };
48
- }
49
-
50
- if (data.type === AUTH_CERT_TYPE.BLOCKLET_USER) {
51
- return {
52
- did: data.did,
53
- role: `blocklet-${data.role}`,
54
- blockletDid: data.blockletDid,
55
- };
56
- }
57
-
58
- if (data.type === AUTH_CERT_TYPE.BLOCKLET_CONTROLLER) {
59
- return {
60
- role: SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER,
61
- did: data.did,
62
- controller: data.controller,
63
-
64
- // just for frond-end display
65
- passports: [{ name: SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER, title: 'External' }],
66
- };
67
- }
68
-
69
- const { role, passport } = data;
70
-
71
- const user = await getUser(node, did);
72
- if (!user) {
73
- throw new Error('Invalid jwt token: user not in whitelist');
74
- }
75
-
76
- if (passport && passport.id && isUserPassportRevoked(user, passport)) {
77
- throw new Error(`Passport ${passport.name} has been revoked`);
78
- }
79
-
80
- user.role = role;
81
- if (passport) {
82
- user.passportId = passport.id;
83
- }
84
-
85
- return user;
86
- };
87
-
88
- function authWithJwt(token, node) {
89
- return new Promise((resolve, reject) => {
90
- jwt.verify(token, secret, async (err, decoded) => {
91
- if (err) {
92
- return reject(err);
93
- }
94
-
95
- return resolve(parseUserByDecodedJwtToken({ data: decoded, node }));
96
- });
97
- });
98
- }
99
-
100
- async function authWithAccessKey({ keyId, stamp, signature, node, blockletDid }) {
101
- // request from blocklet
102
- if (blockletDid) {
103
- const [blocklet, info] = await Promise.all([
104
- node.getBlocklet({ did: blockletDid, attachRuntimeInfo: false }),
105
- node.getNodeInfo(),
106
- ]);
107
- if (!blocklet) {
108
- throw new Error(`blocklet is not valid: ${blockletDid}`);
109
- }
110
-
111
- const { wallet, name } = getBlockletInfo(blocklet, info.sk);
112
- if (wallet.address !== keyId) {
113
- throw new Error(`keyId is not valid: ${keyId}`);
114
- }
115
-
116
- if (!wallet.verify(`${stamp}-${keyId}`, signature)) {
117
- throw new Error(`verify failed. keyId: ${keyId}, stamp: ${stamp}, signature: ${signature}`);
118
- }
119
-
120
- return {
121
- did: blockletDid,
122
- role: SERVER_ROLES.BLOCKLET_SDK,
123
- blockletDid,
124
- fullName: name,
125
- };
126
- }
127
-
128
- const accessKey = await node.getAccessKey({ accessKeyId: keyId });
129
- if (!accessKey) {
130
- throw new Error(`Access Key ${keyId} does not exist`);
131
- }
132
- const { accessKeyPublic, passport, remark } = accessKey;
133
-
134
- const role = getRoleFromLocalPassport({ name: passport });
135
- const wallet = fromPublicKey(accessKeyPublic);
136
- if (!wallet.verify(`${stamp}-${keyId}`, signature)) {
137
- throw new Error(`verify failed. keyId: ${keyId}, stamp: ${stamp}, signature: ${signature}`);
138
- }
139
- await node.refreshLastUsed(keyId);
140
- return {
141
- did: keyId,
142
- fullName: remark || keyId,
143
- role,
144
- };
145
- }
146
-
147
- const authWithVcPresentation = async ({ node, vcPresentation, challenge }) => {
148
- const vc = getVcFromPresentation(vcPresentation);
149
-
150
- if (vc.type.includes(VC_TYPE_NODE_PASSPORT)) {
151
- const { did } = await node.getNodeInfo();
152
- // FIXME: 这个地方需要考虑外部 Passport(trustedPassports) 的权限
153
- verifyPresentation({ presentation: vcPresentation, trustedIssuers: [did], challenge });
154
-
155
- const userDid = get(vc, 'credentialSubject.id');
156
- const user = await node.getNodeUser(userDid);
157
- if (!user) {
158
- throw new Error('The user of verifiable credential presentation does not exist');
159
- }
160
-
161
- const passport = user.passports.find(x => x.id === vc.id);
162
- if (!passport) {
163
- throw new Error('The user does not match the passport');
164
- }
165
-
166
- if (!isPassportAvailable(passport)) {
167
- throw new Error('The passport is no longer available');
168
- }
169
-
170
- return {
171
- did: user.did,
172
- role: passport.name,
173
- };
174
- }
175
-
176
- if (vc.type.includes('ServiceOwnershipCredential')) {
177
- // FIXME: 这里的 trustedIssuers 相当于相信任何 VC,需要想更安全的方法
178
- verifyPresentation({ presentation: vcPresentation, trustedIssuers: [get(vc, 'issuer.id')], challenge });
179
-
180
- const { did: abtnodeDid, ownerNft } = await node.getNodeInfo();
181
- const abtnodeDidInVc = get(vc, 'credentialSubject.isOwnerOf.abtnode.id');
182
- if (abtnodeDidInVc !== abtnodeDid) {
183
- logger.error('Invalid ownership vc: ABT Node DID not matched the DID in VC');
184
- throw new Error('Invalid Ownership VC');
185
- }
186
-
187
- const userDid = get(vc, 'credentialSubject.id');
188
- const abtnodeHolder = get(ownerNft, 'holder');
189
-
190
- if (userDid !== abtnodeHolder) {
191
- logger.error('Invalid ownership vc: ABT Node holder not matched the owner DID in VC');
192
- throw new Error('Invalid Ownership VC');
193
- }
194
-
195
- return {
196
- did: userDid,
197
- role: SERVER_ROLES.OWNER,
198
- };
199
- }
200
-
201
- throw new Error('Invalid verifiable credential presentation');
202
- };
203
-
204
- module.exports = {
205
- createSessionToken,
206
- authWithJwt,
207
- authWithAccessKey,
208
- authWithVcPresentation,
209
- getUser,
210
- secret,
211
- parseUserByDecodedJwtToken,
212
- };
@@ -1,90 +0,0 @@
1
- const get = require('lodash/get');
2
- const { parse } = require('graphql');
3
- const { NODE_MODES, ROLES } = require('@abtnode/constant');
4
-
5
- const isDebugMode = info => info.enableWelcomePage && info.mode === NODE_MODES.DEBUG;
6
-
7
- const whiteList = {
8
- getNodeInfo: true,
9
- getBlockletMetaFromUrl: true,
10
- getBlocklets: info => isDebugMode(info),
11
- getRoutingSites: info => isDebugMode(info),
12
- resetNode: () => process.env.NODE_ENV === 'e2e',
13
- };
14
-
15
- const protectGQL = (instance, gqlConfig) => async (req, res, next) => {
16
- const query = req.query.query || req.body.query;
17
- if (query) {
18
- const info = await instance.states.node.read();
19
- try {
20
- const { definitions } = parse(query);
21
-
22
- // get operations that need checked, excluded by whitelist
23
- const operations = definitions
24
- .map(x => {
25
- const selections = get(x, 'selectionSet.selections') || [];
26
- const names = selections.map(y => get(y, 'name.value'));
27
- return names;
28
- })
29
- .reduce((arr, names) => {
30
- arr.push(...names);
31
- return arr;
32
- }, [])
33
- .filter(d => d !== '__schema')
34
- .filter(name => {
35
- if (typeof whiteList[name] === 'function') {
36
- return !whiteList[name](info);
37
- }
38
- return !whiteList[name];
39
- });
40
-
41
- // check auth
42
- if (!req.user && operations.length) {
43
- return res.status(401).json({ code: 'forbidden', error: 'not allowed' });
44
- }
45
-
46
- // check batch mutation
47
- const isBatchMutation = definitions.filter(x => x.operation === 'mutation').length > 1;
48
- if (isBatchMutation) {
49
- return res.status(403).json({ code: 'forbidden', error: 'batch mutation not allowed' });
50
- }
51
-
52
- // check maintenance
53
- const hasMutation = definitions.some(x => x.operation === 'mutation');
54
- if (hasMutation && [NODE_MODES.MAINTENANCE].includes(info.mode)) {
55
- return res.status(503).json({ code: 'under maintenance', error: 'Blocklet server is under maintenance' });
56
- }
57
-
58
- // check permission
59
- if (req.user && req.user.role !== ROLES.OWNER && operations.length) {
60
- const rbac = await instance.getRBAC();
61
-
62
- const results = await Promise.all(
63
- operations.map(async apiName => {
64
- if (!gqlConfig[apiName]) {
65
- return true;
66
- }
67
-
68
- return !!(await rbac.canAny(
69
- req.user.role,
70
- gqlConfig[apiName].permissions.map(p => p.split('_'))
71
- ));
72
- })
73
- );
74
-
75
- const can = results.every(Boolean);
76
- if (!can) {
77
- return res.status(403).json({ code: 'forbidden', error: 'no permission' });
78
- }
79
- }
80
- } catch (err) {
81
- // eslint-disable-next-line no-console
82
- console.error('Failed to validate query', { err, query });
83
- return res.json({ code: 'internal', error: err.message });
84
- }
85
- }
86
-
87
- return next();
88
- };
89
-
90
- module.exports = { protectGQL };