@abtnode/core 1.16.32-beta-93e1a798 → 1.16.32-beta-76103be3
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 +11 -5
- package/lib/states/user.js +18 -6
- package/lib/states/verify-code.js +7 -5
- package/lib/util/blocklet.js +3 -0
- package/lib/util/docker/create-docker-image.js +84 -56
- package/lib/util/docker/parse-docker-options-from-pm2.js +102 -24
- package/lib/validators/util.js +13 -1
- package/package.json +22 -22
package/lib/api/team.js
CHANGED
|
@@ -421,14 +421,20 @@ class TeamAPI extends EventEmitter {
|
|
|
421
421
|
|
|
422
422
|
async updateUser({ teamDid, user }) {
|
|
423
423
|
const state = await this.getUserState(teamDid);
|
|
424
|
-
const
|
|
424
|
+
const exist = await state.getUserByDid(user.did);
|
|
425
|
+
const updated = await state.updateUser(user.did, user);
|
|
425
426
|
logger.info('user updated successfully', { teamDid, userDid: user.did });
|
|
426
|
-
|
|
427
|
-
|
|
427
|
+
|
|
428
|
+
this.emit(TeamEvents.userUpdated, { teamDid, user: updated });
|
|
429
|
+
const kycChanged =
|
|
430
|
+
(typeof user.emailVerified === 'boolean' && user.emailVerified !== exist.emailVerified) ||
|
|
431
|
+
(typeof user.phoneVerified === 'boolean' && user.phoneVerified !== exist.phoneVerified);
|
|
432
|
+
if (kycChanged) {
|
|
428
433
|
logger.info('user updated with kycChanged', { teamDid, userDid: user.did });
|
|
429
|
-
this.emit(TeamEvents.userPermissionUpdated, { teamDid, user:
|
|
434
|
+
this.emit(TeamEvents.userPermissionUpdated, { teamDid, user: updated });
|
|
430
435
|
}
|
|
431
|
-
|
|
436
|
+
|
|
437
|
+
return updated;
|
|
432
438
|
}
|
|
433
439
|
|
|
434
440
|
updateUserExtra(args) {
|
package/lib/states/user.js
CHANGED
|
@@ -71,13 +71,15 @@ class User extends ExtendBase {
|
|
|
71
71
|
throw new Error('user is invalid');
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
await this.insert({
|
|
74
|
+
const newUser = {
|
|
76
75
|
...user,
|
|
77
76
|
...(await this._extractInviteInfo(user)),
|
|
78
77
|
sourceProvider: user.sourceProvider || LOGIN_PROVIDER.WALLET,
|
|
79
78
|
approved: !!user.approved,
|
|
80
|
-
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// create user
|
|
82
|
+
await this.insert(this._normalizeUser(newUser));
|
|
81
83
|
|
|
82
84
|
// create passports and connectedAccounts
|
|
83
85
|
await Promise.all((get(user, 'passports') || []).map((x) => this.passport.insert({ ...x, userDid: user.did })));
|
|
@@ -103,7 +105,7 @@ class User extends ExtendBase {
|
|
|
103
105
|
}
|
|
104
106
|
|
|
105
107
|
// Allow to update inviter only when inviter is not set
|
|
106
|
-
const pending = cloneDeep(updates);
|
|
108
|
+
const pending = this._normalizeUser(cloneDeep(updates));
|
|
107
109
|
if (exist.inviter) {
|
|
108
110
|
delete pending.inviter;
|
|
109
111
|
} else {
|
|
@@ -659,7 +661,7 @@ SELECT did,inviter,generation FROM UserTree`.trim();
|
|
|
659
661
|
}
|
|
660
662
|
|
|
661
663
|
async isEmailUsed(email, verified = false) {
|
|
662
|
-
const condition = { email };
|
|
664
|
+
const condition = this._normalizeUser({ email });
|
|
663
665
|
if (verified) {
|
|
664
666
|
condition.emailVerified = true;
|
|
665
667
|
}
|
|
@@ -668,13 +670,23 @@ SELECT did,inviter,generation FROM UserTree`.trim();
|
|
|
668
670
|
}
|
|
669
671
|
|
|
670
672
|
async isPhoneUsed(phone, verified = false) {
|
|
671
|
-
const condition = { phone };
|
|
673
|
+
const condition = this._normalizeUser({ phone });
|
|
672
674
|
if (verified) {
|
|
673
675
|
condition.phoneVerified = true;
|
|
674
676
|
}
|
|
675
677
|
const doc = await this.findOne(condition);
|
|
676
678
|
return phone && !!doc;
|
|
677
679
|
}
|
|
680
|
+
|
|
681
|
+
_normalizeUser(user) {
|
|
682
|
+
if (user.email) {
|
|
683
|
+
user.email = String(user.email).trim().toLowerCase();
|
|
684
|
+
}
|
|
685
|
+
if (user.phone) {
|
|
686
|
+
user.phone = String(user.phone).trim().toLowerCase().replace(/\s/g, '');
|
|
687
|
+
}
|
|
688
|
+
return user;
|
|
689
|
+
}
|
|
678
690
|
}
|
|
679
691
|
|
|
680
692
|
module.exports = User;
|
|
@@ -6,18 +6,20 @@ const { VERIFY_CODE_LENGTH, VERIFY_CODE_TTL, VERIFY_SEND_TTL } = require('@abtno
|
|
|
6
6
|
|
|
7
7
|
const BaseState = require('./base');
|
|
8
8
|
|
|
9
|
-
const schema = Joi.string().email().required();
|
|
9
|
+
const schema = Joi.string().email().lowercase().required();
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* @extends BaseState<import('@abtnode/models').VerifyCodeState>
|
|
13
13
|
*/
|
|
14
14
|
class VerifyCodeState extends BaseState {
|
|
15
|
-
async create(
|
|
15
|
+
async create(raw, scope = 'email') {
|
|
16
|
+
let subject = raw;
|
|
16
17
|
if (scope === 'email') {
|
|
17
|
-
const { error } = schema.validate(subject);
|
|
18
|
+
const { error, value } = schema.validate(subject);
|
|
18
19
|
if (error) {
|
|
19
20
|
throw new Error('Invalid email specified when create verify code');
|
|
20
21
|
}
|
|
22
|
+
subject = value;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
const count = await super.remove({ subject, verified: false });
|
|
@@ -87,12 +89,12 @@ class VerifyCodeState extends BaseState {
|
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
async isVerified(subject) {
|
|
90
|
-
const doc = await this.findOne({ subject, verified: true });
|
|
92
|
+
const doc = await this.findOne({ subject: String(subject).trim().toLowerCase(), verified: true });
|
|
91
93
|
return !!doc;
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
async isSent(subject) {
|
|
95
|
-
const doc = await this.findOne({ subject, sent: true });
|
|
97
|
+
const doc = await this.findOne({ subject: String(subject).trim().toLowerCase(), sent: true });
|
|
96
98
|
if (!doc) {
|
|
97
99
|
return false;
|
|
98
100
|
}
|
package/lib/util/blocklet.js
CHANGED
|
@@ -346,6 +346,7 @@ const getAppSystemEnvironments = (blocklet, nodeInfo, dataDirs) => {
|
|
|
346
346
|
BLOCKLET_APP_URL: appUrl,
|
|
347
347
|
BLOCKLET_APP_DATA_DIR: path.join(dataDirs.data, blocklet.meta.name),
|
|
348
348
|
BLOCKLET_APP_TENANT_MODE: result.tenantMode || BLOCKLET_TENANT_MODES.SINGLE,
|
|
349
|
+
BLOCKLET_APP_SHARE_DIR: path.join(path.join(dataDirs.data, blocklet.meta.name), '.share'),
|
|
349
350
|
};
|
|
350
351
|
};
|
|
351
352
|
|
|
@@ -678,6 +679,8 @@ const startBlockletProcess = async (
|
|
|
678
679
|
serverSk: nodeEnvironments.ABT_NODE_SK,
|
|
679
680
|
});
|
|
680
681
|
|
|
682
|
+
options.env.BLOCKLET_SHARE_DIR = path.join(options.env.BLOCKLET_APP_SHARE_DIR, b.meta.did);
|
|
683
|
+
|
|
681
684
|
const nextOptions = await parseDockerOptionsFromPm2(options, nodeInfo);
|
|
682
685
|
await pm2.startAsync(nextOptions);
|
|
683
686
|
|
|
@@ -3,7 +3,7 @@ const path = require('path');
|
|
|
3
3
|
const { execSync } = require('child_process');
|
|
4
4
|
const logger = require('@abtnode/logger')('@abtnode/core:util:blocklet');
|
|
5
5
|
|
|
6
|
-
const DOCKER_IMAGE_NAME = 'blocklet-node-
|
|
6
|
+
const DOCKER_IMAGE_NAME = 'blocklet-node-v1';
|
|
7
7
|
|
|
8
8
|
let isCreated = false;
|
|
9
9
|
|
|
@@ -13,67 +13,95 @@ async function createDockerImage() {
|
|
|
13
13
|
}
|
|
14
14
|
isCreated = true;
|
|
15
15
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
# RUN apk add --no-cache shadow
|
|
36
|
-
RUN apk add --no-cache socat
|
|
37
|
-
|
|
38
|
-
RUN node -v
|
|
39
|
-
RUN npm i -g pnpm
|
|
40
|
-
RUN npm i -g nr
|
|
41
|
-
|
|
42
|
-
# 使用主机用户的 home 目录
|
|
43
|
-
WORKDIR /blocklet
|
|
44
|
-
|
|
45
|
-
RUN mkdir -p /blocklet/app
|
|
46
|
-
RUN mkdir -p /blocklet/data
|
|
47
|
-
RUN mkdir -p /blocklet/logs
|
|
48
|
-
RUN mkdir -p /blocklet/cache
|
|
49
|
-
RUN mkdir -p /data/bin/meilisearch
|
|
50
|
-
RUN chmod -R 775 /blocklet
|
|
51
|
-
RUN chown -R ${uid}:${gid} /blocklet
|
|
52
|
-
RUN chown -R ${uid}:${gid} /data/bin/meilisearch
|
|
53
|
-
# USER ${uid}:${gid}
|
|
54
|
-
`;
|
|
16
|
+
const runner = async () => {
|
|
17
|
+
const dir = process.env.ABT_NODE_DATA_DIR;
|
|
18
|
+
if (!dir) {
|
|
19
|
+
logger.error('ABT_NODE_DATA_DIR is not set');
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
// 生成 Dockerfile
|
|
23
|
+
const uid = process.getuid();
|
|
24
|
+
const gid = process.getgid();
|
|
25
|
+
const dockerfilePath = path.join(dir, 'Dockerfile');
|
|
26
|
+
const dockerfilePathDone = path.join(dir, `Dockerfile.done-${DOCKER_IMAGE_NAME}-${uid}-${gid}`);
|
|
27
|
+
const [accessDone] = await Promise.allSettled([fs.access(`${dockerfilePathDone}`)]);
|
|
28
|
+
if (accessDone.status === 'fulfilled') {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const dockerfileContent = `
|
|
32
|
+
# Base image
|
|
33
|
+
FROM node:22-alpine
|
|
55
34
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
35
|
+
# Install necessary packages
|
|
36
|
+
RUN apk add --no-cache python3 make gcc g++ build-base socat curl gnupg wget su-exec shadow git ca-certificates
|
|
37
|
+
|
|
38
|
+
# Create a symlink for python if necessary
|
|
39
|
+
RUN ln -sf /usr/bin/python3 /usr/bin/python
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# RUN install --verbose --directory --owner blocklet --group blocklet --mode 3777 /var/run/blocklet
|
|
43
|
+
|
|
44
|
+
ENV DOCKER_DATA /var/lib/blocklet
|
|
45
|
+
VOLUME /var/lib/blocklet
|
|
46
|
+
|
|
47
|
+
RUN mkdir -p /var/lib/blocklet
|
|
48
|
+
# RUN chown -R blocklet:blocklet /var/lib/blocklet
|
|
49
|
+
|
|
50
|
+
# Environment variables
|
|
51
|
+
ENV NPM_CONFIG_CACHE=/var/lib/blocklet/.npm
|
|
52
|
+
|
|
53
|
+
# Set appropriate ownership and permission
|
|
54
|
+
RUN mkdir -p /var/lib/blocklet/.npm
|
|
55
|
+
RUN mkdir -p /var/lib/blocklet/logs
|
|
56
|
+
RUN mkdir -p /var/lib/blocklet/cache
|
|
57
|
+
RUN mkdir -p /var/lib/blocklet/data
|
|
58
|
+
RUN mkdir -p /var/lib/blocklet/blocklets
|
|
59
|
+
RUN chmod -R 777 /var/lib/blocklet
|
|
60
|
+
|
|
61
|
+
# Install global npm packages
|
|
62
|
+
RUN npm install -g pnpm nr
|
|
63
|
+
|
|
64
|
+
# Ensure correct PATH
|
|
65
|
+
ENV PATH=/sbin:$PATH
|
|
66
|
+
|
|
67
|
+
# Set working directory
|
|
68
|
+
WORKDIR /var/lib/blocklet
|
|
69
|
+
|
|
70
|
+
`.trim();
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
await fs.access(dockerfilePath);
|
|
74
|
+
await fs.unlink(dockerfilePath);
|
|
75
|
+
} catch (_) {
|
|
76
|
+
// File doesn't exist, no need to remove
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
await fs.writeFile(dockerfilePath, dockerfileContent);
|
|
80
|
+
try {
|
|
81
|
+
execSync(
|
|
82
|
+
`docker build -f ${path.join(dir, 'Dockerfile')} --no-cache --build-arg uid=$(id -u) --build-arg gid=$(id -g) -t ${DOCKER_IMAGE_NAME} .`,
|
|
83
|
+
{
|
|
84
|
+
stdio: 'inherit',
|
|
85
|
+
encoding: 'utf-8',
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
} catch (error) {
|
|
89
|
+
// 如果 docker 会报错: ERROR: failed to solve: failed to read dockerfile: open /var/snap/docker/common/var-lib-docker/tmp/buildkit-mount875872699/Dockerfile: no such file or directory
|
|
90
|
+
// 表示 docker 没有权限访问 ABT_NODE_DATA_DIR 目录, 后续的一系列操作也会失败
|
|
91
|
+
logger.error('Failed to build Docker image. Error:', error.message);
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
await fs.rename(dockerfilePath, dockerfilePathDone);
|
|
95
|
+
logger.info('Success build docker image');
|
|
96
|
+
};
|
|
62
97
|
|
|
63
|
-
await fs.writeFile(dockerfilePath, dockerfileContent);
|
|
64
98
|
try {
|
|
65
|
-
|
|
66
|
-
stdio: 'inherit',
|
|
67
|
-
encoding: 'utf-8',
|
|
68
|
-
});
|
|
99
|
+
await runner();
|
|
69
100
|
} catch (error) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
logger.error('Failed to build Docker image. Error:', error.message);
|
|
101
|
+
logger.error('Failed to build docker image. Error:', error.message);
|
|
102
|
+
isCreated = false;
|
|
73
103
|
throw error;
|
|
74
104
|
}
|
|
75
|
-
await fs.rename(dockerfilePath, dockerfilePathDone);
|
|
76
|
-
logger.info('Success build docker image');
|
|
77
105
|
}
|
|
78
106
|
|
|
79
107
|
module.exports = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require('./docker-container-prune');
|
|
2
|
-
|
|
2
|
+
const { COMPONENT_DOCKER_ENV_FILE_NAME } = require('@blocklet/constant');
|
|
3
3
|
const { stringify: stringifyEnvFile } = require('envfile');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const fs = require('fs/promises');
|
|
@@ -44,18 +44,50 @@ async function parseDockerOptionsFromPm2(input, nodeInfo) {
|
|
|
44
44
|
options.env.INTERNAL_HOST = 'host.docker.internal';
|
|
45
45
|
|
|
46
46
|
const dockerEnv = { ...options.env };
|
|
47
|
-
const baseDir = '/blocklet';
|
|
48
|
-
|
|
49
|
-
dockerEnv.
|
|
47
|
+
const baseDir = '/var/lib/blocklet';
|
|
48
|
+
const serverDir = process.env.ABT_NODE_DATA_DIR;
|
|
49
|
+
dockerEnv.ABT_NODE_DATA_DIR = baseDir;
|
|
50
|
+
dockerEnv.BLOCKLET_APP_DATA_DIR = options.env.BLOCKLET_APP_DATA_DIR.replace(serverDir, baseDir);
|
|
51
|
+
dockerEnv.BLOCKLET_APP_DIR = options.env.BLOCKLET_APP_DIR.replace(serverDir, baseDir);
|
|
52
|
+
dockerEnv.BLOCKLET_DATA_DIR = options.env.BLOCKLET_DATA_DIR.replace(serverDir, baseDir);
|
|
50
53
|
dockerEnv.BLOCKLET_LOG_DIR = path.join(baseDir, 'logs');
|
|
51
54
|
dockerEnv.BLOCKLET_CACHE_DIR = path.join(baseDir, 'cache');
|
|
55
|
+
dockerEnv.BLOCKLET_APP_SHARE_DIR = options.env.BLOCKLET_APP_SHARE_DIR.replace(serverDir, baseDir);
|
|
56
|
+
dockerEnv.BLOCKLET_SHARE_DIR = options.env.BLOCKLET_SHARE_DIR.replace(serverDir, baseDir);
|
|
52
57
|
dockerEnv.BLOCKLET_DOCKER_NAME = name;
|
|
53
58
|
dockerEnv.BLOCKLET_HOST = 'host.docker.internal';
|
|
54
59
|
dockerEnv.USING_DOCKER = 'true';
|
|
55
|
-
|
|
60
|
+
dockerEnv.LOCAL_USER_ID = process.getuid();
|
|
61
|
+
|
|
62
|
+
// 清理冗余的 docker-env 文件, 应该放到 APP_CONFIG_DIR 目录下
|
|
63
|
+
const oldDockerEnvFile = path.join(options.env.BLOCKLET_DATA_DIR, 'docker-env');
|
|
64
|
+
if (existsSync(oldDockerEnvFile)) {
|
|
65
|
+
await fs.rm(oldDockerEnvFile);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let nodeModulesName = 'node_modules';
|
|
69
|
+
let installScript = '';
|
|
70
|
+
if (existsSync(path.join(options.env.BLOCKLET_APP_DIR, 'package.json'))) {
|
|
71
|
+
const packageJson = JSON.parse(await fs.readFile(path.join(options.env.BLOCKLET_APP_DIR, 'package.json'), 'utf-8'));
|
|
72
|
+
if (packageJson.dependencies || packageJson.devDependencies) {
|
|
73
|
+
dockerEnv.BLOCKLET_APP_PACKAGE_JSON = JSON.stringify(packageJson);
|
|
74
|
+
nodeModulesName = 'docker_node_modules';
|
|
75
|
+
installScript = 'pnpm install --unsafe-perm --fetch-timeout=60000 --fetch-retries=5 && ';
|
|
76
|
+
}
|
|
77
|
+
}
|
|
56
78
|
|
|
57
|
-
|
|
79
|
+
let envVars = stringifyEnvFile(dockerEnv);
|
|
80
|
+
envVars = envVars.replace(new RegExp(serverDir, 'g'), baseDir);
|
|
81
|
+
const dockerEnvFile = path.join(
|
|
82
|
+
serverDir,
|
|
83
|
+
'tmp',
|
|
84
|
+
'docker',
|
|
85
|
+
options.env.BLOCKLET_REAL_NAME,
|
|
86
|
+
COMPONENT_DOCKER_ENV_FILE_NAME
|
|
87
|
+
);
|
|
88
|
+
await mkdirpWithPermissions(path.dirname(dockerEnvFile));
|
|
58
89
|
await fs.writeFile(dockerEnvFile, envVars);
|
|
90
|
+
|
|
59
91
|
const runScript = /(npm|yarn|pnpm|bun)/g.test(options.script) ? options.script : `node ${options.script}`;
|
|
60
92
|
const networkHost = os.platform() === 'linux' ? '--network host' : '';
|
|
61
93
|
const port = os.platform() === 'linux' ? '' : `-p ${options.env.BLOCKLET_PORT}:${options.env.BLOCKLET_PORT}`;
|
|
@@ -70,48 +102,94 @@ async function parseDockerOptionsFromPm2(input, nodeInfo) {
|
|
|
70
102
|
.join(' ');
|
|
71
103
|
|
|
72
104
|
options.args = [];
|
|
105
|
+
options.namespace = 'blocklets_docker';
|
|
106
|
+
const uid = process.getuid();
|
|
107
|
+
const gid = process.getgid();
|
|
108
|
+
|
|
109
|
+
const sourceDirs = new Set();
|
|
73
110
|
|
|
74
111
|
const bindMounts = [
|
|
75
|
-
{ source: options.env.BLOCKLET_APP_DIR, target: dockerEnv.BLOCKLET_APP_DIR },
|
|
76
|
-
{ source: options.env.BLOCKLET_DATA_DIR, target: dockerEnv.BLOCKLET_DATA_DIR },
|
|
77
|
-
{ source: options.env.BLOCKLET_LOG_DIR, target: dockerEnv.BLOCKLET_LOG_DIR },
|
|
78
|
-
{ source: options.env.BLOCKLET_CACHE_DIR, target: dockerEnv.BLOCKLET_CACHE_DIR },
|
|
79
112
|
{
|
|
80
|
-
source: path.join(
|
|
81
|
-
target:
|
|
113
|
+
source: path.join(serverDir, 'blocklets'),
|
|
114
|
+
target: path.join(baseDir, 'blocklets'),
|
|
115
|
+
canEdit: false,
|
|
116
|
+
},
|
|
117
|
+
{ source: options.env.BLOCKLET_APP_DIR, target: dockerEnv.BLOCKLET_APP_DIR, canEdit: true },
|
|
118
|
+
{ source: options.env.BLOCKLET_DATA_DIR, target: dockerEnv.BLOCKLET_DATA_DIR, canEdit: true },
|
|
119
|
+
{ source: options.env.BLOCKLET_LOG_DIR, target: dockerEnv.BLOCKLET_LOG_DIR, canEdit: true },
|
|
120
|
+
{ source: options.env.BLOCKLET_CACHE_DIR, target: dockerEnv.BLOCKLET_CACHE_DIR, canEdit: true },
|
|
121
|
+
{
|
|
122
|
+
source: path.join(options.env.BLOCKLET_APP_DIR, nodeModulesName),
|
|
123
|
+
target: path.join(dockerEnv.BLOCKLET_APP_DIR, 'node_modules'),
|
|
124
|
+
canEdit: true,
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
source: path.join(options.env.BLOCKLET_SHARE_DIR),
|
|
128
|
+
target: path.join(dockerEnv.BLOCKLET_SHARE_DIR),
|
|
129
|
+
canEdit: false,
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
source: path.join(options.env.BLOCKLET_APP_SHARE_DIR),
|
|
133
|
+
target: path.join(dockerEnv.BLOCKLET_APP_SHARE_DIR),
|
|
134
|
+
canEdit: true,
|
|
82
135
|
},
|
|
83
|
-
|
|
136
|
+
{
|
|
137
|
+
source: path.join(options.env.BLOCKLET_APP_DATA_DIR, '.config'),
|
|
138
|
+
target: path.join(dockerEnv.BLOCKLET_APP_DATA_DIR, '.config'),
|
|
139
|
+
canEdit: false,
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
source: path.join(options.env.BLOCKLET_APP_DATA_DIR, '.assets'),
|
|
143
|
+
target: path.join(dockerEnv.BLOCKLET_APP_DATA_DIR, '.assets'),
|
|
144
|
+
canEdit: false,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
source: path.join(options.env.BLOCKLET_APP_DATA_DIR),
|
|
148
|
+
target: path.join(dockerEnv.BLOCKLET_APP_DATA_DIR),
|
|
149
|
+
canEdit: false,
|
|
150
|
+
},
|
|
151
|
+
].filter((v) => {
|
|
152
|
+
if (sourceDirs.has(v.source)) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
sourceDirs.add(v.source);
|
|
156
|
+
return true;
|
|
157
|
+
});
|
|
84
158
|
let mount = '';
|
|
85
159
|
for (const bindMount of bindMounts) {
|
|
86
160
|
if (!existsSync(bindMount.source)) {
|
|
87
161
|
// eslint-disable-next-line no-await-in-loop
|
|
88
162
|
await mkdirpWithPermissions(bindMount.source);
|
|
89
163
|
}
|
|
90
|
-
|
|
91
|
-
// mount += ` --mount type=bind,source=${bindMount.source},target=${bindMount.target},bind-propagation=rshared`;
|
|
92
|
-
mount += ` -v ${bindMount.source}:${bindMount.target}:rw `;
|
|
93
|
-
}
|
|
94
|
-
if (!existsSync(path.join(options.env.BLOCKLET_APP_DIR, 'node_modules'))) {
|
|
95
|
-
await mkdirpWithPermissions(path.join(options.env.BLOCKLET_APP_DIR, 'node_modules'));
|
|
164
|
+
mount += ` -v ${bindMount.source}:${bindMount.target}:${bindMount.canEdit ? 'rw' : 'ro'} `;
|
|
96
165
|
}
|
|
166
|
+
await mkdirpWithPermissions(path.join(options.env.BLOCKLET_APP_DIR, 'node_modules'));
|
|
97
167
|
|
|
98
|
-
options.script = `
|
|
168
|
+
options.script = `
|
|
169
|
+
docker rm -f ${name} > /dev/null 2>&1 || true && \
|
|
170
|
+
docker run --name ${name} \
|
|
99
171
|
${port} \
|
|
100
172
|
${mount} \
|
|
101
|
-
-v ${path.join(options.env.BLOCKLET_APP_DIR, 'node_modules')} \
|
|
102
173
|
${diskSize} \
|
|
103
174
|
--cpus="${dockerEnv.BLOCKLET_DOCKER_CPUS}" \
|
|
104
175
|
--memory="${dockerEnv.BLOCKLET_DOCKER_MEMORY}" \
|
|
105
176
|
--env-file ${dockerEnvFile} \
|
|
106
177
|
${networkHost} \
|
|
107
178
|
${DOCKER_IMAGE_NAME} \
|
|
108
|
-
sh -c
|
|
109
|
-
|
|
110
|
-
|
|
179
|
+
sh -c '
|
|
180
|
+
${socatCommand}
|
|
181
|
+
chown ${uid}:${gid} ${baseDir} && \
|
|
182
|
+
exec su-exec ${uid}:${gid} sh -c "
|
|
183
|
+
cd ${dockerEnv.BLOCKLET_APP_DIR} && \
|
|
184
|
+
${installScript} \
|
|
185
|
+
${runScript}
|
|
186
|
+
"
|
|
187
|
+
'`;
|
|
111
188
|
|
|
112
189
|
options.env = {
|
|
113
190
|
USING_DOCKER: 'true',
|
|
114
191
|
};
|
|
192
|
+
fs.writeFile(path.join(serverDir, 'docker-options.json'), JSON.stringify(options, null, 2));
|
|
115
193
|
|
|
116
194
|
return options;
|
|
117
195
|
}
|
package/lib/validators/util.js
CHANGED
|
@@ -33,7 +33,16 @@ const sessionConfigSchema = Joi.object({
|
|
|
33
33
|
requireVerified: Joi.boolean().default(false),
|
|
34
34
|
requireUnique: Joi.boolean().default(false),
|
|
35
35
|
trustOauthProviders: Joi.boolean().default(false),
|
|
36
|
-
|
|
36
|
+
enableDomainBlackList: Joi.boolean().default(false),
|
|
37
|
+
domainBlackList: Joi.array()
|
|
38
|
+
.items(Joi.string().uri({ scheme: ['http', 'https'] }))
|
|
39
|
+
.optional()
|
|
40
|
+
.default([]),
|
|
41
|
+
enableDomainWhiteList: Joi.boolean().default(false),
|
|
42
|
+
domainWhiteList: Joi.array()
|
|
43
|
+
.items(Joi.string().uri({ scheme: ['http', 'https'] }))
|
|
44
|
+
.optional()
|
|
45
|
+
.default([]),
|
|
37
46
|
trustedIssuers: Joi.array()
|
|
38
47
|
.items(
|
|
39
48
|
Joi.object({
|
|
@@ -49,7 +58,10 @@ const sessionConfigSchema = Joi.object({
|
|
|
49
58
|
enabled: Joi.boolean().default(false),
|
|
50
59
|
requireVerified: Joi.boolean().default(false),
|
|
51
60
|
requireUnique: Joi.boolean().default(false),
|
|
61
|
+
enableRegionBlackList: Joi.boolean().default(false),
|
|
52
62
|
regionBlackList: Joi.array().items(Joi.string()).optional().default([]),
|
|
63
|
+
enableRegionWhiteList: Joi.boolean().default(false),
|
|
64
|
+
regionWhiteList: Joi.array().items(Joi.string()).optional().default([]),
|
|
53
65
|
trustedIssuers: Joi.array()
|
|
54
66
|
.items(
|
|
55
67
|
Joi.object({
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.16.32-beta-
|
|
6
|
+
"version": "1.16.32-beta-76103be3",
|
|
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.32-beta-
|
|
23
|
-
"@abtnode/auth": "1.16.32-beta-
|
|
24
|
-
"@abtnode/certificate-manager": "1.16.32-beta-
|
|
25
|
-
"@abtnode/constant": "1.16.32-beta-
|
|
26
|
-
"@abtnode/cron": "1.16.32-beta-
|
|
27
|
-
"@abtnode/logger": "1.16.32-beta-
|
|
28
|
-
"@abtnode/models": "1.16.32-beta-
|
|
29
|
-
"@abtnode/queue": "1.16.32-beta-
|
|
30
|
-
"@abtnode/rbac": "1.16.32-beta-
|
|
31
|
-
"@abtnode/router-provider": "1.16.32-beta-
|
|
32
|
-
"@abtnode/static-server": "1.16.32-beta-
|
|
33
|
-
"@abtnode/timemachine": "1.16.32-beta-
|
|
34
|
-
"@abtnode/util": "1.16.32-beta-
|
|
22
|
+
"@abtnode/analytics": "1.16.32-beta-76103be3",
|
|
23
|
+
"@abtnode/auth": "1.16.32-beta-76103be3",
|
|
24
|
+
"@abtnode/certificate-manager": "1.16.32-beta-76103be3",
|
|
25
|
+
"@abtnode/constant": "1.16.32-beta-76103be3",
|
|
26
|
+
"@abtnode/cron": "1.16.32-beta-76103be3",
|
|
27
|
+
"@abtnode/logger": "1.16.32-beta-76103be3",
|
|
28
|
+
"@abtnode/models": "1.16.32-beta-76103be3",
|
|
29
|
+
"@abtnode/queue": "1.16.32-beta-76103be3",
|
|
30
|
+
"@abtnode/rbac": "1.16.32-beta-76103be3",
|
|
31
|
+
"@abtnode/router-provider": "1.16.32-beta-76103be3",
|
|
32
|
+
"@abtnode/static-server": "1.16.32-beta-76103be3",
|
|
33
|
+
"@abtnode/timemachine": "1.16.32-beta-76103be3",
|
|
34
|
+
"@abtnode/util": "1.16.32-beta-76103be3",
|
|
35
35
|
"@arcblock/did": "1.18.135",
|
|
36
36
|
"@arcblock/did-auth": "1.18.135",
|
|
37
37
|
"@arcblock/did-ext": "^1.18.135",
|
|
@@ -42,13 +42,13 @@
|
|
|
42
42
|
"@arcblock/pm2-events": "^0.0.5",
|
|
43
43
|
"@arcblock/validator": "^1.18.135",
|
|
44
44
|
"@arcblock/vc": "1.18.135",
|
|
45
|
-
"@blocklet/constant": "1.16.32-beta-
|
|
46
|
-
"@blocklet/env": "1.16.32-beta-
|
|
47
|
-
"@blocklet/meta": "1.16.32-beta-
|
|
48
|
-
"@blocklet/resolver": "1.16.32-beta-
|
|
49
|
-
"@blocklet/sdk": "1.16.32-beta-
|
|
50
|
-
"@blocklet/store": "1.16.32-beta-
|
|
51
|
-
"@did-space/client": "^0.5.
|
|
45
|
+
"@blocklet/constant": "1.16.32-beta-76103be3",
|
|
46
|
+
"@blocklet/env": "1.16.32-beta-76103be3",
|
|
47
|
+
"@blocklet/meta": "1.16.32-beta-76103be3",
|
|
48
|
+
"@blocklet/resolver": "1.16.32-beta-76103be3",
|
|
49
|
+
"@blocklet/sdk": "1.16.32-beta-76103be3",
|
|
50
|
+
"@blocklet/store": "1.16.32-beta-76103be3",
|
|
51
|
+
"@did-space/client": "^0.5.39",
|
|
52
52
|
"@fidm/x509": "^1.2.1",
|
|
53
53
|
"@ocap/mcrypto": "1.18.135",
|
|
54
54
|
"@ocap/util": "1.18.135",
|
|
@@ -105,5 +105,5 @@
|
|
|
105
105
|
"jest": "^29.7.0",
|
|
106
106
|
"unzipper": "^0.10.11"
|
|
107
107
|
},
|
|
108
|
-
"gitHead": "
|
|
108
|
+
"gitHead": "6d7afe107a349b1267b29e7f2216db9997085015"
|
|
109
109
|
}
|