@saltcorn/cli 0.7.2-beta.4 → 0.7.2-beta.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/README.md +97 -54
- package/oclif.manifest.json +1 -1
- package/package.json +7 -8
- package/src/commands/add-schema.js +23 -1
- package/src/commands/backup.js +7 -3
- package/src/commands/create-user.js +14 -8
- package/src/commands/delete-tenants.js +24 -20
- package/src/commands/delete-user.js +105 -0
- package/src/commands/modify-user.js +163 -0
- package/src/commands/release.js +3 -0
- package/src/commands/reset-schema.js +11 -2
- package/src/commands/restore.js +5 -0
- package/src/commands/rm-tenant.js +39 -6
- package/src/commands/run-tests.js +5 -4
- package/src/commands/setup.js +21 -10
- package/src/common.js +13 -5
- package/src/index.js +9 -2
|
@@ -27,27 +27,31 @@ class DeleteTenantsCommand extends Command {
|
|
|
27
27
|
|
|
28
28
|
for (const ten of tensExamine) {
|
|
29
29
|
let nusers, ntables, nviews, npages;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (nusers < 2 && ntables < 2 && nviews < 1 && npages < 1) {
|
|
37
|
-
console.log("deleting ", ten.subdomain, {
|
|
38
|
-
nusers,
|
|
39
|
-
ntables,
|
|
40
|
-
nviews,
|
|
41
|
-
npages,
|
|
42
|
-
});
|
|
43
|
-
await deleteTenant(ten.subdomain);
|
|
44
|
-
} else {
|
|
45
|
-
console.log("leaving", ten.subdomain, {
|
|
46
|
-
nusers,
|
|
47
|
-
ntables,
|
|
48
|
-
nviews,
|
|
49
|
-
npages,
|
|
30
|
+
try {
|
|
31
|
+
await db.runWithTenant(ten.subdomain, async () => {
|
|
32
|
+
nusers = await db.count("users");
|
|
33
|
+
ntables = await db.count("_sc_tables");
|
|
34
|
+
nviews = await db.count("_sc_views");
|
|
35
|
+
npages = await db.count("_sc_pages");
|
|
50
36
|
});
|
|
37
|
+
if (nusers < 2 && ntables < 2 && nviews < 1 && npages < 1) {
|
|
38
|
+
console.log("deleting ", ten.subdomain, {
|
|
39
|
+
nusers,
|
|
40
|
+
ntables,
|
|
41
|
+
nviews,
|
|
42
|
+
npages,
|
|
43
|
+
});
|
|
44
|
+
await deleteTenant(ten.subdomain);
|
|
45
|
+
} else {
|
|
46
|
+
console.log("leaving", ten.subdomain, {
|
|
47
|
+
nusers,
|
|
48
|
+
ntables,
|
|
49
|
+
nviews,
|
|
50
|
+
npages,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
} catch (e) {
|
|
54
|
+
console.error("Error in tenant", ten.subdomain, e);
|
|
51
55
|
}
|
|
52
56
|
}
|
|
53
57
|
this.exit(0);
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @category saltcorn-cli
|
|
3
|
+
* @module commands/delete-user
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// todo support for users without emails (using user.id)
|
|
7
|
+
const { Command, flags } = require("@oclif/command");
|
|
8
|
+
const { cli } = require("cli-ux");
|
|
9
|
+
const { maybe_as_tenant } = require("../common");
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* DeleteUserCommand Class
|
|
14
|
+
* @extends oclif.Command
|
|
15
|
+
* @category saltcorn-cli
|
|
16
|
+
*/
|
|
17
|
+
class DeleteUserCommand extends Command {
|
|
18
|
+
/**
|
|
19
|
+
* @returns {Promise<void>}
|
|
20
|
+
*/
|
|
21
|
+
async run() {
|
|
22
|
+
|
|
23
|
+
const User = require("@saltcorn/data/models/user");
|
|
24
|
+
|
|
25
|
+
const { args } = this.parse(DeleteUserCommand);
|
|
26
|
+
const { flags } = this.parse(DeleteUserCommand);
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
// run function as specified tenant
|
|
30
|
+
await maybe_as_tenant(flags.tenant, async () => {
|
|
31
|
+
// try to find user
|
|
32
|
+
const u = await User.findOne({email: args.user_email});
|
|
33
|
+
if (u === null) {
|
|
34
|
+
console.error(`Error: User ${args.user_email} is not found`);
|
|
35
|
+
this.exit(1);
|
|
36
|
+
}
|
|
37
|
+
if (!u instanceof User) {
|
|
38
|
+
console.error(`Error: ${u.error}`);
|
|
39
|
+
this.exit(1);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// make changes
|
|
43
|
+
// todo handle errors
|
|
44
|
+
if (!flags.force) {
|
|
45
|
+
const ans = await cli.confirm(
|
|
46
|
+
`This will delete user ${args.user_email} ${
|
|
47
|
+
typeof flags.tenant !== "undefined" ? "from " + flags.tenant : ""
|
|
48
|
+
}.\nContinue (y/n)?`);
|
|
49
|
+
if (!ans) {
|
|
50
|
+
console.log(`Success: Command execution canceled`);
|
|
51
|
+
this.exit(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// delete user
|
|
57
|
+
await u.delete();
|
|
58
|
+
console.log(`Success: User ${args.user_email} deleted ${
|
|
59
|
+
typeof flags.tenant !== "undefined" ? "from " + flags.tenant : ""
|
|
60
|
+
}`);
|
|
61
|
+
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
);
|
|
65
|
+
this.exit(0);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @type {object}
|
|
71
|
+
*/
|
|
72
|
+
DeleteUserCommand.args = [
|
|
73
|
+
{ name: "user_email", required: true, description: "User to delete" },
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @type {string}
|
|
78
|
+
*/
|
|
79
|
+
DeleteUserCommand.description = `Delete user.
|
|
80
|
+
|
|
81
|
+
Command deletes the user specified by USER_EMAIL.
|
|
82
|
+
|
|
83
|
+
`;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @type {string}
|
|
87
|
+
*/
|
|
88
|
+
DeleteUserCommand.help = `Delete user.
|
|
89
|
+
|
|
90
|
+
Command deletes the user specified by USER_EMAIL.
|
|
91
|
+
|
|
92
|
+
`;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @type {object}
|
|
96
|
+
*/
|
|
97
|
+
DeleteUserCommand.flags = {
|
|
98
|
+
force: flags.boolean({ char: "f", description: "force command execution" }),
|
|
99
|
+
tenant: flags.string({
|
|
100
|
+
char: "t",
|
|
101
|
+
description: "tenant",
|
|
102
|
+
}),
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
module.exports = DeleteUserCommand;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @category saltcorn-cli
|
|
3
|
+
* @module commands/modify-user
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// todo support for users without emails (using user.id)
|
|
7
|
+
const { Command, flags } = require("@oclif/command");
|
|
8
|
+
const { cli } = require("cli-ux");
|
|
9
|
+
const { maybe_as_tenant, init_some_tenants } = require("../common");
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* ModifyUserCommand Class
|
|
14
|
+
* @extends oclif.Command
|
|
15
|
+
* @category saltcorn-cli
|
|
16
|
+
*/
|
|
17
|
+
class ModifyUserCommand extends Command {
|
|
18
|
+
/**
|
|
19
|
+
* @returns {Promise<void>}
|
|
20
|
+
*/
|
|
21
|
+
async run() {
|
|
22
|
+
|
|
23
|
+
const User = require("@saltcorn/data/models/user");
|
|
24
|
+
|
|
25
|
+
const { args } = this.parse(ModifyUserCommand);
|
|
26
|
+
const { flags } = this.parse(ModifyUserCommand);
|
|
27
|
+
|
|
28
|
+
if (flags.admin && flags.role && flags.role !== "admin") {
|
|
29
|
+
console.error("Error: specify at most one of admin and role");
|
|
30
|
+
this.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// init tenant
|
|
34
|
+
await init_some_tenants(flags.tenant);
|
|
35
|
+
|
|
36
|
+
// run function as specified tenant
|
|
37
|
+
await maybe_as_tenant(flags.tenant, async () => {
|
|
38
|
+
// role_id
|
|
39
|
+
let role_id; // = flags.admin ? 1 : 8;
|
|
40
|
+
if (flags.admin) role_id = 1;
|
|
41
|
+
else if (flags.role) {
|
|
42
|
+
const roles = await User.get_roles();
|
|
43
|
+
const role = roles.find((r) => r.role === flags.role);
|
|
44
|
+
if (!role) {
|
|
45
|
+
console.error(`Error: role ${flags.role} not found`);
|
|
46
|
+
this.exit(1);
|
|
47
|
+
}
|
|
48
|
+
role_id = role.id;
|
|
49
|
+
}
|
|
50
|
+
// email
|
|
51
|
+
let email;
|
|
52
|
+
if (flags.email) email = flags.email;
|
|
53
|
+
else if (flags.imode) email = await cli.prompt("New Email address", { default : args.user_email });
|
|
54
|
+
if(email === args.user_email) email = undefined; // little trick - we won't update email if it already same
|
|
55
|
+
if (email)
|
|
56
|
+
if (!User.valid_email(email)){
|
|
57
|
+
console.error(`Error: Email is invalid`);
|
|
58
|
+
this.exit(1);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// password
|
|
62
|
+
// todo check for repeated passwords
|
|
63
|
+
let password;
|
|
64
|
+
if (flags.password) password = flags.password;
|
|
65
|
+
else if (flags.imode) password = await cli.prompt("New Password", { type: "hide" });
|
|
66
|
+
if (password)
|
|
67
|
+
if (User.unacceptable_password_reason(password)){
|
|
68
|
+
console.error(`Error: ${User.unacceptable_password_reason(password)}`);
|
|
69
|
+
this.exit(1);
|
|
70
|
+
}
|
|
71
|
+
// check that user with new email does not exists
|
|
72
|
+
const u_new_email = await User.findOne({ email });
|
|
73
|
+
if(u_new_email !== null&&args.user_email!==email){
|
|
74
|
+
console.error(`Error: Cannot change email from ${args.user_email} to ${email}. User with email ${email} exists`);
|
|
75
|
+
this.exit(1);
|
|
76
|
+
}
|
|
77
|
+
// try to find user
|
|
78
|
+
const u = await User.findOne({ email: args.user_email });
|
|
79
|
+
if(u === null){
|
|
80
|
+
console.error(`Error: User ${args.user_email} is not found`);
|
|
81
|
+
this.exit(1);
|
|
82
|
+
}
|
|
83
|
+
if(!u instanceof User){
|
|
84
|
+
console.error(`Error: ${u.error}`);
|
|
85
|
+
this.exit(1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// make changes
|
|
89
|
+
if (email && role_id)
|
|
90
|
+
await u.update({ email, role_id });
|
|
91
|
+
else if(email)
|
|
92
|
+
await u.update({ email });
|
|
93
|
+
else if(role_id)
|
|
94
|
+
await u.update({ role_id });
|
|
95
|
+
|
|
96
|
+
if (password)
|
|
97
|
+
await u.changePasswordTo(password, false);
|
|
98
|
+
|
|
99
|
+
console.log(`Success: User ${email?email:args.user_email} updated successfully ${
|
|
100
|
+
typeof flags.tenant !== "undefined" ? "in tenant " + flags.tenant : ""
|
|
101
|
+
}`);
|
|
102
|
+
|
|
103
|
+
});
|
|
104
|
+
this.exit(0);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* @type {object}
|
|
110
|
+
*/
|
|
111
|
+
ModifyUserCommand.args = [
|
|
112
|
+
{ name: "user_email", required: true, description: "User to modify" },
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @type {string}
|
|
117
|
+
*/
|
|
118
|
+
ModifyUserCommand.description = `Modify (update) user.
|
|
119
|
+
|
|
120
|
+
Command changes the user specified by USER_EMAIL.
|
|
121
|
+
|
|
122
|
+
You can change the user group, password and email.
|
|
123
|
+
|
|
124
|
+
NOTE that -a and -r role (--role=role) can give conflict.
|
|
125
|
+
`;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @type {string}
|
|
129
|
+
*/
|
|
130
|
+
ModifyUserCommand.help = `Modify (update) user.
|
|
131
|
+
|
|
132
|
+
Command changes the user specified by USER_EMAIL.
|
|
133
|
+
|
|
134
|
+
You can change the user group, password and email.
|
|
135
|
+
|
|
136
|
+
NOTE that -a and -r role (--role=role) can give conflict.
|
|
137
|
+
`;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @type {object}
|
|
141
|
+
*/
|
|
142
|
+
ModifyUserCommand.flags = {
|
|
143
|
+
admin: flags.boolean({ char: "a", description: "make user be Admin" }),
|
|
144
|
+
tenant: flags.string({
|
|
145
|
+
char: "t",
|
|
146
|
+
description: "tenant",
|
|
147
|
+
}),
|
|
148
|
+
email: flags.string({
|
|
149
|
+
char: "e",
|
|
150
|
+
description: "new email",
|
|
151
|
+
}),
|
|
152
|
+
role: flags.string({
|
|
153
|
+
char: "r",
|
|
154
|
+
description: "new role (can conflict with -a option)",
|
|
155
|
+
}),
|
|
156
|
+
password: flags.string({
|
|
157
|
+
char: "p",
|
|
158
|
+
description: "new password",
|
|
159
|
+
}),
|
|
160
|
+
imode: flags.boolean({ char: "i", description: "interactive mode" }),
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
module.exports = ModifyUserCommand;
|
package/src/commands/release.js
CHANGED
|
@@ -24,6 +24,7 @@ class ReleaseCommand extends Command {
|
|
|
24
24
|
"@saltcorn/e2e": { dir: "e2e" },
|
|
25
25
|
"@saltcorn/db-common": { dir: "db-common", publish: true },
|
|
26
26
|
"@saltcorn/sqlite": { dir: "sqlite", publish: true },
|
|
27
|
+
"@saltcorn/sqlite-mobile": { dir: "sqlite-mobile", publish: true },
|
|
27
28
|
"@saltcorn/postgres": { dir: "postgres", publish: true },
|
|
28
29
|
"@saltcorn/types": { dir: "saltcorn-types", publish: true },
|
|
29
30
|
"@saltcorn/builder": { dir: "saltcorn-builder", publish: true },
|
|
@@ -37,6 +38,8 @@ class ReleaseCommand extends Command {
|
|
|
37
38
|
"@saltcorn/base-plugin": { dir: "saltcorn-base-plugin", publish: true },
|
|
38
39
|
//"saltcorn-cli", publish: true},
|
|
39
40
|
"@saltcorn/markup": { dir: "saltcorn-markup", publish: true },
|
|
41
|
+
"@saltcorn/mobile-app": { dir: "saltcorn-mobile-app", publish: true },
|
|
42
|
+
"@saltcorn/mobile-builder": { dir: "saltcorn-mobile-builder", publish: true },
|
|
40
43
|
"@saltcorn/sbadmin2": { dir: "saltcorn-sbadmin2", publish: true },
|
|
41
44
|
};
|
|
42
45
|
|
|
@@ -17,7 +17,7 @@ class ResetCommand extends Command {
|
|
|
17
17
|
*/
|
|
18
18
|
async run() {
|
|
19
19
|
const reset = require("@saltcorn/data/db/reset_schema");
|
|
20
|
-
const db = require("@saltcorn/data/db
|
|
20
|
+
const db = require("@saltcorn/data/db");
|
|
21
21
|
const { flags } = this.parse(ResetCommand);
|
|
22
22
|
await maybe_as_tenant(flags.tenant, async () => {
|
|
23
23
|
const schema = db.getTenantSchema();
|
|
@@ -32,6 +32,7 @@ class ResetCommand extends Command {
|
|
|
32
32
|
if (ans) await reset(false, schema);
|
|
33
33
|
}
|
|
34
34
|
});
|
|
35
|
+
console.log(`Success: Command execution successfully`);
|
|
35
36
|
this.exit(0);
|
|
36
37
|
}
|
|
37
38
|
}
|
|
@@ -44,11 +45,19 @@ ResetCommand.description = `Reset the database
|
|
|
44
45
|
This will delete all existing information
|
|
45
46
|
`;
|
|
46
47
|
|
|
48
|
+
/**
|
|
49
|
+
* @type {string}
|
|
50
|
+
*/
|
|
51
|
+
ResetCommand.help = `Reset the database
|
|
52
|
+
...
|
|
53
|
+
This will delete all existing information
|
|
54
|
+
`;
|
|
55
|
+
|
|
47
56
|
/**
|
|
48
57
|
* @type {object}
|
|
49
58
|
*/
|
|
50
59
|
ResetCommand.flags = {
|
|
51
|
-
force: flags.boolean({ char: "f", description: "force" }),
|
|
60
|
+
force: flags.boolean({ char: "f", description: "force command execution" }),
|
|
52
61
|
tenant: flags.string({
|
|
53
62
|
char: "t",
|
|
54
63
|
description: "tenant",
|
package/src/commands/restore.js
CHANGED
|
@@ -91,6 +91,11 @@ RestoreCommand.args = [
|
|
|
91
91
|
*/
|
|
92
92
|
RestoreCommand.description = `Restore a previously backed up database (zip or sqlc format)`;
|
|
93
93
|
|
|
94
|
+
/**
|
|
95
|
+
* @type {string}
|
|
96
|
+
*/
|
|
97
|
+
RestoreCommand.help = `Restore a previously backed up database (zip or sqlc format)`;
|
|
98
|
+
|
|
94
99
|
/**
|
|
95
100
|
* @type {object}
|
|
96
101
|
*/
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* @module commands/rm-tenant
|
|
4
4
|
*/
|
|
5
5
|
const { Command, flags } = require("@oclif/command");
|
|
6
|
+
const {cli} = require("cli-ux");
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* RmTenantCommand Class
|
|
@@ -14,9 +15,23 @@ class RmTenantCommand extends Command {
|
|
|
14
15
|
* @returns {Promise<void>}
|
|
15
16
|
*/
|
|
16
17
|
async run() {
|
|
17
|
-
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
const { flags } = this.parse(RmTenantCommand);
|
|
21
|
+
|
|
18
22
|
const { deleteTenant } = require("@saltcorn/admin-models/models/tenant");
|
|
19
|
-
|
|
23
|
+
|
|
24
|
+
if (!flags.force) {
|
|
25
|
+
const ans = await cli.confirm(
|
|
26
|
+
`This will delete tenant ${flags.tenant}. Attention! All tenant data will be lost!\nContinue (y/n)?`);
|
|
27
|
+
if (!ans) {
|
|
28
|
+
console.log(`Success: Command execution canceled`);
|
|
29
|
+
this.exit(1);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// make changes
|
|
33
|
+
await deleteTenant(flags.tenant);
|
|
34
|
+
|
|
20
35
|
this.exit(0);
|
|
21
36
|
}
|
|
22
37
|
}
|
|
@@ -24,18 +39,36 @@ class RmTenantCommand extends Command {
|
|
|
24
39
|
/**
|
|
25
40
|
* @type {object}
|
|
26
41
|
*/
|
|
27
|
-
RmTenantCommand.args = [
|
|
42
|
+
RmTenantCommand.args = []; /*[
|
|
28
43
|
{ name: "tenant", required: true, description: "Tenant to remove" },
|
|
29
44
|
];
|
|
30
|
-
|
|
45
|
+
*/
|
|
31
46
|
/**
|
|
32
47
|
* @type {string}
|
|
33
48
|
*/
|
|
34
|
-
RmTenantCommand.description = `Remove a tenant
|
|
49
|
+
RmTenantCommand.description = `Remove a tenant.
|
|
50
|
+
Attention! All tenant data will be lost!
|
|
51
|
+
It recommended to make backup of tenant before perform this command.
|
|
52
|
+
`;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @type {object}
|
|
56
|
+
*/
|
|
57
|
+
RmTenantCommand.help = `Remove a tenant.
|
|
58
|
+
Attention! All tenant data will be lost!
|
|
59
|
+
It recommended to make backup of tenant before perform this command.
|
|
60
|
+
`;
|
|
35
61
|
|
|
36
62
|
/**
|
|
37
63
|
* @type {object}
|
|
38
64
|
*/
|
|
39
|
-
RmTenantCommand.flags = {
|
|
65
|
+
RmTenantCommand.flags = {
|
|
66
|
+
force: flags.boolean({ char: "f", description: "force command execution" }),
|
|
67
|
+
tenant: flags.string({
|
|
68
|
+
char: "t",
|
|
69
|
+
description: "tenant",
|
|
70
|
+
required: true,
|
|
71
|
+
}),
|
|
72
|
+
};
|
|
40
73
|
|
|
41
74
|
module.exports = RmTenantCommand;
|
|
@@ -156,11 +156,12 @@ class RunTestsCommand extends Command {
|
|
|
156
156
|
const cwd = "packages/" + args.package;
|
|
157
157
|
await this.do_test("npm", ["run", "test", ...jestParams], env, cwd);
|
|
158
158
|
} else {
|
|
159
|
-
const
|
|
159
|
+
const cwd = ".";
|
|
160
160
|
await this.do_test(
|
|
161
|
-
|
|
162
|
-
["
|
|
163
|
-
env
|
|
161
|
+
"npm",
|
|
162
|
+
["--workspaces", "run", "test", ...jestParams],
|
|
163
|
+
env,
|
|
164
|
+
cwd
|
|
164
165
|
);
|
|
165
166
|
//await this.e2etest(env);
|
|
166
167
|
}
|
package/src/commands/setup.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Set up new saltcorn configuration
|
|
2
3
|
* @category saltcorn-cli
|
|
3
4
|
* @module commands/setup
|
|
4
5
|
*/
|
|
@@ -20,20 +21,25 @@ const sudo = require("sudo");
|
|
|
20
21
|
const crypto = require("crypto");
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
|
-
*
|
|
24
|
+
* Generate password for user
|
|
24
25
|
* @returns {string}
|
|
25
26
|
*/
|
|
27
|
+
// todo deduplicate code - the same function in User
|
|
26
28
|
const gen_password = () => {
|
|
27
29
|
const s = is.str.generate().replace(" ", "");
|
|
28
30
|
if (s.length > 7) return s;
|
|
29
31
|
else return gen_password();
|
|
30
32
|
};
|
|
31
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Generate jwt secret
|
|
35
|
+
* @returns {string}
|
|
36
|
+
*/
|
|
32
37
|
const genJwtSecret = () => {
|
|
33
38
|
return crypto.randomBytes(64).toString("hex");
|
|
34
39
|
};
|
|
35
40
|
|
|
36
41
|
/**
|
|
42
|
+
* Ask for platform run mode (dev - run manually, server - run as system service)
|
|
37
43
|
*
|
|
38
44
|
* @returns {Promise<object>}
|
|
39
45
|
*/
|
|
@@ -63,7 +69,7 @@ const askDevServer = async () => {
|
|
|
63
69
|
};
|
|
64
70
|
|
|
65
71
|
/**
|
|
66
|
-
*
|
|
72
|
+
* Unload module
|
|
67
73
|
* @param {*} mod
|
|
68
74
|
*/
|
|
69
75
|
const unloadModule = (mod) => {
|
|
@@ -72,6 +78,7 @@ const unloadModule = (mod) => {
|
|
|
72
78
|
};
|
|
73
79
|
|
|
74
80
|
/**
|
|
81
|
+
* Set up platform run mode (dev - run manually, server - run as system service)
|
|
75
82
|
* @returns {Promise<void>}
|
|
76
83
|
*/
|
|
77
84
|
const setupDevMode = async () => {
|
|
@@ -95,6 +102,8 @@ const setupDevMode = async () => {
|
|
|
95
102
|
};
|
|
96
103
|
|
|
97
104
|
/**
|
|
105
|
+
* Check for locally running database (ip 127.0.0.1, port 5432)
|
|
106
|
+
*
|
|
98
107
|
* @returns {Promise<void>}
|
|
99
108
|
*/
|
|
100
109
|
const check_db = async () => {
|
|
@@ -125,7 +134,7 @@ const check_db = async () => {
|
|
|
125
134
|
};
|
|
126
135
|
|
|
127
136
|
/**
|
|
128
|
-
*
|
|
137
|
+
* Execute Linux commands
|
|
129
138
|
* @param {*} args
|
|
130
139
|
* @returns {Promise<void>}
|
|
131
140
|
*/
|
|
@@ -146,7 +155,7 @@ const asyncSudo = (args) => {
|
|
|
146
155
|
};
|
|
147
156
|
|
|
148
157
|
/**
|
|
149
|
-
*
|
|
158
|
+
* Execute Postgres commands
|
|
150
159
|
* @param {*} args
|
|
151
160
|
* @returns {Promise<void>}
|
|
152
161
|
*/
|
|
@@ -155,7 +164,7 @@ const asyncSudoPostgres = (args) => {
|
|
|
155
164
|
};
|
|
156
165
|
|
|
157
166
|
/**
|
|
158
|
-
*
|
|
167
|
+
* Ask for passworf
|
|
159
168
|
* @param {string} for_who
|
|
160
169
|
* @returns {Promise<string>}
|
|
161
170
|
*/
|
|
@@ -173,6 +182,7 @@ const get_password = async (for_who) => {
|
|
|
173
182
|
};
|
|
174
183
|
|
|
175
184
|
/**
|
|
185
|
+
* Install Database
|
|
176
186
|
* @returns {Promise<void>}
|
|
177
187
|
*/
|
|
178
188
|
const install_db = async () => {
|
|
@@ -228,7 +238,7 @@ const install_db = async () => {
|
|
|
228
238
|
};
|
|
229
239
|
|
|
230
240
|
/**
|
|
231
|
-
*
|
|
241
|
+
* Ask for Database parameters
|
|
232
242
|
* @returns {Promise<object>}
|
|
233
243
|
*/
|
|
234
244
|
const prompt_connection = async () => {
|
|
@@ -262,6 +272,7 @@ const prompt_connection = async () => {
|
|
|
262
272
|
};
|
|
263
273
|
|
|
264
274
|
/**
|
|
275
|
+
* Write platform config
|
|
265
276
|
* @returns {Promise<void>}
|
|
266
277
|
*/
|
|
267
278
|
const setup_connection_config = async () => {
|
|
@@ -310,10 +321,10 @@ const setup_connection = async () => {
|
|
|
310
321
|
* @returns {Promise<boolean>}
|
|
311
322
|
*/
|
|
312
323
|
const table_exists = async (db, tblname) => {
|
|
313
|
-
const { rows } = await db.query(`SELECT EXISTS
|
|
324
|
+
const { rows } = await db.query(`SELECT EXISTS
|
|
314
325
|
(
|
|
315
326
|
SELECT 1
|
|
316
|
-
FROM information_schema.tables
|
|
327
|
+
FROM information_schema.tables
|
|
317
328
|
WHERE table_schema = 'public'
|
|
318
329
|
AND table_name = '${tblname}'
|
|
319
330
|
);`);
|
|
@@ -381,7 +392,7 @@ class SetupCommand extends Command {
|
|
|
381
392
|
*/
|
|
382
393
|
SetupCommand.description = `Set up a new system
|
|
383
394
|
...
|
|
384
|
-
This will attempt to install or connect a database, and set up a
|
|
395
|
+
This will attempt to install or connect a database, and set up a
|
|
385
396
|
configuration file
|
|
386
397
|
`;
|
|
387
398
|
|
package/src/common.js
CHANGED
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
* @category saltcorn-cli
|
|
3
3
|
* @module common
|
|
4
4
|
*/
|
|
5
|
-
|
|
5
|
+
// todo need to be reorganized
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
* @param {
|
|
7
|
+
* Execute function for specified tenant
|
|
8
|
+
* @param {object} ten - specified tenant
|
|
9
|
+
* @param {function} f - function
|
|
9
10
|
* @returns {Promise<void>}
|
|
10
11
|
*/
|
|
11
12
|
const maybe_as_tenant = async (ten, f) => {
|
|
@@ -13,7 +14,11 @@ const maybe_as_tenant = async (ten, f) => {
|
|
|
13
14
|
const db = require("@saltcorn/data/db");
|
|
14
15
|
return await db.runWithTenant(ten, f);
|
|
15
16
|
};
|
|
16
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Init specified tenant
|
|
19
|
+
* @param tenant - specified tenant
|
|
20
|
+
* @returns {Promise<void>}
|
|
21
|
+
*/
|
|
17
22
|
const init_some_tenants = async (tenant) => {
|
|
18
23
|
const { loadAllPlugins } = require("@saltcorn/server/load_plugins");
|
|
19
24
|
const { init_multi_tenant } = require("@saltcorn/data/db/state");
|
|
@@ -24,6 +29,7 @@ const init_some_tenants = async (tenant) => {
|
|
|
24
29
|
};
|
|
25
30
|
|
|
26
31
|
/**
|
|
32
|
+
* parse JSON or String
|
|
27
33
|
* @param {string} s
|
|
28
34
|
* @returns {object}
|
|
29
35
|
*/
|
|
@@ -36,12 +42,14 @@ const parseJSONorString = (s) => {
|
|
|
36
42
|
};
|
|
37
43
|
|
|
38
44
|
/**
|
|
39
|
-
*
|
|
45
|
+
* Sleep ms miliseconds
|
|
46
|
+
* @param {number} ms
|
|
40
47
|
* @returns {Promise<void>}
|
|
41
48
|
*/
|
|
42
49
|
function sleep(ms) {
|
|
43
50
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
44
51
|
}
|
|
52
|
+
|
|
45
53
|
module.exports = {
|
|
46
54
|
maybe_as_tenant,
|
|
47
55
|
parseJSONorString,
|
package/src/index.js
CHANGED
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
* @property {module:commands/backup} backup
|
|
11
11
|
* @property {module:commands/create-tenant} create-tenant
|
|
12
12
|
* @property {module:commands/create-user} create-user
|
|
13
|
+
* @property {module:commands/create-user} delete-tenants
|
|
14
|
+
* @property {module:commands/create-user} delete-user
|
|
13
15
|
* @property {module:commands/fixtures} fixtures
|
|
16
|
+
* @property {module:commands/fixtures} get-cfg
|
|
14
17
|
* @property {module:commands/info} info
|
|
15
18
|
* @property {module:commands/install-pack} install-pack
|
|
16
19
|
* @property {module:commands/install-plugin} install-plugin
|
|
@@ -18,17 +21,21 @@
|
|
|
18
21
|
* @property {module:commands/localize-plugin} localize-plugin
|
|
19
22
|
* @property {module:commands/make-migration} make-migration
|
|
20
23
|
* @property {module:commands/migrate} migrate
|
|
24
|
+
* @property {module:commands/modify-user} modify-user
|
|
21
25
|
* @property {module:commands/plugins} plugins
|
|
22
26
|
* @property {module:commands/release} release
|
|
23
27
|
* @property {module:commands/reset-schema} reset-schema
|
|
24
28
|
* @property {module:commands/restore} restore
|
|
25
29
|
* @property {module:commands/rm-tenant} rm-tenant
|
|
26
30
|
* @property {module:commands/run-benchmark} run-benchmark
|
|
31
|
+
* @property {module:commands/run-benchmark} run-test
|
|
32
|
+
* @property {module:commands/setup} scheduler
|
|
27
33
|
* @property {module:commands/setup} setup
|
|
34
|
+
* @property {module:commands/setup} setup-benchmark
|
|
28
35
|
* @property {module:commands/test-plugin} test-plugin
|
|
29
36
|
* @property {module:commands/transform-field} transform-field
|
|
30
|
-
*
|
|
37
|
+
*
|
|
31
38
|
* @category saltcorn-cli
|
|
32
|
-
*/
|
|
39
|
+
*/
|
|
33
40
|
|
|
34
41
|
module.exports = require("@oclif/command");
|