@modular-rest/server 1.11.12 → 1.11.14
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/.nvmrc +1 -0
- package/.prettierrc.json +9 -0
- package/.releaserc.json +24 -0
- package/README.md +79 -94
- package/dist/index.js +79 -0
- package/docs/.keep +0 -0
- package/docs/system-access-type.md +26 -0
- package/package.json +58 -45
- package/src/application.ts +206 -0
- package/src/class/cms_trigger.ts +68 -0
- package/src/class/collection_definition.ts +134 -0
- package/src/class/combinator.ts +176 -0
- package/src/class/database_trigger.ts +99 -0
- package/src/class/db_schemas.ts +44 -0
- package/src/class/{directory.js → directory.ts} +40 -18
- package/src/class/paginator.ts +51 -0
- package/src/class/reply.ts +59 -0
- package/src/class/security.ts +250 -0
- package/src/class/trigger_operator.ts +142 -0
- package/src/class/user.ts +199 -0
- package/src/class/validator.ts +123 -0
- package/src/config.ts +122 -0
- package/src/defult-permissions.ts +31 -0
- package/src/events.ts +59 -0
- package/src/helper/data_insertion.ts +94 -0
- package/src/helper/presetup_services.ts +96 -0
- package/src/index.ts +146 -0
- package/src/middlewares.ts +75 -0
- package/src/play-test.ts +8 -0
- package/src/services/data_provider/router.ts +191 -0
- package/src/services/data_provider/service.ts +305 -0
- package/src/services/data_provider/typeCasters.ts +15 -0
- package/src/services/file/db.ts +29 -0
- package/src/services/file/router.ts +88 -0
- package/src/services/file/service.ts +387 -0
- package/src/services/functions/router.ts +34 -0
- package/src/services/functions/service.ts +203 -0
- package/src/services/jwt/router.ts +73 -0
- package/src/services/jwt/service.ts +139 -0
- package/src/services/user_manager/db.ts +87 -0
- package/src/services/user_manager/permissionManager.ts +49 -0
- package/src/services/user_manager/router.ts +193 -0
- package/src/services/user_manager/service.ts +698 -0
- package/tsconfig.json +16 -9
- package/typedoc.mjs +41 -0
- package/LICENSE +0 -21
- package/package-lock.json +0 -1373
- package/src/application.js +0 -239
- package/src/class/cms_trigger.js +0 -20
- package/src/class/collection_definition.js +0 -33
- package/src/class/combinator.js +0 -133
- package/src/class/database_trigger.js +0 -20
- package/src/class/db_schemas.js +0 -18
- package/src/class/paginator.js +0 -31
- package/src/class/reply.js +0 -37
- package/src/class/security.js +0 -141
- package/src/class/trigger_operator.js +0 -39
- package/src/class/user.js +0 -112
- package/src/class/validator.js +0 -91
- package/src/config.js +0 -67
- package/src/events.js +0 -15
- package/src/helper/data_insertion.js +0 -64
- package/src/helper/presetup_services.js +0 -31
- package/src/index.js +0 -66
- package/src/middlewares.js +0 -44
- package/src/services/data_provider/router.js +0 -552
- package/src/services/data_provider/service.js +0 -262
- package/src/services/data_provider/typeCasters.js +0 -10
- package/src/services/file/db.js +0 -29
- package/src/services/file/router.js +0 -92
- package/src/services/file/service.js +0 -231
- package/src/services/functions/router.js +0 -37
- package/src/services/functions/service.js +0 -74
- package/src/services/jwt/router.js +0 -70
- package/src/services/jwt/service.js +0 -37
- package/src/services/user_manager/db.js +0 -83
- package/src/services/user_manager/permissionManager.js +0 -43
- package/src/services/user_manager/router.js +0 -176
- package/src/services/user_manager/service.js +0 -377
- package/types/application.d.ts +0 -97
- package/types/class/cms_trigger.d.ts +0 -24
- package/types/class/collection_definition.d.ts +0 -36
- package/types/class/combinator.d.ts +0 -30
- package/types/class/database_trigger.d.ts +0 -28
- package/types/class/db_schemas.d.ts +0 -2
- package/types/class/directory.d.ts +0 -2
- package/types/class/paginator.d.ts +0 -8
- package/types/class/reply.d.ts +0 -8
- package/types/class/security.d.ts +0 -109
- package/types/class/trigger_operator.d.ts +0 -19
- package/types/class/user.d.ts +0 -24
- package/types/class/validator.d.ts +0 -9
- package/types/config.d.ts +0 -101
- package/types/events.d.ts +0 -7
- package/types/helper/data_insertion.d.ts +0 -4
- package/types/helper/presetup_services.d.ts +0 -5
- package/types/index.d.ts +0 -72
- package/types/middlewares.d.ts +0 -9
- package/types/services/data_provider/router.d.ts +0 -3
- package/types/services/data_provider/service.d.ts +0 -40
- package/types/services/data_provider/typeCasters.d.ts +0 -3
- package/types/services/file/db.d.ts +0 -3
- package/types/services/file/router.d.ts +0 -3
- package/types/services/file/service.d.ts +0 -81
- package/types/services/functions/router.d.ts +0 -3
- package/types/services/functions/service.d.ts +0 -23
- package/types/services/jwt/router.d.ts +0 -3
- package/types/services/jwt/service.d.ts +0 -10
- package/types/services/user_manager/db.d.ts +0 -3
- package/types/services/user_manager/permissionManager.d.ts +0 -3
- package/types/services/user_manager/router.d.ts +0 -3
- package/types/services/user_manager/service.d.ts +0 -131
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response status type
|
|
3
|
+
*/
|
|
4
|
+
export type ResponseStatus = 's' | 'f' | 'e';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Response object interface
|
|
8
|
+
*/
|
|
9
|
+
export interface ResponseObject {
|
|
10
|
+
status: 'success' | 'fail' | 'error';
|
|
11
|
+
[key: string]: any;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates a response object with the given status and detail.
|
|
16
|
+
*
|
|
17
|
+
* @param status - The status of the response. Can be "s" for success, "f" for fail, or "e" for error.
|
|
18
|
+
* @param detail - The detail of the response. Can contain any additional information about the response.
|
|
19
|
+
* @returns The response object with the given status and detail.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* import { reply } from '@modular-rest/server';
|
|
24
|
+
*
|
|
25
|
+
* // inside the router
|
|
26
|
+
* const response = reply.create("s", { message: "Hello, world!" });
|
|
27
|
+
* ctx.body = response;
|
|
28
|
+
* ctx.status = 200;
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function create(status: ResponseStatus, detail: Record<string, any> = {}): ResponseObject {
|
|
32
|
+
// Initialize with a default status that will be overwritten
|
|
33
|
+
const result: ResponseObject = {
|
|
34
|
+
status: 'success',
|
|
35
|
+
...detail,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// define status
|
|
39
|
+
switch (status) {
|
|
40
|
+
case 's':
|
|
41
|
+
result.status = 'success';
|
|
42
|
+
break;
|
|
43
|
+
|
|
44
|
+
case 'f':
|
|
45
|
+
result.status = 'fail';
|
|
46
|
+
break;
|
|
47
|
+
|
|
48
|
+
case 'e':
|
|
49
|
+
result.status = 'error';
|
|
50
|
+
break;
|
|
51
|
+
|
|
52
|
+
default:
|
|
53
|
+
result.status = 'success';
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// return
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permission type string literal type that defines various access levels and capabilities
|
|
3
|
+
|
|
4
|
+
* @inline
|
|
5
|
+
*/
|
|
6
|
+
export type AccessType =
|
|
7
|
+
| 'god_access'
|
|
8
|
+
| 'user_access'
|
|
9
|
+
| 'upload_file_access'
|
|
10
|
+
| 'remove_file_access'
|
|
11
|
+
| 'anonymous_access'
|
|
12
|
+
| 'advanced_settings'
|
|
13
|
+
| string;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Defines access control for a specific database collection
|
|
17
|
+
*
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
export class AccessDefinition {
|
|
21
|
+
/** @hidden */
|
|
22
|
+
database: string;
|
|
23
|
+
/** @hidden */
|
|
24
|
+
collection: string;
|
|
25
|
+
/** @hidden */
|
|
26
|
+
permissionList: Permission[];
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Creates a new AccessDefinition instance
|
|
30
|
+
* @param {Object} options - Configuration options
|
|
31
|
+
* @param {string} options.database - The name of the database
|
|
32
|
+
* @param {string} options.collection - The name of the collection
|
|
33
|
+
* @param {Permission[]} options.permissionList - List of permissions
|
|
34
|
+
*/
|
|
35
|
+
constructor({
|
|
36
|
+
database,
|
|
37
|
+
collection,
|
|
38
|
+
permissionList,
|
|
39
|
+
}: {
|
|
40
|
+
database: string;
|
|
41
|
+
collection: string;
|
|
42
|
+
permissionList: Permission[];
|
|
43
|
+
}) {
|
|
44
|
+
this.database = database;
|
|
45
|
+
this.collection = collection;
|
|
46
|
+
this.permissionList = permissionList;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Defines a permission for accessing data within the system. This class is a fundamental component used in both the {@link defineCollection} method and {@link CollectionDefinition} class
|
|
52
|
+
* by specifying which permission types can interact with them. The permission system matches a user's assigned permission types against
|
|
53
|
+
* the collection's permissions to determine access levels. For example, a collection can allow read access for 'user_access' while
|
|
54
|
+
* restricting writes to 'advanced_settings' permissions.
|
|
55
|
+
*
|
|
56
|
+
* @remark
|
|
57
|
+
* {@include ../../docs/system-access-type.md}
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* import { Permission } from '@modular-rest/server';
|
|
62
|
+
*
|
|
63
|
+
* const permission = new Permission({
|
|
64
|
+
* type: 'user_access',
|
|
65
|
+
* read: true,
|
|
66
|
+
* write: true,
|
|
67
|
+
* onlyOwnData: true,
|
|
68
|
+
* ownerIdField: 'userId'
|
|
69
|
+
* });
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export class Permission {
|
|
73
|
+
/** @hidden */
|
|
74
|
+
accessType: AccessType;
|
|
75
|
+
/** @hidden */
|
|
76
|
+
read: boolean;
|
|
77
|
+
/** @hidden */
|
|
78
|
+
write: boolean;
|
|
79
|
+
/** @hidden */
|
|
80
|
+
onlyOwnData: boolean;
|
|
81
|
+
/** @hidden */
|
|
82
|
+
ownerIdField: string;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Creates a new Permission instance
|
|
86
|
+
* @param {Object} options - Configuration options
|
|
87
|
+
*
|
|
88
|
+
* @param {AccessType} options.type - The type of permission,system defined or custom. check the **Remarks section** for more information.
|
|
89
|
+
*
|
|
90
|
+
* @param {boolean} [options.read=false] - Whether read access is granted
|
|
91
|
+
* @param {boolean} [options.write=false] - Whether write access is granted
|
|
92
|
+
* @param {boolean} [options.onlyOwnData=false] - Whether access is limited to own data
|
|
93
|
+
* @param {string} [options.ownerIdField='refId'] - Field name for owner identification
|
|
94
|
+
*/
|
|
95
|
+
constructor({
|
|
96
|
+
accessType: type,
|
|
97
|
+
read = false,
|
|
98
|
+
write = false,
|
|
99
|
+
onlyOwnData = false,
|
|
100
|
+
ownerIdField = 'refId',
|
|
101
|
+
}: {
|
|
102
|
+
accessType: AccessType;
|
|
103
|
+
read?: boolean;
|
|
104
|
+
write?: boolean;
|
|
105
|
+
onlyOwnData?: boolean;
|
|
106
|
+
ownerIdField?: string;
|
|
107
|
+
}) {
|
|
108
|
+
this.accessType = type;
|
|
109
|
+
this.read = read;
|
|
110
|
+
this.write = write;
|
|
111
|
+
this.onlyOwnData = onlyOwnData;
|
|
112
|
+
this.ownerIdField = ownerIdField;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* A comprehensive access control mechanism that manages user permissions through grouped access types.
|
|
118
|
+
*
|
|
119
|
+
* Permission groups are a fundamental security concept that define and enforce what actions users
|
|
120
|
+
* can perform within the system. They provide a flexible and maintainable way to handle authorization
|
|
121
|
+
* by grouping related access types together.
|
|
122
|
+
*
|
|
123
|
+
* These groups enable users to:
|
|
124
|
+
* 1. Read and write data from collections that match their access types, allowing granular control
|
|
125
|
+
* over database operations
|
|
126
|
+
* 2. Execute specific functions that require matching access types, ensuring that sensitive
|
|
127
|
+
* operations are only performed by authorized users
|
|
128
|
+
* 3. Perform custom developer-defined actions by validating against the user's access types,
|
|
129
|
+
* enabling extensible permission-based features
|
|
130
|
+
*
|
|
131
|
+
* Permission groups can be configured as default groups for new users or anonymous groups for
|
|
132
|
+
* unauthenticated access, providing a complete authorization framework.
|
|
133
|
+
*
|
|
134
|
+
* @class PermissionGroup
|
|
135
|
+
* @property {string} title - The title of the permission group
|
|
136
|
+
* @property {boolean} isDefault - This is a default group, on `true` this permission group will be given to any new user automatically.
|
|
137
|
+
* @property {boolean} isAnonymous - This is a anonymous group, on `true` will be used for anonymous users.
|
|
138
|
+
* @property {AccessType[]} allowedAccessTypes - List of valid access types.
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* const group = new PermissionGroup({
|
|
142
|
+
* title: 'Admin',
|
|
143
|
+
* isDefault: true,
|
|
144
|
+
* allowedAccessTypes: ['god_access', 'advanced_settings']
|
|
145
|
+
* });
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
export class PermissionGroup {
|
|
149
|
+
/** @hidden */
|
|
150
|
+
title: string;
|
|
151
|
+
/** @hidden */
|
|
152
|
+
isDefault: boolean;
|
|
153
|
+
/** @hidden */
|
|
154
|
+
isAnonymous: boolean;
|
|
155
|
+
/** @hidden */
|
|
156
|
+
allowedAccessTypes: AccessType[];
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Creates a new PermissionGroup instance
|
|
160
|
+
* @param {Object} options - Configuration options
|
|
161
|
+
* @param {string} options.title - The title of the group
|
|
162
|
+
* @param {boolean} [options.isDefault=false] - Whether this is a default group
|
|
163
|
+
* @param {boolean} [options.isAnonymous=false] - Whether this group is for anonymous users
|
|
164
|
+
* @param {AccessType[]} [options.allowedAccessTypes=[]] - List of valid permission types
|
|
165
|
+
*/
|
|
166
|
+
constructor({
|
|
167
|
+
title,
|
|
168
|
+
isDefault = false,
|
|
169
|
+
isAnonymous = false,
|
|
170
|
+
allowedAccessTypes = [],
|
|
171
|
+
}: {
|
|
172
|
+
title: string;
|
|
173
|
+
isDefault?: boolean;
|
|
174
|
+
isAnonymous?: boolean;
|
|
175
|
+
allowedAccessTypes?: AccessType[];
|
|
176
|
+
}) {
|
|
177
|
+
this.title = title;
|
|
178
|
+
this.isDefault = isDefault;
|
|
179
|
+
this.isAnonymous = isAnonymous;
|
|
180
|
+
this.allowedAccessTypes = allowedAccessTypes;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Provides static access to access type constants
|
|
186
|
+
* @class AccessTypes
|
|
187
|
+
*/
|
|
188
|
+
export class AccessTypes {
|
|
189
|
+
/**
|
|
190
|
+
* Get the string representing read access type
|
|
191
|
+
* @returns {string} The read access type
|
|
192
|
+
*/
|
|
193
|
+
static get read(): string {
|
|
194
|
+
return 'read';
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Get the string representing write access type
|
|
199
|
+
* @returns {string} The write access type
|
|
200
|
+
*/
|
|
201
|
+
static get write(): string {
|
|
202
|
+
return 'write';
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Provides static access to permission type constants
|
|
208
|
+
* @class PermissionTypes
|
|
209
|
+
*/
|
|
210
|
+
export class PermissionTypes {
|
|
211
|
+
/**
|
|
212
|
+
* Get the string representing god access permission type
|
|
213
|
+
* @returns {string} The god access permission type
|
|
214
|
+
*/
|
|
215
|
+
static get god_access(): AccessType {
|
|
216
|
+
return 'god_access';
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Get the string representing advanced settings permission type
|
|
221
|
+
* @returns {string} The advanced settings permission type
|
|
222
|
+
*/
|
|
223
|
+
static get advanced_settings(): AccessType {
|
|
224
|
+
return 'advanced_settings';
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Get the string representing user access permission type
|
|
229
|
+
* @returns {string} The user access permission type
|
|
230
|
+
*/
|
|
231
|
+
static get user_access(): AccessType {
|
|
232
|
+
return 'user_access';
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Get the string representing upload file access permission type
|
|
237
|
+
* @returns {string} The upload file access permission type
|
|
238
|
+
*/
|
|
239
|
+
static get upload_file_access(): AccessType {
|
|
240
|
+
return 'upload_file_access';
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Get the string representing remove file access permission type
|
|
245
|
+
* @returns {string} The remove file access permission type
|
|
246
|
+
*/
|
|
247
|
+
static get remove_file_access(): AccessType {
|
|
248
|
+
return 'remove_file_access';
|
|
249
|
+
}
|
|
250
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { DatabaseOperation } from './database_trigger';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Interface defining a database trigger
|
|
5
|
+
* @interface Trigger
|
|
6
|
+
* @property {DatabaseOperation} operation - The database operation that triggers this callback
|
|
7
|
+
* @property {string} database - The database name to monitor
|
|
8
|
+
* @property {string} collection - The collection name to monitor
|
|
9
|
+
* @property {(data: any) => void} callback - Function to execute when trigger conditions are met
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const trigger: Trigger = {
|
|
13
|
+
* operation: 'insert',
|
|
14
|
+
* database: 'myDB',
|
|
15
|
+
* collection: 'users',
|
|
16
|
+
* callback: (data) => {
|
|
17
|
+
* console.log('New user inserted:', data);
|
|
18
|
+
* }
|
|
19
|
+
* };
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
interface Trigger {
|
|
23
|
+
operation: DatabaseOperation;
|
|
24
|
+
database: string;
|
|
25
|
+
collection: string;
|
|
26
|
+
callback: (data: any) => void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Singleton class for managing database triggers
|
|
31
|
+
* Provides functionality to add and execute triggers based on database operations
|
|
32
|
+
* @class TriggerOperator
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* // Add a trigger for user insertions
|
|
36
|
+
* TriggerOperator.instance.addTrigger({
|
|
37
|
+
* operation: 'insert',
|
|
38
|
+
* database: 'myDB',
|
|
39
|
+
* collection: 'users',
|
|
40
|
+
* callback: (data) => {
|
|
41
|
+
* console.log('New user inserted:', data);
|
|
42
|
+
* }
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
class TriggerOperator {
|
|
47
|
+
private triggers: Trigger[] = [];
|
|
48
|
+
private static _instance: TriggerOperator | null = null;
|
|
49
|
+
|
|
50
|
+
private constructor() {}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Gets the singleton instance of TriggerOperator
|
|
54
|
+
* @static
|
|
55
|
+
* @returns {TriggerOperator} The singleton instance
|
|
56
|
+
*/
|
|
57
|
+
static get instance(): TriggerOperator {
|
|
58
|
+
if (!TriggerOperator._instance) {
|
|
59
|
+
TriggerOperator._instance = new TriggerOperator();
|
|
60
|
+
}
|
|
61
|
+
return TriggerOperator._instance;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Adds a new trigger to the registry
|
|
66
|
+
* @param {Trigger} trigger - The trigger configuration to add
|
|
67
|
+
* @throws {Error} If trigger is invalid or already exists
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* // Add a trigger for document updates
|
|
71
|
+
* TriggerOperator.instance.addTrigger({
|
|
72
|
+
* operation: 'update',
|
|
73
|
+
* database: 'myDB',
|
|
74
|
+
* collection: 'documents',
|
|
75
|
+
* callback: (data) => {
|
|
76
|
+
* console.log('Document updated:', data);
|
|
77
|
+
* }
|
|
78
|
+
* });
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
addTrigger(trigger: Trigger): void {
|
|
82
|
+
// Validate trigger
|
|
83
|
+
if (!trigger.operation || !trigger.database || !trigger.collection || !trigger.callback) {
|
|
84
|
+
throw new Error('Invalid trigger configuration');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Check for duplicate triggers
|
|
88
|
+
const exists = this.triggers.some(
|
|
89
|
+
t =>
|
|
90
|
+
t.operation === trigger.operation &&
|
|
91
|
+
t.database === trigger.database &&
|
|
92
|
+
t.collection === trigger.collection
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
if (exists) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
`Trigger already exists for operation ${trigger.operation} on ${trigger.database}.${trigger.collection}`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
this.triggers.push(trigger);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Executes all matching triggers for a given database operation
|
|
106
|
+
* @param {DatabaseOperation} operation - The database operation that occurred
|
|
107
|
+
* @param {string} database - The database where the operation occurred
|
|
108
|
+
* @param {string} collection - The collection where the operation occurred
|
|
109
|
+
* @param {any} data - The data associated with the operation
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* // This would typically be called by the database layer
|
|
113
|
+
* TriggerOperator.instance.call(
|
|
114
|
+
* 'insert',
|
|
115
|
+
* 'myDB',
|
|
116
|
+
* 'users',
|
|
117
|
+
* { id: 1, name: 'John' }
|
|
118
|
+
* );
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
call(operation: DatabaseOperation, database: string, collection: string, data: any): void {
|
|
122
|
+
this.triggers.forEach(trigger => {
|
|
123
|
+
if (
|
|
124
|
+
operation === trigger.operation &&
|
|
125
|
+
database === trigger.database &&
|
|
126
|
+
collection === trigger.collection &&
|
|
127
|
+
trigger.callback
|
|
128
|
+
) {
|
|
129
|
+
try {
|
|
130
|
+
trigger.callback(data);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
console.error(
|
|
133
|
+
`Error executing trigger for ${operation} on ${database}.${collection}:`,
|
|
134
|
+
error
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export = TriggerOperator.instance;
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { config } from '../config';
|
|
2
|
+
import { PermissionGroup, AccessType } from './security';
|
|
3
|
+
import { validator as validateObject } from './validator';
|
|
4
|
+
import { Document, Model } from 'mongoose';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* User detail interface
|
|
8
|
+
*/
|
|
9
|
+
interface UserDetail {
|
|
10
|
+
permissionGroup?: string | PermissionGroup;
|
|
11
|
+
phone?: string;
|
|
12
|
+
email?: string;
|
|
13
|
+
password?: string;
|
|
14
|
+
fullname?: string;
|
|
15
|
+
type?: string;
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* User class representing a user in the system
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export class User {
|
|
25
|
+
id: string;
|
|
26
|
+
permissionGroup: string;
|
|
27
|
+
phone: string;
|
|
28
|
+
email: string;
|
|
29
|
+
password: string;
|
|
30
|
+
type: string;
|
|
31
|
+
dbModel: any;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Create a user
|
|
35
|
+
* @param id - User ID
|
|
36
|
+
* @param permissionGroup - Permission group name
|
|
37
|
+
* @param phone - User phone
|
|
38
|
+
* @param email - User email
|
|
39
|
+
* @param password - User password
|
|
40
|
+
* @param type - User type
|
|
41
|
+
* @param model - Database model
|
|
42
|
+
*
|
|
43
|
+
* @hidden
|
|
44
|
+
*/
|
|
45
|
+
constructor(
|
|
46
|
+
id: string,
|
|
47
|
+
permissionGroup: string,
|
|
48
|
+
phone: string,
|
|
49
|
+
email: string,
|
|
50
|
+
password: string,
|
|
51
|
+
type: string,
|
|
52
|
+
model: any
|
|
53
|
+
) {
|
|
54
|
+
this.id = id;
|
|
55
|
+
this.permissionGroup = permissionGroup;
|
|
56
|
+
this.email = email;
|
|
57
|
+
this.phone = phone;
|
|
58
|
+
this.password = password;
|
|
59
|
+
this.type = type;
|
|
60
|
+
this.dbModel = model;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Get brief user information
|
|
65
|
+
* @returns Brief user info object
|
|
66
|
+
*/
|
|
67
|
+
getBrief(): UserDetail {
|
|
68
|
+
const permissionGroup = config.permissionGroups?.find(
|
|
69
|
+
group => group.title === this.permissionGroup
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
if (!permissionGroup) {
|
|
73
|
+
throw new Error('Permission group not found on user object');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const brief: UserDetail = {
|
|
77
|
+
id: this.id,
|
|
78
|
+
permissionGroup: permissionGroup,
|
|
79
|
+
phone: this.phone,
|
|
80
|
+
email: this.email,
|
|
81
|
+
type: this.type,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
return brief;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Update user details
|
|
89
|
+
* @param detail - Object containing user details to update
|
|
90
|
+
*/
|
|
91
|
+
setNewDetail(detail: UserDetail): void {
|
|
92
|
+
if (detail.phone) this.phone = detail.phone;
|
|
93
|
+
if (detail.email) this.email = detail.email;
|
|
94
|
+
if (detail.password) this.password = detail.password;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Check if user has a specific permission
|
|
99
|
+
* @param accessType - Permission to check
|
|
100
|
+
* @returns True if user has permission, false otherwise
|
|
101
|
+
*/
|
|
102
|
+
hasPermission(accessType: string): boolean {
|
|
103
|
+
const permissionGroup = config.permissionGroups?.find(
|
|
104
|
+
group => group.title === this.permissionGroup
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
if (permissionGroup == null) return false;
|
|
108
|
+
|
|
109
|
+
let key = false;
|
|
110
|
+
|
|
111
|
+
if (permissionGroup.allowedAccessTypes) {
|
|
112
|
+
for (let i = 0; i < permissionGroup.allowedAccessTypes.length; i++) {
|
|
113
|
+
const userPermissionType = permissionGroup.allowedAccessTypes[i];
|
|
114
|
+
|
|
115
|
+
if (userPermissionType === accessType) {
|
|
116
|
+
key = true;
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return key;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Save user to database
|
|
127
|
+
*/
|
|
128
|
+
async save(): Promise<void> {
|
|
129
|
+
if (!this.dbModel) {
|
|
130
|
+
throw new Error('User model is not initialized');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
this.dbModel['permissionGroup'] = this.permissionGroup;
|
|
134
|
+
this.dbModel['phone'] = this.phone;
|
|
135
|
+
this.dbModel['email'] = this.email;
|
|
136
|
+
this.dbModel['password'] = this.password;
|
|
137
|
+
|
|
138
|
+
await this.dbModel.save();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Load user from database model
|
|
143
|
+
* @param model - Database model
|
|
144
|
+
* @returns Promise resolving to User instance
|
|
145
|
+
*/
|
|
146
|
+
static loadFromModel(model: any): Promise<User> {
|
|
147
|
+
return new Promise((done, reject) => {
|
|
148
|
+
// check required fields
|
|
149
|
+
const isValidData = validateObject(model, '_id permissionGroup');
|
|
150
|
+
|
|
151
|
+
if (!isValidData.isValid) {
|
|
152
|
+
return reject(User.notValid(model));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const id = model.id;
|
|
156
|
+
const permissionGroup = model.permissionGroup;
|
|
157
|
+
const phone = model.phone;
|
|
158
|
+
const email = model.email;
|
|
159
|
+
const password = model.password;
|
|
160
|
+
const type = model.type;
|
|
161
|
+
|
|
162
|
+
//create user
|
|
163
|
+
const newUser = new User(id, permissionGroup, phone, email, password, type, model);
|
|
164
|
+
done(newUser);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Create user from model and details
|
|
170
|
+
* @param model - Mongoose model
|
|
171
|
+
* @param detail - User details
|
|
172
|
+
* @returns Promise resolving to User instance
|
|
173
|
+
*/
|
|
174
|
+
static createFromModel(model: Model<any>, detail: UserDetail): Promise<User> {
|
|
175
|
+
return new Promise(async (done, reject) => {
|
|
176
|
+
//create user
|
|
177
|
+
try {
|
|
178
|
+
const newUserDoc = await new model(detail).save();
|
|
179
|
+
const newUser = await User.loadFromModel(newUserDoc);
|
|
180
|
+
done(newUser);
|
|
181
|
+
} catch (error) {
|
|
182
|
+
reject(error);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Create error for invalid user
|
|
189
|
+
* @param object - Invalid user object
|
|
190
|
+
* @returns Error message
|
|
191
|
+
*/
|
|
192
|
+
static notValid(object: any): string {
|
|
193
|
+
const error = `user detail are not valid ${JSON.stringify(object)}`;
|
|
194
|
+
console.error(error);
|
|
195
|
+
return error;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export default User;
|