@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,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation result interface
|
|
3
|
+
*/
|
|
4
|
+
export interface ValidationResult {
|
|
5
|
+
isValid: boolean;
|
|
6
|
+
requires: string[];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Validates an object by checking if it contains all the required fields.
|
|
11
|
+
* @param obj - The object to be validated.
|
|
12
|
+
* @param requiredFields - The list of required fields. If it's a string, it should contain keys separated by spaces. If it's an object, it should contain key-value pairs where the key is the field name and the value is a boolean indicating whether the field is required or not.
|
|
13
|
+
* @returns Returns a ValidationResult object with validation status and missing fields.
|
|
14
|
+
* @throws Throws an error if the requiredFields parameter is not a string or an object.
|
|
15
|
+
*/
|
|
16
|
+
export function validator(
|
|
17
|
+
obj: Record<string, any> | null,
|
|
18
|
+
requiredFields: string | Record<string, string>
|
|
19
|
+
): ValidationResult {
|
|
20
|
+
/*
|
|
21
|
+
this method could validate an Object by given field's name list and return bool.
|
|
22
|
+
- requiredFields: is a string that contains keys being spared by " ".
|
|
23
|
+
*/
|
|
24
|
+
const type = typeof requiredFields;
|
|
25
|
+
let result: ValidationResult;
|
|
26
|
+
|
|
27
|
+
if (type === 'string') result = checkSimple(obj, requiredFields as string);
|
|
28
|
+
else if (type === 'object') result = checkComplex(obj, requiredFields as Record<string, string>);
|
|
29
|
+
else throw 'requiredFields has wrong form, it must be string or object';
|
|
30
|
+
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Check simple validation with space-separated string of keys
|
|
36
|
+
*/
|
|
37
|
+
function checkSimple(
|
|
38
|
+
obj: Record<string, any> | null,
|
|
39
|
+
requiredFields: string = ''
|
|
40
|
+
): ValidationResult {
|
|
41
|
+
let isValid = false;
|
|
42
|
+
const requires = requiredFields.split(' ');
|
|
43
|
+
|
|
44
|
+
const validMembers = [];
|
|
45
|
+
const notValidKeys = [];
|
|
46
|
+
|
|
47
|
+
// return if obj is null
|
|
48
|
+
if (obj == null) return _returnResult(isValid, requires);
|
|
49
|
+
|
|
50
|
+
// Filter empty strings that might result from extra spaces
|
|
51
|
+
const requiredKeys = requires.filter(key => key !== '');
|
|
52
|
+
|
|
53
|
+
for (const key of requiredKeys) {
|
|
54
|
+
if (obj[key] !== undefined && obj[key] !== null) validMembers.push(key);
|
|
55
|
+
else notValidKeys.push(key);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// check validation
|
|
59
|
+
isValid = requiredKeys.length === validMembers.length;
|
|
60
|
+
return _returnResult(isValid, notValidKeys);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Check complex validation with object containing expected values
|
|
65
|
+
*/
|
|
66
|
+
function checkComplex(
|
|
67
|
+
obj: Record<string, any> | null,
|
|
68
|
+
requiredFields: Record<string, string> = {}
|
|
69
|
+
): ValidationResult {
|
|
70
|
+
let isValid = false;
|
|
71
|
+
const requireKeys = Object.keys(requiredFields);
|
|
72
|
+
|
|
73
|
+
let validMembers = 0;
|
|
74
|
+
const notValidKeys: string[] = [];
|
|
75
|
+
|
|
76
|
+
// return if obj is null
|
|
77
|
+
if (obj == null) return _returnResult(isValid, requireKeys);
|
|
78
|
+
|
|
79
|
+
for (let i = 0; i < requireKeys.length; i++) {
|
|
80
|
+
const key = requireKeys[i];
|
|
81
|
+
let isValidField = false;
|
|
82
|
+
|
|
83
|
+
// if field has specific values
|
|
84
|
+
if (requiredFields[key].length > 0) {
|
|
85
|
+
const expectedValues = requiredFields[key].split(' ');
|
|
86
|
+
|
|
87
|
+
if (typeof expectedValues !== 'object') throw `${key} must be array of strings`;
|
|
88
|
+
|
|
89
|
+
for (const value of expectedValues) {
|
|
90
|
+
if (obj[key] === value) {
|
|
91
|
+
isValidField = true;
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// else does not have specific value
|
|
97
|
+
else if (obj[key] != null) {
|
|
98
|
+
isValidField = true;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (isValidField) validMembers++;
|
|
102
|
+
else notValidKeys.push(key);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// check validation
|
|
106
|
+
isValid = requireKeys.length === validMembers;
|
|
107
|
+
return _returnResult(isValid, notValidKeys);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Create a validation result object
|
|
112
|
+
*/
|
|
113
|
+
function _returnResult(isValid: boolean, notValidKeys: string[]): ValidationResult {
|
|
114
|
+
return {
|
|
115
|
+
isValid: isValid,
|
|
116
|
+
requires: notValidKeys,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Return the validator function to maintain compatibility with the JavaScript version
|
|
122
|
+
*/
|
|
123
|
+
export const validateObject = validator;
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import Koa from 'koa';
|
|
2
|
+
|
|
3
|
+
import { CollectionDefinition } from './class/collection_definition';
|
|
4
|
+
import { PermissionGroup } from './class/security';
|
|
5
|
+
import { CmsTrigger } from './class/cms_trigger';
|
|
6
|
+
import { DefinedFunction } from './services/functions/service';
|
|
7
|
+
import { Options as KoaCorsOptions } from '@koa/cors';
|
|
8
|
+
import { Options as KoaStaticOptionsBase } from 'koa-static';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The options for the static file server, it's a combination of modular-rest and [koa-static options](https://github.com/koajs/static?tab=readme-ov-file#options)
|
|
12
|
+
*/
|
|
13
|
+
export type StaticPathOptions = KoaStaticOptionsBase & {
|
|
14
|
+
/**
|
|
15
|
+
* The actual path of the static files on your server
|
|
16
|
+
*/
|
|
17
|
+
actualPath: string;
|
|
18
|
+
/**
|
|
19
|
+
* The path you want to serve the static files from
|
|
20
|
+
*/
|
|
21
|
+
path: string;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* JWT keypair configuration
|
|
26
|
+
* @interface KeyPair
|
|
27
|
+
* @property {string} private - Private key for JWT signing
|
|
28
|
+
* @property {string} public - Public key for JWT verification
|
|
29
|
+
*/
|
|
30
|
+
interface KeyPair {
|
|
31
|
+
private: string;
|
|
32
|
+
public: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* MongoDB connection options
|
|
37
|
+
* @interface MongoOptions
|
|
38
|
+
* @property {string} dbPrefix - Prefix for database names
|
|
39
|
+
* @property {string} mongoBaseAddress - MongoDB connection URL
|
|
40
|
+
*/
|
|
41
|
+
interface MongoOptions {
|
|
42
|
+
dbPrefix: string;
|
|
43
|
+
mongoBaseAddress: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Admin user configuration
|
|
48
|
+
* @interface AdminUser
|
|
49
|
+
* @property {string} email - Admin user email
|
|
50
|
+
* @property {string} password - Admin user password
|
|
51
|
+
*/
|
|
52
|
+
interface AdminUser {
|
|
53
|
+
email: string;
|
|
54
|
+
password: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Configuration options for creating a REST API instance
|
|
59
|
+
* @interface RestOptions
|
|
60
|
+
* @property {KoaCorsOptions} [cors] - CORS configuration [options](https://github.com/koajs/cors?tab=readme-ov-file#corsoptions)
|
|
61
|
+
* @property {string} [modulesPath] - Path to custom modules directory
|
|
62
|
+
* @property {string} [uploadDirectory] - Directory for file uploads
|
|
63
|
+
* @property {any} [koaBodyOptions] - Options for koa-body middleware
|
|
64
|
+
* @property {StaticPathOptions} [staticPath] - Static file serving options
|
|
65
|
+
* @property {Function} [onBeforeInit] - Hook called before initialization
|
|
66
|
+
* @property {Function} [onAfterInit] - Hook called after initialization
|
|
67
|
+
* @property {number} [port] - Port to listen on
|
|
68
|
+
* @property {boolean} [dontListen] - Don't start the server
|
|
69
|
+
* @property {MongoOptions} [mongo] - MongoDB connection options
|
|
70
|
+
* @property {Object} [keypair] - JWT keypair for authentication
|
|
71
|
+
* @property {AdminUser} [adminUser] - Admin user configuration
|
|
72
|
+
* @property {Function} [verificationCodeGeneratorMethod] - Custom verification code generator
|
|
73
|
+
* @property {CollectionDefinition[]} [collectionDefinitions] - Custom collection definitions
|
|
74
|
+
* @property {PermissionGroup[]} [permissionGroups] - Custom permission groups
|
|
75
|
+
* @property {CmsTrigger[]} [authTriggers] - Authentication triggers
|
|
76
|
+
* @property {CmsTrigger[]} [fileTriggers] - File handling triggers
|
|
77
|
+
* @property {DefinedFunction[]} [functions] - Custom API functions
|
|
78
|
+
*/
|
|
79
|
+
export interface RestOptions {
|
|
80
|
+
cors?: KoaCorsOptions;
|
|
81
|
+
modulesPath?: string;
|
|
82
|
+
uploadDirectory?: string;
|
|
83
|
+
koaBodyOptions?: any;
|
|
84
|
+
staticPath?: StaticPathOptions;
|
|
85
|
+
onBeforeInit?: (koaApp: Koa) => void;
|
|
86
|
+
onAfterInit?: (koaApp: Koa) => void;
|
|
87
|
+
port?: number;
|
|
88
|
+
dontListen?: boolean;
|
|
89
|
+
mongo?: MongoOptions;
|
|
90
|
+
keypair?: KeyPair;
|
|
91
|
+
adminUser?: AdminUser;
|
|
92
|
+
verificationCodeGeneratorMethod?: () => string;
|
|
93
|
+
collectionDefinitions?: CollectionDefinition[];
|
|
94
|
+
permissionGroups?: PermissionGroup[];
|
|
95
|
+
authTriggers?: CmsTrigger[];
|
|
96
|
+
fileTriggers?: CmsTrigger[];
|
|
97
|
+
functions?: DefinedFunction[];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Global configuration object
|
|
102
|
+
* @type {RestOptions}
|
|
103
|
+
*/
|
|
104
|
+
export const config: RestOptions = {};
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Updates the global configuration with new options
|
|
108
|
+
* @param {RestOptions} options - New configuration options to merge
|
|
109
|
+
* @example
|
|
110
|
+
* ```typescript
|
|
111
|
+
* setConfig({
|
|
112
|
+
* port: 3000,
|
|
113
|
+
* mongo: {
|
|
114
|
+
* mongoBaseAddress: 'mongodb://localhost:27017',
|
|
115
|
+
* dbPrefix: 'myapp_'
|
|
116
|
+
* }
|
|
117
|
+
* });
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export function setConfig(options: RestOptions): void {
|
|
121
|
+
Object.assign(config, options);
|
|
122
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { PermissionGroup } from './class/security';
|
|
2
|
+
|
|
3
|
+
export const permissionGroups = [
|
|
4
|
+
new PermissionGroup({
|
|
5
|
+
title: 'anonymous',
|
|
6
|
+
isAnonymous: true,
|
|
7
|
+
allowedAccessTypes: ['anonymous_access'],
|
|
8
|
+
}),
|
|
9
|
+
|
|
10
|
+
new PermissionGroup({
|
|
11
|
+
title: 'end-user',
|
|
12
|
+
isDefault: true,
|
|
13
|
+
allowedAccessTypes: [
|
|
14
|
+
'user_access',
|
|
15
|
+
'anonymous_access',
|
|
16
|
+
'upload_file_access',
|
|
17
|
+
'remove_file_access',
|
|
18
|
+
],
|
|
19
|
+
}),
|
|
20
|
+
|
|
21
|
+
new PermissionGroup({
|
|
22
|
+
title: 'administrator',
|
|
23
|
+
allowedAccessTypes: [
|
|
24
|
+
'user_access',
|
|
25
|
+
'anonymous_access',
|
|
26
|
+
'upload_file_access',
|
|
27
|
+
'remove_file_access',
|
|
28
|
+
'advanced_settings',
|
|
29
|
+
],
|
|
30
|
+
}),
|
|
31
|
+
];
|
package/src/events.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import Koa from "koa";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Event callback interface
|
|
5
|
+
*/
|
|
6
|
+
interface EventCallback {
|
|
7
|
+
event: string;
|
|
8
|
+
callback: (...args: any[]) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Array to store all registered event callbacks
|
|
13
|
+
*/
|
|
14
|
+
const eventCallbacks: EventCallback[] = [];
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Supported event types:
|
|
18
|
+
* - onBeforeInit: (koaApp: Koa) => void; // A callback called before initializing the Koa server.
|
|
19
|
+
* - onAfterInit: (koaApp: Koa) => void; // A callback called after server initialization.
|
|
20
|
+
* - onNewUser: (user: any) => void; // A callback called when a new user is created.
|
|
21
|
+
*
|
|
22
|
+
* @param event - The event name to register
|
|
23
|
+
* @param callback - The callback function to be called when the event is triggered
|
|
24
|
+
* @throws Error if event is not a string or callback is not a function
|
|
25
|
+
*/
|
|
26
|
+
export function registerEventCallback(
|
|
27
|
+
event: string,
|
|
28
|
+
callback: (...args: any[]) => void
|
|
29
|
+
): void {
|
|
30
|
+
if (typeof event !== "string") throw new Error("Event must be a string");
|
|
31
|
+
|
|
32
|
+
if (typeof callback !== "function")
|
|
33
|
+
throw new Error("Callback must be a function");
|
|
34
|
+
|
|
35
|
+
eventCallbacks.push({ event, callback });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get all registered callbacks for a specific event
|
|
40
|
+
* @param event - The event name to get callbacks for
|
|
41
|
+
* @returns Array of callbacks registered for the event
|
|
42
|
+
*/
|
|
43
|
+
export function getEventCallbacks(event: string): ((...args: any[]) => void)[] {
|
|
44
|
+
return eventCallbacks
|
|
45
|
+
.filter((cb) => cb.event === event)
|
|
46
|
+
.map((cb) => cb.callback);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Trigger an event with arguments
|
|
51
|
+
* @param event - The event name to trigger
|
|
52
|
+
* @param args - Arguments to pass to the callback functions
|
|
53
|
+
*/
|
|
54
|
+
export function triggerEvent(event: string, ...args: any[]): void {
|
|
55
|
+
const callbacks = getEventCallbacks(event);
|
|
56
|
+
for (const callback of callbacks) {
|
|
57
|
+
callback(...args);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as DataProvider from '../services/data_provider/service';
|
|
2
|
+
import {
|
|
3
|
+
getDefaultAnonymousPermissionGroup,
|
|
4
|
+
getDefaultAdministratorPermissionGroup,
|
|
5
|
+
} from '../services/user_manager/permissionManager';
|
|
6
|
+
import * as userManager from '../services/user_manager/service';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Admin user credentials interface
|
|
10
|
+
* @interface AdminCredentials
|
|
11
|
+
* @property {string} email - Admin user email address
|
|
12
|
+
* @property {string} password - Admin user password
|
|
13
|
+
*/
|
|
14
|
+
interface AdminCredentials {
|
|
15
|
+
email: string;
|
|
16
|
+
password: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Creates default system users if they don't exist
|
|
21
|
+
* @function createAdminUser
|
|
22
|
+
* @param {AdminCredentials} credentials - Admin user credentials
|
|
23
|
+
* @returns {Promise<void>} A promise that resolves when the operation is complete
|
|
24
|
+
* @throws {Error} If admin credentials are invalid or if the operation fails
|
|
25
|
+
* @description
|
|
26
|
+
* This function performs the following operations:
|
|
27
|
+
* 1. Checks if an anonymous user exists, creates one if it doesn't
|
|
28
|
+
* 2. Checks if an administrator user exists, creates one if it doesn't
|
|
29
|
+
* 3. Uses the provided credentials for the administrator user
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* // Create default system users
|
|
34
|
+
* await createAdminUser({
|
|
35
|
+
* email: 'admin@example.com',
|
|
36
|
+
* password: 'secure-password'
|
|
37
|
+
* });
|
|
38
|
+
*
|
|
39
|
+
* // The function will:
|
|
40
|
+
* // 1. Create an anonymous user if it doesn't exist
|
|
41
|
+
* // 2. Create an admin user with the provided credentials if it doesn't exist
|
|
42
|
+
* // 3. Do nothing if both users already exist
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export async function createAdminUser({ email, password }: AdminCredentials): Promise<void> {
|
|
46
|
+
const authModel = DataProvider.getCollection('cms', 'auth');
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const isAnonymousExisted = await authModel.countDocuments({ type: 'anonymous' }).exec();
|
|
50
|
+
|
|
51
|
+
const isAdministratorExisted = await authModel
|
|
52
|
+
.countDocuments({ type: 'user', email: email })
|
|
53
|
+
.exec();
|
|
54
|
+
|
|
55
|
+
if (isAnonymousExisted === 0) {
|
|
56
|
+
await userManager.main.registerUser({
|
|
57
|
+
permissionGroup: getDefaultAnonymousPermissionGroup().title,
|
|
58
|
+
email: '',
|
|
59
|
+
phone: '',
|
|
60
|
+
password: '',
|
|
61
|
+
type: 'anonymous',
|
|
62
|
+
});
|
|
63
|
+
// await new authModel({
|
|
64
|
+
// permission: getDefaultAnonymousPermissionGroup().title,
|
|
65
|
+
// email: "",
|
|
66
|
+
// phone: "",
|
|
67
|
+
// password: "",
|
|
68
|
+
// type: "anonymous",
|
|
69
|
+
// }).save();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (isAdministratorExisted === 0) {
|
|
73
|
+
if (!email || !password) {
|
|
74
|
+
return Promise.reject('Invalid email or password for admin user.');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
await userManager.main.registerUser({
|
|
78
|
+
permissionGroup: getDefaultAdministratorPermissionGroup().title,
|
|
79
|
+
email: email,
|
|
80
|
+
password: password,
|
|
81
|
+
type: 'user',
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// await new authModel({
|
|
85
|
+
// permission: getDefaultAdministratorPermissionGroup().title,
|
|
86
|
+
// email: email,
|
|
87
|
+
// password: password,
|
|
88
|
+
// type: "user",
|
|
89
|
+
// }).save();
|
|
90
|
+
}
|
|
91
|
+
} catch (e) {
|
|
92
|
+
return Promise.reject(e);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import * as DataInsertion from './data_insertion';
|
|
2
|
+
import * as JWT from '../services/jwt/service';
|
|
3
|
+
import * as FileService from '../services/file/service';
|
|
4
|
+
import generateKeypair from 'keypair';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Setup options interface for initializing required services
|
|
8
|
+
* @interface SetupOptions
|
|
9
|
+
* @property {Object} [keypair] - JWT keypair configuration
|
|
10
|
+
* @property {string} keypair.private - Private key for JWT signing
|
|
11
|
+
* @property {string} keypair.public - Public key for JWT verification
|
|
12
|
+
* @property {Object} adminUser - Admin user configuration
|
|
13
|
+
* @property {string} adminUser.email - Admin user email address
|
|
14
|
+
* @property {string} adminUser.password - Admin user password
|
|
15
|
+
* @property {string} [uploadDirectory] - Directory for file uploads
|
|
16
|
+
*/
|
|
17
|
+
interface SetupOptions {
|
|
18
|
+
keypair?: {
|
|
19
|
+
private: string;
|
|
20
|
+
public: string;
|
|
21
|
+
};
|
|
22
|
+
adminUser: {
|
|
23
|
+
email: string;
|
|
24
|
+
password: string;
|
|
25
|
+
};
|
|
26
|
+
uploadDirectory?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Sets up required services for the application to run
|
|
31
|
+
* @function setup
|
|
32
|
+
* @param {SetupOptions} options - Setup configuration options
|
|
33
|
+
* @returns {Promise<void>} A promise that resolves when setup is complete
|
|
34
|
+
* @throws {Error} If admin user configuration is missing or if setup fails
|
|
35
|
+
* @description
|
|
36
|
+
* This function performs the following setup operations:
|
|
37
|
+
* 1. Configures JWT with provided or generated keypair
|
|
38
|
+
* 2. Creates default system users (admin and anonymous)
|
|
39
|
+
* 3. Configures file upload directory if specified
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* // Setup with custom keypair
|
|
44
|
+
* await setup({
|
|
45
|
+
* keypair: {
|
|
46
|
+
* private: 'your-private-key',
|
|
47
|
+
* public: 'your-public-key'
|
|
48
|
+
* },
|
|
49
|
+
* adminUser: {
|
|
50
|
+
* email: 'admin@example.com',
|
|
51
|
+
* password: 'secure-password'
|
|
52
|
+
* },
|
|
53
|
+
* uploadDirectory: './uploads'
|
|
54
|
+
* });
|
|
55
|
+
*
|
|
56
|
+
* // Setup with auto-generated keypair
|
|
57
|
+
* await setup({
|
|
58
|
+
* adminUser: {
|
|
59
|
+
* email: 'admin@example.com',
|
|
60
|
+
* password: 'secure-password'
|
|
61
|
+
* }
|
|
62
|
+
* });
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export async function setup({ keypair, adminUser, uploadDirectory }: SetupOptions): Promise<void> {
|
|
66
|
+
/**
|
|
67
|
+
* Json web Token
|
|
68
|
+
*
|
|
69
|
+
* Setup private and public keys for JWT module
|
|
70
|
+
*/
|
|
71
|
+
let keyPairToUse = keypair;
|
|
72
|
+
if (!keyPairToUse) {
|
|
73
|
+
// generate new keypair
|
|
74
|
+
keyPairToUse = generateKeypair();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
JWT.main.setKies(keyPairToUse.private, keyPairToUse.public);
|
|
78
|
+
|
|
79
|
+
if (!adminUser) {
|
|
80
|
+
throw new Error('Admin user is not supported in TypeScript version');
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Data Insertion
|
|
84
|
+
*
|
|
85
|
+
* Insert admin user
|
|
86
|
+
* for the first time
|
|
87
|
+
*/
|
|
88
|
+
await DataInsertion.createAdminUser(adminUser);
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* File Service
|
|
92
|
+
*/
|
|
93
|
+
if (uploadDirectory) {
|
|
94
|
+
FileService.main.setUploadDirectory(uploadDirectory);
|
|
95
|
+
}
|
|
96
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// Application
|
|
2
|
+
import { createRest } from './application';
|
|
3
|
+
import { Schema } from 'mongoose';
|
|
4
|
+
|
|
5
|
+
// Utilities
|
|
6
|
+
import * as paginator from './class/paginator';
|
|
7
|
+
import * as reply from './class/reply';
|
|
8
|
+
import { validator } from './class/validator';
|
|
9
|
+
import { getCollection } from './services/data_provider/service';
|
|
10
|
+
import { defineFunction } from './services/functions/service';
|
|
11
|
+
import TypeCasters from './services/data_provider/typeCasters';
|
|
12
|
+
|
|
13
|
+
import { main as userManager } from './services/user_manager/service';
|
|
14
|
+
import { main as fileService } from './services/file/service';
|
|
15
|
+
|
|
16
|
+
// Base class
|
|
17
|
+
import { CollectionDefinition, defineCollection } from './class/collection_definition';
|
|
18
|
+
import { schemas } from './class/db_schemas';
|
|
19
|
+
import DatabaseTrigger from './class/database_trigger';
|
|
20
|
+
import CmsTrigger from './class/cms_trigger';
|
|
21
|
+
import {
|
|
22
|
+
AccessDefinition,
|
|
23
|
+
Permission,
|
|
24
|
+
PermissionTypes,
|
|
25
|
+
PermissionGroup,
|
|
26
|
+
AccessTypes,
|
|
27
|
+
} from './class/security';
|
|
28
|
+
import * as middleware from './middlewares';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @description Creates a new REST API instance
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const rest = createRest();
|
|
35
|
+
* ```
|
|
36
|
+
* @returns A new REST API instance
|
|
37
|
+
*/
|
|
38
|
+
export { createRest };
|
|
39
|
+
|
|
40
|
+
export { CollectionDefinition, defineCollection };
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @description Provides predefined database schemas
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const userSchema = new Schema({
|
|
47
|
+
* name: String,
|
|
48
|
+
* avatar: Schemas.file
|
|
49
|
+
* });
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export { schemas };
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @description Mongoose Schema class for defining data models
|
|
56
|
+
*/
|
|
57
|
+
export { Schema };
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @description Handles database triggers and events
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* const trigger = new DatabaseTrigger('insert-one', (data) => {
|
|
64
|
+
* // Handle insert event
|
|
65
|
+
* });
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export { DatabaseTrigger };
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @description Handles CMS triggers and events
|
|
72
|
+
*/
|
|
73
|
+
export { CmsTrigger };
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @description Security and access control definitions
|
|
77
|
+
* @example
|
|
78
|
+
* ```typescript
|
|
79
|
+
* const permission = new Permission({
|
|
80
|
+
* type: 'user_access',
|
|
81
|
+
* read: true,
|
|
82
|
+
* write: true
|
|
83
|
+
* });
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export { AccessDefinition, Permission, PermissionTypes, PermissionGroup, AccessTypes };
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @description Defines custom functions for the API
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* defineFunction('sendEmail', async (data) => {
|
|
93
|
+
* // Send email logic
|
|
94
|
+
* });
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export { defineFunction };
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @description Type casting utilities for data transformation
|
|
101
|
+
*/
|
|
102
|
+
export { TypeCasters };
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @description Input validation utilities
|
|
106
|
+
*/
|
|
107
|
+
export { validator };
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @description Response handling utilities
|
|
111
|
+
*/
|
|
112
|
+
export { reply };
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @description Pagination utilities
|
|
116
|
+
*/
|
|
117
|
+
export { paginator };
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* @description Database collection access utilities
|
|
121
|
+
*/
|
|
122
|
+
export { getCollection };
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @description File handling utilities
|
|
126
|
+
* @example
|
|
127
|
+
* ```typescript
|
|
128
|
+
* const file = await fileService.getFile('fileId');
|
|
129
|
+
* const link = fileService.getFileLink('fileId');
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
export { fileService };
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* @description Middleware utilities
|
|
136
|
+
*/
|
|
137
|
+
export { middleware };
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @description User management utilities
|
|
141
|
+
* @example
|
|
142
|
+
* ```typescript
|
|
143
|
+
* const user = await userManager.getUserById('userId');
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
export { userManager };
|