@abtnode/core 1.15.17 → 1.16.0-beta-8ee536d7

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 (119) hide show
  1. package/lib/api/node.js +67 -69
  2. package/lib/api/team.js +386 -55
  3. package/lib/blocklet/downloader/blocklet-downloader.js +226 -0
  4. package/lib/blocklet/downloader/bundle-downloader.js +272 -0
  5. package/lib/blocklet/downloader/constants.js +3 -0
  6. package/lib/blocklet/downloader/resolve-download.js +199 -0
  7. package/lib/blocklet/extras.js +83 -26
  8. package/lib/blocklet/hooks.js +18 -65
  9. package/lib/blocklet/manager/base.js +10 -16
  10. package/lib/blocklet/manager/disk.js +1680 -1566
  11. package/lib/blocklet/manager/helper/install-application-from-backup.js +177 -0
  12. package/lib/blocklet/manager/helper/install-application-from-dev.js +94 -0
  13. package/lib/blocklet/manager/helper/install-application-from-general.js +188 -0
  14. package/lib/blocklet/manager/helper/install-component-from-dev.js +84 -0
  15. package/lib/blocklet/manager/helper/install-component-from-upload.js +181 -0
  16. package/lib/blocklet/manager/helper/install-component-from-url.js +173 -0
  17. package/lib/blocklet/manager/helper/migrate-application-to-struct-v2.js +450 -0
  18. package/lib/blocklet/manager/helper/rollback-cache.js +41 -0
  19. package/lib/blocklet/manager/helper/upgrade-components.js +152 -0
  20. package/lib/blocklet/migration.js +30 -52
  21. package/lib/blocklet/storage/backup/audit-log.js +27 -0
  22. package/lib/blocklet/storage/backup/base.js +62 -0
  23. package/lib/blocklet/storage/backup/blocklet-extras.js +92 -0
  24. package/lib/blocklet/storage/backup/blocklet.js +70 -0
  25. package/lib/blocklet/storage/backup/blocklets.js +74 -0
  26. package/lib/blocklet/storage/backup/data.js +19 -0
  27. package/lib/blocklet/storage/backup/logs.js +24 -0
  28. package/lib/blocklet/storage/backup/routing-rule.js +19 -0
  29. package/lib/blocklet/storage/backup/spaces.js +240 -0
  30. package/lib/blocklet/storage/restore/base.js +67 -0
  31. package/lib/blocklet/storage/restore/blocklet-extras.js +86 -0
  32. package/lib/blocklet/storage/restore/blocklet.js +56 -0
  33. package/lib/blocklet/storage/restore/blocklets.js +43 -0
  34. package/lib/blocklet/storage/restore/logs.js +21 -0
  35. package/lib/blocklet/storage/restore/spaces.js +156 -0
  36. package/lib/blocklet/storage/utils/hash.js +51 -0
  37. package/lib/blocklet/storage/utils/zip.js +43 -0
  38. package/lib/cert.js +206 -0
  39. package/lib/event.js +237 -64
  40. package/lib/index.js +191 -83
  41. package/lib/migrations/1.0.21-update-config.js +1 -1
  42. package/lib/migrations/1.0.22-max-memory.js +1 -1
  43. package/lib/migrations/1.0.25.js +1 -1
  44. package/lib/migrations/1.0.32-update-config.js +1 -1
  45. package/lib/migrations/1.0.33-blocklets.js +1 -1
  46. package/lib/migrations/1.5.20-registry.js +15 -0
  47. package/lib/migrations/1.6.17-blocklet-children.js +48 -0
  48. package/lib/migrations/1.6.21-rename-ip-echo-domain.js +35 -0
  49. package/lib/migrations/1.6.4-security.js +59 -0
  50. package/lib/migrations/1.6.5-security.js +60 -0
  51. package/lib/migrations/1.6.9-update-node-info-and-certificate.js +38 -0
  52. package/lib/migrations/1.7.1-blocklet-setup.js +18 -0
  53. package/lib/migrations/1.7.12-blocklet-meta.js +51 -0
  54. package/lib/migrations/1.7.15-blocklet-bundle-source.js +42 -0
  55. package/lib/migrations/1.7.20-blocklet-component.js +41 -0
  56. package/lib/migrations/1.8.33-blocklet-mem-limit.js +20 -0
  57. package/lib/migrations/README.md +1 -1
  58. package/lib/migrations/index.js +6 -2
  59. package/lib/monitor/blocklet-runtime-monitor.js +200 -0
  60. package/lib/monitor/get-history-list.js +37 -0
  61. package/lib/monitor/node-runtime-monitor.js +228 -0
  62. package/lib/router/helper.js +576 -500
  63. package/lib/router/index.js +85 -21
  64. package/lib/router/manager.js +146 -187
  65. package/lib/states/README.md +36 -1
  66. package/lib/states/access-key.js +39 -17
  67. package/lib/states/audit-log.js +462 -0
  68. package/lib/states/base.js +4 -213
  69. package/lib/states/blocklet-extras.js +195 -138
  70. package/lib/states/blocklet.js +371 -110
  71. package/lib/states/cache.js +8 -6
  72. package/lib/states/challenge.js +5 -5
  73. package/lib/states/index.js +19 -36
  74. package/lib/states/migration.js +4 -4
  75. package/lib/states/node.js +135 -46
  76. package/lib/states/notification.js +22 -35
  77. package/lib/states/session.js +17 -9
  78. package/lib/states/site.js +50 -25
  79. package/lib/states/user.js +74 -20
  80. package/lib/states/webhook.js +10 -6
  81. package/lib/team/manager.js +124 -7
  82. package/lib/util/blocklet.js +1223 -246
  83. package/lib/util/chain.js +1 -1
  84. package/lib/util/default-node-config.js +5 -23
  85. package/lib/util/disk-monitor.js +13 -10
  86. package/lib/util/domain-status.js +84 -15
  87. package/lib/util/get-accessible-external-node-ip.js +2 -2
  88. package/lib/util/get-domain-for-blocklet.js +13 -0
  89. package/lib/util/get-meta-from-url.js +33 -0
  90. package/lib/util/index.js +207 -272
  91. package/lib/util/ip.js +6 -0
  92. package/lib/util/maintain.js +233 -0
  93. package/lib/util/public-to-store.js +85 -0
  94. package/lib/util/ready.js +1 -1
  95. package/lib/util/requirement.js +28 -9
  96. package/lib/util/reset-node.js +22 -7
  97. package/lib/util/router.js +13 -0
  98. package/lib/util/rpc.js +16 -0
  99. package/lib/util/store.js +179 -0
  100. package/lib/util/sysinfo.js +44 -0
  101. package/lib/util/ua.js +54 -0
  102. package/lib/validators/blocklet-extra.js +24 -0
  103. package/lib/validators/node.js +25 -12
  104. package/lib/validators/permission.js +16 -1
  105. package/lib/validators/role.js +17 -3
  106. package/lib/validators/router.js +40 -20
  107. package/lib/validators/trusted-passport.js +1 -0
  108. package/lib/validators/util.js +22 -5
  109. package/lib/webhook/index.js +45 -35
  110. package/lib/webhook/sender/index.js +5 -0
  111. package/lib/webhook/sender/slack/index.js +1 -1
  112. package/lib/webhook/sender/wallet/index.js +48 -0
  113. package/package.json +54 -36
  114. package/lib/blocklet/registry.js +0 -205
  115. package/lib/states/https-cert.js +0 -67
  116. package/lib/util/get-ip-dns-domain-for-blocklet.js +0 -19
  117. package/lib/util/service.js +0 -66
  118. package/lib/util/upgrade.js +0 -178
  119. /package/lib/{queue.js → util/queue.js} +0 -0
@@ -9,17 +9,17 @@ class ChallengeState extends BaseState {
9
9
  /**
10
10
  * Creates an instance of ChallengeState
11
11
  * @param {string} baseDir
12
- * @param {object} options
12
+ * @param {object} config
13
13
  * @memberof ChallengeState
14
14
  */
15
- constructor(baseDir, options = {}) {
16
- super(baseDir, { filename: 'challenge.db', ...options });
15
+ constructor(baseDir, config = {}) {
16
+ super(baseDir, { filename: 'challenge.db', ...config });
17
17
  }
18
18
 
19
19
  generate() {
20
20
  return new Promise((resolve, reject) => {
21
21
  const challenge = stripHexPrefix(Mcrypto.getRandomBytes(16)).toUpperCase();
22
- this.db.insert({ challenge }, (err, data) => {
22
+ this.insert({ challenge }, (err, data) => {
23
23
  if (err) {
24
24
  logger.error('generating error', { error: err });
25
25
  return reject(err);
@@ -38,7 +38,7 @@ class ChallengeState extends BaseState {
38
38
  return;
39
39
  }
40
40
 
41
- this.db.findOne({ challenge }, (err, data) => {
41
+ this.findOne({ challenge }, (err, data) => {
42
42
  if (err) {
43
43
  logger.error('error find challenge', { error: err });
44
44
  }
@@ -1,38 +1,35 @@
1
- const BaseState = require('./base');
1
+ const stateFactory = require('@abtnode/db/lib/factory');
2
2
  const NodeState = require('./node');
3
3
  const ChallengeState = require('./challenge');
4
4
  const BlockletState = require('./blocklet');
5
5
  const NotificationState = require('./notification');
6
6
  const SiteState = require('./site');
7
- const HttpsCertState = require('./https-cert');
8
7
  const AccessKeyState = require('./access-key');
9
8
  const WebhookState = require('./webhook');
10
9
  const MigrationState = require('./migration');
11
10
  const SessionState = require('./session');
12
11
  const ExtrasState = require('./blocklet-extras');
13
12
  const CacheState = require('./cache');
13
+ const AuditLogState = require('./audit-log');
14
14
 
15
- const states = {};
15
+ const init = (dataDirs, config) => {
16
+ const notificationState = new NotificationState(dataDirs.core, config);
17
+ const nodeState = new NodeState(dataDirs.core, config, dataDirs, notificationState);
18
+ const blockletState = new BlockletState(dataDirs.core, config);
19
+ const challengeState = new ChallengeState(dataDirs.core, config);
20
+ const siteState = new SiteState(dataDirs.core, config);
21
+ const accessKeyState = new AccessKeyState(dataDirs.core, config);
22
+ const webhookState = new WebhookState(dataDirs.core, config);
23
+ const migrationState = new MigrationState(dataDirs.core, config);
24
+ const sessionState = new SessionState(dataDirs.core, config);
25
+ const extrasState = new ExtrasState(dataDirs.core, config);
26
+ const cacheState = new CacheState(dataDirs.core, config);
27
+ const auditLogState = new AuditLogState(dataDirs.core, config);
16
28
 
17
- const init = (dataDirs, options) => {
18
- const notificationState = new NotificationState(dataDirs.core, options);
19
- const nodeState = new NodeState(dataDirs.core, options, dataDirs, notificationState);
20
- const blockletState = new BlockletState(dataDirs.core, options);
21
- const challengeState = new ChallengeState(dataDirs.core, options);
22
- const siteState = new SiteState(dataDirs.core, options);
23
- const httpsCertState = new HttpsCertState(dataDirs.core, options);
24
- const accessKeyState = new AccessKeyState(dataDirs.core, options);
25
- const webhookState = new WebhookState(dataDirs.core, options);
26
- const migrationState = new MigrationState(dataDirs.core, options);
27
- const sessionState = new SessionState(dataDirs.core, options);
28
- const extrasState = new ExtrasState(dataDirs.core, options);
29
- const cacheState = new CacheState(dataDirs.core, options);
30
-
31
- Object.assign(states, {
29
+ return {
32
30
  node: nodeState,
33
31
  blocklet: blockletState,
34
32
  notification: notificationState,
35
- certificate: httpsCertState,
36
33
  site: siteState,
37
34
  accessKey: accessKeyState,
38
35
  webhook: webhookState,
@@ -41,22 +38,8 @@ const init = (dataDirs, options) => {
41
38
  session: sessionState,
42
39
  blockletExtras: extrasState,
43
40
  cache: cacheState,
44
- });
41
+ auditLog: auditLogState,
42
+ };
45
43
  };
46
44
 
47
- module.exports = new Proxy(
48
- {},
49
- {
50
- get(target, prop) {
51
- if (prop === 'init') {
52
- return init;
53
- }
54
-
55
- if (states[prop] instanceof BaseState) {
56
- return states[prop];
57
- }
58
-
59
- throw new Error(`State ${String(prop)} may not be initialized`);
60
- },
61
- }
62
- );
45
+ module.exports = stateFactory(init);
@@ -4,14 +4,14 @@ const logger = require('@abtnode/logger')('@abtnode/core:states:migration');
4
4
  const BaseState = require('./base');
5
5
 
6
6
  class MigrationState extends BaseState {
7
- constructor(baseDir, options = {}) {
8
- super(baseDir, { filename: 'migration.db', ...options });
7
+ constructor(baseDir, config = {}) {
8
+ super(baseDir, { filename: 'migration.db', ...config });
9
9
  }
10
10
 
11
11
  // eslint-disable-next-line no-unused-vars
12
12
  async isExecuted({ script, version }, context) {
13
13
  try {
14
- const item = await this.asyncDB.findOne({ script, version });
14
+ const item = await this.findOne({ script, version });
15
15
  return !!item;
16
16
  } catch (err) {
17
17
  logger.error('failed to find migration', { script, version });
@@ -22,7 +22,7 @@ class MigrationState extends BaseState {
22
22
  // eslint-disable-next-line no-unused-vars
23
23
  async markExecuted({ script, version }, context) {
24
24
  try {
25
- const result = await this.asyncDB.insert({ script, version, executedAt: new Date() });
25
+ const result = await this.insert({ script, version, executedAt: new Date() });
26
26
  logger.info('mark executed', result);
27
27
  return result;
28
28
  } catch (error) {
@@ -1,10 +1,11 @@
1
1
  /* eslint-disable no-underscore-dangle */
2
+ const semver = require('semver');
2
3
  const omit = require('lodash/omit');
3
- const isEqual = require('lodash/isEqual');
4
4
  const isEmpty = require('lodash/isEmpty');
5
+ const security = require('@abtnode/util/lib/security');
5
6
  const { isFromPublicKey } = require('@arcblock/did');
6
7
  const logger = require('@abtnode/logger')('@abtnode/core:node');
7
- const { ROUTER_PROVIDER_NONE, NODE_MODES, DISK_ALERT_THRESHOLD_PERCENT } = require('@abtnode/constant');
8
+ const { NODE_MODES, DISK_ALERT_THRESHOLD_PERCENT, EVENTS, SERVER_STATUS } = require('@abtnode/constant');
8
9
 
9
10
  const BaseState = require('./base');
10
11
  const { validateOwner } = require('../util');
@@ -14,23 +15,23 @@ class NodeState extends BaseState {
14
15
  /**
15
16
  * Creates an instance of NodeState.
16
17
  * @param {string} baseDir
17
- * @param {object} options
18
+ * @param {object} config
18
19
  * @memberof NodeState
19
20
  */
20
- constructor(baseDir, options = {}, dataDirs = {}, notification) {
21
- super(baseDir, { filename: 'node.db', ...options });
21
+ constructor(baseDir, config = {}, dataDirs = {}, notification) {
22
+ super(baseDir, { filename: 'node.db', ...config });
22
23
 
23
24
  // Initialize the store
24
- if (!options.nodeSk) {
25
+ if (!config.nodeSk) {
25
26
  throw new Error('Can not initialize node store without valid nodeSk');
26
27
  }
27
- if (!options.nodePk) {
28
+ if (!config.nodePk) {
28
29
  throw new Error('Can not initialize node store without valid nodePk');
29
30
  }
30
- if (!options.nodeDid) {
31
+ if (!config.nodeDid) {
31
32
  throw new Error('Can not initialize node store without valid nodeDid');
32
33
  }
33
- if (!isFromPublicKey(options.nodeDid, options.nodePk)) {
34
+ if (!isFromPublicKey(config.nodeDid, config.nodePk)) {
34
35
  throw new Error('Node pk and did does not match');
35
36
  }
36
37
 
@@ -38,7 +39,7 @@ class NodeState extends BaseState {
38
39
  this.notification = notification;
39
40
 
40
41
  this.onReady(() => {
41
- this.db.ensureIndex({ fieldName: 'did', unique: true }, (err) => {
42
+ this.ensureIndex({ fieldName: 'did', unique: true }, (err) => {
42
43
  if (err) {
43
44
  console.error('Failed to ensure unique index', err);
44
45
  }
@@ -47,7 +48,10 @@ class NodeState extends BaseState {
47
48
  }
48
49
 
49
50
  isInitialized(doc) {
50
- return !!doc.nodeOwner;
51
+ const isOwnerConnected = !!doc.nodeOwner;
52
+ const isControlledBy3rdParty =
53
+ !doc.enablePassportIssuance && Array.isArray(doc.trustedPassports) && doc.trustedPassports.length > 0;
54
+ return isOwnerConnected || isControlledBy3rdParty;
51
55
  }
52
56
 
53
57
  /**
@@ -58,7 +62,8 @@ class NodeState extends BaseState {
58
62
  */
59
63
  read() {
60
64
  return new Promise((resolve, reject) => {
61
- this.db.findOne({ did: this.options.nodeDid }, (err, record) => {
65
+ const { nodeDid, dek } = this.config;
66
+ this.findOne({ did: nodeDid }, (err, record) => {
62
67
  if (err) {
63
68
  // eslint-disable-next-line no-console
64
69
  console.error(err);
@@ -66,6 +71,10 @@ class NodeState extends BaseState {
66
71
  }
67
72
 
68
73
  if (record) {
74
+ if (dek) {
75
+ record.sk = security.decrypt(record.sk, record.did, dek);
76
+ }
77
+
69
78
  return resolve(record);
70
79
  }
71
80
 
@@ -74,33 +83,37 @@ class NodeState extends BaseState {
74
83
  description,
75
84
  nodeSk,
76
85
  nodePk,
77
- nodeDid,
78
86
  nodeOwner,
79
87
  port,
80
88
  version,
81
- routing = { provider: ROUTER_PROVIDER_NONE },
89
+ routing = { provider: 'default' },
82
90
  docker,
83
91
  mode,
84
92
  runtimeConfig,
85
93
  ownerNft,
86
- launcherInfo,
87
- } = this.options;
94
+ launcher,
95
+ didRegistry,
96
+ didDomain,
97
+ enablePassportIssuance = true,
98
+ trustedPassports = [],
99
+ webWalletUrl,
100
+ } = this.config;
88
101
 
89
102
  if (nodeOwner && !validateOwner(nodeOwner)) {
90
103
  return reject(new Error('Node owner is invalid'));
91
104
  }
92
105
 
93
- const initialized = this.isInitialized({ nodeOwner });
106
+ const initialized = this.isInitialized({ nodeOwner, enablePassportIssuance, trustedPassports });
94
107
 
95
108
  return getDefaultConfigs()
96
109
  .then((defaultConfigs) =>
97
- this.db.insert(
110
+ this.insert(
98
111
  {
99
112
  ...(defaultConfigs || {}),
100
113
  name,
101
114
  description,
102
115
  pk: nodePk,
103
- sk: nodeSk,
116
+ sk: dek ? security.encrypt(nodeSk, nodeDid, dek) : nodeSk,
104
117
  did: nodeDid,
105
118
  initialized,
106
119
  version,
@@ -111,11 +124,17 @@ class NodeState extends BaseState {
111
124
  routing,
112
125
  docker,
113
126
  mode,
114
- enableWelcomePage: true,
127
+ enableWelcomePage: mode !== NODE_MODES.SERVERLESS,
115
128
  runtimeConfig,
116
129
  ownerNft,
117
130
  diskAlertThreshold: DISK_ALERT_THRESHOLD_PERCENT,
118
- launcherInfo: launcherInfo || undefined,
131
+ launcher: launcher || undefined,
132
+ didRegistry,
133
+ didDomain,
134
+ enablePassportIssuance,
135
+ trustedPassports,
136
+ customBlockletNumber: 0,
137
+ webWalletUrl,
119
138
  },
120
139
  async (e, data) => {
121
140
  if (e) {
@@ -128,6 +147,10 @@ class NodeState extends BaseState {
128
147
  }
129
148
 
130
149
  logger.info('create', { data });
150
+ if (dek) {
151
+ data.sk = security.decrypt(data.sk, data.did, dek);
152
+ }
153
+
131
154
  return resolve(data);
132
155
  }
133
156
  )
@@ -140,8 +163,8 @@ class NodeState extends BaseState {
140
163
  // FIXME: 这个接口比较危险,可能会修改一些本不应该修改的字段,后续需要考虑改进
141
164
  async updateNodeInfo(entity = {}) {
142
165
  const record = await this.read();
143
- const updateResult = await this.update(record._id, { $set: omit(entity, ['ownerNft']) });
144
- this.emit('node.updated', updateResult, record);
166
+ const updateResult = await this.update(record._id, { $set: omit(entity, ['ownerNft', 'sk']) });
167
+ this.emit(EVENTS.NODE_UPDATED, updateResult, record);
145
168
  return updateResult;
146
169
  }
147
170
 
@@ -151,14 +174,14 @@ class NodeState extends BaseState {
151
174
  }
152
175
 
153
176
  const nodeInfo = await this.updateNodeInfo({ routing: entity });
154
- this.emit('routing.updated', nodeInfo);
177
+ this.emit(EVENTS.ROUTING_UPDATED, nodeInfo);
155
178
 
156
179
  return nodeInfo;
157
180
  }
158
181
 
159
- cleanupDirtyUpgradeState() {
182
+ cleanupDirtyMaintainState() {
160
183
  return this.read().then((doc) => {
161
- if (doc.nextVersion === doc.version) {
184
+ if (doc.nextVersion && semver.lte(doc.nextVersion, doc.version)) {
162
185
  const updates = { nextVersion: '', upgradeSessionId: '' };
163
186
 
164
187
  // FIXME: this may cause the node exit some mode unexpectedly if it is not being upgraded
@@ -174,33 +197,58 @@ class NodeState extends BaseState {
174
197
  });
175
198
  }
176
199
 
177
- addNodeOwner(owner) {
178
- if (owner && !validateOwner(owner)) {
200
+ async addOwner(owner, doc) {
201
+ const initialized = this.isInitialized({ nodeOwner: owner });
202
+
203
+ if (this.notification && typeof this.notification.setDefaultReceiver === 'function') {
204
+ this.notification.setDefaultReceiver(owner.did);
205
+ }
206
+
207
+ const updateResult = await this.update(doc._id, {
208
+ $set: { nodeOwner: owner, initialized, initializedAt: initialized ? new Date() : null },
209
+ });
210
+
211
+ this.emit(EVENTS.NODE_ADDED_OWNER, updateResult);
212
+
213
+ return updateResult;
214
+ }
215
+
216
+ async updateNodeOwner({ nodeOwner, ownerNft }) {
217
+ if (!validateOwner(nodeOwner)) {
179
218
  throw new Error('Node owner is invalid');
180
219
  }
181
220
 
182
- return this.read().then(async (doc) => {
183
- if (doc.nodeOwner) {
184
- if (isEqual(owner, doc.nodeOwner)) {
185
- return doc;
186
- }
221
+ const doc = await this.read();
187
222
 
188
- throw new Error('Cannot set owner because owner already exists');
189
- }
223
+ const initialized = this.isInitialized({ nodeOwner });
190
224
 
191
- const initialized = this.isInitialized({ nodeOwner: owner });
225
+ if (this.notification && typeof this.notification.setDefaultReceiver === 'function') {
226
+ this.notification.setDefaultReceiver(nodeOwner.did);
227
+ }
192
228
 
193
- if (this.notification && typeof this.notification.setDefaultReceiver === 'function') {
194
- this.notification.setDefaultReceiver(owner.did);
195
- }
229
+ const entities = { nodeOwner, initialized, initializedAt: initialized ? new Date() : null };
230
+ if (ownerNft) {
231
+ entities.ownerNft = ownerNft;
232
+ }
196
233
 
197
- const updateResult = await this.update(doc._id, {
198
- $set: { nodeOwner: owner, initialized, initializedAt: initialized ? new Date() : null },
199
- });
234
+ const updateResult = await this.update(doc._id, {
235
+ $set: entities,
236
+ });
237
+
238
+ this.emit(EVENTS.NODE_ADDED_OWNER, updateResult);
239
+
240
+ return updateResult;
241
+ }
242
+
243
+ async updateNftHolder(holder) {
244
+ if (!holder) {
245
+ throw new Error('NFT holder can not be empty');
246
+ }
200
247
 
201
- this.emit('node.addedOwner', updateResult);
248
+ const doc = await this.read();
202
249
 
203
- return updateResult;
250
+ return this.update(doc._id, {
251
+ $set: { 'ownerNft.holder': holder },
204
252
  });
205
253
  }
206
254
 
@@ -234,18 +282,59 @@ class NodeState extends BaseState {
234
282
  return this.updateNodeInfo({ previousMode: '', mode: info.previousMode });
235
283
  }
236
284
 
285
+ async setMode(mode) {
286
+ if (Object.values(NODE_MODES).includes(mode) === false) {
287
+ throw new Error(`Can not update server to unsupported mode: ${mode}`);
288
+ }
289
+
290
+ return this.updateNodeInfo({ previousMode: '', mode });
291
+ }
292
+
237
293
  async getEnvironments() {
238
294
  return this.read().then((info) => ({
239
295
  ABT_NODE: info.version,
240
296
  ABT_NODE_DID: info.did,
297
+ ABT_NODE_SK: info.sk,
241
298
  ABT_NODE_PK: info.pk,
242
299
  ABT_NODE_PORT: info.port,
243
300
  ABT_NODE_SERVICE_PORT: process.env.ABT_NODE_SERVICE_PORT,
301
+ ABT_NODE_MODE: info.mode,
244
302
  }));
245
303
  }
246
304
 
247
- getBlockletRegistry() {
248
- return this.read().then((info) => info.blockletRegistryList.find((item) => item.selected).url);
305
+ // deprecated
306
+ async increaseCustomBlockletNumber() {
307
+ const { _id, customBlockletNumber = 0 } = await this.read();
308
+ const num = customBlockletNumber + 1;
309
+ await this.update(_id, { $set: { customBlockletNumber: num } });
310
+ return num;
311
+ }
312
+
313
+ async updateGateway(gateway) {
314
+ const [, nodeInfo] = await this.update(
315
+ {},
316
+ { $set: { 'routing.requestLimit': gateway.requestLimit, 'routing.cacheEnabled': gateway.cacheEnabled } }
317
+ );
318
+
319
+ this.emit(EVENTS.RELOAD_GATEWAY, nodeInfo);
320
+
321
+ return nodeInfo.routing;
322
+ }
323
+
324
+ async updateStatus(status) {
325
+ if (!Object.values(SERVER_STATUS).includes(status)) {
326
+ throw new Error('status is invalid');
327
+ }
328
+
329
+ const record = await this.read();
330
+ await this.update(record._id, { $set: { status } });
331
+
332
+ record.status = status;
333
+ return record;
334
+ }
335
+
336
+ async resetStatus() {
337
+ return this.updateStatus(SERVER_STATUS.RUNNING);
249
338
  }
250
339
  }
251
340
 
@@ -1,14 +1,15 @@
1
1
  const get = require('lodash/get');
2
2
  const logger = require('@abtnode/logger')('@abtnode/core:states:notification');
3
+ const { EVENTS } = require('@abtnode/constant');
3
4
 
4
5
  const BaseState = require('./base');
5
6
 
6
7
  class NotificationState extends BaseState {
7
- constructor(baseDir, options = {}) {
8
- super(baseDir, { filename: 'notification.db', ...options });
8
+ constructor(baseDir, config = {}) {
9
+ super(baseDir, { filename: 'notification.db', ...config });
9
10
 
10
- this.defaultSender = options.defaultSender || '';
11
- this.defaultReceiver = options.defaultReceiver || '';
11
+ this.defaultSender = config.defaultSender || '';
12
+ this.defaultReceiver = config.defaultReceiver || '';
12
13
  }
13
14
 
14
15
  setDefaultSender(sender) {
@@ -27,7 +28,7 @@ class NotificationState extends BaseState {
27
28
  });
28
29
 
29
30
  return new Promise((resolve, reject) => {
30
- this.db.insert(
31
+ this.insert(
31
32
  {
32
33
  sender: payload.sender || this.defaultSender,
33
34
  receiver: payload.receiver || this.defaultReceiver,
@@ -46,14 +47,14 @@ class NotificationState extends BaseState {
46
47
  }
47
48
 
48
49
  logger.info('create', { data });
49
- this.emit('notification.create', data);
50
+ this.emit(EVENTS.NOTIFICATION_CREATE, data);
50
51
  return resolve(data);
51
52
  }
52
53
  );
53
54
  });
54
55
  }
55
56
 
56
- async find({ receiver, sender, read, paging } = {}, context) {
57
+ async findPaginated({ receiver, sender, read, paging } = {}, context) {
57
58
  const conditions = {};
58
59
  // eslint-disable-next-line no-param-reassign
59
60
  receiver = receiver || get(context, 'user.did');
@@ -75,44 +76,30 @@ class NotificationState extends BaseState {
75
76
  }
76
77
 
77
78
  // eslint-disable-next-line no-unused-vars
78
- read({ id }, context) {
79
+ async read({ id }, context) {
79
80
  const idList = id.split(',').map((x) => x.trim());
80
81
  logger.info('mark notification as read', { idList });
81
82
 
82
- return new Promise((resolve, reject) => {
83
- this.db.update(
84
- { _id: { $in: idList } },
85
- { $set: { read: true } },
86
- { multi: true, upsert: false, returnUpdatedDocs: false },
87
- (err, numAffected) => {
88
- if (err) {
89
- return reject(err);
90
- }
83
+ const [numAffected] = await this.update(
84
+ { _id: { $in: idList } },
85
+ { $set: { read: true } },
86
+ { multi: true, upsert: false, returnUpdatedDocs: false }
87
+ );
91
88
 
92
- return resolve(numAffected);
93
- }
94
- );
95
- });
89
+ return numAffected;
96
90
  }
97
91
 
98
92
  // eslint-disable-next-line no-unused-vars
99
- unread({ id }, context) {
93
+ async unread({ id }, context) {
100
94
  const idList = Array.isArray(id) ? id : [id];
101
95
 
102
- return new Promise((resolve, reject) => {
103
- this.db.update(
104
- { _id: { $in: idList } },
105
- { $set: { read: false } },
106
- { multi: true, upsert: false, returnUpdatedDocs: false },
107
- (err, numAffected) => {
108
- if (err) {
109
- return reject(err);
110
- }
96
+ const [numAffected] = await this.update(
97
+ { _id: { $in: idList } },
98
+ { $set: { read: false } },
99
+ { multi: true, upsert: false, returnUpdatedDocs: false }
100
+ );
111
101
 
112
- return resolve(numAffected);
113
- }
114
- );
115
- });
102
+ return numAffected;
116
103
  }
117
104
  }
118
105
 
@@ -5,18 +5,26 @@ const BaseState = require('./base');
5
5
  * This db is used to save session data generated in a http session. the session is NOT user auth session.
6
6
  */
7
7
  class SessionState extends BaseState {
8
- constructor(baseDir, options = {}) {
9
- super(baseDir, { filename: 'session.db', ...options });
8
+ constructor(baseDir, config = {}) {
9
+ super(baseDir, { filename: 'session.db', ...config });
10
10
 
11
- this.db.ensureIndex({ fieldName: 'createdAt' }, (error) => {
12
- if (error) {
13
- logger.error('ensure index failed', { error });
14
- }
11
+ this.onReady(() => {
12
+ this.ensureIndex({ fieldName: 'createdAt' }, (error) => {
13
+ if (error) {
14
+ logger.error('ensure createdAt index failed', { error });
15
+ }
16
+ });
17
+
18
+ this.ensureIndex({ fieldName: 'expireDate', expireAfterSeconds: 0 }, (error) => {
19
+ if (error) {
20
+ logger.error('ensure expireDate index failed', { error });
21
+ }
22
+ });
15
23
  });
16
24
  }
17
25
 
18
26
  async start(initialData) {
19
- const { _id, ...data } = await this.asyncDB.insert(initialData);
27
+ const { _id, ...data } = await this.insert(initialData);
20
28
  return { id: _id, ...data };
21
29
  }
22
30
 
@@ -29,7 +37,7 @@ class SessionState extends BaseState {
29
37
 
30
38
  // eslint-disable-next-line no-underscore-dangle
31
39
  delete exist._id;
32
- await this.asyncDB.update({ _id: id }, { $set: { ...exist, ...data } }, { multi: false, upsert: false });
40
+ await super.update({ _id: id }, { $set: { ...exist, ...data } }, { multi: false, upsert: false });
33
41
 
34
42
  return { id, ...exist, ...data };
35
43
  }
@@ -51,7 +59,7 @@ class SessionState extends BaseState {
51
59
  throw new Error(`Session does not exist: ${id}`);
52
60
  }
53
61
 
54
- await this.asyncDB.remove({ _id: id });
62
+ await this.remove({ _id: id });
55
63
 
56
64
  data.id = id;
57
65
  return data;