beech-api 3.9.0-beta.9-rc → 3.9.80
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/LICENSE +21 -21
- package/README.md +1717 -1649
- package/index.js +2 -2
- package/package.json +92 -84
- package/packages/cli/beech +9 -10
- package/packages/cli/bin/beech-app.js +390 -390
- package/packages/cli/bin/beech-service.js +263 -170
- package/packages/cli/core/auth/Credentials.js +174 -174
- package/packages/cli/core/auth/Passport.js +664 -664
- package/packages/cli/core/auth/_Request.js +12 -12
- package/packages/cli/core/configure/_gitignore +16 -15
- package/packages/cli/core/configure/_sequelizerc +9 -9
- package/packages/cli/core/configure/app.config-basic.js +55 -55
- package/packages/cli/core/configure/app.config-sequelize.js +88 -88
- package/packages/cli/core/configure/beech.config.js +9 -9
- package/packages/cli/core/configure/global.config-basic.js +8 -8
- package/packages/cli/core/configure/global.config-sequelize.js +8 -8
- package/packages/cli/core/configure/jest.config.js +6 -6
- package/packages/cli/core/configure/jsconfig.json +8 -7
- package/packages/cli/core/configure/passport.config.js +97 -97
- package/packages/cli/core/databases/mysql.js +94 -95
- package/packages/cli/core/databases/sequelize.js +187 -188
- package/packages/cli/core/databases/test.js +250 -255
- package/packages/cli/core/file-walk/file-walk.js +35 -35
- package/packages/cli/core/generator/_endpoints +15 -15
- package/packages/cli/core/generator/_endpoints_basic +42 -42
- package/packages/cli/core/generator/_help +29 -19
- package/packages/cli/core/generator/_help_create +10 -10
- package/packages/cli/core/generator/_help_service +10 -10
- package/packages/cli/core/generator/_helpers +9 -9
- package/packages/cli/core/generator/_helpers_basic +166 -22
- package/packages/cli/core/generator/_models +6 -6
- package/packages/cli/core/generator/_models_basic +13 -13
- package/packages/cli/core/generator/_package +23 -19
- package/packages/cli/core/generator/_scheduler +32 -32
- package/packages/cli/core/generator/_spec +29 -29
- package/packages/cli/core/generator/index.js +1229 -992
- package/packages/cli/core/helpers/2fa.js +106 -106
- package/packages/cli/core/helpers/math.js +115 -115
- package/packages/cli/core/helpers/poolEntity.js +103 -103
- package/packages/cli/core/index.js +264 -266
- package/packages/cli/core/middleware/express/duplicateRequest.js +16 -16
- package/packages/cli/core/middleware/express/jwtCheckAllow.js +85 -85
- package/packages/cli/core/middleware/express/rateLimit.js +29 -29
- package/packages/cli/core/middleware/express/slowDown.js +2 -2
- package/packages/cli/core/middleware/index.js +6 -6
- package/packages/cli/core/middleware/origin/guard/advance.js +75 -75
- package/packages/cli/core/middleware/origin/whitelist/cors.js +94 -94
- package/packages/cli/core/services/http.express.js +481 -481
- package/packages/cli/core/test/check-node.js +21 -21
- package/packages/cli/core/test/utils.js +7 -7
- package/packages/cli/entry +10 -0
- package/packages/lib/index.js +6 -6
- package/packages/lib/src/endpoint.js +947 -885
- package/packages/lib/src/guard.js +60 -60
- package/packages/lib/src/salt.js +3 -3
- package/packages/lib/src/schema.js +96 -96
- package/packages/lib/src/specificExpress.js +7 -7
- package/packages/lib/src/user.js +271 -271
|
@@ -1,885 +1,947 @@
|
|
|
1
|
-
const walk = require("walk");
|
|
2
|
-
const fs = require("fs");
|
|
3
|
-
const moment = require("moment");
|
|
4
|
-
const { checkRoleMiddlewareWithDefaultProject } = require("../../cli/core/middleware/express/jwtCheckAllow");
|
|
5
|
-
const { Limiter, Duplicater } = require("../../cli/core/middleware/index");
|
|
6
|
-
|
|
7
|
-
function walkModel(cb) {
|
|
8
|
-
try {
|
|
9
|
-
let jsfiles = [];
|
|
10
|
-
let walker = walk.walk(appRoot + "/src/models", { followLinks: false });
|
|
11
|
-
// Walk file on push
|
|
12
|
-
walker.on("file", (root, stat, next) => {
|
|
13
|
-
jsfiles.push(root + "/" + stat.name);
|
|
14
|
-
next();
|
|
15
|
-
});
|
|
16
|
-
// Walking
|
|
17
|
-
walker.on("end", () => {
|
|
18
|
-
let preProject = [];
|
|
19
|
-
if(jsfiles.length) {
|
|
20
|
-
jsfiles.forEach((file, k) => {
|
|
21
|
-
let schemaPath = "@/models" + file.split("models")[1].replace(/\\/g, "/");
|
|
22
|
-
let endpoint = file
|
|
23
|
-
.split("models")[1]
|
|
24
|
-
.replace(/\\/g, "/")
|
|
25
|
-
.replace(/_/g, "-")
|
|
26
|
-
.toLowerCase()
|
|
27
|
-
.slice(0, -3);
|
|
28
|
-
preProject.push([schemaPath, endpoint]);
|
|
29
|
-
if (jsfiles.length == k + 1) {
|
|
30
|
-
cb(null, preProject);
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
} else {
|
|
34
|
-
// model not found.
|
|
35
|
-
cb(null, preProject);
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
} catch (error) {
|
|
39
|
-
cb(error, null);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function filterProject(Projects, reqUrl, params = "", method = "", req, res, cb) {
|
|
44
|
-
try {
|
|
45
|
-
let pj = Projects.shift();
|
|
46
|
-
let leaveParamsAlone = params.slice(0);
|
|
47
|
-
let paramsItem = leaveParamsAlone.replace(/^\/|\/$/g, "").split('/');
|
|
48
|
-
let leaveReqUrlAlone = reqUrl.slice(0);
|
|
49
|
-
let newParams = params.split("/").filter((e) => (e !== 'undefined')).join("/");
|
|
50
|
-
let urlWithoutParams = leaveReqUrlAlone.replace(newParams, '').split("?")[0].replace(/\/$/, "");
|
|
51
|
-
// sub-way for PATCH method
|
|
52
|
-
urlWithoutParams = (method == "PATCH" || method == "DELETE") ? urlWithoutParams.substring(0, urlWithoutParams.lastIndexOf('/')) : urlWithoutParams;
|
|
53
|
-
// check match project by url
|
|
54
|
-
if(pj[1] == urlWithoutParams) {
|
|
55
|
-
return checkOffset(Object.values(require(pj[0]))[0], req, res, (thenChecked) => {
|
|
56
|
-
if(thenChecked) {
|
|
57
|
-
return cb(null, Object.values(require(pj[0]))[0], paramsItem);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
// Finally recursive filterProject function
|
|
62
|
-
if (Projects.length > 0) {
|
|
63
|
-
filterProject(Projects, reqUrl, params, method, req, res, cb);
|
|
64
|
-
} else {
|
|
65
|
-
// not match
|
|
66
|
-
return notfound(res);
|
|
67
|
-
}
|
|
68
|
-
} catch (error) {
|
|
69
|
-
console.log(error);
|
|
70
|
-
cb(error, null, []);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function filterProjectForByPass(Projects, reqUrl, req, res, cb) {
|
|
75
|
-
try {
|
|
76
|
-
let pj = Projects.shift();
|
|
77
|
-
let regx = new RegExp(pj[1] + "?[^\/].?[a-zA-Z0-9].*$", 'g');
|
|
78
|
-
let regxMatch = reqUrl.match(regx);
|
|
79
|
-
let regxMatchLength = (regxMatch) ? regxMatch.length: 0;
|
|
80
|
-
if (pj[1] == reqUrl) {
|
|
81
|
-
return checkOffset(Object.values(require(pj[0]))[0], req, res, (thenChecked) => {
|
|
82
|
-
if(thenChecked) {
|
|
83
|
-
return cb(null, Object.values(require(pj[0]))[0]);
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
} else if(regxMatchLength) {
|
|
87
|
-
return checkOffset(Object.values(require(pj[0]))[0], req, res, (thenChecked) => {
|
|
88
|
-
if(thenChecked) {
|
|
89
|
-
return cb(null, Object.values(require(pj[0]))[0]);
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
// Finally recursive filterProjectForByPass function
|
|
94
|
-
if (Projects.length > 0) {
|
|
95
|
-
filterProjectForByPass(Projects, reqUrl, req, res, cb);
|
|
96
|
-
} else {
|
|
97
|
-
// not match
|
|
98
|
-
return notfound(res);
|
|
99
|
-
}
|
|
100
|
-
} catch (error) {
|
|
101
|
-
cb(error, null);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function checkOffset(Project, req, res, cb) {
|
|
106
|
-
if (!Project) {
|
|
107
|
-
return notfound(res);
|
|
108
|
-
}
|
|
109
|
-
// check offset is Ingeter as well as Zero number
|
|
110
|
-
let offset = req.params.offset || undefined;
|
|
111
|
-
let limit = req.params.limit || undefined;
|
|
112
|
-
let offsetRegxMatch = (offset !== undefined) ? offset.match(/^[0-9]+$/) : undefined;
|
|
113
|
-
let limitRegxMatch = (limit !== undefined) ? limit.match(/^[0-9]+$/) : undefined;
|
|
114
|
-
if (offsetRegxMatch && limitRegxMatch) {
|
|
115
|
-
cb(true);
|
|
116
|
-
} else {
|
|
117
|
-
if(offset === undefined) {
|
|
118
|
-
cb(true);
|
|
119
|
-
} else {
|
|
120
|
-
return notfound(res);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function notfound(res) {
|
|
126
|
-
return res.status(404).json({
|
|
127
|
-
code: 404,
|
|
128
|
-
status: "404_NOT_FOUND",
|
|
129
|
-
message: "The Endpoint not found!.",
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function errMessage(err, res) {
|
|
134
|
-
let errTurnOffDbDefine = JSON.stringify(err.toString()).match(/'define'/);
|
|
135
|
-
let errTurnOffDbOption = JSON.stringify(err.toString()).match(/'options'/);
|
|
136
|
-
if(errTurnOffDbDefine || errTurnOffDbOption) {
|
|
137
|
-
// @return
|
|
138
|
-
return res.status(500).json({
|
|
139
|
-
code: 500,
|
|
140
|
-
status: "ERR_INTERNAL_SERVER",
|
|
141
|
-
message: "Database connection name is CLOSED.",
|
|
142
|
-
});
|
|
143
|
-
} else {
|
|
144
|
-
// @return
|
|
145
|
-
return res.status(500).json({
|
|
146
|
-
code: 500,
|
|
147
|
-
status: "ERR_INTERNAL_SERVER",
|
|
148
|
-
message: err.toString(),
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function whereCond(objectCond, cb) {
|
|
154
|
-
if(typeof objectCond === 'object' && Object.keys(objectCond).length) {
|
|
155
|
-
let keys = Object.keys(objectCond);
|
|
156
|
-
let where = {};
|
|
157
|
-
let orderBy = {};
|
|
158
|
-
let groupBy = {};
|
|
159
|
-
// Start Recursive for Check Where condition OR GroupBy OR OrderBy
|
|
160
|
-
recursiveWhereCond(keys, objectCond, where, groupBy, orderBy, (err, cbWhere, cbGroupBy, cbOrderBy) => {
|
|
161
|
-
cb(err, cbWhere, cbGroupBy, cbOrderBy);
|
|
162
|
-
});
|
|
163
|
-
} else {
|
|
164
|
-
cb(null, {}, { group: { groupby: [] } }, { order: { orderby: [] } });
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function getValueType(value) {
|
|
169
|
-
if (typeof value === 'string') {
|
|
170
|
-
// Check for ISO-like date string with optional time part
|
|
171
|
-
const isoDateRegex = /^\d{4}-\d{2}-\d{2}(?:[ T]\d{2}:\d{2}:\d{2})?$/;
|
|
172
|
-
const date = new Date(value);
|
|
173
|
-
if (!isNaN(date.getTime()) && isoDateRegex.test(value)) {
|
|
174
|
-
return 'Date';
|
|
175
|
-
}
|
|
176
|
-
return 'String';
|
|
177
|
-
}
|
|
178
|
-
if (typeof value === 'number' && !isNaN(value)) return 'Number';
|
|
179
|
-
if (typeof value === 'boolean') return 'Boolean';
|
|
180
|
-
if (value instanceof Date && !isNaN(value)) return 'Date';
|
|
181
|
-
if (value === null) return 'Null';
|
|
182
|
-
if (typeof value === 'undefined') return 'Undefined';
|
|
183
|
-
if (Array.isArray(value)) return 'Array';
|
|
184
|
-
if (typeof value === 'function') return 'Function';
|
|
185
|
-
if (typeof value === 'symbol') return 'Symbol';
|
|
186
|
-
if (typeof value === 'bigint') return 'BigInt';
|
|
187
|
-
if (typeof value === 'object') return 'Object';
|
|
188
|
-
return 'Unknown';
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
async function recursiveWhereCond(keys, objectCond, where, groupBy, orderBy, cb) {
|
|
192
|
-
if(keys.length > 0) {
|
|
193
|
-
let k = keys.shift();
|
|
194
|
-
// Check param key for Where condition OR GroupBy OR OrderBy
|
|
195
|
-
if(k == 'orderby') {
|
|
196
|
-
let oderByValueItemFromQueryString = objectCond[k].replace(/\w+/g, '"$&"').replace(/\[\s*\]/g, '[]');
|
|
197
|
-
// Check Array syntax from Query String
|
|
198
|
-
isValidArrayFormat(oderByValueItemFromQueryString, (err, isArray, strArr) => {
|
|
199
|
-
if(err) {
|
|
200
|
-
cb(["SyntaxError: Unexpected end of Array or String input", ` (${k})`], null, null, null);
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
return
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
1
|
+
const walk = require("walk");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const moment = require("moment");
|
|
4
|
+
const { checkRoleMiddlewareWithDefaultProject } = require("../../cli/core/middleware/express/jwtCheckAllow");
|
|
5
|
+
const { Limiter, Duplicater } = require("../../cli/core/middleware/index");
|
|
6
|
+
|
|
7
|
+
function walkModel(cb) {
|
|
8
|
+
try {
|
|
9
|
+
let jsfiles = [];
|
|
10
|
+
let walker = walk.walk(appRoot + "/src/models", { followLinks: false });
|
|
11
|
+
// Walk file on push
|
|
12
|
+
walker.on("file", (root, stat, next) => {
|
|
13
|
+
jsfiles.push(root + "/" + stat.name);
|
|
14
|
+
next();
|
|
15
|
+
});
|
|
16
|
+
// Walking
|
|
17
|
+
walker.on("end", () => {
|
|
18
|
+
let preProject = [];
|
|
19
|
+
if(jsfiles.length) {
|
|
20
|
+
jsfiles.forEach((file, k) => {
|
|
21
|
+
let schemaPath = "@/models" + file.split("models")[1].replace(/\\/g, "/");
|
|
22
|
+
let endpoint = file
|
|
23
|
+
.split("models")[1]
|
|
24
|
+
.replace(/\\/g, "/")
|
|
25
|
+
.replace(/_/g, "-")
|
|
26
|
+
.toLowerCase()
|
|
27
|
+
.slice(0, -3);
|
|
28
|
+
preProject.push([schemaPath, endpoint]);
|
|
29
|
+
if (jsfiles.length == k + 1) {
|
|
30
|
+
cb(null, preProject);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
} else {
|
|
34
|
+
// model not found.
|
|
35
|
+
cb(null, preProject);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
} catch (error) {
|
|
39
|
+
cb(error, null);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function filterProject(Projects, reqUrl, params = "", method = "", req, res, cb) {
|
|
44
|
+
try {
|
|
45
|
+
let pj = Projects.shift();
|
|
46
|
+
let leaveParamsAlone = params.slice(0);
|
|
47
|
+
let paramsItem = leaveParamsAlone.replace(/^\/|\/$/g, "").split('/');
|
|
48
|
+
let leaveReqUrlAlone = reqUrl.slice(0);
|
|
49
|
+
let newParams = params.split("/").filter((e) => (e !== 'undefined')).join("/");
|
|
50
|
+
let urlWithoutParams = leaveReqUrlAlone.replace(newParams, '').split("?")[0].replace(/\/$/, "");
|
|
51
|
+
// sub-way for PATCH method
|
|
52
|
+
urlWithoutParams = (method == "PATCH" || method == "DELETE") ? urlWithoutParams.substring(0, urlWithoutParams.lastIndexOf('/')) : urlWithoutParams;
|
|
53
|
+
// check match project by url
|
|
54
|
+
if(pj[1] == urlWithoutParams) {
|
|
55
|
+
return checkOffset(Object.values(require(pj[0]))[0], req, res, (thenChecked) => {
|
|
56
|
+
if(thenChecked) {
|
|
57
|
+
return cb(null, Object.values(require(pj[0]))[0], paramsItem);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// Finally recursive filterProject function
|
|
62
|
+
if (Projects.length > 0) {
|
|
63
|
+
filterProject(Projects, reqUrl, params, method, req, res, cb);
|
|
64
|
+
} else {
|
|
65
|
+
// not match
|
|
66
|
+
return notfound(res);
|
|
67
|
+
}
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.log(error);
|
|
70
|
+
cb(error, null, []);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function filterProjectForByPass(Projects, reqUrl, req, res, cb) {
|
|
75
|
+
try {
|
|
76
|
+
let pj = Projects.shift();
|
|
77
|
+
let regx = new RegExp(pj[1] + "?[^\/].?[a-zA-Z0-9].*$", 'g');
|
|
78
|
+
let regxMatch = reqUrl.match(regx);
|
|
79
|
+
let regxMatchLength = (regxMatch) ? regxMatch.length: 0;
|
|
80
|
+
if (pj[1] == reqUrl) {
|
|
81
|
+
return checkOffset(Object.values(require(pj[0]))[0], req, res, (thenChecked) => {
|
|
82
|
+
if(thenChecked) {
|
|
83
|
+
return cb(null, Object.values(require(pj[0]))[0]);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
} else if(regxMatchLength) {
|
|
87
|
+
return checkOffset(Object.values(require(pj[0]))[0], req, res, (thenChecked) => {
|
|
88
|
+
if(thenChecked) {
|
|
89
|
+
return cb(null, Object.values(require(pj[0]))[0]);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// Finally recursive filterProjectForByPass function
|
|
94
|
+
if (Projects.length > 0) {
|
|
95
|
+
filterProjectForByPass(Projects, reqUrl, req, res, cb);
|
|
96
|
+
} else {
|
|
97
|
+
// not match
|
|
98
|
+
return notfound(res);
|
|
99
|
+
}
|
|
100
|
+
} catch (error) {
|
|
101
|
+
cb(error, null);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function checkOffset(Project, req, res, cb) {
|
|
106
|
+
if (!Project) {
|
|
107
|
+
return notfound(res);
|
|
108
|
+
}
|
|
109
|
+
// check offset is Ingeter as well as Zero number
|
|
110
|
+
let offset = req.params.offset || undefined;
|
|
111
|
+
let limit = req.params.limit || undefined;
|
|
112
|
+
let offsetRegxMatch = (offset !== undefined) ? offset.match(/^[0-9]+$/) : undefined;
|
|
113
|
+
let limitRegxMatch = (limit !== undefined) ? limit.match(/^[0-9]+$/) : undefined;
|
|
114
|
+
if (offsetRegxMatch && limitRegxMatch) {
|
|
115
|
+
cb(true);
|
|
116
|
+
} else {
|
|
117
|
+
if(offset === undefined) {
|
|
118
|
+
cb(true);
|
|
119
|
+
} else {
|
|
120
|
+
return notfound(res);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function notfound(res) {
|
|
126
|
+
return res.status(404).json({
|
|
127
|
+
code: 404,
|
|
128
|
+
status: "404_NOT_FOUND",
|
|
129
|
+
message: "The Endpoint not found!.",
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function errMessage(err, res) {
|
|
134
|
+
let errTurnOffDbDefine = JSON.stringify(err.toString()).match(/'define'/);
|
|
135
|
+
let errTurnOffDbOption = JSON.stringify(err.toString()).match(/'options'/);
|
|
136
|
+
if(errTurnOffDbDefine || errTurnOffDbOption) {
|
|
137
|
+
// @return
|
|
138
|
+
return res.status(500).json({
|
|
139
|
+
code: 500,
|
|
140
|
+
status: "ERR_INTERNAL_SERVER",
|
|
141
|
+
message: "Database connection name is CLOSED.",
|
|
142
|
+
});
|
|
143
|
+
} else {
|
|
144
|
+
// @return
|
|
145
|
+
return res.status(500).json({
|
|
146
|
+
code: 500,
|
|
147
|
+
status: "ERR_INTERNAL_SERVER",
|
|
148
|
+
message: err.toString(),
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function whereCond(objectCond, cb) {
|
|
154
|
+
if(typeof objectCond === 'object' && Object.keys(objectCond).length) {
|
|
155
|
+
let keys = Object.keys(objectCond);
|
|
156
|
+
let where = {};
|
|
157
|
+
let orderBy = {};
|
|
158
|
+
let groupBy = {};
|
|
159
|
+
// Start Recursive for Check Where condition OR GroupBy OR OrderBy
|
|
160
|
+
recursiveWhereCond(keys, objectCond, where, groupBy, orderBy, (err, cbWhere, cbGroupBy, cbOrderBy) => {
|
|
161
|
+
cb(err, cbWhere, cbGroupBy, cbOrderBy);
|
|
162
|
+
});
|
|
163
|
+
} else {
|
|
164
|
+
cb(null, {}, { group: { groupby: [] } }, { order: { orderby: [] } });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function getValueType(value) {
|
|
169
|
+
if (typeof value === 'string') {
|
|
170
|
+
// Check for ISO-like date string with optional time part
|
|
171
|
+
const isoDateRegex = /^\d{4}-\d{2}-\d{2}(?:[ T]\d{2}:\d{2}:\d{2})?$/;
|
|
172
|
+
const date = new Date(value);
|
|
173
|
+
if (!isNaN(date.getTime()) && isoDateRegex.test(value)) {
|
|
174
|
+
return 'Date';
|
|
175
|
+
}
|
|
176
|
+
return 'String';
|
|
177
|
+
}
|
|
178
|
+
if (typeof value === 'number' && !isNaN(value)) return 'Number';
|
|
179
|
+
if (typeof value === 'boolean') return 'Boolean';
|
|
180
|
+
if (value instanceof Date && !isNaN(value)) return 'Date';
|
|
181
|
+
if (value === null) return 'Null';
|
|
182
|
+
if (typeof value === 'undefined') return 'Undefined';
|
|
183
|
+
if (Array.isArray(value)) return 'Array';
|
|
184
|
+
if (typeof value === 'function') return 'Function';
|
|
185
|
+
if (typeof value === 'symbol') return 'Symbol';
|
|
186
|
+
if (typeof value === 'bigint') return 'BigInt';
|
|
187
|
+
if (typeof value === 'object') return 'Object';
|
|
188
|
+
return 'Unknown';
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
async function recursiveWhereCond(keys, objectCond, where, groupBy, orderBy, cb) {
|
|
192
|
+
if(keys.length > 0) {
|
|
193
|
+
let k = keys.shift();
|
|
194
|
+
// Check param key for Where condition OR GroupBy OR OrderBy
|
|
195
|
+
if(k == 'orderby') {
|
|
196
|
+
let oderByValueItemFromQueryString = objectCond[k].replace(/\w+/g, '"$&"').replace(/\[\s*\]/g, '[]');
|
|
197
|
+
// Check Array syntax from Query String
|
|
198
|
+
isValidArrayFormat(oderByValueItemFromQueryString, (err, isArray, strArr) => {
|
|
199
|
+
if(err) {
|
|
200
|
+
cb(["SyntaxError: Unexpected end of Array or String input", ` (${k})`], null, null, null);
|
|
201
|
+
return;
|
|
202
|
+
} else {
|
|
203
|
+
let order = JSON.parse(strArr);
|
|
204
|
+
orderBy[k] = order.length ? order : null;
|
|
205
|
+
// Recursive re-call function
|
|
206
|
+
recursiveWhereCond(keys, objectCond, where, groupBy, orderBy, cb);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
} else if(k == 'groupby') {
|
|
210
|
+
let groupByValueItemFromQueryString = objectCond[k].replace(/\w+/g, '"$&"').replace(/\[\s*\]/g, '[]');
|
|
211
|
+
// Check Array syntax from Query String
|
|
212
|
+
isValidArrayFormat(groupByValueItemFromQueryString, (err, isArray, strArr) => {
|
|
213
|
+
if(err) {
|
|
214
|
+
cb(["SyntaxError: Unexpected end of Array or String input", ` (${k})`], null, null, null);
|
|
215
|
+
return;
|
|
216
|
+
} else {
|
|
217
|
+
let group = JSON.parse(strArr);
|
|
218
|
+
groupBy[k] = group.length ? group : null;
|
|
219
|
+
// Recursive re-call function
|
|
220
|
+
recursiveWhereCond(keys, objectCond, where, groupBy, orderBy, cb);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
} else {
|
|
224
|
+
// 1. Get raw value, force to String and replace %22 to double quote "
|
|
225
|
+
let rawInput = objectCond[k];
|
|
226
|
+
if (Array.isArray(rawInput)) {
|
|
227
|
+
rawInput = rawInput.join(",");
|
|
228
|
+
}
|
|
229
|
+
let decodedQueryString = String(rawInput).replace(/%22/g, '"').replace(/'/g, '"');
|
|
230
|
+
// 2. Advanced decoding logic (works for all operations like LIKE, EQUAL, IN, BETWEEN)
|
|
231
|
+
// Force to look for groups of language codes (% followed by two hexadecimal digits like %E0, %B8)
|
|
232
|
+
// It will capture consecutive codes as a single group and decode them together for accuracy
|
|
233
|
+
decodedQueryString = decodedQueryString.replace(/(?:%[0-9A-F]{2})+/gi, (match) => {
|
|
234
|
+
try {
|
|
235
|
+
return decodeURIComponent(match);
|
|
236
|
+
} catch (e) {
|
|
237
|
+
// This fallback will attempt to decode each %XX sequence individually, which can help recover partial decoding even if the full group is malformed
|
|
238
|
+
return match.replace(/%([0-9A-F]{2})/gi, (subMatch) => {
|
|
239
|
+
try { return decodeURIComponent(subMatch); } catch { return subMatch; }
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
// 3. Special handling for BETWEEN and NOT BETWEEN operations to ensure date formats are preserved correctly
|
|
244
|
+
let isBetweenOp = decodedQueryString.toLowerCase().includes('between') || decodedQueryString.toLowerCase().includes('notbetween');
|
|
245
|
+
if (isBetweenOp) {
|
|
246
|
+
try {
|
|
247
|
+
let arrayMatch = decodedQueryString.match(/\[\s*(between|notbetween)\s*,\s*(\[.*\])\s*\]/i);
|
|
248
|
+
if (arrayMatch && arrayMatch[2]) {
|
|
249
|
+
let op = arrayMatch[1];
|
|
250
|
+
let dateArrayStr = arrayMatch[2];
|
|
251
|
+
if (!dateArrayStr.includes('"')) {
|
|
252
|
+
dateArrayStr = dateArrayStr.replace(/([^\[\],]+)/g, '"$1"');
|
|
253
|
+
}
|
|
254
|
+
let parsedDates = JSON.parse(dateArrayStr);
|
|
255
|
+
if (Array.isArray(parsedDates) && parsedDates.length >= 2) {
|
|
256
|
+
// Trim and remove any extraneous quotes from the parsed date strings
|
|
257
|
+
let dateStart = parsedDates[0].trim().replace(/"/g, '');
|
|
258
|
+
let dateEnd = parsedDates[1].trim().replace(/"/g, '');
|
|
259
|
+
// Ensure that if the date string is in a format like "2026-05-17 00:00:00", it is converted to "2026-05-17T00:00:00" for proper Date parsing
|
|
260
|
+
dateStart = dateStart.replace(' ', 'T');
|
|
261
|
+
dateEnd = dateEnd.replace(' ', 'T');
|
|
262
|
+
decodedQueryString = `[${op},${dateStart},${dateEnd}]`;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
} catch (err) {
|
|
266
|
+
cb(["SyntaxError: Invalid format for BETWEEN/NOT BETWEEN operation", ` (${k})`], null, null, null);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// 4. Format the decoded query string to prepare for Sequelize operators
|
|
271
|
+
let fieldValueItemFromQueryString = decodedQueryString.replace(/([^[\]," ]+)/g, '"$1"').replace(/""/g, '"');
|
|
272
|
+
let valueItem = decodedQueryString.replace(/[\[\]']+/g, '').replace(/"/g, '').split(',');
|
|
273
|
+
let cleanValueItem = valueItem.map((e) => e.trim()).filter((e) => e !== '');
|
|
274
|
+
// Check Array syntax from Query String
|
|
275
|
+
isValidArrayFormat(fieldValueItemFromQueryString, async (err) => {
|
|
276
|
+
if(err || cleanValueItem.length < 1) {
|
|
277
|
+
cb(["SyntaxError: Unexpected end of Array or String input", ` (${k})`], null, null, null);
|
|
278
|
+
return;
|
|
279
|
+
} else {
|
|
280
|
+
try {
|
|
281
|
+
let targetValue = cleanValueItem[1];
|
|
282
|
+
if (cleanValueItem[0] === 'like' || cleanValueItem[0] === 'notLike') {
|
|
283
|
+
targetValue = cleanValueItem.slice(1).join("");
|
|
284
|
+
}
|
|
285
|
+
where[k] = (cleanValueItem[1])
|
|
286
|
+
? {
|
|
287
|
+
[Op[cleanValueItem[0]]]: (cleanValueItem[1] == 'null') ? null :
|
|
288
|
+
(cleanValueItem[1] == 'true') ? true :
|
|
289
|
+
(cleanValueItem[1] == 'false') ? false :
|
|
290
|
+
(cleanValueItem[0] == 'between' || cleanValueItem[0] == 'notBetween') ? [
|
|
291
|
+
(getValueType(cleanValueItem[1]) == 'Date')
|
|
292
|
+
? (() => {
|
|
293
|
+
let mDate = moment(cleanValueItem[1]);
|
|
294
|
+
if (cleanValueItem[1].length <= 10 && !cleanValueItem[1].includes(':')) {
|
|
295
|
+
mDate.startOf('day');
|
|
296
|
+
}
|
|
297
|
+
return mDate.format('YYYY-MM-DD HH:mm:ss');
|
|
298
|
+
})()
|
|
299
|
+
: cleanValueItem[1],
|
|
300
|
+
(getValueType(cleanValueItem[2]) == 'Date')
|
|
301
|
+
? (() => {
|
|
302
|
+
let mDate = moment(cleanValueItem[2]);
|
|
303
|
+
if (cleanValueItem[2].length <= 10 && !cleanValueItem[2].includes(':')) {
|
|
304
|
+
mDate.endOf('day');
|
|
305
|
+
}
|
|
306
|
+
return mDate.format('YYYY-MM-DD HH:mm:ss');
|
|
307
|
+
})()
|
|
308
|
+
: cleanValueItem[2],
|
|
309
|
+
] :
|
|
310
|
+
(cleanValueItem[0] == 'or' || cleanValueItem[0] == 'in' || cleanValueItem[0] == 'notIn') ? [...cleanValueItem.slice(1)] :
|
|
311
|
+
(cleanValueItem[0] == 'like') ? targetValue :
|
|
312
|
+
(cleanValueItem[0] == 'notLike') ? targetValue :
|
|
313
|
+
(cleanValueItem[0] == 'startsWith') ? cleanValueItem[1] :
|
|
314
|
+
(cleanValueItem[0] == 'endsWith') ? cleanValueItem[1] :
|
|
315
|
+
(cleanValueItem[0] == 'substring') ? cleanValueItem[1] :
|
|
316
|
+
[cleanValueItem[1]]
|
|
317
|
+
}
|
|
318
|
+
: cleanValueItem[0];
|
|
319
|
+
// Recursive re-call function
|
|
320
|
+
recursiveWhereCond(keys, objectCond, where, groupBy, orderBy, cb);
|
|
321
|
+
} catch (error) {
|
|
322
|
+
return cb([`Error with (${k})`, error], null, null, null);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
} else {
|
|
328
|
+
// End of recursive function
|
|
329
|
+
cb(null, where, groupBy, orderBy);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function isValidArrayFormat(str, cb) {
|
|
334
|
+
try {
|
|
335
|
+
const parsed = JSON.parse(str);
|
|
336
|
+
cb(null, Array.isArray(parsed), str);
|
|
337
|
+
} catch (err) {
|
|
338
|
+
cb(err, false, null);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// function parseRawQuery(search) {
|
|
343
|
+
// const rawParams = {};
|
|
344
|
+
// if (search.startsWith('?')) {
|
|
345
|
+
// const queryString = search.slice(1); // Remove '?'
|
|
346
|
+
// const pairs = queryString.split('&');
|
|
347
|
+
|
|
348
|
+
// for (const pair of pairs) {
|
|
349
|
+
// const [key, value = ''] = pair.split('=');
|
|
350
|
+
// if (key) {
|
|
351
|
+
// rawParams[key] = value;
|
|
352
|
+
// }
|
|
353
|
+
// }
|
|
354
|
+
// }
|
|
355
|
+
// return rawParams;
|
|
356
|
+
// }
|
|
357
|
+
|
|
358
|
+
async function findAll(Project, where, offset, group, order, limitRow, cb) {
|
|
359
|
+
try {
|
|
360
|
+
await Project.findAll({
|
|
361
|
+
where,
|
|
362
|
+
group: (group.groupby) ? group.groupby : [],
|
|
363
|
+
order: (order.orderby) ? [order.orderby] : [],
|
|
364
|
+
offset: offset,
|
|
365
|
+
limit: limitRow,
|
|
366
|
+
}).then((results) => {
|
|
367
|
+
cb(null, results)
|
|
368
|
+
}).catch((error) => {
|
|
369
|
+
cb(error, null);
|
|
370
|
+
});
|
|
371
|
+
} catch (error) {
|
|
372
|
+
cb(error, null);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
async function retrieving(authEndpoint, Projects, req, res, next) {
|
|
377
|
+
let params = req.params;
|
|
378
|
+
let hash = "/" + req.params.hash;
|
|
379
|
+
// allow official stetragy
|
|
380
|
+
if(hash == authEndpoint && (params[0] == "/facebook" || params[0] == "/facebook/callback" || params[0] == "/google" || params[0] == "/google/callback")) {
|
|
381
|
+
return next();
|
|
382
|
+
}
|
|
383
|
+
// declare variable for check request with params
|
|
384
|
+
let leaveMeAlone = await Projects.slice(0);
|
|
385
|
+
let mergeDuoVar = [req.params.limit, req.params.offset].map((e) => (e || 'undefined')).join("/");
|
|
386
|
+
let reqUrl = req.originalUrl.replace(_publicPath_, '/');
|
|
387
|
+
let checkConditionIsQueryOrId = Object.keys(req.query).length
|
|
388
|
+
? req.query
|
|
389
|
+
: 'undefined';
|
|
390
|
+
/**
|
|
391
|
+
* Function whereCond with callback property
|
|
392
|
+
*
|
|
393
|
+
* @where Object|String
|
|
394
|
+
*
|
|
395
|
+
*/
|
|
396
|
+
whereCond(checkConditionIsQueryOrId, async (err, where, groupBy, orderBy) => {
|
|
397
|
+
if(err) {
|
|
398
|
+
res.status(400).json({
|
|
399
|
+
code: 400,
|
|
400
|
+
status: "BAD_REQUEST",
|
|
401
|
+
err: String(err),
|
|
402
|
+
});
|
|
403
|
+
} else {
|
|
404
|
+
/**
|
|
405
|
+
* Filter Project with callback property
|
|
406
|
+
*
|
|
407
|
+
* @err String
|
|
408
|
+
* @Project Require
|
|
409
|
+
* @params Object [0=limit, 1=offset]
|
|
410
|
+
*
|
|
411
|
+
*/
|
|
412
|
+
await filterProject(leaveMeAlone, reqUrl, "/".concat(mergeDuoVar), "", req, res, async (err, Project, params) => {
|
|
413
|
+
if (!err) {
|
|
414
|
+
try {
|
|
415
|
+
// declare default limit offset
|
|
416
|
+
let offset = 0;
|
|
417
|
+
let limitRow = await (Project.options.limitRows) ? Project.options.limitRows : 100;
|
|
418
|
+
// check assign limit, offset ?
|
|
419
|
+
if ((params[0] && params[0] != 'undefined') && ((params[1] && params[1] != 'undefined') || parseInt(params[1]) === 0)) {
|
|
420
|
+
// Only case: /limit/offset
|
|
421
|
+
limitRow = parseInt(params[0]);
|
|
422
|
+
offset = parseInt(params[1]);
|
|
423
|
+
}
|
|
424
|
+
// findAll data
|
|
425
|
+
await findAll(Project, where, offset, groupBy, orderBy, limitRow, (err, results) => {
|
|
426
|
+
if(err) {
|
|
427
|
+
res.status(500).json({
|
|
428
|
+
code: 500,
|
|
429
|
+
status: "READ_CATCH",
|
|
430
|
+
err: String(err),
|
|
431
|
+
});
|
|
432
|
+
} else {
|
|
433
|
+
// @ return findAll
|
|
434
|
+
res.json({
|
|
435
|
+
code: 200,
|
|
436
|
+
status: "SUCCESS",
|
|
437
|
+
results,
|
|
438
|
+
length: results.length,
|
|
439
|
+
limitRow,
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
});
|
|
443
|
+
} catch (error) {
|
|
444
|
+
// @return
|
|
445
|
+
return errMessage(error, res);
|
|
446
|
+
}
|
|
447
|
+
} else {
|
|
448
|
+
// @return
|
|
449
|
+
return errMessage(err, res);
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Duplicater cache for each config, avoid create new instance with same config
|
|
457
|
+
const duplicaterCache = new Map();
|
|
458
|
+
function getDuplicaterInstance(dupConfig = {}) {
|
|
459
|
+
const key = JSON.stringify(dupConfig || {});
|
|
460
|
+
if (!duplicaterCache.has(key)) {
|
|
461
|
+
duplicaterCache.set(key, Duplicater(dupConfig || {}));
|
|
462
|
+
}
|
|
463
|
+
return duplicaterCache.get(key);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// Limiter cache for each config, avoid create new instance with same config
|
|
467
|
+
const limiterCache = new Map();
|
|
468
|
+
function getLimiterInstance(rateConfig = {}) {
|
|
469
|
+
const key = JSON.stringify(rateConfig);
|
|
470
|
+
if (!limiterCache.has(key)) {
|
|
471
|
+
limiterCache.set(key, Limiter(rateConfig));
|
|
472
|
+
}
|
|
473
|
+
return limiterCache.get(key);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
const byPassCheckRole = (Projects, method, passport_config) => {
|
|
477
|
+
return async function (req, res, next) {
|
|
478
|
+
try {
|
|
479
|
+
if(passport_config[0] !== undefined) {
|
|
480
|
+
if(req.params.hash == passport_config[0].replace(/^\/|\/$/g, "")) {
|
|
481
|
+
return next();
|
|
482
|
+
} else {
|
|
483
|
+
if(passport_config[1].jwt_allow === true) {
|
|
484
|
+
let leaveMeAlone = await Projects.slice(0);
|
|
485
|
+
await filterProjectForByPass(leaveMeAlone, req.originalUrl.replace(_publicPath_, '/'), req, res, async (err, Project) => {
|
|
486
|
+
if(!err) {
|
|
487
|
+
// Set Duplicater and Limiter for each project with method
|
|
488
|
+
const dupConfig = (Project.options?.defaultEndpoint?.[method]?.duplicate_request) ? Project.options.defaultEndpoint[method].duplicate_request : {};
|
|
489
|
+
const duplicaterMiddleware = getDuplicaterInstance(dupConfig);
|
|
490
|
+
return duplicaterMiddleware(req, res, (err) => {
|
|
491
|
+
if (!err) {
|
|
492
|
+
const rateConfig = (Project.options?.defaultEndpoint?.[method]?.rate_limit) ? Project.options.defaultEndpoint[method].rate_limit : {};
|
|
493
|
+
const limiterMiddleware = getLimiterInstance(rateConfig);
|
|
494
|
+
limiterMiddleware(req, res, (err) => {
|
|
495
|
+
if (!err) {
|
|
496
|
+
if(Project.options.defaultEndpoint === undefined || Project.options.defaultEndpoint === true) {
|
|
497
|
+
// Project is not use options
|
|
498
|
+
return Credentials(req, res, () => {
|
|
499
|
+
return checkRoleMiddlewareWithDefaultProject(null)(req, res, next);
|
|
500
|
+
});
|
|
501
|
+
} else {
|
|
502
|
+
// Method is set
|
|
503
|
+
if(Project.options.defaultEndpoint[method]) {
|
|
504
|
+
if(Project.options.defaultEndpoint[method]["allow"] === undefined || Project.options.defaultEndpoint[method]["allow"] === true) {
|
|
505
|
+
if(Project.options.defaultEndpoint[method]["jwt"]?.allow === false) {
|
|
506
|
+
// by project jwt_allow is false
|
|
507
|
+
return checkRoleMiddlewareWithDefaultProject(null)(req, res, next);
|
|
508
|
+
} else {
|
|
509
|
+
//return Credentials(req, res, () => {
|
|
510
|
+
// return checkRoleMiddlewareWithDefaultProject(Project.options.defaultEndpoint[method].jwt?.broken_role)(req, res, next);
|
|
511
|
+
//});
|
|
512
|
+
return Credentials(req, res, () => checkRoleMiddlewareWithDefaultProject(Project.options.defaultEndpoint[method].jwt?.broken_role || null)(req, res, next));
|
|
513
|
+
}
|
|
514
|
+
} else {
|
|
515
|
+
// METHOD.allow is false || METHOD.allow is undefined
|
|
516
|
+
return notfound(res);
|
|
517
|
+
}
|
|
518
|
+
} else if(Project.options.defaultEndpoint[method] === true || Project.options.defaultEndpoint[method] === undefined) {
|
|
519
|
+
// Method is not set
|
|
520
|
+
return Credentials(req, res, () => {
|
|
521
|
+
return checkRoleMiddlewareWithDefaultProject(null)(req, res, next);
|
|
522
|
+
});
|
|
523
|
+
} else {
|
|
524
|
+
// METHOD is false || METHOD is not undefined
|
|
525
|
+
return notfound(res);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
} else {
|
|
529
|
+
return res.status(429).json({
|
|
530
|
+
code: 429,
|
|
531
|
+
status: "TOO_MANY_REQUEST",
|
|
532
|
+
message: "Too Many Requests.",
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
});
|
|
536
|
+
} else {
|
|
537
|
+
return res.status(409).json({
|
|
538
|
+
code: 409,
|
|
539
|
+
status: "DUPLICATE_REQUEST",
|
|
540
|
+
message: "Duplicate request detected.",
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
});
|
|
544
|
+
} else {
|
|
545
|
+
return errMessage(err, res);
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
} else {
|
|
549
|
+
// global jwt_allow is false
|
|
550
|
+
return next();
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
} else {
|
|
554
|
+
// passport config not found
|
|
555
|
+
return next();
|
|
556
|
+
}
|
|
557
|
+
} catch (error) {
|
|
558
|
+
return errMessage(error, res);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
function Base() {
|
|
564
|
+
return new Promise((resolve, reject) => {
|
|
565
|
+
try {
|
|
566
|
+
walkModel((err, Projects) => {
|
|
567
|
+
if (err) {
|
|
568
|
+
reject(err);
|
|
569
|
+
} else {
|
|
570
|
+
const checkPassport = new Promise((resolve) => {
|
|
571
|
+
const passport_config_file = appRoot + "/passport.config.js";
|
|
572
|
+
let passport_config_auth = undefined;
|
|
573
|
+
if (fs.existsSync(passport_config_file)) {
|
|
574
|
+
const _passport_config_ = require(passport_config_file);
|
|
575
|
+
resolve([_passport_config_.auth_endpoint || "/authentication", _passport_config_]);
|
|
576
|
+
} else {
|
|
577
|
+
// passport config not found
|
|
578
|
+
resolve([passport_config_auth, {}]);
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
// passport conifg promise
|
|
582
|
+
checkPassport.then((passport_config) => {
|
|
583
|
+
if(Projects.length) {
|
|
584
|
+
// GET method with /:limit/:offset
|
|
585
|
+
endpoint.get("/:hash([a-zA-Z0-9-]+)*/:limit([0-9]+)/:offset([0-9]+)", (req, res, next) => byPassCheckRole(Projects, "GET", passport_config)(req, res, next), async (req, res, next) => {
|
|
586
|
+
await retrieving(passport_config[0], Projects, req, res, next);
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
// GET method only hash/*
|
|
590
|
+
endpoint.get("/:hash([a-zA-Z0-9-]+)*", (req, res, next) => byPassCheckRole(Projects, "GET", passport_config)(req, res, next), async (req, res, next) => {
|
|
591
|
+
await retrieving(passport_config[0], Projects, req, res, next);
|
|
592
|
+
});
|
|
593
|
+
|
|
594
|
+
// POST method
|
|
595
|
+
endpoint.post("/:hash*", (req, res, next) => byPassCheckRole(Projects, "POST", passport_config)(req, res, next), async (req, res, next) => {
|
|
596
|
+
// Check auth request match send next
|
|
597
|
+
if(passport_config[0] !== undefined) {
|
|
598
|
+
if(req.params.hash == passport_config[0].replace(/^\/|\/$/g, "")) {
|
|
599
|
+
return next();
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
// When lost IF
|
|
603
|
+
let leaveMeAlone = await Projects.slice(0);
|
|
604
|
+
let reqUrl = req.originalUrl.replace(_publicPath_, '/');
|
|
605
|
+
let bodyIsArray = Array.isArray(req.body);
|
|
606
|
+
await filterProject(leaveMeAlone, reqUrl, "", "", req, res, async (err, Project) => {
|
|
607
|
+
if (!err) {
|
|
608
|
+
try {
|
|
609
|
+
// Leave pool by project for check pool error
|
|
610
|
+
let pool = Project.sequelize;
|
|
611
|
+
// Transaction create
|
|
612
|
+
Project.transaction(async t => {
|
|
613
|
+
try {
|
|
614
|
+
if (bodyIsArray) {
|
|
615
|
+
// Store with bulk body
|
|
616
|
+
const bulkCreated = await Project.bulkCreate(req.body, { transaction: t });
|
|
617
|
+
await t.commit();
|
|
618
|
+
// @return
|
|
619
|
+
res.status(201).json({
|
|
620
|
+
code: 201,
|
|
621
|
+
status: "CREATE_SUCCESS",
|
|
622
|
+
mode: {
|
|
623
|
+
type: "BULK",
|
|
624
|
+
affectedRows: bulkCreated.length,
|
|
625
|
+
},
|
|
626
|
+
createdId: [
|
|
627
|
+
...bulkCreated.map(item => (item.id) ? item.id : item[Project.primaryKeyAttributes[0]]),
|
|
628
|
+
],
|
|
629
|
+
});
|
|
630
|
+
} else {
|
|
631
|
+
// Store with single body
|
|
632
|
+
const singleCreated = await Project.create(req.body, { transaction: t });
|
|
633
|
+
await t.commit();
|
|
634
|
+
// @return
|
|
635
|
+
res.status(201).json({
|
|
636
|
+
code: 201,
|
|
637
|
+
status: "CREATE_SUCCESS",
|
|
638
|
+
mode: {
|
|
639
|
+
type: "SINGLE",
|
|
640
|
+
affectedRows: 1,
|
|
641
|
+
},
|
|
642
|
+
createdId: (singleCreated.id) ? singleCreated.id : singleCreated[Project.primaryKeyAttributes[0]],
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
} catch (error) {
|
|
646
|
+
await t.rollback();
|
|
647
|
+
if(pool.options.logging) {
|
|
648
|
+
// @return with all error
|
|
649
|
+
res.status(501).json({
|
|
650
|
+
code: 501,
|
|
651
|
+
status: "CREATE_FAILED",
|
|
652
|
+
mode: {
|
|
653
|
+
debug: true,
|
|
654
|
+
type: (bodyIsArray) ? "BULK" : "SINGLE",
|
|
655
|
+
affectedRows: 0,
|
|
656
|
+
},
|
|
657
|
+
error: error,
|
|
658
|
+
});
|
|
659
|
+
} else {
|
|
660
|
+
if(error.sql) {
|
|
661
|
+
delete error.sql;
|
|
662
|
+
if(error.errors) {
|
|
663
|
+
delete error.errors;
|
|
664
|
+
}
|
|
665
|
+
if(error.parent) {
|
|
666
|
+
delete error.parent;
|
|
667
|
+
}
|
|
668
|
+
if(error.original) {
|
|
669
|
+
delete error.original.sql;
|
|
670
|
+
if(error.original.parameters) {
|
|
671
|
+
delete error.original.parameters;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
if(error.parameters) {
|
|
675
|
+
delete error.parameters;
|
|
676
|
+
}
|
|
677
|
+
// @return with some error
|
|
678
|
+
res.status(501).json({
|
|
679
|
+
code: 501,
|
|
680
|
+
status: "CREATE_FAILED",
|
|
681
|
+
mode: {
|
|
682
|
+
debug: false,
|
|
683
|
+
type: (bodyIsArray) ? "BULK" : "SINGLE",
|
|
684
|
+
affectedRows: 0,
|
|
685
|
+
},
|
|
686
|
+
error: error,
|
|
687
|
+
});
|
|
688
|
+
} else {
|
|
689
|
+
// @return with some string error
|
|
690
|
+
res.status(501).json({
|
|
691
|
+
code: 501,
|
|
692
|
+
status: "CREATE_FAILED",
|
|
693
|
+
mode: {
|
|
694
|
+
debug: false,
|
|
695
|
+
type: (bodyIsArray) ? "BULK" : "SINGLE",
|
|
696
|
+
affectedRows: 0,
|
|
697
|
+
},
|
|
698
|
+
error: String(error),
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
} catch (error) {
|
|
705
|
+
// @return
|
|
706
|
+
return errMessage(error, res);
|
|
707
|
+
}
|
|
708
|
+
} else {
|
|
709
|
+
// @return
|
|
710
|
+
return errMessage(err, res);
|
|
711
|
+
}
|
|
712
|
+
});
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
// PATCH method
|
|
716
|
+
endpoint.patch("/:hash*/:id([a-zA-Z0-9-]+)", (req, res, next) => byPassCheckRole(Projects, "PATCH", passport_config)(req, res, next), async (req, res, next) => {
|
|
717
|
+
let leaveMeAlone = await Projects.slice(0);
|
|
718
|
+
let reqUrl = req.originalUrl.replace(_publicPath_, '/');
|
|
719
|
+
await filterProject(leaveMeAlone, reqUrl, "", "PATCH", req, res, async (err, Project) => {
|
|
720
|
+
if (!err) {
|
|
721
|
+
try {
|
|
722
|
+
// Check body is empty
|
|
723
|
+
if(Object.keys(req.body).length === 0) {
|
|
724
|
+
return res.status(400).json({
|
|
725
|
+
code: 400,
|
|
726
|
+
status: "BAD_REQUEST",
|
|
727
|
+
message: "Bad request.",
|
|
728
|
+
info: {
|
|
729
|
+
status: "BAD_ENTIRY",
|
|
730
|
+
message: "Unprocessable Entity.",
|
|
731
|
+
},
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
// Leave pool by project for check pool error
|
|
735
|
+
let pool = Project.sequelize;
|
|
736
|
+
// Transaction update|patch
|
|
737
|
+
Project.transaction(async t => {
|
|
738
|
+
try {
|
|
739
|
+
// Assign update pk
|
|
740
|
+
let updatePk = { [Project.primaryKeyAttributes[0]]: req.params.id };
|
|
741
|
+
// Patch with body
|
|
742
|
+
const updated = await Project.update(req.body, {
|
|
743
|
+
where: updatePk,
|
|
744
|
+
}, { transaction: t });
|
|
745
|
+
if(updated[0]) {
|
|
746
|
+
await t.commit();
|
|
747
|
+
// @return
|
|
748
|
+
res.status(200).json({
|
|
749
|
+
code: 200,
|
|
750
|
+
status: "UPDATE_SUCCESS",
|
|
751
|
+
mode: {
|
|
752
|
+
debug: true,
|
|
753
|
+
},
|
|
754
|
+
result: {
|
|
755
|
+
updateId: req.params.id,
|
|
756
|
+
affectedRows: updated[0],
|
|
757
|
+
},
|
|
758
|
+
});
|
|
759
|
+
} else {
|
|
760
|
+
await t.rollback();
|
|
761
|
+
res.status(406).json({
|
|
762
|
+
code: 406,
|
|
763
|
+
status: "NOT_ACCEPTABLE",
|
|
764
|
+
result: {
|
|
765
|
+
affectedRows: updated[0],
|
|
766
|
+
},
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
} catch (error) {
|
|
770
|
+
await t.rollback();
|
|
771
|
+
if(pool.options.logging) {
|
|
772
|
+
// @return with all error
|
|
773
|
+
res.status(501).json({
|
|
774
|
+
code: 501,
|
|
775
|
+
status: "UPDATE_FAILED",
|
|
776
|
+
mode: {
|
|
777
|
+
debug: false,
|
|
778
|
+
},
|
|
779
|
+
error: error,
|
|
780
|
+
});
|
|
781
|
+
} else {
|
|
782
|
+
if(error.sql) {
|
|
783
|
+
delete error.sql;
|
|
784
|
+
if(error.parent) {
|
|
785
|
+
delete error.parent;
|
|
786
|
+
}
|
|
787
|
+
if(error.original) {
|
|
788
|
+
delete error.original.sql;
|
|
789
|
+
if(error.original.parameters) {
|
|
790
|
+
delete error.original.parameters;
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
if(error.parameters) {
|
|
794
|
+
delete error.parameters;
|
|
795
|
+
}
|
|
796
|
+
if(error.errors) {
|
|
797
|
+
delete error.errors;
|
|
798
|
+
}
|
|
799
|
+
// @return with some error
|
|
800
|
+
res.status(501).json({
|
|
801
|
+
code: 501,
|
|
802
|
+
status: "UPDATE_FAILED",
|
|
803
|
+
mode: {
|
|
804
|
+
debug: false,
|
|
805
|
+
},
|
|
806
|
+
error: error,
|
|
807
|
+
});
|
|
808
|
+
} else {
|
|
809
|
+
// @return with some string error
|
|
810
|
+
res.status(501).json({
|
|
811
|
+
code: 501,
|
|
812
|
+
status: "UPDATE_FAILED",
|
|
813
|
+
mode: {
|
|
814
|
+
debug: false,
|
|
815
|
+
},
|
|
816
|
+
error: String(error),
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
});
|
|
822
|
+
} catch (error) {
|
|
823
|
+
// @return
|
|
824
|
+
return errMessage(error, res);
|
|
825
|
+
}
|
|
826
|
+
} else {
|
|
827
|
+
// @return
|
|
828
|
+
return errMessage(err, res);
|
|
829
|
+
}
|
|
830
|
+
});
|
|
831
|
+
});
|
|
832
|
+
|
|
833
|
+
// DELETE method
|
|
834
|
+
endpoint.delete("/:hash*/:id([a-zA-Z0-9-]+)", (req, res, next) => byPassCheckRole(Projects, "DELETE", passport_config)(req, res, next), async (req, res, next) => {
|
|
835
|
+
let leaveMeAlone = await Projects.slice(0);
|
|
836
|
+
await filterProject(leaveMeAlone, req.originalUrl.replace(_publicPath_, '/'), "", "DELETE", req, res, async (err, Project) => {
|
|
837
|
+
if (!err) {
|
|
838
|
+
try {
|
|
839
|
+
// Leave pool by project for check pool error
|
|
840
|
+
let pool = Project.sequelize;
|
|
841
|
+
// Transaction update|patch
|
|
842
|
+
Project.transaction(async t => {
|
|
843
|
+
try {
|
|
844
|
+
// Assign delete pk
|
|
845
|
+
let deletePk = { [Project.primaryKeyAttributes[0]]: req.params.id };
|
|
846
|
+
// Delete with params
|
|
847
|
+
const deleted = await Project.destroy({
|
|
848
|
+
where: deletePk,
|
|
849
|
+
}, { transaction: t });
|
|
850
|
+
if (deleted) {
|
|
851
|
+
await t.commit();
|
|
852
|
+
// @return
|
|
853
|
+
res.status(200).json({
|
|
854
|
+
code: 200,
|
|
855
|
+
status: "DELETE_SUCCESS",
|
|
856
|
+
result: {
|
|
857
|
+
deleteId: req.params.id,
|
|
858
|
+
affectedRows: deleted,
|
|
859
|
+
},
|
|
860
|
+
});
|
|
861
|
+
} else {
|
|
862
|
+
await t.rollback();
|
|
863
|
+
res.status(406).json({
|
|
864
|
+
code: 406,
|
|
865
|
+
status: "NOT_ACCEPTABLE",
|
|
866
|
+
result: {
|
|
867
|
+
affectedRows: deleted,
|
|
868
|
+
},
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
} catch (error) {
|
|
872
|
+
if(pool.options.logging) {
|
|
873
|
+
// @return with all error
|
|
874
|
+
res.status(501).json({
|
|
875
|
+
code: 501,
|
|
876
|
+
status: "DELETE_FAILED",
|
|
877
|
+
mode: {
|
|
878
|
+
debug: true,
|
|
879
|
+
},
|
|
880
|
+
error: error,
|
|
881
|
+
});
|
|
882
|
+
} else {
|
|
883
|
+
if(error.sql) {
|
|
884
|
+
delete error.sql;
|
|
885
|
+
if(error.parent) {
|
|
886
|
+
delete error.parent;
|
|
887
|
+
}
|
|
888
|
+
if(error.original) {
|
|
889
|
+
delete error.original.sql;
|
|
890
|
+
if(error.original.parameters) {
|
|
891
|
+
delete error.original.parameters;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
if(error.parameters) {
|
|
895
|
+
delete error.parameters;
|
|
896
|
+
}
|
|
897
|
+
if(error.errors) {
|
|
898
|
+
delete error.errors;
|
|
899
|
+
}
|
|
900
|
+
// @return with some error
|
|
901
|
+
res.status(501).json({
|
|
902
|
+
code: 501,
|
|
903
|
+
status: "DELETE_FAILED",
|
|
904
|
+
mode: {
|
|
905
|
+
debug: false,
|
|
906
|
+
},
|
|
907
|
+
error: error,
|
|
908
|
+
});
|
|
909
|
+
} else {
|
|
910
|
+
// @return with some string error
|
|
911
|
+
res.status(501).json({
|
|
912
|
+
code: 501,
|
|
913
|
+
status: "DELETE_FAILED",
|
|
914
|
+
mode: {
|
|
915
|
+
debug: false,
|
|
916
|
+
},
|
|
917
|
+
error: String(error),
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
});
|
|
923
|
+
} catch (error) {
|
|
924
|
+
// @return
|
|
925
|
+
return errMessage(error, res);
|
|
926
|
+
}
|
|
927
|
+
} else {
|
|
928
|
+
// @return
|
|
929
|
+
return errMessage(err, res);
|
|
930
|
+
}
|
|
931
|
+
});
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
// resolve it.
|
|
935
|
+
resolve(true);
|
|
936
|
+
}).catch((err) => {
|
|
937
|
+
reject(err);
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
});
|
|
941
|
+
} catch (error) {
|
|
942
|
+
reject(error);
|
|
943
|
+
}
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
module.exports = { Base };
|