@modular-rest/server 1.11.13 → 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.
Files changed (112) hide show
  1. package/.nvmrc +1 -0
  2. package/.prettierrc.json +9 -0
  3. package/.releaserc.json +24 -0
  4. package/README.md +79 -94
  5. package/dist/index.js +79 -0
  6. package/docs/.keep +0 -0
  7. package/docs/system-access-type.md +26 -0
  8. package/package.json +58 -45
  9. package/src/application.ts +206 -0
  10. package/src/class/cms_trigger.ts +68 -0
  11. package/src/class/collection_definition.ts +134 -0
  12. package/src/class/combinator.ts +176 -0
  13. package/src/class/database_trigger.ts +99 -0
  14. package/src/class/db_schemas.ts +44 -0
  15. package/src/class/{directory.js → directory.ts} +40 -18
  16. package/src/class/paginator.ts +51 -0
  17. package/src/class/reply.ts +59 -0
  18. package/src/class/security.ts +250 -0
  19. package/src/class/trigger_operator.ts +142 -0
  20. package/src/class/user.ts +199 -0
  21. package/src/class/validator.ts +123 -0
  22. package/src/config.ts +122 -0
  23. package/src/defult-permissions.ts +31 -0
  24. package/src/events.ts +59 -0
  25. package/src/helper/data_insertion.ts +94 -0
  26. package/src/helper/presetup_services.ts +96 -0
  27. package/src/index.ts +146 -0
  28. package/src/middlewares.ts +75 -0
  29. package/src/play-test.ts +8 -0
  30. package/src/services/data_provider/router.ts +191 -0
  31. package/src/services/data_provider/service.ts +305 -0
  32. package/src/services/data_provider/typeCasters.ts +15 -0
  33. package/src/services/file/db.ts +29 -0
  34. package/src/services/file/router.ts +88 -0
  35. package/src/services/file/service.ts +387 -0
  36. package/src/services/functions/router.ts +34 -0
  37. package/src/services/functions/service.ts +203 -0
  38. package/src/services/jwt/router.ts +73 -0
  39. package/src/services/jwt/service.ts +139 -0
  40. package/src/services/user_manager/db.ts +87 -0
  41. package/src/services/user_manager/permissionManager.ts +49 -0
  42. package/src/services/user_manager/router.ts +193 -0
  43. package/src/services/user_manager/service.ts +698 -0
  44. package/tsconfig.json +16 -9
  45. package/typedoc.mjs +41 -0
  46. package/LICENSE +0 -21
  47. package/package-lock.json +0 -1373
  48. package/src/application.js +0 -239
  49. package/src/class/cms_trigger.js +0 -20
  50. package/src/class/collection_definition.js +0 -33
  51. package/src/class/combinator.js +0 -133
  52. package/src/class/database_trigger.js +0 -20
  53. package/src/class/db_schemas.js +0 -18
  54. package/src/class/paginator.js +0 -31
  55. package/src/class/reply.js +0 -37
  56. package/src/class/security.js +0 -141
  57. package/src/class/trigger_operator.js +0 -39
  58. package/src/class/user.js +0 -112
  59. package/src/class/validator.js +0 -91
  60. package/src/config.js +0 -67
  61. package/src/events.js +0 -15
  62. package/src/helper/data_insertion.js +0 -64
  63. package/src/helper/presetup_services.js +0 -31
  64. package/src/index.js +0 -66
  65. package/src/middlewares.js +0 -44
  66. package/src/services/data_provider/router.js +0 -552
  67. package/src/services/data_provider/service.js +0 -262
  68. package/src/services/data_provider/typeCasters.js +0 -10
  69. package/src/services/file/db.js +0 -29
  70. package/src/services/file/router.js +0 -92
  71. package/src/services/file/service.js +0 -231
  72. package/src/services/functions/router.js +0 -37
  73. package/src/services/functions/service.js +0 -74
  74. package/src/services/jwt/router.js +0 -82
  75. package/src/services/jwt/service.js +0 -37
  76. package/src/services/user_manager/db.js +0 -83
  77. package/src/services/user_manager/permissionManager.js +0 -43
  78. package/src/services/user_manager/router.js +0 -176
  79. package/src/services/user_manager/service.js +0 -377
  80. package/types/application.d.ts +0 -97
  81. package/types/class/cms_trigger.d.ts +0 -24
  82. package/types/class/collection_definition.d.ts +0 -36
  83. package/types/class/combinator.d.ts +0 -30
  84. package/types/class/database_trigger.d.ts +0 -28
  85. package/types/class/db_schemas.d.ts +0 -2
  86. package/types/class/directory.d.ts +0 -2
  87. package/types/class/paginator.d.ts +0 -8
  88. package/types/class/reply.d.ts +0 -8
  89. package/types/class/security.d.ts +0 -109
  90. package/types/class/trigger_operator.d.ts +0 -19
  91. package/types/class/user.d.ts +0 -24
  92. package/types/class/validator.d.ts +0 -9
  93. package/types/config.d.ts +0 -101
  94. package/types/events.d.ts +0 -7
  95. package/types/helper/data_insertion.d.ts +0 -4
  96. package/types/helper/presetup_services.d.ts +0 -5
  97. package/types/index.d.ts +0 -72
  98. package/types/middlewares.d.ts +0 -10
  99. package/types/services/data_provider/router.d.ts +0 -3
  100. package/types/services/data_provider/service.d.ts +0 -40
  101. package/types/services/data_provider/typeCasters.d.ts +0 -3
  102. package/types/services/file/db.d.ts +0 -3
  103. package/types/services/file/router.d.ts +0 -3
  104. package/types/services/file/service.d.ts +0 -81
  105. package/types/services/functions/router.d.ts +0 -3
  106. package/types/services/functions/service.d.ts +0 -23
  107. package/types/services/jwt/router.d.ts +0 -3
  108. package/types/services/jwt/service.d.ts +0 -10
  109. package/types/services/user_manager/db.d.ts +0 -3
  110. package/types/services/user_manager/permissionManager.d.ts +0 -3
  111. package/types/services/user_manager/router.d.ts +0 -3
  112. 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;