@abtnode/core 1.6.3 → 1.6.7
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.
- package/lib/blocklet/extras.js +26 -1
- package/lib/blocklet/manager/disk.js +126 -131
- package/lib/cert.js +116 -0
- package/lib/index.js +26 -9
- package/lib/migrations/1.6.4-security.js +59 -0
- package/lib/migrations/1.6.5-security.js +60 -0
- package/lib/migrations/1.6.7-certificate.js +30 -0
- package/lib/router/helper.js +99 -107
- package/lib/router/index.js +1 -1
- package/lib/router/manager.js +10 -6
- package/lib/states/base.js +3 -212
- package/lib/states/blocklet-extras.js +20 -15
- package/lib/states/blocklet.js +58 -17
- package/lib/states/index.js +4 -21
- package/lib/states/node.js +9 -3
- package/lib/util/blocklet.js +1 -1
- package/lib/util/index.js +2 -0
- package/package.json +22 -20
package/lib/router/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const get = require('lodash/get');
|
|
2
|
+
const pick = require('lodash/pick');
|
|
2
3
|
const cloneDeep = require('lodash/cloneDeep');
|
|
3
4
|
const {
|
|
4
5
|
DOMAIN_FOR_DEFAULT_SITE,
|
|
@@ -9,7 +10,6 @@ const {
|
|
|
9
10
|
BLOCKLET_SITE_GROUP_SUFFIX,
|
|
10
11
|
} = require('@abtnode/constant');
|
|
11
12
|
const { BLOCKLET_UI_INTERFACES } = require('@blocklet/meta/lib/constants');
|
|
12
|
-
const { pick } = require('lodash');
|
|
13
13
|
const logger = require('@abtnode/logger')('@abtnode/core:router');
|
|
14
14
|
|
|
15
15
|
const expandSites = (sites = []) => {
|
package/lib/router/manager.js
CHANGED
|
@@ -70,8 +70,9 @@ const normalizeRedirectUrl = (url) => {
|
|
|
70
70
|
};
|
|
71
71
|
|
|
72
72
|
class RouterManager extends EventEmitter {
|
|
73
|
-
constructor() {
|
|
73
|
+
constructor({ certManager }) {
|
|
74
74
|
super();
|
|
75
|
+
this.certManager = certManager;
|
|
75
76
|
|
|
76
77
|
// HACK: do not emit any events from CLI
|
|
77
78
|
if (isCLI()) {
|
|
@@ -300,7 +301,10 @@ class RouterManager extends EventEmitter {
|
|
|
300
301
|
await this.validateRouterConfig('updateRoutingRule', { id, rule });
|
|
301
302
|
|
|
302
303
|
// update rules
|
|
303
|
-
const newRules = [
|
|
304
|
+
const newRules = [
|
|
305
|
+
...dbSite.rules.filter((x) => x.groupId !== rule.id || x.id !== rule.id), // 有些路由没有 rule.groupId
|
|
306
|
+
...(await this.getRules(rule)),
|
|
307
|
+
];
|
|
304
308
|
|
|
305
309
|
const updateResult = await states.site.update({ _id: id }, { $set: { rules: newRules } });
|
|
306
310
|
logger.info('update result', { updateResult });
|
|
@@ -363,7 +367,7 @@ class RouterManager extends EventEmitter {
|
|
|
363
367
|
domain,
|
|
364
368
|
});
|
|
365
369
|
logger.info('add certificate result', { domain: newCert.domain });
|
|
366
|
-
this.emit('
|
|
370
|
+
this.emit('cert.added', { type: 'nginx', data: newCert });
|
|
367
371
|
}
|
|
368
372
|
|
|
369
373
|
// eslint-disable-next-line no-unused-vars
|
|
@@ -376,7 +380,7 @@ class RouterManager extends EventEmitter {
|
|
|
376
380
|
const removeResult = await states.certificate.remove({ _id: id });
|
|
377
381
|
|
|
378
382
|
logger.info('delete certificate', { removeResult, domain: tmpCert.domain });
|
|
379
|
-
this.emit('
|
|
383
|
+
this.emit('cert.removed', { type: 'nginx', data: { domain: tmpCert.domain } });
|
|
380
384
|
return {};
|
|
381
385
|
}
|
|
382
386
|
|
|
@@ -386,7 +390,7 @@ class RouterManager extends EventEmitter {
|
|
|
386
390
|
this.fixCertificate(entity);
|
|
387
391
|
this.validateCertificate(entity, entity.domain);
|
|
388
392
|
const dbEntity = await states.certificate.upsert(entity);
|
|
389
|
-
this.emit('
|
|
393
|
+
this.emit('cert.issued', { type: 'nginx', data: dbEntity });
|
|
390
394
|
}
|
|
391
395
|
|
|
392
396
|
findCertificateByDomain(domain) {
|
|
@@ -448,7 +452,7 @@ class RouterManager extends EventEmitter {
|
|
|
448
452
|
}
|
|
449
453
|
|
|
450
454
|
async getMatchedCert(domain) {
|
|
451
|
-
const certs = await
|
|
455
|
+
const certs = await this.certManager.getAll();
|
|
452
456
|
const matchedCert = certs.find((cert) => this.isCertMatchedDomain(cert, domain));
|
|
453
457
|
|
|
454
458
|
if (matchedCert) {
|
package/lib/states/base.js
CHANGED
|
@@ -1,226 +1,17 @@
|
|
|
1
|
-
const
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const util = require('util');
|
|
4
|
-
const { EventEmitter } = require('events');
|
|
5
|
-
const cloneDeep = require('lodash/cloneDeep');
|
|
6
|
-
const DataStore =
|
|
7
|
-
process.env.NODE_ENV === 'test' ? require('@nedb/core') : require('@nedb/multi')(Number(process.env.NEDB_MULTI_PORT));
|
|
1
|
+
const DB = require('@abtnode/db');
|
|
8
2
|
const logger = require('@abtnode/logger')('@abtnode/core:states');
|
|
9
3
|
|
|
10
4
|
const { isCLI } = require('../util');
|
|
11
5
|
|
|
12
|
-
class BaseState extends
|
|
6
|
+
class BaseState extends DB {
|
|
13
7
|
constructor(baseDir, options) {
|
|
14
|
-
super();
|
|
8
|
+
super(baseDir, options);
|
|
15
9
|
|
|
16
10
|
// HACK: do not emit any events from CLI
|
|
17
11
|
if (isCLI() && process.env.NODE_ENV !== 'test') {
|
|
18
12
|
this.emit = (name) => logger.debug('stopped state db event in CLI', name);
|
|
19
13
|
}
|
|
20
|
-
|
|
21
|
-
const dbOptions = options.db || {};
|
|
22
|
-
this.filename = path.join(baseDir, options.filename);
|
|
23
|
-
this.options = Object.freeze(cloneDeep(options));
|
|
24
|
-
this.db = new DataStore({
|
|
25
|
-
filename: this.filename,
|
|
26
|
-
timestampData: true,
|
|
27
|
-
...dbOptions,
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
logger.info('initialized', { filename: this.filename });
|
|
31
|
-
|
|
32
|
-
this.ready = false;
|
|
33
|
-
this.readyCallbacks = [];
|
|
34
|
-
this.db.loadDatabase((err) => {
|
|
35
|
-
if (err) {
|
|
36
|
-
logger.error(`failed to load disk database ${this.filename}`, { error: err });
|
|
37
|
-
console.error(err);
|
|
38
|
-
} else {
|
|
39
|
-
this.ready = true;
|
|
40
|
-
if (this.readyCallbacks.length) {
|
|
41
|
-
this.readyCallbacks.forEach((x) => x());
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
this.asyncDB = new Proxy(this.db, {
|
|
47
|
-
get(target, property) {
|
|
48
|
-
if (typeof target[property] === 'function') {
|
|
49
|
-
return util
|
|
50
|
-
.promisify((...args) => {
|
|
51
|
-
const cb = args[args.length - 1];
|
|
52
|
-
const rest = args.slice(0, args.length - 1);
|
|
53
|
-
|
|
54
|
-
target[property](...rest, (err, ...result) => {
|
|
55
|
-
if (err) {
|
|
56
|
-
return cb(err);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (result.length === 1) {
|
|
60
|
-
return cb(null, result[0]);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return cb(null, result);
|
|
64
|
-
});
|
|
65
|
-
})
|
|
66
|
-
.bind(target);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return target[property];
|
|
70
|
-
},
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
onReady(cb) {
|
|
75
|
-
if (this.ready) {
|
|
76
|
-
cb();
|
|
77
|
-
} else {
|
|
78
|
-
this.readyCallbacks.push(cb);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
createNotification(payload) {
|
|
83
|
-
if (this.notification && typeof this.notification.create === 'function') {
|
|
84
|
-
this.notification.create(payload);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
paginate(conditions, sort, paging) {
|
|
89
|
-
const { pageSize: size = 20, page = 1 } = paging || {};
|
|
90
|
-
const pageSize = Math.min(100, size);
|
|
91
|
-
|
|
92
|
-
return new Promise((resolve, reject) => {
|
|
93
|
-
this.db
|
|
94
|
-
.find(conditions)
|
|
95
|
-
.sort(sort)
|
|
96
|
-
.exec((err, docs) => {
|
|
97
|
-
if (err) {
|
|
98
|
-
return reject(err);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const pageCount = Math.ceil(docs.length / pageSize);
|
|
102
|
-
const total = docs.length;
|
|
103
|
-
const skip = (page - 1) * pageSize;
|
|
104
|
-
const list = docs.slice(skip, skip + pageSize);
|
|
105
|
-
|
|
106
|
-
list.forEach((doc) => {
|
|
107
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
108
|
-
doc.id = doc._id;
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
return resolve({
|
|
112
|
-
list,
|
|
113
|
-
paging: {
|
|
114
|
-
total,
|
|
115
|
-
pageSize,
|
|
116
|
-
pageCount,
|
|
117
|
-
page,
|
|
118
|
-
},
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
async updateById(id, updates, options = {}) {
|
|
125
|
-
const [, doc] = await this.asyncDB.update({ _id: id }, updates, {
|
|
126
|
-
multi: false,
|
|
127
|
-
upsert: false,
|
|
128
|
-
returnUpdatedDocs: true,
|
|
129
|
-
...options,
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
return doc;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
update(...args) {
|
|
136
|
-
if (args.length === 0) {
|
|
137
|
-
throw new Error('param is required by update method');
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (typeof args[0] === 'string') {
|
|
141
|
-
return this.updateById(...args);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return this.asyncDB.update(args[0], args[1], { returnUpdatedDocs: true, ...(args[2] || {}) });
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
count(conditions = {}) {
|
|
148
|
-
return new Promise((resolve, reject) => {
|
|
149
|
-
this.db.count(conditions, (err, num) => {
|
|
150
|
-
if (err) {
|
|
151
|
-
return reject(err);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return resolve(num);
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
remove(conditions = {}, options = { multi: false }) {
|
|
160
|
-
return new Promise((resolve, reject) => {
|
|
161
|
-
this.db.remove(conditions, options, (err, num) => {
|
|
162
|
-
if (err) {
|
|
163
|
-
return reject(err);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return resolve(num);
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
reset() {
|
|
172
|
-
fs.unlinkSync(this.filename);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
find(...args) {
|
|
176
|
-
if (args.length === 0) {
|
|
177
|
-
return this.asyncDB.find({});
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return this.asyncDB.find(...args);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
findOne(...args) {
|
|
184
|
-
if (args.length === 0) {
|
|
185
|
-
return this.asyncDB.findOne({});
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return this.asyncDB.findOne(...args);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
insert(...args) {
|
|
192
|
-
return this.asyncDB.insert(...args);
|
|
193
14
|
}
|
|
194
15
|
}
|
|
195
16
|
|
|
196
|
-
/**
|
|
197
|
-
* Rename _id field name to id, this method has side effects
|
|
198
|
-
* @param {object} entities
|
|
199
|
-
*/
|
|
200
|
-
const renameIdFiledName = (entities, from = '_id', to = 'id') => {
|
|
201
|
-
/* eslint-disable no-underscore-dangle, no-param-reassign */
|
|
202
|
-
|
|
203
|
-
if (!entities) {
|
|
204
|
-
return entities;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
const mapEntity = (entity) => {
|
|
208
|
-
if (entity[from]) {
|
|
209
|
-
entity[to] = entity[from];
|
|
210
|
-
delete entity[from];
|
|
211
|
-
}
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
if (!Array.isArray(entities)) {
|
|
215
|
-
mapEntity(entities);
|
|
216
|
-
return entities;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
entities.forEach(mapEntity);
|
|
220
|
-
|
|
221
|
-
return entities;
|
|
222
|
-
};
|
|
223
|
-
|
|
224
|
-
BaseState.renameIdFiledName = renameIdFiledName;
|
|
225
|
-
|
|
226
17
|
module.exports = BaseState;
|
|
@@ -6,7 +6,9 @@ const camelCase = require('lodash/camelCase');
|
|
|
6
6
|
|
|
7
7
|
const BaseState = require('./base');
|
|
8
8
|
|
|
9
|
-
const { mergeConfigs } = require('../blocklet/extras');
|
|
9
|
+
const { mergeConfigs, parseConfigs } = require('../blocklet/extras');
|
|
10
|
+
|
|
11
|
+
const noop = (k) => (v) => v[k];
|
|
10
12
|
|
|
11
13
|
class BlockletExtrasState extends BaseState {
|
|
12
14
|
constructor(baseDir, options = {}) {
|
|
@@ -17,12 +19,13 @@ class BlockletExtrasState extends BaseState {
|
|
|
17
19
|
{
|
|
18
20
|
name: 'configs',
|
|
19
21
|
beforeSet: mergeConfigs,
|
|
22
|
+
afterGet: parseConfigs,
|
|
20
23
|
},
|
|
21
24
|
|
|
22
25
|
// setting
|
|
23
26
|
{
|
|
24
27
|
name: 'settings',
|
|
25
|
-
beforeSet: (old, cur) => {
|
|
28
|
+
beforeSet: ({ old, cur }) => {
|
|
26
29
|
const merged = { ...old, ...cur };
|
|
27
30
|
Object.keys(merged).forEach((key) => {
|
|
28
31
|
if (merged[key] === undefined || merged[key] === null) {
|
|
@@ -67,22 +70,23 @@ class BlockletExtrasState extends BaseState {
|
|
|
67
70
|
|
|
68
71
|
generateGetFn(extra) {
|
|
69
72
|
return async (did) => {
|
|
70
|
-
const {
|
|
73
|
+
const { dek } = this.options;
|
|
74
|
+
const { name, afterGet = noop('data') } = extra;
|
|
71
75
|
const item = await this.asyncDB.findOne({ did });
|
|
72
|
-
return item ? item[name] : item;
|
|
76
|
+
return afterGet({ data: item ? item[name] : item, did, dek });
|
|
73
77
|
};
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
generateSetFn(extra) {
|
|
77
81
|
return async (did, data) => {
|
|
78
|
-
const {
|
|
79
|
-
const
|
|
82
|
+
const { dek } = this.options;
|
|
83
|
+
const { name, beforeSet = noop('cur') } = extra;
|
|
80
84
|
const item = await this.asyncDB.findOne({ did });
|
|
81
85
|
|
|
82
86
|
if (!item) {
|
|
83
87
|
const insertData = {
|
|
84
88
|
did,
|
|
85
|
-
[name]:
|
|
89
|
+
[name]: beforeSet({ old: undefined, cur: data, did, dek }),
|
|
86
90
|
};
|
|
87
91
|
|
|
88
92
|
const info = await this.asyncDB.insert(insertData);
|
|
@@ -93,7 +97,7 @@ class BlockletExtrasState extends BaseState {
|
|
|
93
97
|
const itemNameValue = item[name];
|
|
94
98
|
const updated = await this.update(item._id, {
|
|
95
99
|
$set: {
|
|
96
|
-
[name]:
|
|
100
|
+
[name]: beforeSet({ old: itemNameValue, cur: data, did, dek }),
|
|
97
101
|
},
|
|
98
102
|
});
|
|
99
103
|
return updated[name];
|
|
@@ -132,22 +136,23 @@ class BlockletExtrasState extends BaseState {
|
|
|
132
136
|
|
|
133
137
|
generateGetChildFn(extra) {
|
|
134
138
|
return async (did, childDid) => {
|
|
135
|
-
const {
|
|
139
|
+
const { dek } = this.options;
|
|
140
|
+
const { name, afterGet = noop('data') } = extra;
|
|
136
141
|
const item = await this.asyncDB.findOne({ did });
|
|
137
142
|
const children = (item || {}).children || [];
|
|
138
143
|
const subItem = (children || []).find((x) => x.did === childDid);
|
|
139
|
-
return subItem ? subItem[name] : null;
|
|
144
|
+
return afterGet({ data: subItem ? subItem[name] : null, did, dek });
|
|
140
145
|
};
|
|
141
146
|
}
|
|
142
147
|
|
|
143
148
|
generateSetChildFn(extra) {
|
|
144
149
|
return async (did, childDid, data) => {
|
|
145
|
-
const {
|
|
146
|
-
const
|
|
150
|
+
const { dek } = this.options;
|
|
151
|
+
const { name, beforeSet = noop('cur') } = extra;
|
|
147
152
|
const item = await this.asyncDB.findOne({ did });
|
|
148
153
|
|
|
149
154
|
if (!item) {
|
|
150
|
-
const newData =
|
|
155
|
+
const newData = beforeSet({ old: undefined, cur: data, did, dek });
|
|
151
156
|
const insertData = {
|
|
152
157
|
did,
|
|
153
158
|
children: [
|
|
@@ -168,7 +173,7 @@ class BlockletExtrasState extends BaseState {
|
|
|
168
173
|
const subItem = (children || []).find((x) => x.did === childDid);
|
|
169
174
|
|
|
170
175
|
if (!subItem) {
|
|
171
|
-
const newData =
|
|
176
|
+
const newData = beforeSet({ old: undefined, cur: data, did, dek });
|
|
172
177
|
await this.update(item._id, {
|
|
173
178
|
$addToSet: {
|
|
174
179
|
children: {
|
|
@@ -182,7 +187,7 @@ class BlockletExtrasState extends BaseState {
|
|
|
182
187
|
return newData;
|
|
183
188
|
}
|
|
184
189
|
|
|
185
|
-
const newData =
|
|
190
|
+
const newData = beforeSet({ old: subItem[name], cur: data, did, dek });
|
|
186
191
|
|
|
187
192
|
children.forEach((x) => {
|
|
188
193
|
if (x.did === childDid) {
|
package/lib/states/blocklet.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable no-async-promise-executor */
|
|
1
2
|
/* eslint-disable no-await-in-loop */
|
|
2
3
|
/* eslint-disable function-paren-newline */
|
|
3
4
|
/* eslint-disable no-underscore-dangle */
|
|
@@ -5,6 +6,7 @@ const omit = require('lodash/omit');
|
|
|
5
6
|
const uniq = require('lodash/uniq');
|
|
6
7
|
const detectPort = require('detect-port');
|
|
7
8
|
const Lock = require('@abtnode/util/lib/lock');
|
|
9
|
+
const security = require('@abtnode/util/lib/security');
|
|
8
10
|
const { fixPerson, fixInterfaces } = require('@blocklet/meta/lib/fix');
|
|
9
11
|
const {
|
|
10
12
|
BlockletStatus,
|
|
@@ -27,6 +29,40 @@ const getMaxPort = (ports = {}) => Math.max(Object.values(ports).map(Number));
|
|
|
27
29
|
const getExternalPortsFromMeta = (meta) =>
|
|
28
30
|
(meta.interfaces || []).map((x) => x.port && x.port.external).filter(Boolean);
|
|
29
31
|
|
|
32
|
+
const formatBlocklet = (blocklet, phase, dek) => {
|
|
33
|
+
forEachBlocklet(
|
|
34
|
+
blocklet,
|
|
35
|
+
(b) => {
|
|
36
|
+
if (b.meta) {
|
|
37
|
+
fixPerson(b.meta);
|
|
38
|
+
fixInterfaces(b.meta);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
b.children = b.children || [];
|
|
42
|
+
|
|
43
|
+
if (!b.environments || !b.meta || !dek) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
['BLOCKLET_APP_SK'].forEach((key) => {
|
|
48
|
+
const env = b.environments.find((x) => x.key === key);
|
|
49
|
+
if (!env) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (phase === 'onUpdate' && env.value.indexOf('0x') === 0) {
|
|
53
|
+
env.value = security.encrypt(env.value, b.meta.did, dek);
|
|
54
|
+
}
|
|
55
|
+
if (phase === 'onRead' && env.value.indexOf('0x') === -1) {
|
|
56
|
+
env.value = security.decrypt(env.value, b.meta.did, dek);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
{ sync: true }
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
return blocklet;
|
|
64
|
+
};
|
|
65
|
+
|
|
30
66
|
class BlockletState extends BaseState {
|
|
31
67
|
/**
|
|
32
68
|
* Creates an instance of BlockletState
|
|
@@ -48,14 +84,7 @@ class BlockletState extends BaseState {
|
|
|
48
84
|
return reject(err);
|
|
49
85
|
}
|
|
50
86
|
|
|
51
|
-
|
|
52
|
-
// TODO: this only exists for backward compatible
|
|
53
|
-
fixPerson(doc.meta);
|
|
54
|
-
fixInterfaces(doc.meta);
|
|
55
|
-
doc.children = doc.children || [];
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return resolve(doc);
|
|
87
|
+
return resolve(doc ? formatBlocklet(doc, 'onRead', this.options.dek) : null);
|
|
59
88
|
});
|
|
60
89
|
});
|
|
61
90
|
}
|
|
@@ -70,14 +99,7 @@ class BlockletState extends BaseState {
|
|
|
70
99
|
return reject(err);
|
|
71
100
|
}
|
|
72
101
|
|
|
73
|
-
return resolve(
|
|
74
|
-
docs.filter(Boolean).map((doc) => {
|
|
75
|
-
// TODO: this only exists for backward compatible
|
|
76
|
-
fixPerson(doc.meta);
|
|
77
|
-
fixInterfaces(doc.meta);
|
|
78
|
-
return doc;
|
|
79
|
-
})
|
|
80
|
-
);
|
|
102
|
+
return resolve(docs.filter(Boolean).map((doc) => formatBlocklet(doc, 'onRead', this.options.dek)));
|
|
81
103
|
});
|
|
82
104
|
});
|
|
83
105
|
}
|
|
@@ -114,7 +136,6 @@ class BlockletState extends BaseState {
|
|
|
114
136
|
} = {}) {
|
|
115
137
|
return this.getBlocklet(did).then(
|
|
116
138
|
(doc) =>
|
|
117
|
-
// eslint-disable-next-line no-async-promise-executor
|
|
118
139
|
new Promise(async (resolve, reject) => {
|
|
119
140
|
if (doc) {
|
|
120
141
|
reject(new Error('Blocklet already added'));
|
|
@@ -165,6 +186,26 @@ class BlockletState extends BaseState {
|
|
|
165
186
|
);
|
|
166
187
|
}
|
|
167
188
|
|
|
189
|
+
updateBlocklet(did, updates) {
|
|
190
|
+
return this.getBlocklet(did).then(
|
|
191
|
+
(doc) =>
|
|
192
|
+
new Promise(async (resolve, reject) => {
|
|
193
|
+
if (!doc) {
|
|
194
|
+
reject(new Error('Blocklet does not exist'));
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
const formatted = formatBlocklet(updates, 'onUpdate', this.options.dek);
|
|
200
|
+
const newDoc = await this.updateById(doc._id, { $set: formatted });
|
|
201
|
+
resolve(newDoc);
|
|
202
|
+
} catch (err) {
|
|
203
|
+
reject(err);
|
|
204
|
+
}
|
|
205
|
+
})
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
168
209
|
upgradeBlocklet({ meta, source, deployedFrom, children } = {}) {
|
|
169
210
|
return this.getBlocklet(meta.did).then(
|
|
170
211
|
(doc) =>
|
package/lib/states/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
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');
|
|
@@ -12,8 +12,6 @@ const SessionState = require('./session');
|
|
|
12
12
|
const ExtrasState = require('./blocklet-extras');
|
|
13
13
|
const CacheState = require('./cache');
|
|
14
14
|
|
|
15
|
-
const states = {};
|
|
16
|
-
|
|
17
15
|
const init = (dataDirs, options) => {
|
|
18
16
|
const notificationState = new NotificationState(dataDirs.core, options);
|
|
19
17
|
const nodeState = new NodeState(dataDirs.core, options, dataDirs, notificationState);
|
|
@@ -28,7 +26,7 @@ const init = (dataDirs, options) => {
|
|
|
28
26
|
const extrasState = new ExtrasState(dataDirs.core, options);
|
|
29
27
|
const cacheState = new CacheState(dataDirs.core, options);
|
|
30
28
|
|
|
31
|
-
|
|
29
|
+
return {
|
|
32
30
|
node: nodeState,
|
|
33
31
|
blocklet: blockletState,
|
|
34
32
|
notification: notificationState,
|
|
@@ -41,22 +39,7 @@ const init = (dataDirs, options) => {
|
|
|
41
39
|
session: sessionState,
|
|
42
40
|
blockletExtras: extrasState,
|
|
43
41
|
cache: cacheState,
|
|
44
|
-
}
|
|
42
|
+
};
|
|
45
43
|
};
|
|
46
44
|
|
|
47
|
-
module.exports =
|
|
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);
|
package/lib/states/node.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/* eslint-disable no-underscore-dangle */
|
|
2
|
+
const semver = require('semver');
|
|
2
3
|
const omit = require('lodash/omit');
|
|
3
4
|
const isEqual = require('lodash/isEqual');
|
|
4
5
|
const isEmpty = require('lodash/isEmpty');
|
|
6
|
+
const security = require('@abtnode/util/lib/security');
|
|
5
7
|
const { isFromPublicKey } = require('@arcblock/did');
|
|
6
8
|
const logger = require('@abtnode/logger')('@abtnode/core:node');
|
|
7
9
|
const { ROUTER_PROVIDER_NONE, NODE_MODES, DISK_ALERT_THRESHOLD_PERCENT } = require('@abtnode/constant');
|
|
@@ -58,6 +60,7 @@ class NodeState extends BaseState {
|
|
|
58
60
|
*/
|
|
59
61
|
read() {
|
|
60
62
|
return new Promise((resolve, reject) => {
|
|
63
|
+
const { nodeDid, dek } = this.options;
|
|
61
64
|
this.db.findOne({ did: this.options.nodeDid }, (err, record) => {
|
|
62
65
|
if (err) {
|
|
63
66
|
// eslint-disable-next-line no-console
|
|
@@ -66,6 +69,10 @@ class NodeState extends BaseState {
|
|
|
66
69
|
}
|
|
67
70
|
|
|
68
71
|
if (record) {
|
|
72
|
+
if (dek) {
|
|
73
|
+
record.sk = security.decrypt(record.sk, record.did, dek);
|
|
74
|
+
}
|
|
75
|
+
|
|
69
76
|
return resolve(record);
|
|
70
77
|
}
|
|
71
78
|
|
|
@@ -74,7 +81,6 @@ class NodeState extends BaseState {
|
|
|
74
81
|
description,
|
|
75
82
|
nodeSk,
|
|
76
83
|
nodePk,
|
|
77
|
-
nodeDid,
|
|
78
84
|
nodeOwner,
|
|
79
85
|
port,
|
|
80
86
|
version,
|
|
@@ -100,7 +106,7 @@ class NodeState extends BaseState {
|
|
|
100
106
|
name,
|
|
101
107
|
description,
|
|
102
108
|
pk: nodePk,
|
|
103
|
-
sk: nodeSk,
|
|
109
|
+
sk: dek ? security.encrypt(nodeSk, nodeDid, dek) : nodeSk,
|
|
104
110
|
did: nodeDid,
|
|
105
111
|
initialized,
|
|
106
112
|
version,
|
|
@@ -158,7 +164,7 @@ class NodeState extends BaseState {
|
|
|
158
164
|
|
|
159
165
|
cleanupDirtyUpgradeState() {
|
|
160
166
|
return this.read().then((doc) => {
|
|
161
|
-
if (doc.nextVersion
|
|
167
|
+
if (doc.nextVersion && semver.lte(doc.nextVersion, doc.version)) {
|
|
162
168
|
const updates = { nextVersion: '', upgradeSessionId: '' };
|
|
163
169
|
|
|
164
170
|
// FIXME: this may cause the node exit some mode unexpectedly if it is not being upgraded
|
package/lib/util/blocklet.js
CHANGED
|
@@ -192,7 +192,6 @@ const fillBlockletConfigs = (blocklet, configs) => {
|
|
|
192
192
|
acc[x.key] = x.value;
|
|
193
193
|
return acc;
|
|
194
194
|
}, {});
|
|
195
|
-
blocklet.userEnvironments = blocklet.configObj; // deprecated
|
|
196
195
|
blocklet.environmentObj = (blocklet.environments || []).reduce((acc, x) => {
|
|
197
196
|
acc[x.key] = x.value;
|
|
198
197
|
return acc;
|
|
@@ -308,6 +307,7 @@ const getRuntimeEnvironments = (blocklet, nodeEnvironments) => {
|
|
|
308
307
|
|
|
309
308
|
return {
|
|
310
309
|
...blocklet.environmentObj,
|
|
310
|
+
...blocklet.configObj,
|
|
311
311
|
...nodeEnvironments,
|
|
312
312
|
...safeNodeEnvironments,
|
|
313
313
|
};
|
package/lib/util/index.js
CHANGED
|
@@ -332,6 +332,8 @@ const getDataDirs = (dataDir) => ({
|
|
|
332
332
|
tmp: path.join(dataDir, 'tmp'),
|
|
333
333
|
blocklets: path.join(dataDir, 'blocklets'),
|
|
334
334
|
services: path.join(dataDir, 'services'),
|
|
335
|
+
modules: path.join(dataDir, 'modules'),
|
|
336
|
+
certManagerModule: path.join(dataDir, 'modules', 'certificate-manager'),
|
|
335
337
|
});
|
|
336
338
|
|
|
337
339
|
// Ensure data dir for Blocklet Server exists
|