@modular-rest/server 1.10.0 → 1.10.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/package.json +1 -1
- package/src/application.js +2 -0
- package/src/class/collection_definition.js +3 -3
- package/src/class/database_trigger.js +4 -3
- package/src/class/trigger_operator.js +4 -7
- package/src/config.js +7 -5
- package/src/events.js +15 -0
- package/src/helper/data_insertion.js +22 -6
- package/src/services/data_provider/service.js +11 -3
- package/src/services/user_manager/db.js +43 -0
- package/src/services/user_manager/service.js +12 -4
package/package.json
CHANGED
package/src/application.js
CHANGED
|
@@ -14,6 +14,7 @@ const defaultServiceRoot = __dirname + "/services";
|
|
|
14
14
|
* @typedef {import('http').Server} server
|
|
15
15
|
* @typedef {import('@koa/cors').Options} Cors
|
|
16
16
|
* @typedef {import('./class/security').PermissionGroup} PermissionGroup
|
|
17
|
+
* @typedef {import('./class/database_trigger.js')} DatabaseTrigger
|
|
17
18
|
*/
|
|
18
19
|
|
|
19
20
|
const { config, setConfig } = require("./config");
|
|
@@ -55,6 +56,7 @@ const { config, setConfig } = require("./config");
|
|
|
55
56
|
* verificationCodeGeneratorMethod: () => string; // A method to return a verification code when registering a new user.
|
|
56
57
|
* collectionDefinitions?: CollectionDefinition[]; // An array of additional collection definitions.
|
|
57
58
|
* permissionGroups?: PermissionGroup[]; // An array of additional permission groups.
|
|
59
|
+
* authTriggers?: DatabaseTrigger[]; // An array of additional database triggers for the auth collection.
|
|
58
60
|
* }} options
|
|
59
61
|
* @returns {Promise<{app: Koa, server: Server}>}
|
|
60
62
|
*/
|
|
@@ -14,9 +14,9 @@ class CollectionDefinition {
|
|
|
14
14
|
* @param {string} option.collection - Collection name
|
|
15
15
|
* @param {Object} option.schema - Mongoose schema
|
|
16
16
|
* @param {Array<Permission>} option.permissions - A list of permissions for this collection
|
|
17
|
-
* @param {Array<DatabaseTrigger>=} option.
|
|
17
|
+
* @param {Array<DatabaseTrigger>=} option.triggers - A database trigger
|
|
18
18
|
*/
|
|
19
|
-
constructor({ db, collection, schema, permissions,
|
|
19
|
+
constructor({ db, collection, schema, permissions, triggers }) {
|
|
20
20
|
// string
|
|
21
21
|
this.database = db;
|
|
22
22
|
// string
|
|
@@ -26,7 +26,7 @@ class CollectionDefinition {
|
|
|
26
26
|
// a list of Permission for this collection
|
|
27
27
|
this.permissions = permissions;
|
|
28
28
|
|
|
29
|
-
this.
|
|
29
|
+
this.triggers = triggers;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -7,10 +7,11 @@ class DatabaseTrigger {
|
|
|
7
7
|
/**
|
|
8
8
|
* Creates a new instance of `DatabaseTrigger`.
|
|
9
9
|
*
|
|
10
|
-
* @param {'find' | 'find-one' | 'count' | 'update-one' | 'insert-one' | 'remove-one' | 'aggregate'} operation - The operation to be triggered. Supported operations are:
|
|
11
|
-
* @param {function(query, queryResult)} callback - The callback to be called when the operation is executed.
|
|
10
|
+
* @param {'find' | 'find-one' | 'count' | 'update-one' | 'insert-one' | 'remove-one' | 'aggregate'} operation - The operation to be triggered. Supported operations are: 'find', 'find-one', 'count', 'update-one', 'insert-one', 'remove-one', 'aggregate'.
|
|
11
|
+
* @param {function({query: any, queryResult: any}): void} [callback=(context) => {}] - The callback to be called when the operation is executed. The callback function takes an object as parameter with two properties: 'query' and 'queryResult'.
|
|
12
|
+
* @constructor
|
|
12
13
|
*/
|
|
13
|
-
constructor(operation, callback = (
|
|
14
|
+
constructor(operation, callback = (context) => {}) {
|
|
14
15
|
this.operation = operation;
|
|
15
16
|
this.callback = callback;
|
|
16
17
|
}
|
|
@@ -13,24 +13,21 @@ class TriggerOperator {
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Call a trigger
|
|
16
|
-
* @param {
|
|
16
|
+
* @param {'find' | 'find-one' | 'count' | 'update-one' | 'insert-one' | 'remove-one' | 'aggregate'} operation operation name
|
|
17
17
|
* @param {string} database database name
|
|
18
18
|
* @param {string} collection collection name
|
|
19
19
|
* @param {string} data
|
|
20
20
|
*/
|
|
21
21
|
call(operation, database, collection, data) {
|
|
22
|
-
let result;
|
|
23
|
-
|
|
24
22
|
this.triggers.forEach((trigger) => {
|
|
25
23
|
if (
|
|
26
24
|
operation == trigger.operation &&
|
|
27
25
|
database == trigger.database &&
|
|
28
|
-
collection == trigger.collection
|
|
26
|
+
collection == trigger.collection &&
|
|
27
|
+
trigger.callback
|
|
29
28
|
)
|
|
30
|
-
|
|
29
|
+
trigger.callback(data);
|
|
31
30
|
});
|
|
32
|
-
|
|
33
|
-
return result;
|
|
34
31
|
}
|
|
35
32
|
|
|
36
33
|
static get instance() {
|
package/src/config.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* @typedef {import('@koa/cors').Options} Cors
|
|
4
4
|
* @typedef {import('./class/collection_definition')} CollectionDefinition
|
|
5
5
|
* @typedef {import('./class/security').PermissionGroup} PermissionGroup
|
|
6
|
+
* @typedef {import('./class/database_trigger.js')} DatabaseTrigger
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -41,10 +42,16 @@
|
|
|
41
42
|
* verificationCodeGeneratorMethod: () => string; // A method to return a verification code when registering a new user.
|
|
42
43
|
* collectionDefinitions?: CollectionDefinition[]; // An array of additional collection definitions.
|
|
43
44
|
* permissionGroups?: PermissionGroup[]; // An array of additional permission groups.
|
|
45
|
+
* authTriggers?: DatabaseTrigger[]; // An array of additional database triggers for the auth collection.
|
|
44
46
|
* }} Config
|
|
45
47
|
* @exports Config
|
|
46
48
|
*/
|
|
47
49
|
|
|
50
|
+
/**
|
|
51
|
+
* @type {Config}
|
|
52
|
+
*/
|
|
53
|
+
const config = {};
|
|
54
|
+
|
|
48
55
|
/**
|
|
49
56
|
* @param {Config} options
|
|
50
57
|
*/
|
|
@@ -52,11 +59,6 @@ function setConfig(options) {
|
|
|
52
59
|
Object.assign(config, options);
|
|
53
60
|
}
|
|
54
61
|
|
|
55
|
-
/**
|
|
56
|
-
* @type {Config}
|
|
57
|
-
*/
|
|
58
|
-
const config = {};
|
|
59
|
-
|
|
60
62
|
module.exports = {
|
|
61
63
|
setConfig,
|
|
62
64
|
config,
|
package/src/events.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const eventCallbacks = [];
|
|
2
|
+
/**
|
|
3
|
+
* onBeforeInit: (koaApp:Koa) => void; // A callback called before initializing the Koa server.
|
|
4
|
+
* onAfterInit: (koaApp:Koa) => void; // A callback called after server initialization.
|
|
5
|
+
* onNewUser:
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
function registerEventCallback(event, callback) {
|
|
9
|
+
if (typeof event !== "string") throw new Error("Event must be a string");
|
|
10
|
+
|
|
11
|
+
if (typeof callback !== "function")
|
|
12
|
+
throw new Error("Callback must be a function");
|
|
13
|
+
|
|
14
|
+
eventCallbacks.push({ event, callback });
|
|
15
|
+
}
|
|
@@ -4,6 +4,8 @@ const {
|
|
|
4
4
|
getDefaultAdministratorPermissionGroup,
|
|
5
5
|
} = require("../services/user_manager/permissionManager");
|
|
6
6
|
|
|
7
|
+
const userManager = require("../services/user_manager/service");
|
|
8
|
+
|
|
7
9
|
async function createAdminUser({ email, password }) {
|
|
8
10
|
let authModel = DataProvider.getCollection("cms", "auth");
|
|
9
11
|
|
|
@@ -17,13 +19,20 @@ async function createAdminUser({ email, password }) {
|
|
|
17
19
|
.exec();
|
|
18
20
|
|
|
19
21
|
if (isAnonymousExisted == 0) {
|
|
20
|
-
await
|
|
21
|
-
|
|
22
|
+
await userManager.main.registerUser({
|
|
23
|
+
permissionGroup: getDefaultAnonymousPermissionGroup().title,
|
|
22
24
|
email: "",
|
|
23
25
|
phone: "",
|
|
24
26
|
password: "",
|
|
25
27
|
type: "anonymous",
|
|
26
|
-
})
|
|
28
|
+
});
|
|
29
|
+
// await new authModel({
|
|
30
|
+
// permission: getDefaultAnonymousPermissionGroup().title,
|
|
31
|
+
// email: "",
|
|
32
|
+
// phone: "",
|
|
33
|
+
// password: "",
|
|
34
|
+
// type: "anonymous",
|
|
35
|
+
// }).save();
|
|
27
36
|
}
|
|
28
37
|
|
|
29
38
|
if (isAdministratorExisted == 0) {
|
|
@@ -31,12 +40,19 @@ async function createAdminUser({ email, password }) {
|
|
|
31
40
|
return Promise.reject("Invalid email or password for admin user.");
|
|
32
41
|
}
|
|
33
42
|
|
|
34
|
-
await
|
|
35
|
-
|
|
43
|
+
await userManager.main.registerUser({
|
|
44
|
+
permissionGroup: getDefaultAdministratorPermissionGroup().title,
|
|
36
45
|
email: email,
|
|
37
46
|
password: password,
|
|
38
47
|
type: "user",
|
|
39
|
-
})
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// await new authModel({
|
|
51
|
+
// permission: getDefaultAdministratorPermissionGroup().title,
|
|
52
|
+
// email: email,
|
|
53
|
+
// password: password,
|
|
54
|
+
// type: "user",
|
|
55
|
+
// }).save();
|
|
40
56
|
}
|
|
41
57
|
} catch (e) {
|
|
42
58
|
return Promise.reject(e);
|
|
@@ -67,8 +67,16 @@ function connectToDatabaseByCollectionDefinitionList(
|
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
// add trigger
|
|
70
|
-
if (collectionDefinition.
|
|
71
|
-
|
|
70
|
+
if (collectionDefinition.triggers != undefined) {
|
|
71
|
+
if (!Array.isArray(collectionDefinition.triggers)) {
|
|
72
|
+
throw "Triggers must be an array";
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
collectionDefinition.triggers.forEach((trigger) => {
|
|
76
|
+
trigger.database = collectionDefinition.database;
|
|
77
|
+
trigger.collection = collectionDefinition.collection;
|
|
78
|
+
triggers.addTrigger(trigger);
|
|
79
|
+
});
|
|
72
80
|
}
|
|
73
81
|
});
|
|
74
82
|
|
|
@@ -185,7 +193,7 @@ function checkAccess(db, collection, operationType, queryOrDoc, user) {
|
|
|
185
193
|
} else if (operationType == AccessTypes.read && permission.read) {
|
|
186
194
|
key = user.hasPermission(collectionPermissionType);
|
|
187
195
|
} else if (operationType == AccessTypes.write && permission.write) {
|
|
188
|
-
key = user.
|
|
196
|
+
key = user.hasPermission(collectionPermissionType);
|
|
189
197
|
}
|
|
190
198
|
});
|
|
191
199
|
|
|
@@ -3,6 +3,8 @@ var Schema = mongoose.Schema;
|
|
|
3
3
|
|
|
4
4
|
let CollectionDefinition = require("../../class/collection_definition");
|
|
5
5
|
let { Permission, PermissionTypes } = require("../../class/security");
|
|
6
|
+
const { config } = require("../../config");
|
|
7
|
+
const triggerOperator = require("./../../class/trigger_operator");
|
|
6
8
|
|
|
7
9
|
let authSchema = new Schema({
|
|
8
10
|
permissionGroup: String,
|
|
@@ -21,6 +23,46 @@ authSchema.pre(["save", "updateOne"], function (next) {
|
|
|
21
23
|
next();
|
|
22
24
|
});
|
|
23
25
|
|
|
26
|
+
authSchema.post("save", function (doc, next) {
|
|
27
|
+
triggerOperator.call("insert-one", "cms", "auth", {
|
|
28
|
+
query: null,
|
|
29
|
+
queryResult: doc._doc,
|
|
30
|
+
});
|
|
31
|
+
next();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
authSchema.post("findOneAndUpdate", function (doc, next) {
|
|
35
|
+
triggerOperator.call("update-one", "cms", "auth", {
|
|
36
|
+
query: null,
|
|
37
|
+
queryResult: doc._doc,
|
|
38
|
+
});
|
|
39
|
+
next();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
authSchema.post("updateOne", function (result, next) {
|
|
43
|
+
triggerOperator.call("update-one", "cms", "auth", {
|
|
44
|
+
query: null,
|
|
45
|
+
queryResult: doc._doc,
|
|
46
|
+
});
|
|
47
|
+
next();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
authSchema.post("findOneAndDelete", function (doc, next) {
|
|
51
|
+
triggerOperator.call("remove-one", "cms", "auth", {
|
|
52
|
+
query: null,
|
|
53
|
+
queryResult: doc._doc,
|
|
54
|
+
});
|
|
55
|
+
next();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
authSchema.post("deleteOne", function (result, next) {
|
|
59
|
+
triggerOperator.call("remove-one", "cms", "auth", {
|
|
60
|
+
query: null,
|
|
61
|
+
queryResult: doc._doc,
|
|
62
|
+
});
|
|
63
|
+
next();
|
|
64
|
+
});
|
|
65
|
+
|
|
24
66
|
module.exports = [
|
|
25
67
|
new CollectionDefinition({
|
|
26
68
|
db: "cms",
|
|
@@ -33,5 +75,6 @@ module.exports = [
|
|
|
33
75
|
write: true,
|
|
34
76
|
}),
|
|
35
77
|
],
|
|
78
|
+
triggers: config.authTriggers || [],
|
|
36
79
|
}),
|
|
37
80
|
];
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
const User = require("../../class/user");
|
|
2
2
|
const DataProvider = require("../data_provider/service");
|
|
3
3
|
const JWT = require("../jwt/service");
|
|
4
4
|
const { getDefaultPermissionGroups } = require("./permissionManager");
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* import user type
|
|
8
|
+
* @typedef {import('../../class/user')} User
|
|
9
|
+
*/
|
|
10
|
+
|
|
6
11
|
class UserManager {
|
|
7
12
|
constructor() {
|
|
8
13
|
this.tempIds = {};
|
|
@@ -93,8 +98,9 @@ class UserManager {
|
|
|
93
98
|
* @param {string} token - The token of the user.
|
|
94
99
|
* @returns {Promise<User>} A promise that resolves to the user.
|
|
95
100
|
*/
|
|
96
|
-
getUserByToken(token) {
|
|
97
|
-
|
|
101
|
+
async getUserByToken(token) {
|
|
102
|
+
const { id } = await JWT.main.verify(token);
|
|
103
|
+
return this.getUserById(id);
|
|
98
104
|
}
|
|
99
105
|
|
|
100
106
|
/**
|
|
@@ -311,7 +317,9 @@ class UserManager {
|
|
|
311
317
|
registerUser(detail) {
|
|
312
318
|
return new Promise(async (done, reject) => {
|
|
313
319
|
// get default permission
|
|
314
|
-
detail.permissionGroup
|
|
320
|
+
if (!detail.permissionGroup) {
|
|
321
|
+
detail.permissionGroup = getDefaultPermissionGroups().title;
|
|
322
|
+
}
|
|
315
323
|
|
|
316
324
|
if (!detail.permissionGroup) {
|
|
317
325
|
reject("default permission group not found");
|