@saltcorn/data 0.6.1-beta.0 → 0.6.1
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/base-plugin/actions.js +172 -1
- package/base-plugin/fieldviews.js +63 -0
- package/base-plugin/fileviews.js +41 -0
- package/base-plugin/index.js +35 -0
- package/base-plugin/types.js +345 -9
- package/base-plugin/viewtemplates/edit.js +107 -0
- package/base-plugin/viewtemplates/feed.js +46 -0
- package/base-plugin/viewtemplates/filter.js +43 -0
- package/base-plugin/viewtemplates/list.js +73 -1
- package/base-plugin/viewtemplates/listshowlist.js +54 -3
- package/base-plugin/viewtemplates/room.js +100 -0
- package/base-plugin/viewtemplates/show.js +86 -0
- package/base-plugin/viewtemplates/viewable_fields.js +124 -0
- package/contracts.js +58 -0
- package/db/connect.js +13 -5
- package/db/db.test.js +0 -154
- package/db/fixtures.js +13 -1
- package/db/index.js +42 -3
- package/db/reset_schema.js +11 -0
- package/db/state.js +105 -36
- package/index.js +13 -0
- package/migrate.js +4 -1
- package/models/backup.js +78 -0
- package/models/config.js +113 -22
- package/models/crash.js +44 -0
- package/models/discovery.js +13 -11
- package/models/email.js +17 -0
- package/models/eventlog.js +51 -0
- package/models/expression.js +49 -1
- package/models/field.js +88 -9
- package/models/fieldrepeat.js +33 -0
- package/models/file.js +23 -4
- package/models/form.js +34 -0
- package/models/index.js +42 -0
- package/models/layout.js +33 -0
- package/models/library.js +44 -0
- package/models/pack.js +88 -0
- package/models/page.js +13 -3
- package/models/plugin.js +9 -2
- package/models/random.js +36 -0
- package/models/role.js +36 -0
- package/models/scheduler.js +28 -0
- package/models/table.js +34 -15
- package/models/table_constraints.js +44 -0
- package/models/tenant.js +46 -9
- package/models/trigger.js +24 -11
- package/models/user.js +33 -8
- package/models/view.js +89 -8
- package/models/workflow.js +31 -0
- package/package.json +7 -5
- package/plugin-helper.js +102 -44
- package/plugin-testing.js +4 -0
- package/tests/exact_views.test.js +5 -5
- package/utils.js +4 -0
- package/db/internal.js +0 -229
- package/db/multi-tenant.js +0 -24
- package/db/pg.js +0 -374
- package/db/single-tenant.js +0 -8
- package/db/sqlite.js +0 -280
- package/db/tenants.js +0 -6
package/models/scheduler.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @category saltcorn-data
|
|
3
|
+
* @module models/scheduler
|
|
4
|
+
* @subcategory models
|
|
5
|
+
*/
|
|
1
6
|
const Crash = require("./crash");
|
|
2
7
|
const { eachTenant } = require("./tenant");
|
|
3
8
|
const Trigger = require("./trigger");
|
|
@@ -6,6 +11,11 @@ const { getState } = require("../db/state");
|
|
|
6
11
|
const fetch = require("node-fetch");
|
|
7
12
|
const EventLog = require("./eventlog");
|
|
8
13
|
|
|
14
|
+
/**
|
|
15
|
+
* @param {Date} date
|
|
16
|
+
* @param {number} plusSeconds
|
|
17
|
+
* @returns {Promise<void>}
|
|
18
|
+
*/
|
|
9
19
|
const sleepUntil = (date, plusSeconds) => {
|
|
10
20
|
const waitTill = new Date();
|
|
11
21
|
waitTill.setTime(date.getTime() + 1000 * plusSeconds);
|
|
@@ -14,6 +24,11 @@ const sleepUntil = (date, plusSeconds) => {
|
|
|
14
24
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
15
25
|
};
|
|
16
26
|
|
|
27
|
+
/**
|
|
28
|
+
* @param {string} name
|
|
29
|
+
* @param {number} hours
|
|
30
|
+
* @returns {Promise<Trigger[]>}
|
|
31
|
+
*/
|
|
17
32
|
const getIntervalTriggersDueNow = async (name, hours) => {
|
|
18
33
|
const state = getState();
|
|
19
34
|
const cfgField = `next_${name.toLowerCase()}_event`;
|
|
@@ -51,6 +66,10 @@ const getIntervalTriggersDueNow = async (name, hours) => {
|
|
|
51
66
|
|
|
52
67
|
let availabilityPassed = false;
|
|
53
68
|
|
|
69
|
+
/**
|
|
70
|
+
* @param {string} port
|
|
71
|
+
* @returns {Promise<void>}
|
|
72
|
+
*/
|
|
54
73
|
const checkAvailability = async (port) => {
|
|
55
74
|
try {
|
|
56
75
|
const response = await fetch(`http://127.0.0.1:${port}/auth/login`);
|
|
@@ -72,6 +91,15 @@ const checkAvailability = async (port) => {
|
|
|
72
91
|
}
|
|
73
92
|
};
|
|
74
93
|
|
|
94
|
+
/**
|
|
95
|
+
* @param {object} opts
|
|
96
|
+
* @param {function} [opts.stop_when]
|
|
97
|
+
* @param {number} [opts.number]
|
|
98
|
+
* @param {boolean} opts.watchReaper
|
|
99
|
+
* @param {string} opts.port
|
|
100
|
+
* @param {boolean} opts.disableScheduler
|
|
101
|
+
* @returns {Promise<void>}
|
|
102
|
+
*/
|
|
75
103
|
const runScheduler = async ({
|
|
76
104
|
stop_when = () => false,
|
|
77
105
|
tickSeconds = 60 * 5,
|
package/models/table.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Table Database Access Layer
|
|
3
|
-
*
|
|
3
|
+
* @category saltcorn-data
|
|
4
|
+
* @module models/table
|
|
5
|
+
* @subcategory models
|
|
4
6
|
*/
|
|
5
7
|
const db = require("../db");
|
|
6
|
-
const {
|
|
8
|
+
const {
|
|
9
|
+
sqlsanitize,
|
|
10
|
+
mkWhere,
|
|
11
|
+
mkSelectOptions,
|
|
12
|
+
} = require("@saltcorn/db-common/internal.js");
|
|
7
13
|
const Field = require("./field");
|
|
8
14
|
const Trigger = require("./trigger");
|
|
9
15
|
const {
|
|
@@ -29,7 +35,7 @@ const {
|
|
|
29
35
|
* TODO more detailed explanation
|
|
30
36
|
* TODO refactor - move to object util module?
|
|
31
37
|
* @param objs
|
|
32
|
-
* @returns {
|
|
38
|
+
* @returns {object}
|
|
33
39
|
*/
|
|
34
40
|
const transposeObjects = (objs) => {
|
|
35
41
|
const keys = new Set();
|
|
@@ -64,7 +70,7 @@ const isDate = function (date) {
|
|
|
64
70
|
/**
|
|
65
71
|
* Normalise specific error message according db specific
|
|
66
72
|
* @param msg
|
|
67
|
-
* @returns {
|
|
73
|
+
* @returns {string}
|
|
68
74
|
*/
|
|
69
75
|
// todo refactor
|
|
70
76
|
const normalise_error_message = (msg) =>
|
|
@@ -80,8 +86,13 @@ const normalise_error_message = (msg) =>
|
|
|
80
86
|
|
|
81
87
|
/**
|
|
82
88
|
* Table class
|
|
89
|
+
* @category saltcorn-data
|
|
83
90
|
*/
|
|
84
91
|
class Table {
|
|
92
|
+
/**
|
|
93
|
+
* Table constructor
|
|
94
|
+
* @param {object} o
|
|
95
|
+
*/
|
|
85
96
|
constructor(o) {
|
|
86
97
|
this.name = o.name;
|
|
87
98
|
this.id = o.id;
|
|
@@ -100,7 +111,7 @@ class Table {
|
|
|
100
111
|
*
|
|
101
112
|
* Find one Table
|
|
102
113
|
* @param where - where condition
|
|
103
|
-
* @returns {
|
|
114
|
+
* @returns {*|Table|null} table or null
|
|
104
115
|
*/
|
|
105
116
|
static findOne(where) {
|
|
106
117
|
if (
|
|
@@ -131,9 +142,13 @@ class Table {
|
|
|
131
142
|
* Find Tables
|
|
132
143
|
* @param where - where condition
|
|
133
144
|
* @param selectopts - options
|
|
134
|
-
* @returns {Promise
|
|
145
|
+
* @returns {Promise<Table[]>} table list
|
|
135
146
|
*/
|
|
136
147
|
static async find(where, selectopts = { orderBy: "name", nocase: true }) {
|
|
148
|
+
if (selectopts.cached) {
|
|
149
|
+
const { getState } = require("../db/state");
|
|
150
|
+
return getState().tables.map((t) => new Table(t));
|
|
151
|
+
}
|
|
137
152
|
const tbls = await db.select("_sc_tables", where, selectopts);
|
|
138
153
|
|
|
139
154
|
return tbls.map((t) => new Table(t));
|
|
@@ -143,7 +158,7 @@ class Table {
|
|
|
143
158
|
* Find Tables including external tables
|
|
144
159
|
* @param where0
|
|
145
160
|
* @param selectopts
|
|
146
|
-
* @returns {Promise
|
|
161
|
+
* @returns {Promise<object[]>}
|
|
147
162
|
*/
|
|
148
163
|
static async find_with_external(
|
|
149
164
|
where0 = {},
|
|
@@ -284,7 +299,7 @@ class Table {
|
|
|
284
299
|
|
|
285
300
|
/***
|
|
286
301
|
* get Table SQL Name
|
|
287
|
-
* @
|
|
302
|
+
* @type {string}
|
|
288
303
|
*/
|
|
289
304
|
get sql_name() {
|
|
290
305
|
return `${db.getTenantSchemaPrefix()}"${sqlsanitize(this.name)}"`;
|
|
@@ -339,7 +354,7 @@ class Table {
|
|
|
339
354
|
* Get rows from Table in db
|
|
340
355
|
* @param where
|
|
341
356
|
* @param selopts
|
|
342
|
-
* @returns {Promise
|
|
357
|
+
* @returns {Promise<void>}
|
|
343
358
|
*/
|
|
344
359
|
async getRows(where = {}, selopts) {
|
|
345
360
|
await this.getFields();
|
|
@@ -363,9 +378,8 @@ class Table {
|
|
|
363
378
|
* Return distinct Values for column in table
|
|
364
379
|
* ????
|
|
365
380
|
* @param fieldnm
|
|
366
|
-
* @returns {Promise
|
|
381
|
+
* @returns {Promise<Object[]>}
|
|
367
382
|
*/
|
|
368
|
-
|
|
369
383
|
async distinctValues(fieldnm) {
|
|
370
384
|
const res = await db.query(
|
|
371
385
|
`select distinct "${db.sqlsanitize(fieldnm)}" from ${this.sql_name}`
|
|
@@ -457,7 +471,7 @@ class Table {
|
|
|
457
471
|
|
|
458
472
|
/**
|
|
459
473
|
* Get primary key field
|
|
460
|
-
* @
|
|
474
|
+
* @type {string}
|
|
461
475
|
*/
|
|
462
476
|
get pk_name() {
|
|
463
477
|
return this.fields.find((f) => f.primary_key).name;
|
|
@@ -503,7 +517,7 @@ class Table {
|
|
|
503
517
|
|
|
504
518
|
/**
|
|
505
519
|
* Get Fields list for table
|
|
506
|
-
* @returns {Promise
|
|
520
|
+
* @returns {Promise<Field[]>}
|
|
507
521
|
*/
|
|
508
522
|
async getFields() {
|
|
509
523
|
if (!this.fields) {
|
|
@@ -903,7 +917,7 @@ class Table {
|
|
|
903
917
|
/**
|
|
904
918
|
* Get parent relations for table
|
|
905
919
|
* @param allow_double
|
|
906
|
-
* @returns {Promise<{parent_relations:
|
|
920
|
+
* @returns {Promise<{parent_relations: object[], parent_field_list: object[]}>}
|
|
907
921
|
*/
|
|
908
922
|
async get_parent_relations(allow_double) {
|
|
909
923
|
const fields = await this.getFields();
|
|
@@ -936,7 +950,7 @@ class Table {
|
|
|
936
950
|
|
|
937
951
|
/**
|
|
938
952
|
* Get child relations for table
|
|
939
|
-
* @returns {Promise<{child_relations:
|
|
953
|
+
* @returns {Promise<{child_relations: object[], child_field_list: object[]}>}
|
|
940
954
|
*/
|
|
941
955
|
async get_child_relations() {
|
|
942
956
|
const cfields = await Field.find({ reftable_name: this.name });
|
|
@@ -1083,6 +1097,11 @@ class Table {
|
|
|
1083
1097
|
)}" a ${joinq} ${where} ${mkSelectOptions(selectopts)}`;
|
|
1084
1098
|
return { sql, values };
|
|
1085
1099
|
}
|
|
1100
|
+
|
|
1101
|
+
/**
|
|
1102
|
+
* @param {object} [opts = {}]
|
|
1103
|
+
* @returns {Promise<object[]>}
|
|
1104
|
+
*/
|
|
1086
1105
|
async getJoinedRows(opts = {}) {
|
|
1087
1106
|
const fields = await this.getFields();
|
|
1088
1107
|
|
|
@@ -1,8 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TableConstraint Database Access Layer
|
|
3
|
+
* @category saltcorn-data
|
|
4
|
+
* @module models/table_constraints
|
|
5
|
+
* @subcategory models
|
|
6
|
+
*/
|
|
1
7
|
const db = require("../db");
|
|
2
8
|
const { contract, is } = require("contractis");
|
|
3
9
|
const { stringToJSON } = require("../utils");
|
|
4
10
|
|
|
11
|
+
/**
|
|
12
|
+
* TableConstraint class
|
|
13
|
+
* @category saltcorn-data
|
|
14
|
+
*/
|
|
5
15
|
class TableConstraint {
|
|
16
|
+
/**
|
|
17
|
+
* @param {object} o
|
|
18
|
+
*/
|
|
6
19
|
constructor(o) {
|
|
7
20
|
this.table_id = +o.table_id;
|
|
8
21
|
if (o.table) {
|
|
@@ -14,22 +27,39 @@ class TableConstraint {
|
|
|
14
27
|
contract.class(this);
|
|
15
28
|
}
|
|
16
29
|
|
|
30
|
+
/**
|
|
31
|
+
* @type {object}
|
|
32
|
+
*/
|
|
17
33
|
get toJson() {
|
|
18
34
|
return {
|
|
19
35
|
type: this.type,
|
|
20
36
|
configuration: this.configuration,
|
|
21
37
|
};
|
|
22
38
|
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {*} where
|
|
42
|
+
* @param {*} selectopts
|
|
43
|
+
* @returns {Promise<TableConstraint[]>}
|
|
44
|
+
*/
|
|
23
45
|
static async find(where, selectopts) {
|
|
24
46
|
const db_flds = await db.select("_sc_table_constraints", where, selectopts);
|
|
25
47
|
return db_flds.map((dbf) => new TableConstraint(dbf));
|
|
26
48
|
}
|
|
27
49
|
|
|
50
|
+
/**
|
|
51
|
+
* @param {*} where
|
|
52
|
+
* @returns {Promise<TableConstraint>}
|
|
53
|
+
*/
|
|
28
54
|
static async findOne(where) {
|
|
29
55
|
const p = await db.selectMaybeOne("_sc_table_constraints", where);
|
|
30
56
|
return p ? new TableConstraint(p) : null;
|
|
31
57
|
}
|
|
32
58
|
|
|
59
|
+
/**
|
|
60
|
+
* @param {*} f
|
|
61
|
+
* @returns {Promise<TableConstraint>}
|
|
62
|
+
*/
|
|
33
63
|
static async create(f) {
|
|
34
64
|
const con = new TableConstraint(f);
|
|
35
65
|
const { id, ...rest } = con;
|
|
@@ -43,6 +73,10 @@ class TableConstraint {
|
|
|
43
73
|
|
|
44
74
|
return con;
|
|
45
75
|
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @returns {Promise<void>}
|
|
79
|
+
*/
|
|
46
80
|
async delete() {
|
|
47
81
|
await db.deleteWhere("_sc_table_constraints", { id: this.id });
|
|
48
82
|
if (this.type === "Unique" && this.configuration.fields) {
|
|
@@ -51,6 +85,12 @@ class TableConstraint {
|
|
|
51
85
|
await db.drop_unique_constraint(table.name, this.configuration.fields);
|
|
52
86
|
}
|
|
53
87
|
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @param {*} table
|
|
91
|
+
* @param {*} field
|
|
92
|
+
* @returns {Promise<void>}
|
|
93
|
+
*/
|
|
54
94
|
static async delete_field_constraints(table, field) {
|
|
55
95
|
const tblcs = await TableConstraint.find({ table_id: table.id });
|
|
56
96
|
for (const c of tblcs) {
|
|
@@ -58,6 +98,10 @@ class TableConstraint {
|
|
|
58
98
|
await c.delete();
|
|
59
99
|
}
|
|
60
100
|
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* @type {string[]}
|
|
104
|
+
*/
|
|
61
105
|
static get type_options() {
|
|
62
106
|
return ["Unique"];
|
|
63
107
|
}
|
package/models/tenant.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tenant Management Data Layer Access
|
|
3
|
-
*
|
|
3
|
+
* @category saltcorn-data
|
|
4
|
+
* @module models/tenant
|
|
5
|
+
* @subcategory models
|
|
4
6
|
*/
|
|
5
7
|
const db = require("../db");
|
|
6
8
|
const reset = require("../db/reset_schema");
|
|
7
9
|
const { contract, is } = require("contractis");
|
|
8
|
-
const { sqlsanitize } = require("
|
|
10
|
+
const { sqlsanitize } = require("@saltcorn/db-common/internal");
|
|
9
11
|
const { setConfig } = require("./config");
|
|
12
|
+
const fs = require("fs").promises;
|
|
13
|
+
|
|
10
14
|
/**
|
|
11
15
|
* List all Tenants
|
|
12
|
-
* @
|
|
16
|
+
* @function
|
|
17
|
+
* @returns {Promise<string[]>}
|
|
13
18
|
*/
|
|
14
19
|
const getAllTenants = contract(
|
|
15
20
|
is.fun([], is.promise(is.array(is.str))),
|
|
@@ -24,19 +29,27 @@ const getAllTenants = contract(
|
|
|
24
29
|
* - create db schema
|
|
25
30
|
* - reset db schema (create required )
|
|
26
31
|
* - change current base_url
|
|
27
|
-
* @type {*|(function(...[*]=): *)}
|
|
28
32
|
*
|
|
29
33
|
* Arguments:
|
|
30
34
|
* subdomain - tenant name (subdomain)
|
|
31
35
|
* newurl - base url of tenant
|
|
32
36
|
* email - email of creator
|
|
33
37
|
* description - description of tenant
|
|
38
|
+
* @function
|
|
39
|
+
* @param {string} subdomain
|
|
40
|
+
* @param {string} [newurl]
|
|
41
|
+
* @param {string} [email]
|
|
42
|
+
* @param {string} [description]
|
|
43
|
+
* @returns {Promise<void>}
|
|
34
44
|
*/
|
|
35
45
|
const createTenant = contract(
|
|
36
|
-
is.fun(
|
|
46
|
+
is.fun(
|
|
47
|
+
[is.str, is.maybe(is.str), is.maybe(is.str), is.maybe(is.str)],
|
|
48
|
+
is.promise(is.undefined)
|
|
49
|
+
),
|
|
37
50
|
// TODO how to set names for arguments
|
|
38
|
-
async (
|
|
39
|
-
|
|
51
|
+
async (subdomain, newurl, email, description) => {
|
|
52
|
+
// normalize domain name
|
|
40
53
|
const saneDomain = domain_sanitize(subdomain);
|
|
41
54
|
|
|
42
55
|
// add email
|
|
@@ -61,10 +74,31 @@ const createTenant = contract(
|
|
|
61
74
|
});
|
|
62
75
|
}
|
|
63
76
|
);
|
|
77
|
+
const copy_tenant_template = async ({
|
|
78
|
+
tenant_template,
|
|
79
|
+
target,
|
|
80
|
+
loadAndSaveNewPlugin,
|
|
81
|
+
}) => {
|
|
82
|
+
const { create_backup, restore } = require("./backup");
|
|
83
|
+
// TODO use a hygenic name for backup file
|
|
84
|
+
const backupFile = await db.runWithTenant(tenant_template, create_backup);
|
|
85
|
+
await db.runWithTenant(target, async () => {
|
|
86
|
+
await restore(backupFile, loadAndSaveNewPlugin, true);
|
|
87
|
+
|
|
88
|
+
await db.updateWhere("_sc_files", { user_id: null }, {});
|
|
89
|
+
await db.deleteWhere("users", {});
|
|
90
|
+
await db.reset_sequence("users");
|
|
91
|
+
//
|
|
92
|
+
});
|
|
93
|
+
await fs.unlink(backupFile);
|
|
94
|
+
};
|
|
95
|
+
|
|
64
96
|
/**
|
|
65
97
|
* Delete Tenant
|
|
66
98
|
* Note! This is deleting all tenant data in database!
|
|
67
|
-
* @
|
|
99
|
+
* @function
|
|
100
|
+
* @param {string} sub
|
|
101
|
+
* @returns {Promise<void>}
|
|
68
102
|
*/
|
|
69
103
|
const deleteTenant = contract(
|
|
70
104
|
is.fun(is.str, is.promise(is.undefined)),
|
|
@@ -80,7 +114,9 @@ const deleteTenant = contract(
|
|
|
80
114
|
* Sanitize Domain (Normalize domain name).
|
|
81
115
|
* - force to lower case
|
|
82
116
|
* - remove . in name
|
|
83
|
-
* @
|
|
117
|
+
* @function
|
|
118
|
+
* @param {string} s
|
|
119
|
+
* @returns {string}
|
|
84
120
|
*/
|
|
85
121
|
const domain_sanitize = contract(is.fun(is.str, is.str), (s) =>
|
|
86
122
|
sqlsanitize(s.replace(".", "").toLowerCase())
|
|
@@ -104,4 +140,5 @@ module.exports = {
|
|
|
104
140
|
domain_sanitize,
|
|
105
141
|
deleteTenant,
|
|
106
142
|
eachTenant,
|
|
143
|
+
copy_tenant_template,
|
|
107
144
|
};
|
package/models/trigger.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
2
|
* Trigger Data Access Layer
|
|
3
|
+
* @category saltcorn-data
|
|
4
|
+
* @module models/trigger
|
|
5
|
+
* @subcategory models
|
|
4
6
|
*/
|
|
5
7
|
|
|
6
8
|
const db = require("../db");
|
|
@@ -10,8 +12,13 @@ const EventLog = require("./eventlog");
|
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* Trigger class
|
|
15
|
+
* @category saltcorn-data
|
|
13
16
|
*/
|
|
14
17
|
class Trigger {
|
|
18
|
+
/**
|
|
19
|
+
* Trigger constructor
|
|
20
|
+
* @param {object} o
|
|
21
|
+
*/
|
|
15
22
|
constructor(o) {
|
|
16
23
|
this.name = o.name;
|
|
17
24
|
this.action = o.action;
|
|
@@ -36,7 +43,7 @@ class Trigger {
|
|
|
36
43
|
|
|
37
44
|
/**
|
|
38
45
|
* Get JSON from Trigger
|
|
39
|
-
* @
|
|
46
|
+
* @type {{when_trigger, configuration: any, name, description, action}}
|
|
40
47
|
*/
|
|
41
48
|
get toJson() {
|
|
42
49
|
let table_name = this.table_name;
|
|
@@ -60,7 +67,7 @@ class Trigger {
|
|
|
60
67
|
/**
|
|
61
68
|
* Find triggers in State cache
|
|
62
69
|
* @param where - condition
|
|
63
|
-
* @returns {
|
|
70
|
+
* @returns {Trigger[]}
|
|
64
71
|
*/
|
|
65
72
|
static find(where) {
|
|
66
73
|
const { getState } = require("../db/state");
|
|
@@ -71,7 +78,7 @@ class Trigger {
|
|
|
71
78
|
* Find triggers in DB
|
|
72
79
|
* @param where
|
|
73
80
|
* @param selectopts
|
|
74
|
-
* @returns {Promise
|
|
81
|
+
* @returns {Promise<Trigger[]>}
|
|
75
82
|
*/
|
|
76
83
|
static async findDB(where, selectopts) {
|
|
77
84
|
const db_flds = await db.select("_sc_triggers", where, selectopts);
|
|
@@ -80,7 +87,7 @@ class Trigger {
|
|
|
80
87
|
|
|
81
88
|
/**
|
|
82
89
|
* Find all triggers
|
|
83
|
-
* @returns {Promise
|
|
90
|
+
* @returns {Promise<Trigger[]>}
|
|
84
91
|
*/
|
|
85
92
|
static async findAllWithTableName() {
|
|
86
93
|
const schema = db.getTenantSchemaPrefix();
|
|
@@ -94,7 +101,7 @@ class Trigger {
|
|
|
94
101
|
/**
|
|
95
102
|
* Find one trigger in State cache
|
|
96
103
|
* @param where
|
|
97
|
-
* @returns {
|
|
104
|
+
* @returns {Trigger}
|
|
98
105
|
*/
|
|
99
106
|
static findOne(where) {
|
|
100
107
|
const { getState } = require("../db/state");
|
|
@@ -142,7 +149,13 @@ class Trigger {
|
|
|
142
149
|
await require("../db/state").getState().refresh_triggers();
|
|
143
150
|
}
|
|
144
151
|
|
|
145
|
-
|
|
152
|
+
/**
|
|
153
|
+
* Emit an event: run associated triggers
|
|
154
|
+
* @param {*} eventType
|
|
155
|
+
* @param {*} channel
|
|
156
|
+
* @param {object} [userPW = {}]
|
|
157
|
+
* @param {*} payload
|
|
158
|
+
*/
|
|
146
159
|
static emitEvent(eventType, channel, userPW = {}, payload) {
|
|
147
160
|
setTimeout(async () => {
|
|
148
161
|
const { password, ...user } = userPW || {};
|
|
@@ -205,7 +218,7 @@ class Trigger {
|
|
|
205
218
|
/**
|
|
206
219
|
* Run trigger without row
|
|
207
220
|
* @param runargs
|
|
208
|
-
* @returns {Promise
|
|
221
|
+
* @returns {Promise<boolean>}
|
|
209
222
|
*/
|
|
210
223
|
async runWithoutRow(runargs = {}) {
|
|
211
224
|
const { getState } = require("../db/state");
|
|
@@ -224,7 +237,7 @@ class Trigger {
|
|
|
224
237
|
* get triggers
|
|
225
238
|
* @param when_trigger
|
|
226
239
|
* @param table
|
|
227
|
-
* @returns {Promise
|
|
240
|
+
* @returns {Promise<Trigger[]>}
|
|
228
241
|
*/
|
|
229
242
|
static async getTableTriggers(when_trigger, table) {
|
|
230
243
|
const { getState } = require("../db/state");
|
|
@@ -249,8 +262,8 @@ class Trigger {
|
|
|
249
262
|
}
|
|
250
263
|
|
|
251
264
|
/**
|
|
252
|
-
*
|
|
253
|
-
* @
|
|
265
|
+
* Trigger when options
|
|
266
|
+
* @type {string[]}
|
|
254
267
|
*/
|
|
255
268
|
static get when_options() {
|
|
256
269
|
const { getState } = require("../db/state");
|
package/models/user.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @category saltcorn-data
|
|
3
|
+
* @module models/user
|
|
4
|
+
* @subcategory models
|
|
5
|
+
*/
|
|
1
6
|
const db = require("../db");
|
|
2
7
|
const bcrypt = require("bcryptjs");
|
|
3
8
|
const { contract, is } = require("contractis");
|
|
@@ -5,6 +10,10 @@ const { v4: uuidv4 } = require("uuid");
|
|
|
5
10
|
const dumbPasswords = require("dumb-passwords");
|
|
6
11
|
const validator = require("email-validator");
|
|
7
12
|
|
|
13
|
+
/**
|
|
14
|
+
* @param {object} o
|
|
15
|
+
* @returns {*}
|
|
16
|
+
*/
|
|
8
17
|
const safeUserFields = (o) => {
|
|
9
18
|
const {
|
|
10
19
|
email,
|
|
@@ -25,8 +34,13 @@ const safeUserFields = (o) => {
|
|
|
25
34
|
};
|
|
26
35
|
/**
|
|
27
36
|
* User
|
|
37
|
+
* @category saltcorn-data
|
|
28
38
|
*/
|
|
29
39
|
class User {
|
|
40
|
+
/**
|
|
41
|
+
* User constructor
|
|
42
|
+
* @param {object} o
|
|
43
|
+
*/
|
|
30
44
|
constructor(o) {
|
|
31
45
|
this.email = o.email;
|
|
32
46
|
this.password = o.password;
|
|
@@ -59,7 +73,7 @@ class User {
|
|
|
59
73
|
/**
|
|
60
74
|
* Get bcrypt hash for Password
|
|
61
75
|
* @param pw - password string
|
|
62
|
-
* @returns {Promise
|
|
76
|
+
* @returns {Promise<string>}
|
|
63
77
|
*/
|
|
64
78
|
static async hashPassword(pw) {
|
|
65
79
|
return await bcrypt.hash(pw, 10);
|
|
@@ -68,7 +82,7 @@ class User {
|
|
|
68
82
|
/**
|
|
69
83
|
* Check password
|
|
70
84
|
* @param pw - password string
|
|
71
|
-
* @returns {
|
|
85
|
+
* @returns {boolean}
|
|
72
86
|
*/
|
|
73
87
|
checkPassword(pw) {
|
|
74
88
|
return bcrypt.compareSync(pw, this.password);
|
|
@@ -92,7 +106,7 @@ class User {
|
|
|
92
106
|
* Find or Create User
|
|
93
107
|
* @param k
|
|
94
108
|
* @param v
|
|
95
|
-
* @param uo
|
|
109
|
+
* @param {object} [uo = {}]
|
|
96
110
|
* @returns {Promise<{session_object: {_attributes: {}}, _attributes: {}}|User|*|boolean|{error: string}|User>}
|
|
97
111
|
*/
|
|
98
112
|
static async findOrCreateByAttribute(k, v, uo = {}) {
|
|
@@ -149,7 +163,7 @@ class User {
|
|
|
149
163
|
|
|
150
164
|
/**
|
|
151
165
|
* Create session object for user
|
|
152
|
-
* @
|
|
166
|
+
* @type {{role_id: number, language, id, email, tenant: *}}
|
|
153
167
|
*/
|
|
154
168
|
get session_object() {
|
|
155
169
|
const so = {
|
|
@@ -183,7 +197,7 @@ class User {
|
|
|
183
197
|
* Find users list
|
|
184
198
|
* @param where - where object
|
|
185
199
|
* @param selectopts - select options
|
|
186
|
-
* @returns {Promise
|
|
200
|
+
* @returns {Promise<User[]>}
|
|
187
201
|
*/
|
|
188
202
|
static async find(where, selectopts) {
|
|
189
203
|
const us = await db.select("users", where, selectopts);
|
|
@@ -260,7 +274,7 @@ class User {
|
|
|
260
274
|
|
|
261
275
|
/**
|
|
262
276
|
* Add new API token to user
|
|
263
|
-
* @returns {Promise
|
|
277
|
+
* @returns {Promise<string>}
|
|
264
278
|
*/
|
|
265
279
|
async getNewAPIToken() {
|
|
266
280
|
const api_token = uuidv4();
|
|
@@ -271,7 +285,7 @@ class User {
|
|
|
271
285
|
|
|
272
286
|
/**
|
|
273
287
|
* Remove API token for user
|
|
274
|
-
* @returns {Promise<
|
|
288
|
+
* @returns {Promise<string>}
|
|
275
289
|
*/
|
|
276
290
|
async removeAPIToken() {
|
|
277
291
|
const api_token = null;
|
|
@@ -320,6 +334,9 @@ class User {
|
|
|
320
334
|
return await u.set_to_verified();
|
|
321
335
|
}
|
|
322
336
|
|
|
337
|
+
/**
|
|
338
|
+
* @returns {Promise<boolean>}
|
|
339
|
+
*/
|
|
323
340
|
async set_to_verified() {
|
|
324
341
|
const upd = { verified_on: new Date() };
|
|
325
342
|
const { getState } = require("../db/state");
|
|
@@ -397,7 +414,7 @@ class User {
|
|
|
397
414
|
|
|
398
415
|
/**
|
|
399
416
|
* Generate password
|
|
400
|
-
* @returns {
|
|
417
|
+
* @returns {string}
|
|
401
418
|
*/
|
|
402
419
|
static generate_password() {
|
|
403
420
|
const candidate = is.str.generate().split(" ").join("");
|
|
@@ -405,6 +422,10 @@ class User {
|
|
|
405
422
|
if (candidate.length < 10) return User.generate_password();
|
|
406
423
|
else return candidate;
|
|
407
424
|
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* @returns {Promise<void>}
|
|
428
|
+
*/
|
|
408
429
|
async destroy_sessions() {
|
|
409
430
|
if (!db.isSQLite) {
|
|
410
431
|
const schema = db.getTenantSchema();
|
|
@@ -417,6 +438,10 @@ class User {
|
|
|
417
438
|
);
|
|
418
439
|
}
|
|
419
440
|
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* @param {object} req
|
|
444
|
+
*/
|
|
420
445
|
relogin(req) {
|
|
421
446
|
req.login(this.session_object, function (err) {
|
|
422
447
|
if (err) req.flash("danger", err);
|