@modular-rest/server 1.11.13 → 1.12.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/.nvmrc +1 -0
- package/.prettierrc.json +9 -0
- package/.releaserc.json +24 -0
- package/README.md +79 -94
- package/dist/application.d.ts +29 -0
- package/dist/application.js +217 -0
- package/dist/class/cms_trigger.d.ts +61 -0
- package/dist/class/cms_trigger.js +47 -0
- package/dist/class/collection_definition.d.ts +112 -0
- package/dist/class/collection_definition.js +87 -0
- package/dist/class/combinator.d.ts +43 -0
- package/dist/class/combinator.js +174 -0
- package/dist/class/database_trigger.d.ts +84 -0
- package/dist/class/database_trigger.js +64 -0
- package/dist/class/db_schemas.d.ts +25 -0
- package/dist/class/db_schemas.js +28 -0
- package/dist/class/directory.d.ts +20 -0
- package/dist/class/directory.js +87 -0
- package/dist/class/paginator.d.ts +31 -0
- package/dist/class/paginator.js +43 -0
- package/dist/class/reply.d.ts +29 -0
- package/dist/class/reply.js +44 -0
- package/dist/class/security.d.ts +186 -0
- package/dist/class/security.js +178 -0
- package/dist/class/trigger_operator.d.ts +92 -0
- package/dist/class/trigger_operator.js +99 -0
- package/dist/class/user.d.ts +81 -0
- package/dist/class/user.js +151 -0
- package/dist/class/validator.d.ts +19 -0
- package/dist/class/validator.js +101 -0
- package/dist/config.d.ts +112 -0
- package/dist/config.js +26 -0
- package/dist/defult-permissions.d.ts +2 -0
- package/dist/defult-permissions.js +31 -0
- package/dist/events.d.ts +23 -0
- package/dist/events.js +47 -0
- package/dist/helper/data_insertion.d.ts +38 -0
- package/dist/helper/data_insertion.js +110 -0
- package/dist/helper/presetup_services.d.ts +60 -0
- package/dist/helper/presetup_services.js +108 -0
- package/dist/index.d.ts +118 -0
- package/dist/index.js +79 -0
- package/dist/middlewares.d.ts +53 -0
- package/dist/middlewares.js +106 -0
- package/dist/play-test.d.ts +1 -0
- package/dist/play-test.js +9 -0
- package/dist/services/data_provider/router.d.ts +4 -0
- package/dist/services/data_provider/router.js +187 -0
- package/dist/services/data_provider/service.d.ts +131 -0
- package/dist/services/data_provider/service.js +252 -0
- package/dist/services/data_provider/typeCasters.d.ts +9 -0
- package/dist/services/data_provider/typeCasters.js +18 -0
- package/dist/services/file/db.d.ts +1 -0
- package/dist/services/file/db.js +31 -0
- package/dist/services/file/router.d.ts +4 -0
- package/dist/services/file/router.js +115 -0
- package/dist/services/file/service.d.ts +204 -0
- package/dist/services/file/service.js +341 -0
- package/dist/services/functions/router.d.ts +4 -0
- package/dist/services/functions/router.js +67 -0
- package/dist/services/functions/service.d.ts +132 -0
- package/dist/services/functions/service.js +159 -0
- package/dist/services/jwt/router.d.ts +4 -0
- package/dist/services/jwt/router.js +99 -0
- package/dist/services/jwt/service.d.ts +97 -0
- package/dist/services/jwt/service.js +135 -0
- package/dist/services/user_manager/db.d.ts +1 -0
- package/dist/services/user_manager/db.js +75 -0
- package/dist/services/user_manager/permissionManager.d.ts +19 -0
- package/dist/services/user_manager/permissionManager.js +42 -0
- package/dist/services/user_manager/router.d.ts +4 -0
- package/dist/services/user_manager/router.js +195 -0
- package/dist/services/user_manager/service.d.ts +317 -0
- package/dist/services/user_manager/service.js +628 -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 +121 -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 -82
- 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 -10
- 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,305 @@
|
|
|
1
|
+
import mongoose, { Connection, Model, PopulateOptions, Query } from 'mongoose';
|
|
2
|
+
import { AccessTypes, AccessDefinition } from '../../class/security';
|
|
3
|
+
import triggerOperator from '../../class/trigger_operator';
|
|
4
|
+
import TypeCasters from './typeCasters';
|
|
5
|
+
import { config } from '../../config';
|
|
6
|
+
import { CollectionDefinition } from '../../class/collection_definition';
|
|
7
|
+
import { User } from '../../class/user';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Service name constant
|
|
11
|
+
* @constant {string}
|
|
12
|
+
*/
|
|
13
|
+
export const name = 'dataProvider';
|
|
14
|
+
|
|
15
|
+
// Set mongoose options
|
|
16
|
+
mongoose.set('useCreateIndex', true);
|
|
17
|
+
|
|
18
|
+
// Database connections and collections storage
|
|
19
|
+
const connections: Record<string, Connection> = {};
|
|
20
|
+
const collections: Record<string, Record<string, Model<any>>> = {};
|
|
21
|
+
const permissionDefinitions: Record<string, Record<string, AccessDefinition>> = {};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* MongoDB connection options
|
|
25
|
+
* @interface MongoOption
|
|
26
|
+
* @property {string} [dbPrefix] - Prefix for database names
|
|
27
|
+
* @property {string} mongoBaseAddress - MongoDB connection URL
|
|
28
|
+
*/
|
|
29
|
+
export interface MongoOption {
|
|
30
|
+
dbPrefix?: string;
|
|
31
|
+
mongoBaseAddress: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Collection definition options
|
|
36
|
+
* @interface CollectionDefinitionOption
|
|
37
|
+
* @property {CollectionDefinition[]} list - List of collection definitions
|
|
38
|
+
* @property {MongoOption} mongoOption - MongoDB connection options
|
|
39
|
+
*/
|
|
40
|
+
interface CollectionDefinitionListOption {
|
|
41
|
+
list: CollectionDefinition[];
|
|
42
|
+
mongoOption: MongoOption;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Connects to a database and sets up collections based on collection definitions
|
|
47
|
+
* @function connectToDatabaseByCollectionDefinitionList
|
|
48
|
+
* @param {string} dbName - Name of the database to connect to
|
|
49
|
+
* @param {CollectionDefinition[]} [collectionDefinitionList=[]] - List of collection definitions
|
|
50
|
+
* @param {MongoOption} mongoOption - MongoDB connection options
|
|
51
|
+
* @returns {Promise<void>} A promise that resolves when the connection is established
|
|
52
|
+
* @throws {Error} If triggers are not properly configured
|
|
53
|
+
* @private
|
|
54
|
+
*/
|
|
55
|
+
function connectToDatabaseByCollectionDefinitionList(
|
|
56
|
+
dbName: string,
|
|
57
|
+
collectionDefinitionList: CollectionDefinition[] = [],
|
|
58
|
+
mongoOption: MongoOption
|
|
59
|
+
): Promise<void> {
|
|
60
|
+
return new Promise((done, reject) => {
|
|
61
|
+
// Create db connection
|
|
62
|
+
const fullDbName = (mongoOption.dbPrefix || '') + dbName;
|
|
63
|
+
const connectionString = mongoOption.mongoBaseAddress;
|
|
64
|
+
|
|
65
|
+
console.info(`- Connecting to database: ${fullDbName}`);
|
|
66
|
+
|
|
67
|
+
const connection = mongoose.createConnection(connectionString, {
|
|
68
|
+
useUnifiedTopology: true,
|
|
69
|
+
useNewUrlParser: true,
|
|
70
|
+
dbName: fullDbName,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Store connection
|
|
74
|
+
connections[dbName] = connection;
|
|
75
|
+
|
|
76
|
+
// add db models from schemas
|
|
77
|
+
collectionDefinitionList.forEach(collectionDefinition => {
|
|
78
|
+
const collection = collectionDefinition.collection;
|
|
79
|
+
const schema = collectionDefinition.schema;
|
|
80
|
+
|
|
81
|
+
if (collections[dbName] == undefined) collections[dbName] = {};
|
|
82
|
+
|
|
83
|
+
if (permissionDefinitions[dbName] == undefined) permissionDefinitions[dbName] = {};
|
|
84
|
+
|
|
85
|
+
// create model from schema
|
|
86
|
+
// and store in on global collection object
|
|
87
|
+
const model = connection.model(collection, schema);
|
|
88
|
+
collections[dbName][collection] = model;
|
|
89
|
+
|
|
90
|
+
// define Access Definition from component permissions
|
|
91
|
+
// and store it on global access definition object
|
|
92
|
+
permissionDefinitions[dbName][collection] = new AccessDefinition({
|
|
93
|
+
database: dbName,
|
|
94
|
+
collection: collection,
|
|
95
|
+
permissionList: collectionDefinition.permissions,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// add trigger
|
|
99
|
+
if (collectionDefinition.triggers != undefined) {
|
|
100
|
+
if (!Array.isArray(collectionDefinition.triggers)) {
|
|
101
|
+
throw new Error('Triggers must be an array');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
collectionDefinition.triggers.forEach(trigger => {
|
|
105
|
+
triggerOperator.addTrigger({
|
|
106
|
+
...trigger,
|
|
107
|
+
database: collectionDefinition.database,
|
|
108
|
+
collection: collectionDefinition.collection,
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
connection.on('connected', () => {
|
|
115
|
+
console.info(`- ${fullDbName} database has been connected`);
|
|
116
|
+
done();
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Adds collection definitions and connects to their respective databases
|
|
123
|
+
* @function addCollectionDefinitionByList
|
|
124
|
+
* @param {CollectionDefinitionListOption} options - Collection definition options
|
|
125
|
+
* @returns {Promise<void>} A promise that resolves when all collections are set up
|
|
126
|
+
* @example
|
|
127
|
+
* ```typescript
|
|
128
|
+
* await addCollectionDefinitionByList({
|
|
129
|
+
* list: [
|
|
130
|
+
* new CollectionDefinition({
|
|
131
|
+
* database: 'myapp',
|
|
132
|
+
* collection: 'users',
|
|
133
|
+
* schema: userSchema,
|
|
134
|
+
* permissions: [new Permission({ type: 'user_access', read: true })]
|
|
135
|
+
* })
|
|
136
|
+
* ],
|
|
137
|
+
* mongoOption: {
|
|
138
|
+
* mongoBaseAddress: 'mongodb://localhost:27017',
|
|
139
|
+
* dbPrefix: 'myapp_'
|
|
140
|
+
* }
|
|
141
|
+
* });
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
export async function addCollectionDefinitionByList({
|
|
145
|
+
list,
|
|
146
|
+
mongoOption,
|
|
147
|
+
}: CollectionDefinitionListOption): Promise<void> {
|
|
148
|
+
// Group collection definitions by database
|
|
149
|
+
const dbGroups: Record<string, CollectionDefinition[]> = {};
|
|
150
|
+
list.forEach(collectionDefinition => {
|
|
151
|
+
if (!dbGroups[collectionDefinition.database]) {
|
|
152
|
+
dbGroups[collectionDefinition.database] = [];
|
|
153
|
+
}
|
|
154
|
+
dbGroups[collectionDefinition.database].push(collectionDefinition);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Connect to each database
|
|
158
|
+
const connectionPromises = Object.entries(dbGroups).map(([dbName, collectionDefinitionList]) =>
|
|
159
|
+
connectToDatabaseByCollectionDefinitionList(dbName, collectionDefinitionList, mongoOption)
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
await Promise.all(connectionPromises);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Gets a Mongoose model for a specific collection
|
|
167
|
+
* @function getCollection
|
|
168
|
+
* @param {string} db - Database name
|
|
169
|
+
* @param {string} collection - Collection name
|
|
170
|
+
* @returns {Model<T>} Mongoose model for the collection
|
|
171
|
+
* @throws {Error} If the collection doesn't exist
|
|
172
|
+
* @example
|
|
173
|
+
* ```typescript
|
|
174
|
+
* const userModel = getCollection('myapp', 'users');
|
|
175
|
+
* const users = await userModel.find();
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
export function getCollection<T>(db: string, collection: string): Model<T> {
|
|
179
|
+
if (!collections[db] || !collections[db][collection]) {
|
|
180
|
+
throw new Error(`Collection ${collection} not found in database ${db}`);
|
|
181
|
+
}
|
|
182
|
+
return collections[db][collection];
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Gets the permission list for a specific operation on a collection
|
|
187
|
+
* @function _getPermissionList
|
|
188
|
+
* @param {string} db - Database name
|
|
189
|
+
* @param {string} collection - Collection name
|
|
190
|
+
* @param {string} operationType - Type of operation (read/write)
|
|
191
|
+
* @returns {any[]} List of permissions
|
|
192
|
+
* @private
|
|
193
|
+
*/
|
|
194
|
+
function _getPermissionList(db: string, collection: string, operationType: string): any[] {
|
|
195
|
+
if (!permissionDefinitions[db] || !permissionDefinitions[db][collection]) {
|
|
196
|
+
return [];
|
|
197
|
+
}
|
|
198
|
+
return permissionDefinitions[db][collection].permissionList;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Checks if a user has access to perform an operation on a collection
|
|
203
|
+
* @function checkAccess
|
|
204
|
+
* @param {string} db - Database name
|
|
205
|
+
* @param {string} collection - Collection name
|
|
206
|
+
* @param {string} operationType - Type of operation (read/write)
|
|
207
|
+
* @param {Record<string, any>} queryOrDoc - Query or document being accessed
|
|
208
|
+
* @param {User} user - User performing the operation
|
|
209
|
+
* @returns {boolean} Whether the user has access
|
|
210
|
+
* @example
|
|
211
|
+
* ```typescript
|
|
212
|
+
* const hasAccess = checkAccess('myapp', 'users', 'read', {}, currentUser);
|
|
213
|
+
* if (hasAccess) {
|
|
214
|
+
* const users = await getCollection('myapp', 'users').find();
|
|
215
|
+
* }
|
|
216
|
+
* ```
|
|
217
|
+
*/
|
|
218
|
+
export function checkAccess(
|
|
219
|
+
db: string,
|
|
220
|
+
collection: string,
|
|
221
|
+
operationType: string,
|
|
222
|
+
queryOrDoc: Record<string, any>,
|
|
223
|
+
user: User
|
|
224
|
+
): boolean {
|
|
225
|
+
const permissionList = _getPermissionList(db, collection, operationType);
|
|
226
|
+
return permissionList.some(permission => {
|
|
227
|
+
if (permission.type === 'god_access') return true;
|
|
228
|
+
if (permission.type === 'anonymous_access' && user.type === 'anonymous') return true;
|
|
229
|
+
if (permission.type === 'user_access' && user.type === 'user') return true;
|
|
230
|
+
return false;
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Converts a string ID to a MongoDB ObjectId
|
|
236
|
+
* @function getAsID
|
|
237
|
+
* @param {string} strId - String ID to convert
|
|
238
|
+
* @returns {mongoose.Types.ObjectId | undefined} MongoDB ObjectId or undefined if invalid
|
|
239
|
+
* @example
|
|
240
|
+
* ```typescript
|
|
241
|
+
* const id = getAsID('507f1f77bcf86cd799439011');
|
|
242
|
+
* if (id) {
|
|
243
|
+
* const doc = await collection.findById(id);
|
|
244
|
+
* }
|
|
245
|
+
* ```
|
|
246
|
+
*/
|
|
247
|
+
export function getAsID(strId: string): mongoose.Types.ObjectId | undefined {
|
|
248
|
+
try {
|
|
249
|
+
return mongoose.Types.ObjectId(strId);
|
|
250
|
+
} catch (e) {
|
|
251
|
+
return undefined;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Applies populate options to a Mongoose query
|
|
257
|
+
* @function performPopulateToQueryObject
|
|
258
|
+
* @param {Query<T, any>} queryObj - Mongoose query object
|
|
259
|
+
* @param {PopulateOptions[]} [popArr=[]] - Array of populate options
|
|
260
|
+
* @returns {Query<T, any>} Query with populate options applied
|
|
261
|
+
* @example
|
|
262
|
+
* ```typescript
|
|
263
|
+
* const query = collection.find();
|
|
264
|
+
* const populatedQuery = performPopulateToQueryObject(query, [
|
|
265
|
+
* { path: 'author', select: 'name email' }
|
|
266
|
+
* ]);
|
|
267
|
+
* ```
|
|
268
|
+
*/
|
|
269
|
+
export function performPopulateToQueryObject<T = any>(
|
|
270
|
+
queryObj: Query<T, any>,
|
|
271
|
+
popArr: PopulateOptions[] = []
|
|
272
|
+
): Query<T, any> {
|
|
273
|
+
popArr.forEach(pop => {
|
|
274
|
+
queryObj.populate(pop);
|
|
275
|
+
});
|
|
276
|
+
return queryObj;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Applies additional options to a Mongoose query
|
|
281
|
+
* @function performAdditionalOptionsToQueryObject
|
|
282
|
+
* @param {Query<T, any>} queryObj - Mongoose query object
|
|
283
|
+
* @param {Record<string, any>} options - Additional query options
|
|
284
|
+
* @returns {Query<T, any>} Query with additional options applied
|
|
285
|
+
* @example
|
|
286
|
+
* ```typescript
|
|
287
|
+
* const query = collection.find();
|
|
288
|
+
* const queryWithOptions = performAdditionalOptionsToQueryObject(query, {
|
|
289
|
+
* sort: { createdAt: -1 },
|
|
290
|
+
* limit: 10
|
|
291
|
+
* });
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
export function performAdditionalOptionsToQueryObject<T = any>(
|
|
295
|
+
queryObj: Query<T, any>,
|
|
296
|
+
options: Record<string, any>
|
|
297
|
+
): Query<T, any> {
|
|
298
|
+
Object.entries(options).forEach(([key, value]) => {
|
|
299
|
+
// @ts-ignore
|
|
300
|
+
queryObj[key](value);
|
|
301
|
+
});
|
|
302
|
+
return queryObj;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export { TypeCasters };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import mongoose from 'mongoose';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Type casting functions for MongoDB types
|
|
5
|
+
*/
|
|
6
|
+
const TypeCasters = {
|
|
7
|
+
ObjectId: mongoose.Types.ObjectId,
|
|
8
|
+
Date: (dateValue: string | Date): Date => {
|
|
9
|
+
const strDate = dateValue.toString();
|
|
10
|
+
const mongoDateFormateInString = new Date(strDate).toISOString().split('T')[0];
|
|
11
|
+
return new Date(mongoDateFormateInString);
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default TypeCasters;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import mongoose from 'mongoose';
|
|
2
|
+
import schemas from '../../class/db_schemas';
|
|
3
|
+
import { CollectionDefinition } from '../../class/collection_definition';
|
|
4
|
+
import { Permission, PermissionTypes } from '../../class/security';
|
|
5
|
+
import { config } from '../../config';
|
|
6
|
+
import { Schema } from 'mongoose';
|
|
7
|
+
|
|
8
|
+
module.exports = [
|
|
9
|
+
new CollectionDefinition({
|
|
10
|
+
database: 'cms',
|
|
11
|
+
collection: 'file',
|
|
12
|
+
schema: schemas.file as unknown as Schema,
|
|
13
|
+
permissions: [
|
|
14
|
+
new Permission({
|
|
15
|
+
accessType: PermissionTypes.upload_file_access,
|
|
16
|
+
read: true,
|
|
17
|
+
write: true,
|
|
18
|
+
onlyOwnData: false,
|
|
19
|
+
}),
|
|
20
|
+
new Permission({
|
|
21
|
+
accessType: PermissionTypes.remove_file_access,
|
|
22
|
+
read: true,
|
|
23
|
+
write: true,
|
|
24
|
+
onlyOwnData: false,
|
|
25
|
+
}),
|
|
26
|
+
],
|
|
27
|
+
triggers: config.fileTriggers || [],
|
|
28
|
+
}),
|
|
29
|
+
];
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import Router from 'koa-router';
|
|
2
|
+
import { validateObject } from '../../class/validator';
|
|
3
|
+
import { create as reply } from '../../class/reply';
|
|
4
|
+
import { Context, Next } from 'koa';
|
|
5
|
+
import { AccessTypes } from './../../class/security';
|
|
6
|
+
import * as DataService from './../data_provider/service';
|
|
7
|
+
import { main as service } from './service';
|
|
8
|
+
import * as middleware from '../../middlewares';
|
|
9
|
+
|
|
10
|
+
const name = 'file';
|
|
11
|
+
const fileRouter = new Router();
|
|
12
|
+
|
|
13
|
+
fileRouter.use('/', middleware.auth, async (ctx: Context, next: Next) => {
|
|
14
|
+
await next();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
fileRouter.post('/', async (ctx: Context) => {
|
|
18
|
+
const body = ctx.request.body;
|
|
19
|
+
|
|
20
|
+
// validate result
|
|
21
|
+
const bodyValidate = validateObject(body, 'tag');
|
|
22
|
+
|
|
23
|
+
// fields validation
|
|
24
|
+
if (!bodyValidate.isValid) {
|
|
25
|
+
ctx.status = 412;
|
|
26
|
+
ctx.body = reply('e', { e: bodyValidate.requires });
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Access validation
|
|
31
|
+
const hasAccess = DataService.checkAccess('cms', 'file', AccessTypes.write, body, ctx.state.user);
|
|
32
|
+
if (!hasAccess) {
|
|
33
|
+
ctx.throw(403, 'access denied');
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const files = ctx.request.files;
|
|
38
|
+
const file = files && files.file;
|
|
39
|
+
let result;
|
|
40
|
+
|
|
41
|
+
if (!file) {
|
|
42
|
+
ctx.status = 412;
|
|
43
|
+
result = reply('f', { message: 'file field required' });
|
|
44
|
+
} else {
|
|
45
|
+
await service
|
|
46
|
+
.storeFile({
|
|
47
|
+
file: file as any,
|
|
48
|
+
ownerId: ctx.state.user.id,
|
|
49
|
+
tag: body.tag,
|
|
50
|
+
})
|
|
51
|
+
.then(file => {
|
|
52
|
+
result = reply('s', { file });
|
|
53
|
+
})
|
|
54
|
+
.catch(error => {
|
|
55
|
+
ctx.status = 412;
|
|
56
|
+
result = reply('e', error);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
ctx.body = result;
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
fileRouter.delete('/', async (ctx: Context) => {
|
|
64
|
+
const body = ctx.request.query;
|
|
65
|
+
// validate
|
|
66
|
+
const bodyValidate = validateObject(body as Record<string, any>, 'id');
|
|
67
|
+
|
|
68
|
+
let result;
|
|
69
|
+
|
|
70
|
+
if (!bodyValidate.isValid) {
|
|
71
|
+
ctx.status = 412;
|
|
72
|
+
result = reply('f', { message: 'some fields required.', error: bodyValidate.requires });
|
|
73
|
+
} else {
|
|
74
|
+
await service
|
|
75
|
+
.removeFile(body.id as string)
|
|
76
|
+
.then(() => {
|
|
77
|
+
result = reply('s');
|
|
78
|
+
})
|
|
79
|
+
.catch(e => {
|
|
80
|
+
ctx.status = 412;
|
|
81
|
+
result = reply('e', { error: e });
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
ctx.body = result;
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
export { name, fileRouter as main };
|