@modular-rest/server 1.8.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-lock.json +1373 -0
- package/package.json +4 -2
- package/src/application.js +60 -40
- package/src/class/collection_definition.js +3 -3
- package/src/class/database_trigger.js +4 -3
- package/src/class/directory.js +50 -51
- package/src/class/security.js +32 -17
- package/src/class/trigger_operator.js +4 -7
- package/src/class/user.js +98 -83
- package/src/config.js +65 -0
- package/src/events.js +15 -0
- package/src/helper/data_insertion.js +31 -75
- package/src/helper/presetup_services.js +2 -14
- package/src/services/data_provider/router.js +490 -402
- package/src/services/data_provider/service.js +39 -16
- package/src/services/user_manager/db.js +45 -37
- package/src/services/user_manager/permissionManager.js +43 -0
- package/src/services/user_manager/service.js +19 -41
|
@@ -11,6 +11,7 @@ let permissionDefinitions = {};
|
|
|
11
11
|
|
|
12
12
|
let triggers = require("../../class/trigger_operator");
|
|
13
13
|
let TypeCasters = require("./typeCasters");
|
|
14
|
+
const { config } = require("../../config");
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
*
|
|
@@ -66,8 +67,16 @@ function connectToDatabaseByCollectionDefinitionList(
|
|
|
66
67
|
});
|
|
67
68
|
|
|
68
69
|
// add trigger
|
|
69
|
-
if (collectionDefinition.
|
|
70
|
-
|
|
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
|
+
});
|
|
71
80
|
}
|
|
72
81
|
});
|
|
73
82
|
|
|
@@ -132,7 +141,11 @@ function _getPermissionList(db, collection, operationType) {
|
|
|
132
141
|
|
|
133
142
|
if (!permissionDefinitions.hasOwnProperty(db)) return permissionList;
|
|
134
143
|
|
|
135
|
-
|
|
144
|
+
try {
|
|
145
|
+
permissionDefinition = permissionDefinitions[db][collection];
|
|
146
|
+
} catch (error) {
|
|
147
|
+
return permissionList;
|
|
148
|
+
}
|
|
136
149
|
|
|
137
150
|
permissionDefinition.permissionList.forEach((permission) => {
|
|
138
151
|
if (permission.onlyOwnData == true) {
|
|
@@ -147,30 +160,40 @@ function _getPermissionList(db, collection, operationType) {
|
|
|
147
160
|
return permissionList;
|
|
148
161
|
}
|
|
149
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Check access to a collection.
|
|
165
|
+
* @param {string} db - The database name.
|
|
166
|
+
* @param {string} collection - The collection name.
|
|
167
|
+
* @param {string} operationType - The operation type.
|
|
168
|
+
* @param {object} queryOrDoc - The query or document.
|
|
169
|
+
* @param {import('../../class/user')} user - The user.
|
|
170
|
+
* @returns {boolean} The access result.
|
|
171
|
+
*/
|
|
150
172
|
function checkAccess(db, collection, operationType, queryOrDoc, user) {
|
|
151
173
|
let key = false;
|
|
152
|
-
const permissionList = _getPermissionList(db, collection, operationType);
|
|
153
174
|
|
|
154
|
-
|
|
155
|
-
|
|
175
|
+
const collectionPermissionList = _getPermissionList(
|
|
176
|
+
db,
|
|
177
|
+
collection,
|
|
178
|
+
operationType
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
collectionPermissionList.forEach((permission) => {
|
|
182
|
+
const collectionPermissionType = permission.type;
|
|
156
183
|
|
|
157
184
|
if (permission.onlyOwnData == true) {
|
|
158
185
|
const userId = user.id;
|
|
159
186
|
|
|
160
187
|
try {
|
|
161
|
-
|
|
162
|
-
queryOrDoc[permission.ownerIdField].toString() === userId.toString()
|
|
163
|
-
)
|
|
164
|
-
key = true;
|
|
188
|
+
key =
|
|
189
|
+
queryOrDoc[permission.ownerIdField].toString() === userId.toString();
|
|
165
190
|
} catch (error) {
|
|
166
191
|
key = false;
|
|
167
192
|
}
|
|
168
|
-
} else if (operationType == AccessTypes.read) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (permission.write && user.permission[permissionType] == true)
|
|
173
|
-
key = true;
|
|
193
|
+
} else if (operationType == AccessTypes.read && permission.read) {
|
|
194
|
+
key = user.hasPermission(collectionPermissionType);
|
|
195
|
+
} else if (operationType == AccessTypes.write && permission.write) {
|
|
196
|
+
key = user.hasPermission(collectionPermissionType);
|
|
174
197
|
}
|
|
175
198
|
});
|
|
176
199
|
|
|
@@ -3,37 +3,17 @@ var Schema = mongoose.Schema;
|
|
|
3
3
|
|
|
4
4
|
let CollectionDefinition = require("../../class/collection_definition");
|
|
5
5
|
let { Permission, PermissionTypes } = require("../../class/security");
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* Permission schema
|
|
9
|
-
*
|
|
10
|
-
* This schema is generated dynamically
|
|
11
|
-
* by combining default & custom permissions.
|
|
12
|
-
*/
|
|
13
|
-
let permissionSchemaConstructorOption = {
|
|
14
|
-
title: String,
|
|
15
|
-
isAnonymous: { type: Boolean, default: false },
|
|
16
|
-
isDefault: { type: Boolean, default: false },
|
|
17
|
-
};
|
|
18
|
-
Object.keys(new PermissionTypes()).forEach((key) => {
|
|
19
|
-
let fieldOption = { type: Boolean, default: false };
|
|
20
|
-
permissionSchemaConstructorOption[key] = fieldOption;
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
let permissionSchema = new Schema(permissionSchemaConstructorOption);
|
|
24
|
-
permissionSchema.index({ title: 1 }, { unique: true });
|
|
6
|
+
const { config } = require("../../config");
|
|
7
|
+
const triggerOperator = require("./../../class/trigger_operator");
|
|
25
8
|
|
|
26
9
|
let authSchema = new Schema({
|
|
27
|
-
|
|
28
|
-
type: Schema.Types.ObjectId,
|
|
29
|
-
ref: "permission",
|
|
30
|
-
required: false,
|
|
31
|
-
},
|
|
10
|
+
permissionGroup: String,
|
|
32
11
|
email: String,
|
|
33
12
|
phone: String,
|
|
34
13
|
password: String,
|
|
35
14
|
type: { type: String, default: "user", enum: ["user", "anonymous"] },
|
|
36
15
|
});
|
|
16
|
+
|
|
37
17
|
authSchema.index({ email: 1 }, { unique: true });
|
|
38
18
|
authSchema.pre(["save", "updateOne"], function (next) {
|
|
39
19
|
// Encode the password before saving
|
|
@@ -43,6 +23,46 @@ authSchema.pre(["save", "updateOne"], function (next) {
|
|
|
43
23
|
next();
|
|
44
24
|
});
|
|
45
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
|
+
|
|
46
66
|
module.exports = [
|
|
47
67
|
new CollectionDefinition({
|
|
48
68
|
db: "cms",
|
|
@@ -55,18 +75,6 @@ module.exports = [
|
|
|
55
75
|
write: true,
|
|
56
76
|
}),
|
|
57
77
|
],
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
new CollectionDefinition({
|
|
61
|
-
db: "cms",
|
|
62
|
-
collection: "permission",
|
|
63
|
-
schema: permissionSchema,
|
|
64
|
-
permissions: [
|
|
65
|
-
new Permission({
|
|
66
|
-
type: PermissionTypes.advanced_settings,
|
|
67
|
-
read: true,
|
|
68
|
-
write: true,
|
|
69
|
-
}),
|
|
70
|
-
],
|
|
78
|
+
triggers: config.authTriggers || [],
|
|
71
79
|
}),
|
|
72
80
|
];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const { config } = require("../../config");
|
|
2
|
+
|
|
3
|
+
function getDefaultPermissionGroups() {
|
|
4
|
+
const defaultPermissionGroups = config.permissionGroups.find(
|
|
5
|
+
(group) => group.isDefault
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
if (defaultPermissionGroups == null) {
|
|
9
|
+
throw new Error("Default permission group not found");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return defaultPermissionGroups;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function getDefaultAnonymousPermissionGroup() {
|
|
16
|
+
const anonymousPermission = config.permissionGroups.find(
|
|
17
|
+
(group) => group.isAnonymous
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
if (anonymousPermission == null) {
|
|
21
|
+
throw new Error("Anonymous permission group not found");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return anonymousPermission;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getDefaultAdministratorPermissionGroup() {
|
|
28
|
+
const administratorPermission = config.permissionGroups.find(
|
|
29
|
+
(group) => group.title.toString() == "administrator"
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
if (administratorPermission == null) {
|
|
33
|
+
throw new Error("Administrator permission group not found");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return administratorPermission;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = {
|
|
40
|
+
getDefaultPermissionGroups,
|
|
41
|
+
getDefaultAnonymousPermissionGroup,
|
|
42
|
+
getDefaultAdministratorPermissionGroup,
|
|
43
|
+
};
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
const User = require("../../class/user");
|
|
2
2
|
const DataProvider = require("../data_provider/service");
|
|
3
3
|
const JWT = require("../jwt/service");
|
|
4
|
+
const { getDefaultPermissionGroups } = require("./permissionManager");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* import user type
|
|
8
|
+
* @typedef {import('../../class/user')} User
|
|
9
|
+
*/
|
|
4
10
|
|
|
5
11
|
class UserManager {
|
|
6
12
|
constructor() {
|
|
@@ -42,7 +48,6 @@ class UserManager {
|
|
|
42
48
|
let userDoc = await userModel
|
|
43
49
|
.findOne({ _id: id })
|
|
44
50
|
.select({ password: 0 })
|
|
45
|
-
.populate("permission")
|
|
46
51
|
.exec()
|
|
47
52
|
.catch(reject);
|
|
48
53
|
|
|
@@ -75,7 +80,6 @@ class UserManager {
|
|
|
75
80
|
let userDoc = await userModel
|
|
76
81
|
.findOne(query)
|
|
77
82
|
.select({ password: 0 })
|
|
78
|
-
.populate("permission")
|
|
79
83
|
.exec()
|
|
80
84
|
.catch(reject);
|
|
81
85
|
|
|
@@ -93,21 +97,10 @@ class UserManager {
|
|
|
93
97
|
* Get a user by their token.
|
|
94
98
|
* @param {string} token - The token of the user.
|
|
95
99
|
* @returns {Promise<User>} A promise that resolves to the user.
|
|
96
|
-
* @throws {string} If the user has a wrong permission.
|
|
97
100
|
*/
|
|
98
|
-
getUserByToken(token) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
let permission = await DataProvider.getCollection("cms", "permission")
|
|
102
|
-
.findOne({ _id: user.permission })
|
|
103
|
-
.exec()
|
|
104
|
-
.then();
|
|
105
|
-
|
|
106
|
-
if (!permission) throw "user has a wrong permission";
|
|
107
|
-
|
|
108
|
-
user.permission = permission;
|
|
109
|
-
return user;
|
|
110
|
-
});
|
|
101
|
+
async getUserByToken(token) {
|
|
102
|
+
const { id } = await JWT.main.verify(token);
|
|
103
|
+
return this.getUserById(id);
|
|
111
104
|
}
|
|
112
105
|
|
|
113
106
|
/**
|
|
@@ -155,11 +148,7 @@ class UserManager {
|
|
|
155
148
|
else if (idType == "email") query["email"] = id;
|
|
156
149
|
|
|
157
150
|
// Get from database
|
|
158
|
-
const gottenFromDB = await userModel
|
|
159
|
-
.findOne(query)
|
|
160
|
-
.populate("permission")
|
|
161
|
-
.exec()
|
|
162
|
-
.catch(reject);
|
|
151
|
+
const gottenFromDB = await userModel.findOne(query).exec().catch(reject);
|
|
163
152
|
|
|
164
153
|
if (!gottenFromDB) reject("user not found");
|
|
165
154
|
// Token
|
|
@@ -193,11 +182,7 @@ class UserManager {
|
|
|
193
182
|
const query = { email: email };
|
|
194
183
|
|
|
195
184
|
// Get from database
|
|
196
|
-
const gottenFromDB = await userModel
|
|
197
|
-
.findOne(query)
|
|
198
|
-
.populate("permission")
|
|
199
|
-
.exec()
|
|
200
|
-
.catch(reject);
|
|
185
|
+
const gottenFromDB = await userModel.findOne(query).exec().catch(reject);
|
|
201
186
|
|
|
202
187
|
if (!gottenFromDB) reject("user not found");
|
|
203
188
|
|
|
@@ -230,7 +215,6 @@ class UserManager {
|
|
|
230
215
|
// Get from database
|
|
231
216
|
let gottenFromDB = await userModel
|
|
232
217
|
.findOne(query)
|
|
233
|
-
.populate("permission")
|
|
234
218
|
.exec()
|
|
235
219
|
.then()
|
|
236
220
|
.catch(reject);
|
|
@@ -333,20 +317,14 @@ class UserManager {
|
|
|
333
317
|
registerUser(detail) {
|
|
334
318
|
return new Promise(async (done, reject) => {
|
|
335
319
|
// get default permission
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
let pQuery = { isDefault: true };
|
|
340
|
-
|
|
341
|
-
if (detail.type == "anonymous") pQuery = { isAnonymous: true };
|
|
342
|
-
|
|
343
|
-
await perM
|
|
344
|
-
.findOne(pQuery, "_id")
|
|
345
|
-
.exec()
|
|
346
|
-
.then((doc) => (permissionId = doc._id))
|
|
347
|
-
.catch(reject);
|
|
320
|
+
if (!detail.permissionGroup) {
|
|
321
|
+
detail.permissionGroup = getDefaultPermissionGroups().title;
|
|
322
|
+
}
|
|
348
323
|
|
|
349
|
-
detail.
|
|
324
|
+
if (!detail.permissionGroup) {
|
|
325
|
+
reject("default permission group not found");
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
350
328
|
|
|
351
329
|
let authM = DataProvider.getCollection("cms", "auth");
|
|
352
330
|
return User.createFromModel(authM, detail)
|