@modular-rest/server 1.10.0 → 1.10.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modular-rest/server",
3
- "version": "1.10.0",
3
+ "version": "1.10.2",
4
4
  "description": "a nodejs module based on KOAJS for developing Rest-APIs in a modular solution.",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -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.trigger - A database trigger
17
+ * @param {Array<DatabaseTrigger>=} option.triggers - A database trigger
18
18
  */
19
- constructor({ db, collection, schema, permissions, trigger }) {
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.trigger = trigger;
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 = (query, queryResult) => {}) {
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 {string} operation operation name
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
- result = trigger.callback(data.input, data.output);
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 new authModel({
21
- permission: getDefaultAnonymousPermissionGroup().title,
22
+ await userManager.main.registerUser({
23
+ permissionGroup: getDefaultAnonymousPermissionGroup().title,
22
24
  email: "",
23
25
  phone: "",
24
26
  password: "",
25
27
  type: "anonymous",
26
- }).save();
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 new authModel({
35
- permission: getDefaultAdministratorPermissionGroup().title,
43
+ await userManager.main.registerUser({
44
+ permissionGroup: getDefaultAdministratorPermissionGroup().title,
36
45
  email: email,
37
46
  password: password,
38
47
  type: "user",
39
- }).save();
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);
@@ -35,7 +35,6 @@ function connectToDatabaseByCollectionDefinitionList(
35
35
  colog.info(`- Connecting to database ${connectionString}`);
36
36
 
37
37
  let connection = Mongoose.createConnection(connectionString, {
38
- ...mongoOption,
39
38
  useUnifiedTopology: true,
40
39
  useNewUrlParser: true,
41
40
  });
@@ -67,8 +66,16 @@ function connectToDatabaseByCollectionDefinitionList(
67
66
  });
68
67
 
69
68
  // add trigger
70
- if (collectionDefinition.trigger != undefined) {
71
- triggers.addTrigger(collectionDefinition.trigger);
69
+ if (collectionDefinition.triggers != undefined) {
70
+ if (!Array.isArray(collectionDefinition.triggers)) {
71
+ throw "Triggers must be an array";
72
+ }
73
+
74
+ collectionDefinition.triggers.forEach((trigger) => {
75
+ trigger.database = collectionDefinition.database;
76
+ trigger.collection = collectionDefinition.collection;
77
+ triggers.addTrigger(trigger);
78
+ });
72
79
  }
73
80
  });
74
81
 
@@ -185,7 +192,7 @@ function checkAccess(db, collection, operationType, queryOrDoc, user) {
185
192
  } else if (operationType == AccessTypes.read && permission.read) {
186
193
  key = user.hasPermission(collectionPermissionType);
187
194
  } else if (operationType == AccessTypes.write && permission.write) {
188
- key = user.permission[collectionPermissionType];
195
+ key = user.hasPermission(collectionPermissionType);
189
196
  }
190
197
  });
191
198
 
@@ -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
- let User = require("../../class/user");
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
- return JWT.main.verify(token);
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 = getDefaultPermissionGroups().title;
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");