@abtnode/core 1.16.20-beta-cf6dfce1 → 1.16.20-beta-148929e2

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.
@@ -2483,31 +2483,38 @@ class DiskBlockletManager extends BaseBlockletManager {
2483
2483
  }
2484
2484
  }
2485
2485
 
2486
- async _updateBlockletEnvironment(did) {
2486
+ async getBlockletEnvironments(did) {
2487
2487
  const blockletWithEnv = await this.getBlocklet(did);
2488
- const blocklet = await states.blocklet.getBlocklet(did);
2489
2488
  const nodeInfo = await states.node.read();
2490
-
2491
2489
  const appSystemEnvironments = {
2492
2490
  ...getAppSystemEnvironments(blockletWithEnv, nodeInfo, this.dataDirs),
2493
2491
  ...getAppOverwrittenEnvironments(blockletWithEnv, nodeInfo),
2494
2492
  };
2495
2493
 
2496
2494
  // fill environments to blocklet and components
2497
- blocklet.environments = formatEnvironments({
2498
- ...getComponentSystemEnvironments(blockletWithEnv),
2499
- ...appSystemEnvironments,
2500
- });
2495
+ return {
2496
+ all: formatEnvironments({
2497
+ ...getComponentSystemEnvironments(blockletWithEnv),
2498
+ ...appSystemEnvironments,
2499
+ }),
2500
+ appSystemEnvironments,
2501
+ };
2502
+ }
2503
+
2504
+ async _updateBlockletEnvironment(did) {
2505
+ const blockletWithEnv = await this.getBlocklet(did);
2506
+ const blocklet = await states.blocklet.getBlocklet(did);
2507
+
2508
+ const { all, appSystemEnvironments } = await this.getBlockletEnvironments(did);
2509
+ blocklet.environments = all;
2501
2510
 
2502
2511
  const envMap = {};
2503
2512
  forEachBlockletSync(blockletWithEnv, (child, { ancestors }) => {
2504
2513
  const id = getComponentId(child, ancestors);
2505
2514
  envMap[id] = child;
2506
2515
  });
2507
-
2508
2516
  forEachChildSync(blocklet, (child, { ancestors }) => {
2509
2517
  const id = getComponentId(child, ancestors);
2510
-
2511
2518
  const childWithEnv = envMap[id];
2512
2519
  if (childWithEnv) {
2513
2520
  child.environments = formatEnvironments({
@@ -2516,10 +2523,8 @@ class DiskBlockletManager extends BaseBlockletManager {
2516
2523
  });
2517
2524
  }
2518
2525
  });
2519
-
2520
2526
  // put BLOCKLET_APP_ID at root level for indexing
2521
2527
  blocklet.appDid = appSystemEnvironments.BLOCKLET_APP_ID;
2522
-
2523
2528
  if (!Array.isArray(blocklet.migratedFrom)) {
2524
2529
  blocklet.migratedFrom = [];
2525
2530
  }
@@ -2527,7 +2532,6 @@ class DiskBlockletManager extends BaseBlockletManager {
2527
2532
  if (!blocklet.appPid) {
2528
2533
  blocklet.appPid = appSystemEnvironments.BLOCKLET_APP_PID;
2529
2534
  }
2530
-
2531
2535
  // update state to db
2532
2536
  await states.blockletExtras.updateByDid(did, { appDid: blocklet.appDid });
2533
2537
  return states.blocklet.updateBlocklet(did, blocklet);
package/lib/cert.js CHANGED
@@ -4,50 +4,6 @@ const logger = require('@abtnode/logger')('@abtnode/core:cert');
4
4
  const { EVENTS } = require('@abtnode/constant');
5
5
  const { BlockletEvents } = require('@blocklet/constant');
6
6
 
7
- const onCertExpired = (cert, states) => {
8
- logger.info('send certificate expire notification', { domain: cert.domain });
9
- states.notification.create({
10
- title: 'SSL Certificate Expired',
11
- description: `Your SSL certificate for domain ${cert.domain} has expired, please update it in Blocklet Server`,
12
- severity: 'error',
13
- entityType: 'certificate',
14
- entityId: cert.id,
15
- });
16
- };
17
-
18
- const onCertAboutExpire = (cert, states) => {
19
- logger.info('send certificate about-expire notification', { domain: cert.domain });
20
- states.notification.create({
21
- title: 'SSL Certificate Expire Warning',
22
- description: `Your SSL certificate for domain ${cert.domain} will expire in ${
23
- cert.expireInDays
24
- } days (on ${new Date(cert.validTo).toLocaleString()}), please remember to update it in Blocklet Server`,
25
- severity: 'warning',
26
- entityType: 'certificate',
27
- entityId: cert.id, // eslint-disable-line no-underscore-dangle
28
- });
29
- };
30
-
31
- const onCertIssued = (cert, states) => {
32
- states.notification.create({
33
- title: 'Certificate Issued',
34
- description: `The ${cert.domain} certificate is issued successfully`,
35
- severity: 'success',
36
- entityType: 'certificate',
37
- entityId: cert.id,
38
- });
39
- };
40
-
41
- const onCertIssueFailed = (cert, states) => {
42
- states.notification.create({
43
- title: 'Certificate Issue Failed',
44
- description: `Failed to issue certificate for ${cert.domain}`,
45
- severity: 'error',
46
- entityType: 'certificate',
47
- entityId: cert.id,
48
- });
49
- };
50
-
51
7
  const getDomainFromInput = (input) => {
52
8
  if (Object.prototype.toString.call(input) === '[object Object]') {
53
9
  return input.domain;
@@ -62,15 +18,15 @@ class Cert extends EventEmitter {
62
18
 
63
19
  this.manager = new CertificateManager({ maintainerEmail, dataDir });
64
20
 
65
- this.manager.on('cert.issued', this._onCertIssued.bind(this));
66
- this.manager.on('cert.expired', this._onCertExpired.bind(this));
67
- this.manager.on('cert.about_to_expire', this._onCertAboutToExpire.bind(this));
68
- this.manager.on('cert.error', this._onCertError.bind(this));
21
+ this.manager.on('cert.issued', this.onCertIssued.bind(this));
22
+ this.manager.on('cert.expired', this.onCertExpired.bind(this));
23
+ this.manager.on('cert.about_to_expire', this.onCertAboutToExpire.bind(this));
24
+ this.manager.on('cert.error', this.onCertError.bind(this));
69
25
 
70
26
  /**
71
27
  * Array<{domain: string, did: string}>
72
28
  */
73
- this._blockletDomains = [];
29
+ this.blockletDomains = [];
74
30
  this.states = states;
75
31
  }
76
32
 
@@ -116,18 +72,37 @@ class Cert extends EventEmitter {
116
72
  }
117
73
 
118
74
  /**
119
- * @param {{
120
- * did?:string // blocklet.meta.did
121
- * }}
75
+ * 签发证书
76
+ * @param object data
77
+ * @param string data.domain Domain name
78
+ * @param string data.did Blocklet DID
79
+ * @param object options
80
+ * @param number options.delay Delay time in ms
122
81
  */
123
- issue({ domain, did }) {
82
+ issue({ domain, did, siteId, inBlockletSetup = false }, { delay = 0 } = {}) {
124
83
  logger.info(`generate certificate for ${domain}`);
125
84
 
126
85
  if (did) {
127
- this._bindBlocklet({ domain, did });
86
+ this.bindBlocklet({ domain, did });
128
87
  }
129
88
 
130
- return this.manager.issue(domain);
89
+ return this.manager
90
+ .issue({ domain, siteId, inBlockletSetup }, { delay, metadata: { inBlockletSetup, blockletDid: did } })
91
+ .then(async (cert) => {
92
+ const site = await this.states.site.findOne({ id: siteId });
93
+ for (const d of site.domainAliases) {
94
+ if (d.value === domain) {
95
+ d.certificateId = cert.id;
96
+
97
+ break;
98
+ }
99
+ }
100
+
101
+ await this.states.site.update({ id: siteId }, { $set: { domainAliases: site.domainAliases } });
102
+ logger.info('updated cert id for domain alias', { domain, did, certId: cert.id });
103
+
104
+ return cert;
105
+ });
131
106
  }
132
107
 
133
108
  async upsertByDomain(data) {
@@ -157,11 +132,11 @@ class Cert extends EventEmitter {
157
132
  return this.manager.updateWithoutValidations(id, data);
158
133
  }
159
134
 
160
- _bindBlocklet({ domain, did }) {
135
+ bindBlocklet({ domain, did }) {
161
136
  // only save 100 domains in memory
162
- const list = this._blockletDomains.slice(-100).filter((x) => x.domain !== domain);
137
+ const list = this.blockletDomains.slice(-100).filter((x) => x.domain !== domain);
163
138
  list.push({ domain, did });
164
- this._blockletDomains = list;
139
+ this.blockletDomains = list;
165
140
  }
166
141
 
167
142
  /**
@@ -173,8 +148,8 @@ class Cert extends EventEmitter {
173
148
  * domain: string
174
149
  * }} cert
175
150
  */
176
- _emitEvent(event, cert) {
177
- const blockletDomain = this._blockletDomains.find((x) => x.domain === cert.domain);
151
+ emitEvent(event, cert) {
152
+ const blockletDomain = this.blockletDomains.find((x) => x.domain === cert.domain);
178
153
  if (blockletDomain) {
179
154
  this.emit(event.blocklet, { ...cert, meta: { did: blockletDomain.did } });
180
155
  } else {
@@ -182,24 +157,58 @@ class Cert extends EventEmitter {
182
157
  }
183
158
  }
184
159
 
185
- _onCertIssued(cert) {
186
- this._emitEvent({ blocklet: BlockletEvents.certIssued, server: EVENTS.CERT_ISSUED }, cert);
160
+ onCertIssued(cert) {
161
+ this.emitEvent({ blocklet: BlockletEvents.certIssued, server: EVENTS.CERT_ISSUED }, cert);
187
162
 
188
- onCertIssued(cert, this.states);
163
+ this.states.notification.create({
164
+ title: 'Certificate Issued',
165
+ description: `The ${cert.domain} certificate is issued successfully`,
166
+ severity: 'success',
167
+ entityType: 'certificate',
168
+ entityId: cert.id,
169
+ });
170
+
171
+ logger.info('send certificate issued notification', { domain: cert.domain, certId: cert.id });
189
172
  }
190
173
 
191
- _onCertError(cert) {
192
- this._emitEvent({ blocklet: BlockletEvents.certError, server: EVENTS.CERT_ERROR }, cert);
174
+ onCertError(cert) {
175
+ this.emitEvent({ blocklet: BlockletEvents.certError, server: EVENTS.CERT_ERROR }, cert);
176
+
177
+ this.states.notification.create({
178
+ title: 'Certificate Issue Failed',
179
+ description: `Failed to issue certificate for ${cert.domain}`,
180
+ severity: 'error',
181
+ entityType: 'certificate',
182
+ entityId: cert.id,
183
+ });
193
184
 
194
- onCertIssueFailed(cert, this.states);
185
+ logger.info('send certificate issue failed notification', { domain: cert.domain, certId: cert.id });
195
186
  }
196
187
 
197
- _onCertExpired(cert) {
198
- onCertExpired(cert, this.states);
188
+ onCertExpired(cert) {
189
+ this.states.notification.create({
190
+ title: 'SSL Certificate Expired',
191
+ description: `Your SSL certificate for domain ${cert.domain} has expired, please update it in Blocklet Server`,
192
+ severity: 'error',
193
+ entityType: 'certificate',
194
+ entityId: cert.id,
195
+ });
196
+
197
+ logger.info('send certificate expire notification', { domain: cert.domain, certId: cert.id });
199
198
  }
200
199
 
201
- _onCertAboutToExpire(cert) {
202
- onCertAboutExpire(cert, this.states);
200
+ onCertAboutToExpire(cert) {
201
+ this.states.notification.create({
202
+ title: 'SSL Certificate Expire Warning',
203
+ description: `Your SSL certificate for domain ${cert.domain} will expire in ${
204
+ cert.expireInDays
205
+ } days (on ${new Date(cert.validTo).toLocaleString()}), please remember to update it in Blocklet Server`,
206
+ severity: 'warning',
207
+ entityType: 'certificate',
208
+ entityId: cert.id, // eslint-disable-line no-underscore-dangle
209
+ });
210
+
211
+ logger.info('send certificate about-expire notification', { domain: cert.domain, certId: cert.id });
203
212
  }
204
213
  }
205
214
 
@@ -9,6 +9,7 @@ const {
9
9
  BlockletSource,
10
10
  BlockletEvents,
11
11
  BlockletInternalEvents,
12
+ BLOCKLET_CONFIGURABLE_KEY,
12
13
  } = require('@blocklet/constant');
13
14
  const { EVENTS, BACKUPS } = require('@abtnode/constant');
14
15
  const { NodeMonitSender } = require('../monitor/node-monit-sender');
@@ -380,6 +381,19 @@ module.exports = ({
380
381
  }
381
382
  };
382
383
 
384
+ const updateBlockletAPPURL = async (event, data) => {
385
+ if (data?.metadata?.inBlockletSetup === true && data?.metadata?.blockletDid) {
386
+ await blockletManager.config({
387
+ did: data?.metadata?.blockletDid,
388
+ configs: [{ key: BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_URL, value: `https://${data.domain}` }],
389
+ skipDidDocument: true,
390
+ skipHook: true,
391
+ });
392
+
393
+ logger.info(`update blocklet app url on ${event}`, { domain: data.domain, did: data?.metadata?.blockletDid });
394
+ }
395
+ };
396
+
383
397
  /**
384
398
  *
385
399
  *
@@ -487,6 +501,7 @@ module.exports = ({
487
501
 
488
502
  listen(certManager, EVENTS.CERT_ISSUED, onEvent);
489
503
  listen(certManager, EVENTS.CERT_ERROR, onEvent);
504
+ listen(certManager, BlockletEvents.certIssued, updateBlockletAPPURL);
490
505
  listen(certManager, BlockletEvents.certIssued, onEvent);
491
506
  listen(certManager, BlockletEvents.certError, onEvent);
492
507
 
package/lib/index.js CHANGED
@@ -309,6 +309,7 @@ function ABTNode(options) {
309
309
  getBlocklet: blockletManager.detail.bind(blockletManager),
310
310
  getBlockletDiff: blockletManager.diff.bind(blockletManager),
311
311
  hasBlocklet: blockletManager.hasBlocklet.bind(blockletManager),
312
+ getBlockletEnvironments: blockletManager.getBlockletEnvironments.bind(blockletManager),
312
313
  updateAllBlockletEnvironment: blockletManager.updateAllBlockletEnvironment.bind(blockletManager),
313
314
  setBlockletInitialized: blockletManager.setInitialized.bind(blockletManager),
314
315
  setBlockletOwner: blockletManager.updateOwner.bind(blockletManager),
@@ -186,7 +186,10 @@ class RouterManager extends EventEmitter {
186
186
  return dbSite;
187
187
  }
188
188
 
189
- async addDomainAlias({ id, domainAlias: tmpAlias, force, type, nftDid, chainHost }, context = {}) {
189
+ async addDomainAlias(
190
+ { id, domainAlias: tmpAlias, force, type, nftDid, chainHost, inBlockletSetup = false },
191
+ context = {}
192
+ ) {
190
193
  const domainAlias = await validateAddDomainAlias(tmpAlias, context);
191
194
  const dbSite = await states.site.findOne({ id });
192
195
  if (!dbSite) {
@@ -224,19 +227,28 @@ class RouterManager extends EventEmitter {
224
227
  item.chainHost = chainHost;
225
228
  }
226
229
 
227
- const updateResult = await states.site.update({ id }, { $set: { domainAliases: [...doc.domainAliases, item] } });
228
- logger.debug('add domain alias update result', { id, updateResult, domainAlias });
230
+ await states.site.update({ id }, { $set: { domainAliases: [...doc.domainAliases, item] } });
231
+ logger.info('added domain alias', { id, domainAlias });
229
232
 
233
+ const did = getDidFromDomainGroupName(doc.domain); // TODO: 是不是可靠?
230
234
  if (type === 'nft-domain') {
231
- const did = getDidFromDomainGroupName(doc.domain); // TODO: 是不是可靠?
232
235
  const didDomain = doc.domainAliases.find((x) => isDidDomain(x.value));
233
236
  const blocklet = await states.blocklet.getBlocklet(did);
234
237
  const nodeInfo = await states.node.read();
235
238
 
236
239
  await updateNFTDomainRecord({ name: domainAlias, value: didDomain.value, blocklet, nodeInfo });
237
- logger.info('update nft domain record', { domain: domainAlias, didDomain: '', nftDid, id });
240
+ logger.info('update nft domain record', { domain: domainAlias, didDomain, nftDid, id });
238
241
  }
239
242
 
243
+ this.certManager
244
+ .issue({ domain: domainAlias, did, siteId: id, inBlockletSetup }, { delay: 5000 })
245
+ .then(() => {
246
+ logger.info('issue cert for domain alias', { domain: domainAlias, did });
247
+ })
248
+ .catch((error) => {
249
+ logger.error('issue cert for domain alias failed', { error, domain: domainAlias, did });
250
+ }); // 延迟 5s, 需要等待的原因: Nginx Reload, DNS 生效
251
+
240
252
  const newSite = await states.site.findOne({ id });
241
253
  await attachRuntimeDomainAliases({ sites: newSite, context, node: states.node });
242
254
 
@@ -426,7 +426,6 @@ const getRuntimeEnvironments = (blocklet, nodeEnvironments, ancestors) => {
426
426
  ...getSharedConfigObj((ancestors || [])[0], blocklet),
427
427
  ...blocklet.environmentObj,
428
428
  ...devEnvironments,
429
- BLOCKLET_WEB_PORTS: JSON.stringify(ports),
430
429
  BLOCKLET_MOUNT_POINTS: JSON.stringify(componentsInternalInfo),
431
430
  BLOCKLET_MODE: blocklet.mode || BLOCKLET_MODES.PRODUCTION,
432
431
  BLOCKLET_APP_EK: tmp?.secretKey,
@@ -2,6 +2,7 @@ const path = require('path');
2
2
  const fs = require('fs-extra');
3
3
  const joinUrl = require('url-join');
4
4
  const pick = require('lodash/pick');
5
+ const isEmpty = require('lodash/isEmpty');
5
6
  const {
6
7
  getUserAvatarUrl,
7
8
  extractUserAvatar,
@@ -17,7 +18,7 @@ const { getLauncherUser, getLauncherSession: getLauncherSessionRaw, doRequest }
17
18
  const { createAuthToken, getPassportStatusEndpoint } = require('@abtnode/auth/lib/auth');
18
19
  const { createPassportVC, createPassport, createUserPassport } = require('@abtnode/auth/lib/passport');
19
20
 
20
- const { BlockletStatus, LOGIN_PROVIDER } = require('@blocklet/constant');
21
+ const { LOGIN_PROVIDER } = require('@blocklet/constant');
21
22
  const {
22
23
  WELLKNOWN_SERVICE_PATH_PREFIX,
23
24
  NODE_DATA_DIR_NAME,
@@ -88,8 +89,12 @@ const setupAppOwner = async (node, sessionId) => {
88
89
  if (!blocklet) {
89
90
  throw new Error(`Blocklet not found in server: ${appDid}`);
90
91
  }
91
- if (blocklet.status !== BlockletStatus.installed) {
92
- throw new Error(`Blocklet status not expected: ${appDid}`);
92
+
93
+ // 安装后 blocklet.environments 可能不会立即有值,可以从 node.getBlockletEnvironments 获取
94
+ if (isEmpty(blocklet.environments)) {
95
+ const { all } = await node.getBlockletEnvironments(appDid);
96
+
97
+ blocklet.environments = all;
93
98
  }
94
99
 
95
100
  const { wallet } = getBlockletInfo(blocklet, info.sk);
@@ -193,8 +198,6 @@ const setupAppOwner = async (node, sessionId) => {
193
198
  });
194
199
 
195
200
  await node.setBlockletOwner({ did: appDid, owner: { did: ownerDid, pk: ownerPk } });
196
- await node.endSession({ id: sessionId });
197
- logger.info('Complete install for blocklet', { appDid, ownerDid, sessionId });
198
201
 
199
202
  return {
200
203
  session,
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.16.20-beta-cf6dfce1",
6
+ "version": "1.16.20-beta-148929e2",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,19 +19,19 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "Apache-2.0",
21
21
  "dependencies": {
22
- "@abtnode/analytics": "1.16.20-beta-cf6dfce1",
23
- "@abtnode/auth": "1.16.20-beta-cf6dfce1",
24
- "@abtnode/certificate-manager": "1.16.20-beta-cf6dfce1",
25
- "@abtnode/constant": "1.16.20-beta-cf6dfce1",
26
- "@abtnode/cron": "1.16.20-beta-cf6dfce1",
27
- "@abtnode/logger": "1.16.20-beta-cf6dfce1",
28
- "@abtnode/models": "1.16.20-beta-cf6dfce1",
29
- "@abtnode/queue": "1.16.20-beta-cf6dfce1",
30
- "@abtnode/rbac": "1.16.20-beta-cf6dfce1",
31
- "@abtnode/router-provider": "1.16.20-beta-cf6dfce1",
32
- "@abtnode/static-server": "1.16.20-beta-cf6dfce1",
33
- "@abtnode/timemachine": "1.16.20-beta-cf6dfce1",
34
- "@abtnode/util": "1.16.20-beta-cf6dfce1",
22
+ "@abtnode/analytics": "1.16.20-beta-148929e2",
23
+ "@abtnode/auth": "1.16.20-beta-148929e2",
24
+ "@abtnode/certificate-manager": "1.16.20-beta-148929e2",
25
+ "@abtnode/constant": "1.16.20-beta-148929e2",
26
+ "@abtnode/cron": "1.16.20-beta-148929e2",
27
+ "@abtnode/logger": "1.16.20-beta-148929e2",
28
+ "@abtnode/models": "1.16.20-beta-148929e2",
29
+ "@abtnode/queue": "1.16.20-beta-148929e2",
30
+ "@abtnode/rbac": "1.16.20-beta-148929e2",
31
+ "@abtnode/router-provider": "1.16.20-beta-148929e2",
32
+ "@abtnode/static-server": "1.16.20-beta-148929e2",
33
+ "@abtnode/timemachine": "1.16.20-beta-148929e2",
34
+ "@abtnode/util": "1.16.20-beta-148929e2",
35
35
  "@arcblock/did": "1.18.103",
36
36
  "@arcblock/did-auth": "1.18.103",
37
37
  "@arcblock/did-ext": "^1.18.103",
@@ -42,11 +42,11 @@
42
42
  "@arcblock/pm2-events": "^0.0.5",
43
43
  "@arcblock/validator": "^1.18.103",
44
44
  "@arcblock/vc": "1.18.103",
45
- "@blocklet/constant": "1.16.20-beta-cf6dfce1",
46
- "@blocklet/env": "1.16.20-beta-cf6dfce1",
47
- "@blocklet/meta": "1.16.20-beta-cf6dfce1",
48
- "@blocklet/resolver": "1.16.20-beta-cf6dfce1",
49
- "@blocklet/sdk": "1.16.20-beta-cf6dfce1",
45
+ "@blocklet/constant": "1.16.20-beta-148929e2",
46
+ "@blocklet/env": "1.16.20-beta-148929e2",
47
+ "@blocklet/meta": "1.16.20-beta-148929e2",
48
+ "@blocklet/resolver": "1.16.20-beta-148929e2",
49
+ "@blocklet/sdk": "1.16.20-beta-148929e2",
50
50
  "@did-space/client": "^0.3.41",
51
51
  "@fidm/x509": "^1.2.1",
52
52
  "@ocap/mcrypto": "1.18.103",
@@ -101,5 +101,5 @@
101
101
  "jest": "^27.5.1",
102
102
  "unzipper": "^0.10.11"
103
103
  },
104
- "gitHead": "bc2f0c9c5a39b124c7a7b64ec907527b3e8ccdf1"
104
+ "gitHead": "99e23380f73b63a8e63ce1fe8f75908194df5d80"
105
105
  }