@modular-rest/server 1.13.4 → 1.14.0
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/dist/application.js +1 -1
- package/dist/services/data_provider/router.js +224 -0
- package/dist/services/data_provider/service.d.ts +2 -1
- package/dist/services/data_provider/service.js +2 -1
- package/package.json +1 -1
- package/src/application.ts +1 -1
- package/src/services/data_provider/router.ts +292 -0
- package/src/services/data_provider/service.ts +2 -1
package/dist/application.js
CHANGED
|
@@ -107,7 +107,7 @@ async function createRest(options) {
|
|
|
107
107
|
if (config_1.config.staticPath) {
|
|
108
108
|
const defaultStaticPath = config_1.config.staticPath.actualPath || '';
|
|
109
109
|
const defaultStaticRootPath = config_1.config.staticPath.path || '/assets';
|
|
110
|
-
const staticOptions = { ...config_1.config.staticPath };
|
|
110
|
+
const staticOptions = { ...config_1.config.staticPath, defer: true };
|
|
111
111
|
delete staticOptions.actualPath;
|
|
112
112
|
delete staticOptions.path;
|
|
113
113
|
app.use((0, koa_mount_1.default)(defaultStaticRootPath, (0, koa_static_1.default)(defaultStaticPath, staticOptions)));
|
|
@@ -111,6 +111,11 @@ dataProvider.post('/find', async (ctx) => {
|
|
|
111
111
|
await queryRequest
|
|
112
112
|
.exec()
|
|
113
113
|
.then(async (docs) => {
|
|
114
|
+
// Call trigger
|
|
115
|
+
service.triggers.call('find', body.database, body.collection, {
|
|
116
|
+
query: body.query,
|
|
117
|
+
queryResult: docs,
|
|
118
|
+
});
|
|
114
119
|
ctx.body = { data: docs };
|
|
115
120
|
})
|
|
116
121
|
.catch(err => {
|
|
@@ -152,6 +157,11 @@ dataProvider.post('/find-one', async (ctx) => {
|
|
|
152
157
|
await queryRequest
|
|
153
158
|
.exec()
|
|
154
159
|
.then(async (doc) => {
|
|
160
|
+
// Call trigger
|
|
161
|
+
service.triggers.call('find-one', body.database, body.collection, {
|
|
162
|
+
query: body.query,
|
|
163
|
+
queryResult: doc,
|
|
164
|
+
});
|
|
155
165
|
ctx.body = { data: doc };
|
|
156
166
|
})
|
|
157
167
|
.catch(err => {
|
|
@@ -177,7 +187,13 @@ dataProvider.post('/count', async (ctx) => {
|
|
|
177
187
|
}
|
|
178
188
|
await collection
|
|
179
189
|
.countDocuments(body.query)
|
|
190
|
+
.exec()
|
|
180
191
|
.then(count => {
|
|
192
|
+
// Call trigger
|
|
193
|
+
service.triggers.call('count', body.database, body.collection, {
|
|
194
|
+
query: body.query,
|
|
195
|
+
queryResult: count,
|
|
196
|
+
});
|
|
181
197
|
ctx.body = { data: count };
|
|
182
198
|
})
|
|
183
199
|
.catch(err => {
|
|
@@ -185,3 +201,211 @@ dataProvider.post('/count', async (ctx) => {
|
|
|
185
201
|
ctx.body = err.message;
|
|
186
202
|
});
|
|
187
203
|
});
|
|
204
|
+
dataProvider.post('/update-one', async (ctx) => {
|
|
205
|
+
const body = ctx.request.body;
|
|
206
|
+
const bodyValidate = (0, validator_1.validateObject)(body, 'database collection query update');
|
|
207
|
+
// fields validation
|
|
208
|
+
if (!bodyValidate.isValid) {
|
|
209
|
+
ctx.throw(412, JSON.stringify((0, reply_1.create)('e', { error: bodyValidate.requires })));
|
|
210
|
+
}
|
|
211
|
+
// access validation
|
|
212
|
+
const hasAccess = service.checkAccess(body.database, body.collection, security_1.AccessTypes.write, body.query, ctx.state.user);
|
|
213
|
+
if (!hasAccess)
|
|
214
|
+
ctx.throw(403, 'access denied');
|
|
215
|
+
// collection validation
|
|
216
|
+
const collection = service.getCollection(body.database, body.collection);
|
|
217
|
+
if (collection == null) {
|
|
218
|
+
ctx.throw(412, JSON.stringify((0, reply_1.create)('e', { error: 'wrong database or collection' })));
|
|
219
|
+
}
|
|
220
|
+
// get removing doc as output for triggers
|
|
221
|
+
const output = await collection.findOne(body.query).exec().then();
|
|
222
|
+
// operate on db
|
|
223
|
+
await collection
|
|
224
|
+
.updateOne(body.query, body.update, body.options)
|
|
225
|
+
.exec()
|
|
226
|
+
.then(writeOpResult => {
|
|
227
|
+
// Call trigger
|
|
228
|
+
service.triggers.call('update-one', body.database, body.collection, {
|
|
229
|
+
query: body.query,
|
|
230
|
+
queryResult: writeOpResult,
|
|
231
|
+
});
|
|
232
|
+
ctx.body = { data: writeOpResult };
|
|
233
|
+
})
|
|
234
|
+
.catch(err => {
|
|
235
|
+
ctx.status = err.status || 500;
|
|
236
|
+
ctx.body = err.message;
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
dataProvider.post('/insert-one', async (ctx) => {
|
|
240
|
+
const body = ctx.request.body;
|
|
241
|
+
const bodyValidate = (0, validator_1.validateObject)(body, 'database collection doc');
|
|
242
|
+
// fields validation
|
|
243
|
+
if (!bodyValidate.isValid) {
|
|
244
|
+
ctx.throw(412, JSON.stringify((0, reply_1.create)('e', { error: bodyValidate.requires })));
|
|
245
|
+
}
|
|
246
|
+
// access validation
|
|
247
|
+
const hasAccess = service.checkAccess(body.database, body.collection, security_1.AccessTypes.write, body.doc, ctx.state.user);
|
|
248
|
+
if (!hasAccess) {
|
|
249
|
+
console.log(body);
|
|
250
|
+
console.log(ctx.state.user.permission);
|
|
251
|
+
ctx.throw(403, 'access denied');
|
|
252
|
+
}
|
|
253
|
+
// collection validation
|
|
254
|
+
const collection = service.getCollection(body.database, body.collection);
|
|
255
|
+
if (collection == null) {
|
|
256
|
+
ctx.throw(412, JSON.stringify((0, reply_1.create)('e', { error: 'wrong database or collection' })));
|
|
257
|
+
}
|
|
258
|
+
// operate on db
|
|
259
|
+
await new collection(body.doc)
|
|
260
|
+
.save()
|
|
261
|
+
.then(async (newDoc) => {
|
|
262
|
+
// Call trigger
|
|
263
|
+
service.triggers.call('insert-one', body.database, body.collection, {
|
|
264
|
+
query: body.query,
|
|
265
|
+
queryResult: newDoc,
|
|
266
|
+
});
|
|
267
|
+
ctx.body = { data: newDoc };
|
|
268
|
+
})
|
|
269
|
+
.catch(err => {
|
|
270
|
+
ctx.status = err.status || 500;
|
|
271
|
+
ctx.body = err.message;
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
dataProvider.post('/remove-one', async (ctx) => {
|
|
275
|
+
const body = ctx.request.body;
|
|
276
|
+
const bodyValidate = (0, validator_1.validateObject)(body, 'database collection query');
|
|
277
|
+
// fields validation
|
|
278
|
+
if (!bodyValidate.isValid) {
|
|
279
|
+
ctx.throw(412, JSON.stringify((0, reply_1.create)('e', { error: bodyValidate.requires })));
|
|
280
|
+
}
|
|
281
|
+
// access validation
|
|
282
|
+
const hasAccess = service.checkAccess(body.database, body.collection, security_1.AccessTypes.write, body.query, ctx.state.user);
|
|
283
|
+
if (!hasAccess)
|
|
284
|
+
ctx.throw(403, 'access denied');
|
|
285
|
+
// collection validation
|
|
286
|
+
const collection = service.getCollection(body.database, body.collection);
|
|
287
|
+
if (collection == null) {
|
|
288
|
+
ctx.throw(412, JSON.stringify((0, reply_1.create)('e', { error: 'wrong database or collection' })));
|
|
289
|
+
}
|
|
290
|
+
// get removing doc as output for triggers
|
|
291
|
+
const output = await collection.findOne(body.query).exec().then();
|
|
292
|
+
// operate on db
|
|
293
|
+
await collection
|
|
294
|
+
.deleteOne(body.query)
|
|
295
|
+
.exec()
|
|
296
|
+
.then(async (result) => {
|
|
297
|
+
// Call trigger
|
|
298
|
+
service.triggers.call('remove-one', body.database, body.collection, {
|
|
299
|
+
query: body.query,
|
|
300
|
+
queryResult: result,
|
|
301
|
+
});
|
|
302
|
+
ctx.body = { data: result };
|
|
303
|
+
})
|
|
304
|
+
.catch((err) => {
|
|
305
|
+
ctx.status = err.status || 500;
|
|
306
|
+
ctx.body = err.message;
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
dataProvider.post('/aggregate', async (ctx) => {
|
|
310
|
+
const body = ctx.request.body;
|
|
311
|
+
const bodyValidate = (0, validator_1.validateObject)(body, 'database collection accessQuery');
|
|
312
|
+
// fields validation
|
|
313
|
+
if (!bodyValidate.isValid) {
|
|
314
|
+
ctx.throw(412, JSON.stringify((0, reply_1.create)('e', { error: bodyValidate.requires })));
|
|
315
|
+
}
|
|
316
|
+
// access validation
|
|
317
|
+
const hasAccess = service.checkAccess(body.database, body.collection, security_1.AccessTypes.read, body.accessQuery, ctx.state.user);
|
|
318
|
+
if (!hasAccess)
|
|
319
|
+
ctx.throw(403, 'access denied');
|
|
320
|
+
// collection validation
|
|
321
|
+
const collection = service.getCollection(body.database, body.collection);
|
|
322
|
+
if (collection == null) {
|
|
323
|
+
ctx.throw(412, JSON.stringify((0, reply_1.create)('e', { error: 'wrong database or collection' })));
|
|
324
|
+
}
|
|
325
|
+
// operate on db
|
|
326
|
+
await collection
|
|
327
|
+
.aggregate(body.pipelines)
|
|
328
|
+
.exec()
|
|
329
|
+
.then(async (result) => {
|
|
330
|
+
// Call trigger
|
|
331
|
+
service.triggers.call('aggregate', body.database, body.collection, {
|
|
332
|
+
query: body.query,
|
|
333
|
+
queryResult: result,
|
|
334
|
+
});
|
|
335
|
+
ctx.body = { data: result };
|
|
336
|
+
})
|
|
337
|
+
.catch((err) => {
|
|
338
|
+
ctx.status = err.status || 500;
|
|
339
|
+
ctx.body = err.message;
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
dataProvider.post('/findByIds', async (ctx, next) => {
|
|
343
|
+
const body = ctx.request.body;
|
|
344
|
+
const bodyValidate = (0, validator_1.validateObject)(body, 'database collection ids');
|
|
345
|
+
// fields validation
|
|
346
|
+
if (!bodyValidate.isValid) {
|
|
347
|
+
ctx.throw(412, JSON.stringify((0, reply_1.create)('e', { error: bodyValidate.requires })));
|
|
348
|
+
}
|
|
349
|
+
// access validation
|
|
350
|
+
const hasAccess = service.checkAccess(body.database, body.collection, security_1.AccessTypes.read, body.accessQuery || {}, ctx.state.user);
|
|
351
|
+
if (!hasAccess)
|
|
352
|
+
ctx.throw(403, 'access denied');
|
|
353
|
+
// collection validation
|
|
354
|
+
const collection = service.getCollection(body.database, body.collection);
|
|
355
|
+
if (collection == null) {
|
|
356
|
+
ctx.throw(412, JSON.stringify((0, reply_1.create)('e', { error: 'wrong database or collection' })));
|
|
357
|
+
}
|
|
358
|
+
const or = [];
|
|
359
|
+
try {
|
|
360
|
+
body.ids.forEach((id) => {
|
|
361
|
+
const castedid = service.getAsID(id);
|
|
362
|
+
or.push({ _id: castedid });
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
catch (e) {
|
|
366
|
+
console.log('ids.forEach', e);
|
|
367
|
+
}
|
|
368
|
+
const pipelines = [
|
|
369
|
+
{
|
|
370
|
+
$match: { $or: or },
|
|
371
|
+
},
|
|
372
|
+
// {
|
|
373
|
+
// $sort: body.sort || { _id: 1 }
|
|
374
|
+
// }
|
|
375
|
+
];
|
|
376
|
+
// operate on db
|
|
377
|
+
await collection
|
|
378
|
+
.aggregate(pipelines)
|
|
379
|
+
.exec()
|
|
380
|
+
.then(async (result) => {
|
|
381
|
+
ctx.state = { data: result };
|
|
382
|
+
await next();
|
|
383
|
+
})
|
|
384
|
+
.catch((err) => {
|
|
385
|
+
ctx.status = err.status || 500;
|
|
386
|
+
ctx.body = err.message;
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
// Final middleware for converting mongoose documents to JSON
|
|
390
|
+
dataProvider.use('/', async (ctx, next) => {
|
|
391
|
+
// this event is responsible to covert whole mongoose doc to json form
|
|
392
|
+
// including getters, public properties
|
|
393
|
+
// each mongoose doc must have a "toJson" method being defined on its own Schema.
|
|
394
|
+
const state = ctx.state;
|
|
395
|
+
// let result;
|
|
396
|
+
// // array
|
|
397
|
+
// if(!isNaN(state.length)) {
|
|
398
|
+
// result = [];
|
|
399
|
+
// for (let index = 0; index < state.length; index++) {
|
|
400
|
+
// const element = state[index];
|
|
401
|
+
// if(element.hasOwnProperty('toJson'))
|
|
402
|
+
// result.push(element.toJson());
|
|
403
|
+
// else result.push(element);
|
|
404
|
+
// }
|
|
405
|
+
// }
|
|
406
|
+
// // object
|
|
407
|
+
// else {
|
|
408
|
+
// result = state.toJson();
|
|
409
|
+
// }
|
|
410
|
+
ctx.body = state;
|
|
411
|
+
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import mongoose, { Model, PopulateOptions, Query } from 'mongoose';
|
|
2
|
+
import triggerOperator from '../../class/trigger_operator';
|
|
2
3
|
import TypeCasters from './typeCasters';
|
|
3
4
|
import { CollectionDefinition } from '../../class/collection_definition';
|
|
4
5
|
import { User } from '../../class/user';
|
|
@@ -128,4 +129,4 @@ export declare function performPopulateToQueryObject<T = any>(queryObj: Query<T,
|
|
|
128
129
|
* ```
|
|
129
130
|
*/
|
|
130
131
|
export declare function performAdditionalOptionsToQueryObject<T = any>(queryObj: Query<T, any>, options: Record<string, any>): Query<T, any>;
|
|
131
|
-
export { TypeCasters };
|
|
132
|
+
export { triggerOperator as triggers, TypeCasters };
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.TypeCasters = exports.name = void 0;
|
|
6
|
+
exports.TypeCasters = exports.triggers = exports.name = void 0;
|
|
7
7
|
exports.addCollectionDefinitionByList = addCollectionDefinitionByList;
|
|
8
8
|
exports.getCollection = getCollection;
|
|
9
9
|
exports.checkAccess = checkAccess;
|
|
@@ -13,6 +13,7 @@ exports.performAdditionalOptionsToQueryObject = performAdditionalOptionsToQueryO
|
|
|
13
13
|
const mongoose_1 = __importDefault(require("mongoose"));
|
|
14
14
|
const security_1 = require("../../class/security");
|
|
15
15
|
const trigger_operator_1 = __importDefault(require("../../class/trigger_operator"));
|
|
16
|
+
exports.triggers = trigger_operator_1.default;
|
|
16
17
|
const typeCasters_1 = __importDefault(require("./typeCasters"));
|
|
17
18
|
exports.TypeCasters = typeCasters_1.default;
|
|
18
19
|
/**
|
package/package.json
CHANGED
package/src/application.ts
CHANGED
|
@@ -78,7 +78,7 @@ export async function createRest(options: RestOptions): Promise<{ app: Koa; serv
|
|
|
78
78
|
const defaultStaticPath = config.staticPath.actualPath || '';
|
|
79
79
|
const defaultStaticRootPath = config.staticPath.path || '/assets';
|
|
80
80
|
|
|
81
|
-
const staticOptions: Partial<StaticPathOptions> = { ...config.staticPath };
|
|
81
|
+
const staticOptions: Partial<StaticPathOptions> = { ...config.staticPath, defer: true };
|
|
82
82
|
|
|
83
83
|
delete staticOptions.actualPath;
|
|
84
84
|
delete staticOptions.path;
|
|
@@ -6,6 +6,7 @@ import nestedProperty from 'nested-property';
|
|
|
6
6
|
import * as service from './service';
|
|
7
7
|
import * as middleware from '../../middlewares';
|
|
8
8
|
import { Context, Next } from 'koa';
|
|
9
|
+
import mongoose from 'mongoose';
|
|
9
10
|
|
|
10
11
|
const name = 'data-provider';
|
|
11
12
|
|
|
@@ -91,6 +92,12 @@ dataProvider.post('/find', async (ctx: Context) => {
|
|
|
91
92
|
await queryRequest
|
|
92
93
|
.exec()
|
|
93
94
|
.then(async docs => {
|
|
95
|
+
// Call trigger
|
|
96
|
+
service.triggers.call('find', body.database, body.collection, {
|
|
97
|
+
query: body.query,
|
|
98
|
+
queryResult: docs,
|
|
99
|
+
});
|
|
100
|
+
|
|
94
101
|
ctx.body = { data: docs };
|
|
95
102
|
})
|
|
96
103
|
.catch(err => {
|
|
@@ -144,6 +151,12 @@ dataProvider.post('/find-one', async (ctx: Context) => {
|
|
|
144
151
|
await queryRequest
|
|
145
152
|
.exec()
|
|
146
153
|
.then(async doc => {
|
|
154
|
+
// Call trigger
|
|
155
|
+
service.triggers.call('find-one', body.database, body.collection, {
|
|
156
|
+
query: body.query,
|
|
157
|
+
queryResult: doc,
|
|
158
|
+
});
|
|
159
|
+
|
|
147
160
|
ctx.body = { data: doc };
|
|
148
161
|
})
|
|
149
162
|
.catch(err => {
|
|
@@ -179,7 +192,14 @@ dataProvider.post('/count', async (ctx: Context) => {
|
|
|
179
192
|
|
|
180
193
|
await collection
|
|
181
194
|
.countDocuments(body.query)
|
|
195
|
+
.exec()
|
|
182
196
|
.then(count => {
|
|
197
|
+
// Call trigger
|
|
198
|
+
service.triggers.call('count', body.database, body.collection, {
|
|
199
|
+
query: body.query,
|
|
200
|
+
queryResult: count,
|
|
201
|
+
});
|
|
202
|
+
|
|
183
203
|
ctx.body = { data: count };
|
|
184
204
|
})
|
|
185
205
|
.catch(err => {
|
|
@@ -188,4 +208,276 @@ dataProvider.post('/count', async (ctx: Context) => {
|
|
|
188
208
|
});
|
|
189
209
|
});
|
|
190
210
|
|
|
211
|
+
dataProvider.post('/update-one', async (ctx: Context) => {
|
|
212
|
+
const body = ctx.request.body;
|
|
213
|
+
const bodyValidate = validateObject(body, 'database collection query update');
|
|
214
|
+
|
|
215
|
+
// fields validation
|
|
216
|
+
if (!bodyValidate.isValid) {
|
|
217
|
+
ctx.throw(412, JSON.stringify(reply('e', { error: bodyValidate.requires })));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// access validation
|
|
221
|
+
const hasAccess = service.checkAccess(
|
|
222
|
+
body.database,
|
|
223
|
+
body.collection,
|
|
224
|
+
AccessTypes.write,
|
|
225
|
+
body.query,
|
|
226
|
+
ctx.state.user
|
|
227
|
+
);
|
|
228
|
+
if (!hasAccess) ctx.throw(403, 'access denied');
|
|
229
|
+
|
|
230
|
+
// collection validation
|
|
231
|
+
const collection = service.getCollection(body.database, body.collection);
|
|
232
|
+
if (collection == null) {
|
|
233
|
+
ctx.throw(412, JSON.stringify(reply('e', { error: 'wrong database or collection' })));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// get removing doc as output for triggers
|
|
237
|
+
const output: any = await collection.findOne(body.query).exec().then();
|
|
238
|
+
|
|
239
|
+
// operate on db
|
|
240
|
+
await collection
|
|
241
|
+
.updateOne(body.query, body.update, body.options)
|
|
242
|
+
.exec()
|
|
243
|
+
.then(writeOpResult => {
|
|
244
|
+
// Call trigger
|
|
245
|
+
service.triggers.call('update-one', body.database, body.collection, {
|
|
246
|
+
query: body.query,
|
|
247
|
+
queryResult: writeOpResult,
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
ctx.body = { data: writeOpResult };
|
|
251
|
+
})
|
|
252
|
+
.catch(err => {
|
|
253
|
+
ctx.status = err.status || 500;
|
|
254
|
+
ctx.body = err.message;
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
dataProvider.post('/insert-one', async (ctx: Context) => {
|
|
259
|
+
const body = ctx.request.body;
|
|
260
|
+
const bodyValidate = validateObject(body, 'database collection doc');
|
|
261
|
+
|
|
262
|
+
// fields validation
|
|
263
|
+
if (!bodyValidate.isValid) {
|
|
264
|
+
ctx.throw(412, JSON.stringify(reply('e', { error: bodyValidate.requires })));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// access validation
|
|
268
|
+
const hasAccess = service.checkAccess(
|
|
269
|
+
body.database,
|
|
270
|
+
body.collection,
|
|
271
|
+
AccessTypes.write,
|
|
272
|
+
body.doc,
|
|
273
|
+
ctx.state.user
|
|
274
|
+
);
|
|
275
|
+
if (!hasAccess) {
|
|
276
|
+
console.log(body);
|
|
277
|
+
console.log(ctx.state.user.permission);
|
|
278
|
+
ctx.throw(403, 'access denied');
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// collection validation
|
|
282
|
+
const collection = service.getCollection(body.database, body.collection);
|
|
283
|
+
if (collection == null) {
|
|
284
|
+
ctx.throw(412, JSON.stringify(reply('e', { error: 'wrong database or collection' })));
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// operate on db
|
|
288
|
+
await new collection(body.doc)
|
|
289
|
+
.save()
|
|
290
|
+
.then(async newDoc => {
|
|
291
|
+
// Call trigger
|
|
292
|
+
service.triggers.call('insert-one', body.database, body.collection, {
|
|
293
|
+
query: body.query,
|
|
294
|
+
queryResult: newDoc,
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
ctx.body = { data: newDoc };
|
|
298
|
+
})
|
|
299
|
+
.catch(err => {
|
|
300
|
+
ctx.status = err.status || 500;
|
|
301
|
+
ctx.body = err.message;
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
dataProvider.post('/remove-one', async (ctx: Context) => {
|
|
306
|
+
const body = ctx.request.body;
|
|
307
|
+
const bodyValidate = validateObject(body, 'database collection query');
|
|
308
|
+
|
|
309
|
+
// fields validation
|
|
310
|
+
if (!bodyValidate.isValid) {
|
|
311
|
+
ctx.throw(412, JSON.stringify(reply('e', { error: bodyValidate.requires })));
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// access validation
|
|
315
|
+
const hasAccess = service.checkAccess(
|
|
316
|
+
body.database,
|
|
317
|
+
body.collection,
|
|
318
|
+
AccessTypes.write,
|
|
319
|
+
body.query,
|
|
320
|
+
ctx.state.user
|
|
321
|
+
);
|
|
322
|
+
if (!hasAccess) ctx.throw(403, 'access denied');
|
|
323
|
+
|
|
324
|
+
// collection validation
|
|
325
|
+
const collection = service.getCollection(body.database, body.collection);
|
|
326
|
+
if (collection == null) {
|
|
327
|
+
ctx.throw(412, JSON.stringify(reply('e', { error: 'wrong database or collection' })));
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// get removing doc as output for triggers
|
|
331
|
+
const output: any = await collection.findOne(body.query).exec().then();
|
|
332
|
+
|
|
333
|
+
// operate on db
|
|
334
|
+
await collection
|
|
335
|
+
.deleteOne(body.query)
|
|
336
|
+
.exec()
|
|
337
|
+
.then(async (result: any) => {
|
|
338
|
+
// Call trigger
|
|
339
|
+
service.triggers.call('remove-one', body.database, body.collection, {
|
|
340
|
+
query: body.query,
|
|
341
|
+
queryResult: result,
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
ctx.body = { data: result };
|
|
345
|
+
})
|
|
346
|
+
.catch((err: Error) => {
|
|
347
|
+
ctx.status = (err as any).status || 500;
|
|
348
|
+
ctx.body = err.message;
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
dataProvider.post('/aggregate', async (ctx: Context) => {
|
|
353
|
+
const body = ctx.request.body;
|
|
354
|
+
const bodyValidate = validateObject(body, 'database collection accessQuery');
|
|
355
|
+
|
|
356
|
+
// fields validation
|
|
357
|
+
if (!bodyValidate.isValid) {
|
|
358
|
+
ctx.throw(412, JSON.stringify(reply('e', { error: bodyValidate.requires })));
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// access validation
|
|
362
|
+
const hasAccess = service.checkAccess(
|
|
363
|
+
body.database,
|
|
364
|
+
body.collection,
|
|
365
|
+
AccessTypes.read,
|
|
366
|
+
body.accessQuery,
|
|
367
|
+
ctx.state.user
|
|
368
|
+
);
|
|
369
|
+
if (!hasAccess) ctx.throw(403, 'access denied');
|
|
370
|
+
|
|
371
|
+
// collection validation
|
|
372
|
+
const collection = service.getCollection(body.database, body.collection);
|
|
373
|
+
if (collection == null) {
|
|
374
|
+
ctx.throw(412, JSON.stringify(reply('e', { error: 'wrong database or collection' })));
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// operate on db
|
|
378
|
+
await collection
|
|
379
|
+
.aggregate(body.pipelines)
|
|
380
|
+
.exec()
|
|
381
|
+
.then(async (result: any) => {
|
|
382
|
+
// Call trigger
|
|
383
|
+
service.triggers.call('aggregate', body.database, body.collection, {
|
|
384
|
+
query: body.query,
|
|
385
|
+
queryResult: result,
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
ctx.body = { data: result };
|
|
389
|
+
})
|
|
390
|
+
.catch((err: any) => {
|
|
391
|
+
ctx.status = err.status || 500;
|
|
392
|
+
ctx.body = err.message;
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
dataProvider.post('/findByIds', async (ctx: Context, next: Next) => {
|
|
397
|
+
const body = ctx.request.body;
|
|
398
|
+
const bodyValidate = validateObject(body, 'database collection ids');
|
|
399
|
+
|
|
400
|
+
// fields validation
|
|
401
|
+
if (!bodyValidate.isValid) {
|
|
402
|
+
ctx.throw(412, JSON.stringify(reply('e', { error: bodyValidate.requires })));
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// access validation
|
|
406
|
+
const hasAccess = service.checkAccess(
|
|
407
|
+
body.database,
|
|
408
|
+
body.collection,
|
|
409
|
+
AccessTypes.read,
|
|
410
|
+
body.accessQuery || {},
|
|
411
|
+
ctx.state.user
|
|
412
|
+
);
|
|
413
|
+
if (!hasAccess) ctx.throw(403, 'access denied');
|
|
414
|
+
|
|
415
|
+
// collection validation
|
|
416
|
+
const collection = service.getCollection(body.database, body.collection);
|
|
417
|
+
if (collection == null) {
|
|
418
|
+
ctx.throw(412, JSON.stringify(reply('e', { error: 'wrong database or collection' })));
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const or: Array<{ _id: any }> = [];
|
|
422
|
+
|
|
423
|
+
try {
|
|
424
|
+
body.ids.forEach((id: any) => {
|
|
425
|
+
const castedid = service.getAsID(id);
|
|
426
|
+
or.push({ _id: castedid });
|
|
427
|
+
});
|
|
428
|
+
} catch (e) {
|
|
429
|
+
console.log('ids.forEach', e);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
const pipelines = [
|
|
433
|
+
{
|
|
434
|
+
$match: { $or: or },
|
|
435
|
+
},
|
|
436
|
+
// {
|
|
437
|
+
// $sort: body.sort || { _id: 1 }
|
|
438
|
+
// }
|
|
439
|
+
];
|
|
440
|
+
|
|
441
|
+
// operate on db
|
|
442
|
+
await collection
|
|
443
|
+
.aggregate(pipelines)
|
|
444
|
+
.exec()
|
|
445
|
+
.then(async (result: any[]) => {
|
|
446
|
+
ctx.state = { data: result };
|
|
447
|
+
await next();
|
|
448
|
+
})
|
|
449
|
+
.catch((err: Error) => {
|
|
450
|
+
ctx.status = (err as any).status || 500;
|
|
451
|
+
ctx.body = err.message;
|
|
452
|
+
});
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
// Final middleware for converting mongoose documents to JSON
|
|
456
|
+
dataProvider.use('/', async (ctx: Context, next: Next) => {
|
|
457
|
+
// this event is responsible to covert whole mongoose doc to json form
|
|
458
|
+
// including getters, public properties
|
|
459
|
+
// each mongoose doc must have a "toJson" method being defined on its own Schema.
|
|
460
|
+
|
|
461
|
+
const state = ctx.state;
|
|
462
|
+
// let result;
|
|
463
|
+
|
|
464
|
+
// // array
|
|
465
|
+
// if(!isNaN(state.length)) {
|
|
466
|
+
// result = [];
|
|
467
|
+
|
|
468
|
+
// for (let index = 0; index < state.length; index++) {
|
|
469
|
+
// const element = state[index];
|
|
470
|
+
// if(element.hasOwnProperty('toJson'))
|
|
471
|
+
// result.push(element.toJson());
|
|
472
|
+
// else result.push(element);
|
|
473
|
+
// }
|
|
474
|
+
// }
|
|
475
|
+
// // object
|
|
476
|
+
// else {
|
|
477
|
+
// result = state.toJson();
|
|
478
|
+
// }
|
|
479
|
+
|
|
480
|
+
ctx.body = state;
|
|
481
|
+
});
|
|
482
|
+
|
|
191
483
|
export { name, dataProvider as main };
|