@abtnode/core 1.16.6-beta-4562aa60 → 1.16.6-beta-eaa4d39d
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/api/team.js +38 -2
- package/lib/blocklet/manager/disk.js +67 -36
- package/lib/blocklet/manager/helper/install-application-from-dev.js +5 -3
- package/lib/blocklet/manager/helper/install-component-from-url.js +3 -0
- package/lib/blocklet/storage/backup/spaces.js +5 -1
- package/lib/blocklet/storage/restore/spaces.js +5 -1
- package/lib/crons/check-new-version.js +68 -0
- package/lib/{util/disk-monitor.js → crons/monitor-disk-usage.js} +2 -2
- package/lib/crons/rotate-pm2-logs/index.js +41 -0
- package/lib/crons/rotate-pm2-logs/script.js +56 -0
- package/lib/index.js +8 -4
- package/lib/processes/updater.js +160 -0
- package/lib/router/helper.js +4 -7
- package/lib/states/node.js +1 -0
- package/lib/states/user.js +237 -8
- package/lib/util/blocklet.js +67 -10
- package/lib/util/ip.js +0 -6
- package/lib/util/maintain.js +9 -64
- package/lib/util/rotator.js +194 -0
- package/lib/util/rpc.js +69 -8
- package/lib/validators/user.js +44 -0
- package/package.json +32 -27
package/lib/util/maintain.js
CHANGED
|
@@ -1,59 +1,15 @@
|
|
|
1
1
|
/* eslint-disable no-param-reassign */
|
|
2
|
-
const semver = require('semver');
|
|
3
2
|
const sleep = require('@abtnode/util/lib/sleep');
|
|
4
3
|
const SysInfo = require('systeminformation');
|
|
5
4
|
const { NODE_MODES, NODE_MAINTAIN_PROGRESS, EVENTS } = require('@abtnode/constant');
|
|
6
|
-
const listNpmPackageVersion = require('@abtnode/util/lib/list-npm-package-version');
|
|
7
5
|
const Lock = require('@abtnode/util/lib/lock');
|
|
8
6
|
const logger = require('@abtnode/logger')('@abtnode/core:maintain');
|
|
9
7
|
|
|
10
8
|
const states = require('../states');
|
|
11
|
-
const
|
|
9
|
+
const { doRpcCall, startRpcServer } = require('./rpc');
|
|
12
10
|
|
|
13
11
|
const lock = new Lock('node-upgrade-lock');
|
|
14
12
|
|
|
15
|
-
// eslint-disable-next-line no-unused-vars
|
|
16
|
-
const checkNewVersion = async (params, context) => {
|
|
17
|
-
try {
|
|
18
|
-
const info = await states.node.read();
|
|
19
|
-
|
|
20
|
-
if (!process.env.ABT_NODE_PACKAGE_NAME) {
|
|
21
|
-
logger.error('ABT_NODE_PACKAGE_NAME name was not found in environment');
|
|
22
|
-
return '';
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const versions = await listNpmPackageVersion(process.env.ABT_NODE_PACKAGE_NAME);
|
|
26
|
-
if (Array.isArray(versions) && versions.length) {
|
|
27
|
-
const latestVersion = versions[0].version;
|
|
28
|
-
if (semver.gt(latestVersion, info.version)) {
|
|
29
|
-
// if (semver.gte(latestVersion, info.version)) {
|
|
30
|
-
logger.info('New version found for Blocklet Server', {
|
|
31
|
-
latestVersion,
|
|
32
|
-
currentVersion: info.version,
|
|
33
|
-
nextVersion: info.nextVersion,
|
|
34
|
-
});
|
|
35
|
-
await states.node.updateNodeInfo({ nextVersion: latestVersion });
|
|
36
|
-
await states.notification.create({
|
|
37
|
-
title: 'Blocklet Server upgrade available',
|
|
38
|
-
description: 'A new and improved version of blocklet server is now available',
|
|
39
|
-
entityType: 'node',
|
|
40
|
-
severity: 'info',
|
|
41
|
-
sticky: true,
|
|
42
|
-
action: '/settings/about',
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
return latestVersion;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return '';
|
|
50
|
-
} catch (err) {
|
|
51
|
-
logger.error('Failed to check new version for Blocklet Server', { error: err });
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return '';
|
|
55
|
-
};
|
|
56
|
-
|
|
57
13
|
const triggerMaintain = async ({ action, next }) => {
|
|
58
14
|
if (['upgrade', 'restart'].includes(action) === false) {
|
|
59
15
|
throw new Error(`Unrecognized server maintain action: ${action}`);
|
|
@@ -98,6 +54,8 @@ const triggerMaintain = async ({ action, next }) => {
|
|
|
98
54
|
throw new Error(`${action} aborted due to invalid session: ${sessionId}`);
|
|
99
55
|
}
|
|
100
56
|
|
|
57
|
+
await startRpcServer();
|
|
58
|
+
|
|
101
59
|
process.nextTick(async () => {
|
|
102
60
|
await next(session);
|
|
103
61
|
});
|
|
@@ -134,7 +92,7 @@ const resumeMaintain = async (session) => {
|
|
|
134
92
|
|
|
135
93
|
// 2. install new version
|
|
136
94
|
if (session.stage === NODE_MAINTAIN_PROGRESS.INSTALLING) {
|
|
137
|
-
const result = await
|
|
95
|
+
const result = await doRpcCall({ command: 'install', version: to });
|
|
138
96
|
logger.info('new version installed', { from, to, sessionId });
|
|
139
97
|
if (result.code !== 0) {
|
|
140
98
|
await sleep(3000);
|
|
@@ -144,7 +102,7 @@ const resumeMaintain = async (session) => {
|
|
|
144
102
|
|
|
145
103
|
// 2. verify new version
|
|
146
104
|
if (session.stage === NODE_MAINTAIN_PROGRESS.VERIFYING) {
|
|
147
|
-
const result = await
|
|
105
|
+
const result = await doRpcCall({ command: 'verify', version: to });
|
|
148
106
|
await sleep(3000);
|
|
149
107
|
if (result.code === 0) {
|
|
150
108
|
logger.info('new version verified', { from, to, sessionId });
|
|
@@ -164,6 +122,7 @@ const resumeMaintain = async (session) => {
|
|
|
164
122
|
await states.node.updateNodeInfo({ nextVersion: '', version: from, upgradeSessionId: '' });
|
|
165
123
|
try {
|
|
166
124
|
await states.node.exitMode(NODE_MODES.MAINTENANCE);
|
|
125
|
+
await doRpcCall({ command: 'shutdown' });
|
|
167
126
|
} catch (error) {
|
|
168
127
|
logger.error('Failed to rollback', { error });
|
|
169
128
|
}
|
|
@@ -177,7 +136,7 @@ const resumeMaintain = async (session) => {
|
|
|
177
136
|
await sleep(3000);
|
|
178
137
|
await goNextState(NODE_MAINTAIN_PROGRESS.CLEANUP, true);
|
|
179
138
|
await sleep(3000);
|
|
180
|
-
await
|
|
139
|
+
await doRpcCall({ command: 'restart', dataDir: process.env.ABT_NODE_DATA_DIR });
|
|
181
140
|
await lock.release();
|
|
182
141
|
return; // we should abort here and resume after restart
|
|
183
142
|
}
|
|
@@ -190,6 +149,7 @@ const resumeMaintain = async (session) => {
|
|
|
190
149
|
await states.node.updateNodeInfo({ nextVersion: '', version: to, upgradeSessionId: '' });
|
|
191
150
|
try {
|
|
192
151
|
await states.node.exitMode(NODE_MODES.MAINTENANCE);
|
|
152
|
+
await doRpcCall({ command: 'shutdown' });
|
|
193
153
|
} catch (error) {
|
|
194
154
|
logger.error('Failed to exit maintenance mode', { error });
|
|
195
155
|
}
|
|
@@ -215,19 +175,4 @@ const isBeingMaintained = async () => {
|
|
|
215
175
|
return session;
|
|
216
176
|
};
|
|
217
177
|
|
|
218
|
-
|
|
219
|
-
name: 'check-update',
|
|
220
|
-
time: '0 0 8 * * *', // check every day
|
|
221
|
-
// time: '0 */5 * * * *', // check every 5 minutes
|
|
222
|
-
fn: async () => {
|
|
223
|
-
const info = await states.node.read();
|
|
224
|
-
if (!info.autoUpgrade) {
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
checkNewVersion();
|
|
229
|
-
},
|
|
230
|
-
options: { runOnInit: false },
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
module.exports = { getCron, checkNewVersion, resumeMaintain, triggerMaintain, isBeingMaintained };
|
|
178
|
+
module.exports = { resumeMaintain, triggerMaintain, isBeingMaintained };
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base on: https://github.com/keymetrics/pm2-logrotate
|
|
3
|
+
*/
|
|
4
|
+
const fs = require('fs-extra');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const moment = require('moment-timezone');
|
|
7
|
+
const zlib = require('zlib');
|
|
8
|
+
const log = require('@abtnode/logger');
|
|
9
|
+
|
|
10
|
+
const buildLogger =
|
|
11
|
+
(func) =>
|
|
12
|
+
(...args) => {
|
|
13
|
+
if (typeof args[0] === 'string') {
|
|
14
|
+
func(`pm2.log.rotate.${args[0]}`, ...args.slice(1));
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
func('pm2.log.rotate', ...args);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// eslint-disable-next-line no-console
|
|
22
|
+
const logInfo = buildLogger(console.info);
|
|
23
|
+
const logError = buildLogger(console.error);
|
|
24
|
+
|
|
25
|
+
module.exports = class LogRotate {
|
|
26
|
+
constructor({ compress, dateFormat, tz, retain } = {}) {
|
|
27
|
+
this.compress = compress;
|
|
28
|
+
this.dateFormat = dateFormat;
|
|
29
|
+
this.tz = tz;
|
|
30
|
+
this.retain = retain;
|
|
31
|
+
this.compressedFileFormat = '.gz';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
getLimitSize(maxSize) {
|
|
35
|
+
if (!maxSize) {
|
|
36
|
+
return 1024 * 1024 * 10; // 10M
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (typeof maxSize === 'number') {
|
|
40
|
+
return maxSize;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (typeof maxSize !== 'string') {
|
|
44
|
+
throw new Error('maxSize must be a string or number');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// eslint-disable-next-line no-param-reassign
|
|
48
|
+
maxSize = maxSize.trim();
|
|
49
|
+
|
|
50
|
+
const unit = maxSize[maxSize.length - 1].toUpperCase();
|
|
51
|
+
if (unit === 'G') {
|
|
52
|
+
return parseInt(maxSize, 10) * 1024 * 1024 * 1024;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (unit === 'M') {
|
|
56
|
+
return parseInt(maxSize, 10) * 1024 * 1024;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (unit === 'K') {
|
|
60
|
+
return parseInt(maxSize, 10) * 1024;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return parseInt(maxSize, 10);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Apply the rotation process of the log file.
|
|
68
|
+
*
|
|
69
|
+
* @param {string} file
|
|
70
|
+
*/
|
|
71
|
+
proceed(file, callback = () => {}) {
|
|
72
|
+
// set default final time
|
|
73
|
+
let finalTime = moment().subtract(1, 'day').format(this.dateFormat);
|
|
74
|
+
// check for a timezone
|
|
75
|
+
if (this.tz) {
|
|
76
|
+
try {
|
|
77
|
+
finalTime = moment().tz(this.tz).subtract(1, 'day').format(this.dateFormat);
|
|
78
|
+
} catch (err) {
|
|
79
|
+
// use default
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const filename = path.basename(file, path.extname(file));
|
|
84
|
+
const dirname = path.dirname(file);
|
|
85
|
+
const extName = this.compress ? `.log${this.compressedFileFormat}` : '.log';
|
|
86
|
+
|
|
87
|
+
let finalName = `${path.join(dirname, filename)}-${finalTime}${extName}`;
|
|
88
|
+
|
|
89
|
+
// 这种情况是为了兼容,之间的日志文件名中的日志大了一天,所以升级时旧数据可能存在重复
|
|
90
|
+
if (fs.existsSync(finalName)) {
|
|
91
|
+
finalName = `${path.join(dirname, filename)}-${finalTime}.1${extName}`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// if compression is enabled, add gz extention and create a gzip instance
|
|
95
|
+
let GZIP;
|
|
96
|
+
if (this.compress) {
|
|
97
|
+
GZIP = zlib.createGzip({
|
|
98
|
+
level: zlib.constants.Z_BEST_COMPRESSION,
|
|
99
|
+
memLevel: zlib.constants.Z_BEST_COMPRESSION,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// create our read/write streams
|
|
104
|
+
const readStream = fs.createReadStream(file);
|
|
105
|
+
const writeStream = fs.createWriteStream(finalName, { flags: 'w+' });
|
|
106
|
+
|
|
107
|
+
// pipe all stream
|
|
108
|
+
if (this.compress) {
|
|
109
|
+
readStream.pipe(GZIP).pipe(writeStream);
|
|
110
|
+
} else {
|
|
111
|
+
readStream.pipe(writeStream);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const onError = (err) => {
|
|
115
|
+
logError(err);
|
|
116
|
+
callback(err);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// listen for error
|
|
120
|
+
readStream.on('error', onError);
|
|
121
|
+
writeStream.on('error', onError);
|
|
122
|
+
if (this.compression) {
|
|
123
|
+
GZIP.on('error', onError);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// when the read is done, empty the file and check for retain option
|
|
127
|
+
writeStream.on('finish', () => {
|
|
128
|
+
if (GZIP) {
|
|
129
|
+
GZIP.close();
|
|
130
|
+
}
|
|
131
|
+
readStream.close();
|
|
132
|
+
writeStream.close();
|
|
133
|
+
|
|
134
|
+
fs.truncateSync(file);
|
|
135
|
+
logInfo('rotated file:', finalName);
|
|
136
|
+
|
|
137
|
+
callback(null, finalName);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
proceedSync(file) {
|
|
142
|
+
return new Promise((resolve, reject) => {
|
|
143
|
+
this.proceed(file, (err, res) => {
|
|
144
|
+
if (err) {
|
|
145
|
+
return reject(err);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return resolve(res);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Apply the rotation process if the `file` size exceeds the `SIZE_LIMIT`.
|
|
155
|
+
*
|
|
156
|
+
* @param {string} file
|
|
157
|
+
*/
|
|
158
|
+
async proceedFile(file) {
|
|
159
|
+
if (!fs.existsSync(file)) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (fs.statSync(file).size > 0) {
|
|
164
|
+
await this.proceedSync(file);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
log.deleteOldLogfiles(file, this.retain);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Apply the rotation process of all log files of `app` where the file size exceeds the`SIZE_LIMIT`.
|
|
172
|
+
*
|
|
173
|
+
* @param {Object} app
|
|
174
|
+
*/
|
|
175
|
+
async proceedPm2App(app) {
|
|
176
|
+
// Check all log path
|
|
177
|
+
// Note: If same file is defined for multiple purposes, it will be processed once only.
|
|
178
|
+
if (app.pm2_env.pm_out_log_path) {
|
|
179
|
+
await this.proceedFile(app.pm2_env.pm_out_log_path);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (app.pm2_env.pm_err_log_path && app.pm2_env.pm_err_log_path !== app.pm2_env.pm_out_log_path) {
|
|
183
|
+
await this.proceedFile(app.pm2_env.pm_err_log_path);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (
|
|
187
|
+
app.pm2_env.pm_log_path &&
|
|
188
|
+
app.pm2_env.pm_log_path !== app.pm2_env.pm_out_log_path &&
|
|
189
|
+
app.pm2_env.pm_log_path !== app.pm2_env.pm_err_log_path
|
|
190
|
+
) {
|
|
191
|
+
await this.proceedFile(app.pm2_env.pm_log_path);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
};
|
package/lib/util/rpc.js
CHANGED
|
@@ -1,16 +1,77 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
1
2
|
const axon = require('axon');
|
|
3
|
+
const kill = require('kill-port');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const spawn = require('cross-spawn');
|
|
6
|
+
|
|
2
7
|
const logger = require('@abtnode/logger')('@abtnode/core:rpc');
|
|
3
8
|
|
|
4
|
-
const
|
|
5
|
-
|
|
9
|
+
const host = '127.0.0.1';
|
|
10
|
+
const port = Number(process.env.ABT_NODE_UPDATER_PORT || 40405);
|
|
6
11
|
|
|
7
|
-
const
|
|
12
|
+
const doRpcCall = async (message) =>
|
|
8
13
|
new Promise((resolve) => {
|
|
9
|
-
logger.info('send rpc request', message);
|
|
10
|
-
sock.
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
logger.info('try send rpc request', message);
|
|
15
|
+
const sock = axon.socket('req');
|
|
16
|
+
sock.connect(port, host);
|
|
17
|
+
sock.on('connect', () => {
|
|
18
|
+
sock.send(JSON.stringify(message), (result) => {
|
|
19
|
+
logger.info('receive rpc response', result);
|
|
20
|
+
sock.close();
|
|
21
|
+
resolve(result);
|
|
22
|
+
});
|
|
13
23
|
});
|
|
14
24
|
});
|
|
15
25
|
|
|
16
|
-
|
|
26
|
+
const startRpcServer = async () => {
|
|
27
|
+
try {
|
|
28
|
+
await kill(port, 'tcp');
|
|
29
|
+
console.info('Killed existing rpc server');
|
|
30
|
+
} catch (err) {
|
|
31
|
+
console.error('Failed to kill existing rpc server', err);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
console.info(`Rpc Server started on ${new Date().toISOString()}`);
|
|
35
|
+
const child = spawn('node', [path.join(__dirname, '../processes/updater.js')], {
|
|
36
|
+
detached: true,
|
|
37
|
+
windowsHide: true, // required for Windows
|
|
38
|
+
cwd: process.cwd(),
|
|
39
|
+
timeout: 60 * 60 * 1000, // 60 minutes
|
|
40
|
+
shell: process.env.SHELL || false,
|
|
41
|
+
stdio: ['ignore', process.stdout, process.stderr],
|
|
42
|
+
env: {
|
|
43
|
+
PATH: process.env.PATH,
|
|
44
|
+
PM2_HOME: process.env.PM2_HOME,
|
|
45
|
+
ABT_NODE_UPDATER_PORT: process.env.ABT_NODE_UPDATER_PORT,
|
|
46
|
+
ABT_NODE_PACKAGE_NAME: process.env.ABT_NODE_PACKAGE_NAME,
|
|
47
|
+
ABT_NODE_BINARY_NAME: process.env.ABT_NODE_BINARY_NAME,
|
|
48
|
+
ABT_NODE_COMMAND_NAME: process.env.ABT_NODE_COMMAND_NAME,
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
child.on('error', (err) => {
|
|
53
|
+
console.error('Rpc Server errored', err);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
child.on('close', (code) => {
|
|
57
|
+
console.info(`Rpc Server exited with code ${code} on ${new Date().toISOString()}`);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
child.unref();
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
module.exports = { doRpcCall, startRpcServer };
|
|
64
|
+
|
|
65
|
+
// Following script used to test the upgrade process
|
|
66
|
+
// process.env.SHELL = '/opt/homebrew/bin/zsh';
|
|
67
|
+
// process.env.PM2_HOME = '/Users/wangshijun/.arcblock/abtnode';
|
|
68
|
+
// process.env.ABT_NODE_UPDATER_PORT = '40405';
|
|
69
|
+
// process.env.ABT_NODE_PACKAGE_NAME = '@blocklet/cli';
|
|
70
|
+
// process.env.ABT_NODE_BINARY_NAME = 'blocklet';
|
|
71
|
+
// process.env.ABT_NODE_COMMAND_NAME = 'blocklet server';
|
|
72
|
+
// startRpcServer().then(async () => {
|
|
73
|
+
// let result = await doRpcCall({ command: 'verify', version: '1.16.5' });
|
|
74
|
+
// console.log(result);
|
|
75
|
+
// result = await doRpcCall({ command: 'shutdown', version: '1.16.5' });
|
|
76
|
+
// console.log(result);
|
|
77
|
+
// });
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const JOI = require('joi');
|
|
2
|
+
const { didExtension } = require('@blocklet/meta/lib/extension');
|
|
3
|
+
|
|
4
|
+
const Joi = JOI.extend(didExtension);
|
|
5
|
+
|
|
6
|
+
// TODO: @zhanghan 这里目前仅包含必填的字段,后续需要增加其他字段
|
|
7
|
+
const passportSchema = Joi.object({
|
|
8
|
+
id: Joi.string().required(),
|
|
9
|
+
role: Joi.string().required(),
|
|
10
|
+
name: Joi.string().required(),
|
|
11
|
+
})
|
|
12
|
+
.unknown()
|
|
13
|
+
.empty(null);
|
|
14
|
+
|
|
15
|
+
// TODO: @zhanghan 这里目前仅包含必填的字段,后续需要增加其他字段
|
|
16
|
+
const connectedAccountSchema = Joi.object({
|
|
17
|
+
provider: Joi.string().required(),
|
|
18
|
+
did: Joi.DID().trim().required(),
|
|
19
|
+
pk: Joi.string().optional(),
|
|
20
|
+
id: Joi.string().optional(),
|
|
21
|
+
firstLoginAt: Joi.string().optional(),
|
|
22
|
+
lastLoginAt: Joi.string().optional(),
|
|
23
|
+
})
|
|
24
|
+
.unknown()
|
|
25
|
+
.empty(null);
|
|
26
|
+
|
|
27
|
+
const loginSchema = Joi.object({
|
|
28
|
+
did: Joi.DID().trim().required(),
|
|
29
|
+
pk: Joi.string().required(),
|
|
30
|
+
fullName: Joi.string().empty(''),
|
|
31
|
+
avatar: Joi.string().empty(''),
|
|
32
|
+
email: Joi.string().empty(''),
|
|
33
|
+
role: Joi.string().empty(''),
|
|
34
|
+
locale: Joi.string().empty(''),
|
|
35
|
+
extra: Joi.object(),
|
|
36
|
+
remark: Joi.string().empty(''),
|
|
37
|
+
lastLoginIp: Joi.string().empty(''),
|
|
38
|
+
passport: passportSchema.optional(),
|
|
39
|
+
connectedAccount: Joi.alternatives()
|
|
40
|
+
.try(connectedAccountSchema.required(), Joi.array().items(connectedAccountSchema).min(1).sparse(true))
|
|
41
|
+
.required(),
|
|
42
|
+
}).unknown();
|
|
43
|
+
|
|
44
|
+
exports.loginSchema = loginSchema;
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.16.6-beta-
|
|
6
|
+
"version": "1.16.6-beta-eaa4d39d",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,39 +19,42 @@
|
|
|
19
19
|
"author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@abtnode/auth": "1.16.6-beta-
|
|
23
|
-
"@abtnode/certificate-manager": "1.16.6-beta-
|
|
24
|
-
"@abtnode/constant": "1.16.6-beta-
|
|
25
|
-
"@abtnode/cron": "1.16.6-beta-
|
|
26
|
-
"@abtnode/db": "1.16.6-beta-
|
|
27
|
-
"@abtnode/logger": "1.16.6-beta-
|
|
28
|
-
"@abtnode/queue": "1.16.6-beta-
|
|
29
|
-
"@abtnode/rbac": "1.16.6-beta-
|
|
30
|
-
"@abtnode/router-provider": "1.16.6-beta-
|
|
31
|
-
"@abtnode/static-server": "1.16.6-beta-
|
|
32
|
-
"@abtnode/timemachine": "1.16.6-beta-
|
|
33
|
-
"@abtnode/util": "1.16.6-beta-
|
|
34
|
-
"@arcblock/did": "1.18.
|
|
22
|
+
"@abtnode/auth": "1.16.6-beta-eaa4d39d",
|
|
23
|
+
"@abtnode/certificate-manager": "1.16.6-beta-eaa4d39d",
|
|
24
|
+
"@abtnode/constant": "1.16.6-beta-eaa4d39d",
|
|
25
|
+
"@abtnode/cron": "1.16.6-beta-eaa4d39d",
|
|
26
|
+
"@abtnode/db": "1.16.6-beta-eaa4d39d",
|
|
27
|
+
"@abtnode/logger": "1.16.6-beta-eaa4d39d",
|
|
28
|
+
"@abtnode/queue": "1.16.6-beta-eaa4d39d",
|
|
29
|
+
"@abtnode/rbac": "1.16.6-beta-eaa4d39d",
|
|
30
|
+
"@abtnode/router-provider": "1.16.6-beta-eaa4d39d",
|
|
31
|
+
"@abtnode/static-server": "1.16.6-beta-eaa4d39d",
|
|
32
|
+
"@abtnode/timemachine": "1.16.6-beta-eaa4d39d",
|
|
33
|
+
"@abtnode/util": "1.16.6-beta-eaa4d39d",
|
|
34
|
+
"@arcblock/did": "1.18.73",
|
|
35
|
+
"@arcblock/did-auth": "1.18.73",
|
|
36
|
+
"@arcblock/did-ext": "^1.18.73",
|
|
35
37
|
"@arcblock/did-motif": "^1.1.10",
|
|
36
|
-
"@arcblock/did-util": "1.18.
|
|
37
|
-
"@arcblock/event-hub": "1.18.
|
|
38
|
-
"@arcblock/jwt": "^1.18.
|
|
38
|
+
"@arcblock/did-util": "1.18.73",
|
|
39
|
+
"@arcblock/event-hub": "1.18.73",
|
|
40
|
+
"@arcblock/jwt": "^1.18.73",
|
|
39
41
|
"@arcblock/pm2-events": "^0.0.5",
|
|
40
|
-
"@arcblock/vc": "1.18.
|
|
41
|
-
"@blocklet/constant": "1.16.6-beta-
|
|
42
|
-
"@blocklet/meta": "1.16.6-beta-
|
|
43
|
-
"@blocklet/sdk": "1.16.6-beta-
|
|
44
|
-
"@did-space/client": "^0.2.
|
|
42
|
+
"@arcblock/vc": "1.18.73",
|
|
43
|
+
"@blocklet/constant": "1.16.6-beta-eaa4d39d",
|
|
44
|
+
"@blocklet/meta": "1.16.6-beta-eaa4d39d",
|
|
45
|
+
"@blocklet/sdk": "1.16.6-beta-eaa4d39d",
|
|
46
|
+
"@did-space/client": "^0.2.80",
|
|
45
47
|
"@fidm/x509": "^1.2.1",
|
|
46
|
-
"@ocap/client": "1.18.
|
|
47
|
-
"@ocap/mcrypto": "1.18.
|
|
48
|
-
"@ocap/util": "1.18.
|
|
49
|
-
"@ocap/wallet": "1.18.
|
|
48
|
+
"@ocap/client": "1.18.73",
|
|
49
|
+
"@ocap/mcrypto": "1.18.73",
|
|
50
|
+
"@ocap/util": "1.18.73",
|
|
51
|
+
"@ocap/wallet": "1.18.73",
|
|
50
52
|
"@slack/webhook": "^5.0.4",
|
|
51
53
|
"archiver": "^5.3.1",
|
|
52
54
|
"axios": "^0.27.2",
|
|
53
55
|
"axon": "^2.0.3",
|
|
54
56
|
"chalk": "^4.1.2",
|
|
57
|
+
"cross-spawn": "^7.0.3",
|
|
55
58
|
"dayjs": "^1.11.7",
|
|
56
59
|
"deep-diff": "^1.0.2",
|
|
57
60
|
"detect-port": "^1.5.1",
|
|
@@ -67,8 +70,10 @@
|
|
|
67
70
|
"is-url": "^1.2.4",
|
|
68
71
|
"joi": "17.7.0",
|
|
69
72
|
"js-yaml": "^4.1.0",
|
|
73
|
+
"kill-port": "^2.0.1",
|
|
70
74
|
"lodash": "^4.17.21",
|
|
71
75
|
"lru-cache": "^6.0.0",
|
|
76
|
+
"moment-timezone": "^0.5.37",
|
|
72
77
|
"node-stream-zip": "^1.15.0",
|
|
73
78
|
"p-limit": "^3.1.0",
|
|
74
79
|
"p-retry": "4.6.1",
|
|
@@ -93,5 +98,5 @@
|
|
|
93
98
|
"express": "^4.18.2",
|
|
94
99
|
"jest": "^27.5.1"
|
|
95
100
|
},
|
|
96
|
-
"gitHead": "
|
|
101
|
+
"gitHead": "0d2ab99f67109e989f8182fc70bc3ee9fa430585"
|
|
97
102
|
}
|