db-model-router 1.0.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/.env +7 -0
- package/LICENSE +201 -0
- package/README.md +505 -0
- package/docker-compose.yml +141 -0
- package/docs/README.md +208 -0
- package/docs/SKILL.md +202 -0
- package/docs/adapters/cockroachdb.md +49 -0
- package/docs/adapters/dynamodb.md +53 -0
- package/docs/adapters/mongodb.md +56 -0
- package/docs/adapters/mssql.md +55 -0
- package/docs/adapters/oracle.md +52 -0
- package/docs/adapters/postgres.md +50 -0
- package/docs/adapters/redis.md +53 -0
- package/docs/adapters/sqlite3.md +43 -0
- package/package.json +109 -0
- package/src/cli/generate-app.js +359 -0
- package/src/cli/generate-model.js +760 -0
- package/src/cli/generate-openapi.js +237 -0
- package/src/cli/generate-route.js +346 -0
- package/src/cockroachdb/db.js +563 -0
- package/src/commons/function.js +165 -0
- package/src/commons/model.js +444 -0
- package/src/commons/route.js +214 -0
- package/src/commons/validator.js +172 -0
- package/src/dynamodb/db.js +552 -0
- package/src/index.js +57 -0
- package/src/mongodb/db.js +381 -0
- package/src/mssql/db.js +461 -0
- package/src/mysql/db.js +527 -0
- package/src/oracle/db.js +855 -0
- package/src/oracle/sql_translator.js +406 -0
- package/src/postgres/db.js +666 -0
- package/src/postgres/ddl_translator.js +69 -0
- package/src/postgres/sql_translator.js +396 -0
- package/src/redis/db.js +448 -0
- package/src/serve.js +90 -0
- package/src/sqlite3/db.js +346 -0
package/src/redis/db.js
ADDED
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
const Redis = require("ioredis");
|
|
2
|
+
const { jsonSafeParse } = require("../commons/function");
|
|
3
|
+
|
|
4
|
+
let client = null;
|
|
5
|
+
let primaryKey = "id";
|
|
6
|
+
const WHERE_INVALID = "Invalid filter object";
|
|
7
|
+
|
|
8
|
+
function connect(config) {
|
|
9
|
+
const options = {};
|
|
10
|
+
if (config.host) options.host = config.host;
|
|
11
|
+
if (config.port) options.port = config.port;
|
|
12
|
+
if (config.password) options.password = config.password;
|
|
13
|
+
if (config.db != null) options.db = config.db;
|
|
14
|
+
|
|
15
|
+
if (config.primaryKey) primaryKey = config.primaryKey;
|
|
16
|
+
|
|
17
|
+
client = new Redis(options);
|
|
18
|
+
return client;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function where(filter, safeDelete = null) {
|
|
22
|
+
if (filter !== null && filter !== "" && !Array.isArray(filter)) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
if (
|
|
27
|
+
filter === null ||
|
|
28
|
+
filter === "" ||
|
|
29
|
+
filter.length === 0 ||
|
|
30
|
+
(Array.isArray(filter[0]) && filter[0].length === 0) ||
|
|
31
|
+
(Array.isArray(filter[0]) &&
|
|
32
|
+
Array.isArray(filter[0][0]) &&
|
|
33
|
+
filter[0][0].length === 0)
|
|
34
|
+
) {
|
|
35
|
+
if (safeDelete === null) {
|
|
36
|
+
return { query: () => true, value: [] };
|
|
37
|
+
} else {
|
|
38
|
+
filter = [[]];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
} catch (err) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (safeDelete !== null) {
|
|
46
|
+
for (const filterItem of filter) {
|
|
47
|
+
filterItem.push([safeDelete, "=", 0]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const valid_conditionals = [
|
|
52
|
+
"=",
|
|
53
|
+
"like",
|
|
54
|
+
"not like",
|
|
55
|
+
"in",
|
|
56
|
+
"not in",
|
|
57
|
+
"<",
|
|
58
|
+
">",
|
|
59
|
+
"<=",
|
|
60
|
+
">=",
|
|
61
|
+
"!=",
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
// Build filter groups for in-memory evaluation
|
|
65
|
+
const orGroups = [];
|
|
66
|
+
|
|
67
|
+
for (const group of filter) {
|
|
68
|
+
const andConditions = [];
|
|
69
|
+
for (const condition of group) {
|
|
70
|
+
if (!valid_conditionals.includes(condition[1])) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
if (
|
|
74
|
+
(condition[1] === "in" || condition[1] === "not in") &&
|
|
75
|
+
!Array.isArray(condition[2])
|
|
76
|
+
) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const field = condition[0];
|
|
81
|
+
const op = condition[1];
|
|
82
|
+
const val = condition[2];
|
|
83
|
+
|
|
84
|
+
andConditions.push(buildMatcher(field, op, val));
|
|
85
|
+
}
|
|
86
|
+
if (andConditions.length > 0) {
|
|
87
|
+
orGroups.push(andConditions);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const filterFn = (record) => {
|
|
92
|
+
if (orGroups.length === 0) return true;
|
|
93
|
+
return orGroups.some((andGroup) =>
|
|
94
|
+
andGroup.every((matcher) => matcher(record)),
|
|
95
|
+
);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
return { query: filterFn, value: [] };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function buildMatcher(field, op, val) {
|
|
102
|
+
switch (op) {
|
|
103
|
+
case "=":
|
|
104
|
+
return (rec) => coerce(rec[field]) == val;
|
|
105
|
+
case "!=":
|
|
106
|
+
return (rec) => coerce(rec[field]) != val;
|
|
107
|
+
case "<":
|
|
108
|
+
return (rec) => Number(rec[field]) < Number(val);
|
|
109
|
+
case ">":
|
|
110
|
+
return (rec) => Number(rec[field]) > Number(val);
|
|
111
|
+
case "<=":
|
|
112
|
+
return (rec) => Number(rec[field]) <= Number(val);
|
|
113
|
+
case ">=":
|
|
114
|
+
return (rec) => Number(rec[field]) >= Number(val);
|
|
115
|
+
case "like":
|
|
116
|
+
return (rec) => {
|
|
117
|
+
const str = String(rec[field] || "").toLowerCase();
|
|
118
|
+
return str.includes(String(val).toLowerCase());
|
|
119
|
+
};
|
|
120
|
+
case "not like":
|
|
121
|
+
return (rec) => {
|
|
122
|
+
const str = String(rec[field] || "").toLowerCase();
|
|
123
|
+
return !str.includes(String(val).toLowerCase());
|
|
124
|
+
};
|
|
125
|
+
case "in":
|
|
126
|
+
return (rec) => {
|
|
127
|
+
const v = coerce(rec[field]);
|
|
128
|
+
return val.some((item) => item == v);
|
|
129
|
+
};
|
|
130
|
+
case "not in":
|
|
131
|
+
return (rec) => {
|
|
132
|
+
const v = coerce(rec[field]);
|
|
133
|
+
return !val.some((item) => item == v);
|
|
134
|
+
};
|
|
135
|
+
default:
|
|
136
|
+
return () => true;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function coerce(val) {
|
|
141
|
+
if (val === undefined || val === null) return val;
|
|
142
|
+
// Redis stores everything as strings; try to coerce back to number
|
|
143
|
+
const num = Number(val);
|
|
144
|
+
if (!isNaN(num) && String(num) === val) return num;
|
|
145
|
+
return val;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async function scanAllKeys(pattern) {
|
|
149
|
+
const keys = [];
|
|
150
|
+
let cursor = "0";
|
|
151
|
+
do {
|
|
152
|
+
const [nextCursor, batch] = await client.scan(
|
|
153
|
+
cursor,
|
|
154
|
+
"MATCH",
|
|
155
|
+
pattern,
|
|
156
|
+
"COUNT",
|
|
157
|
+
100,
|
|
158
|
+
);
|
|
159
|
+
cursor = nextCursor;
|
|
160
|
+
keys.push(...batch);
|
|
161
|
+
} while (cursor !== "0");
|
|
162
|
+
return keys;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async function getAllRecords(table) {
|
|
166
|
+
const pattern = `${table}:*`;
|
|
167
|
+
const keys = await scanAllKeys(pattern);
|
|
168
|
+
// Filter out the sequence key
|
|
169
|
+
const seqKey = `${table}:__seq`;
|
|
170
|
+
const recordKeys = keys.filter((k) => k !== seqKey);
|
|
171
|
+
|
|
172
|
+
if (recordKeys.length === 0) return [];
|
|
173
|
+
|
|
174
|
+
const records = [];
|
|
175
|
+
for (const key of recordKeys) {
|
|
176
|
+
const hash = await client.hgetall(key);
|
|
177
|
+
if (hash && Object.keys(hash).length > 0) {
|
|
178
|
+
records.push(parseRecord(hash));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return records;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function parseRecord(hash) {
|
|
185
|
+
const record = {};
|
|
186
|
+
for (const [key, val] of Object.entries(hash)) {
|
|
187
|
+
// Try to parse JSON values (for nested objects/arrays)
|
|
188
|
+
try {
|
|
189
|
+
record[key] = JSON.parse(val);
|
|
190
|
+
} catch {
|
|
191
|
+
// Try numeric coercion
|
|
192
|
+
const num = Number(val);
|
|
193
|
+
if (!isNaN(num) && String(num) === val) {
|
|
194
|
+
record[key] = num;
|
|
195
|
+
} else {
|
|
196
|
+
record[key] = val;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return record;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function flattenForHash(data) {
|
|
204
|
+
const flat = {};
|
|
205
|
+
for (const [key, val] of Object.entries(data)) {
|
|
206
|
+
if (val === null || val === undefined) {
|
|
207
|
+
flat[key] = "";
|
|
208
|
+
} else if (typeof val === "object") {
|
|
209
|
+
flat[key] = JSON.stringify(val);
|
|
210
|
+
} else {
|
|
211
|
+
flat[key] = String(val);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return flat;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async function get(table, filter = [], sort = [], safeDelete = null) {
|
|
218
|
+
const whereData = where(filter, safeDelete);
|
|
219
|
+
if (whereData == null) {
|
|
220
|
+
throw new Error(WHERE_INVALID);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
let records = await getAllRecords(table);
|
|
224
|
+
records = records.filter(whereData.query);
|
|
225
|
+
|
|
226
|
+
if (sort && sort.length > 0) {
|
|
227
|
+
records = sortItems(records, sort);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return { data: jsonSafeParse(records), count: records.length };
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async function list(
|
|
234
|
+
table,
|
|
235
|
+
filter = [],
|
|
236
|
+
sort = [],
|
|
237
|
+
safeDelete = null,
|
|
238
|
+
page = 0,
|
|
239
|
+
limit = 30,
|
|
240
|
+
) {
|
|
241
|
+
const whereData = where(filter, safeDelete);
|
|
242
|
+
if (whereData == null) {
|
|
243
|
+
throw new Error(WHERE_INVALID);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
let records = await getAllRecords(table);
|
|
247
|
+
records = records.filter(whereData.query);
|
|
248
|
+
|
|
249
|
+
if (sort && sort.length > 0) {
|
|
250
|
+
records = sortItems(records, sort);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const count = records.length;
|
|
254
|
+
const offset = page * limit;
|
|
255
|
+
const paged = records.slice(offset, offset + limit);
|
|
256
|
+
|
|
257
|
+
return { data: jsonSafeParse(paged), count };
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async function qcount(table, filter, safeDelete = null) {
|
|
261
|
+
const whereData = where(filter, safeDelete);
|
|
262
|
+
if (whereData == null) {
|
|
263
|
+
return 0;
|
|
264
|
+
}
|
|
265
|
+
try {
|
|
266
|
+
let records = await getAllRecords(table);
|
|
267
|
+
records = records.filter(whereData.query);
|
|
268
|
+
return records.length;
|
|
269
|
+
} catch (err) {
|
|
270
|
+
return 0;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async function remove(table, filter, safeDelete = null) {
|
|
275
|
+
const whereData = where(filter);
|
|
276
|
+
if (whereData == null) {
|
|
277
|
+
throw new Error(WHERE_INVALID);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Check if filter is effectively empty
|
|
281
|
+
let records = await getAllRecords(table);
|
|
282
|
+
const allMatch = records.filter(whereData.query);
|
|
283
|
+
|
|
284
|
+
// If the filter was empty (matches everything), check if we have actual filter conditions
|
|
285
|
+
const emptyFilter = where(filter);
|
|
286
|
+
if (
|
|
287
|
+
emptyFilter &&
|
|
288
|
+
typeof emptyFilter.query === "function" &&
|
|
289
|
+
filter != null &&
|
|
290
|
+
(filter === "" ||
|
|
291
|
+
filter.length === 0 ||
|
|
292
|
+
(filter.length > 0 && filter[0].length === 0))
|
|
293
|
+
) {
|
|
294
|
+
throw new Error("unable to remove as there are no filter attributes");
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (safeDelete != null) {
|
|
298
|
+
for (const record of allMatch) {
|
|
299
|
+
const pkVal = record[primaryKey];
|
|
300
|
+
if (pkVal != null) {
|
|
301
|
+
await client.hset(`${table}:${pkVal}`, safeDelete, "1");
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
} else {
|
|
305
|
+
for (const record of allMatch) {
|
|
306
|
+
const pkVal = record[primaryKey];
|
|
307
|
+
if (pkVal != null) {
|
|
308
|
+
await client.del(`${table}:${pkVal}`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const rows = allMatch.length;
|
|
314
|
+
return {
|
|
315
|
+
message: rows + " " + table + (rows > 1 ? "s" : "") + " removed",
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
async function upsert(table, data, uniqueKeys = []) {
|
|
320
|
+
let array = Array.isArray(data) ? [...data] : [data];
|
|
321
|
+
const total = array.length;
|
|
322
|
+
|
|
323
|
+
if (!uniqueKeys || uniqueKeys.length === 0) {
|
|
324
|
+
return insert(table, data, uniqueKeys);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
let lastId = null;
|
|
328
|
+
for (const row of array) {
|
|
329
|
+
// Find existing record by unique keys
|
|
330
|
+
let pkVal = row[primaryKey];
|
|
331
|
+
|
|
332
|
+
if (pkVal == null) {
|
|
333
|
+
// Try to find existing record by unique key match
|
|
334
|
+
const records = await getAllRecords(table);
|
|
335
|
+
const existing = records.find((rec) =>
|
|
336
|
+
uniqueKeys.every((k) => rec[k] != null && rec[k] == row[k]),
|
|
337
|
+
);
|
|
338
|
+
if (existing) {
|
|
339
|
+
pkVal = existing[primaryKey];
|
|
340
|
+
} else {
|
|
341
|
+
// Generate new id
|
|
342
|
+
pkVal = await client.incr(`${table}:__seq`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const record = { ...row, [primaryKey]: pkVal };
|
|
347
|
+
const flat = flattenForHash(record);
|
|
348
|
+
await client.hset(`${table}:${pkVal}`, flat);
|
|
349
|
+
lastId = pkVal;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const response = {
|
|
353
|
+
rows: total,
|
|
354
|
+
message:
|
|
355
|
+
(total === 1
|
|
356
|
+
? `1 ${namify(table)} is `
|
|
357
|
+
: `${total} ${namify(table)}s are `) + "saved",
|
|
358
|
+
type: "success",
|
|
359
|
+
};
|
|
360
|
+
if (total === 1 && lastId != null) {
|
|
361
|
+
response.id = lastId;
|
|
362
|
+
}
|
|
363
|
+
return response;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
async function insert(table, data, uniqueKeys = []) {
|
|
367
|
+
let array = Array.isArray(data) ? [...data] : [data];
|
|
368
|
+
const total = array.length;
|
|
369
|
+
|
|
370
|
+
try {
|
|
371
|
+
let lastId = null;
|
|
372
|
+
for (const row of array) {
|
|
373
|
+
let pkVal = row[primaryKey];
|
|
374
|
+
|
|
375
|
+
if (pkVal == null) {
|
|
376
|
+
// Auto-generate id using Redis INCR
|
|
377
|
+
pkVal = await client.incr(`${table}:__seq`);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const record = { ...row, [primaryKey]: pkVal };
|
|
381
|
+
const flat = flattenForHash(record);
|
|
382
|
+
await client.hset(`${table}:${pkVal}`, flat);
|
|
383
|
+
lastId = pkVal;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const response = {
|
|
387
|
+
rows: total,
|
|
388
|
+
message:
|
|
389
|
+
(total === 1
|
|
390
|
+
? `1 ${namify(table)} is `
|
|
391
|
+
: `${total} ${namify(table)}s are `) + "saved",
|
|
392
|
+
type: "success",
|
|
393
|
+
};
|
|
394
|
+
if (total === 1 && lastId != null) {
|
|
395
|
+
response.id = lastId;
|
|
396
|
+
}
|
|
397
|
+
return response;
|
|
398
|
+
} catch (err) {
|
|
399
|
+
throw err;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
async function disconnect() {
|
|
404
|
+
if (client) {
|
|
405
|
+
await client.quit();
|
|
406
|
+
client = null;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// --- Utility helpers ---
|
|
411
|
+
|
|
412
|
+
function sortItems(items, sort) {
|
|
413
|
+
return [...items].sort((a, b) => {
|
|
414
|
+
for (const s of sort) {
|
|
415
|
+
let field, dir;
|
|
416
|
+
if (s[0] === "-") {
|
|
417
|
+
field = s.substring(1);
|
|
418
|
+
dir = -1;
|
|
419
|
+
} else {
|
|
420
|
+
field = s;
|
|
421
|
+
dir = 1;
|
|
422
|
+
}
|
|
423
|
+
if (a[field] < b[field]) return -1 * dir;
|
|
424
|
+
if (a[field] > b[field]) return 1 * dir;
|
|
425
|
+
}
|
|
426
|
+
return 0;
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function namify(text) {
|
|
431
|
+
return text
|
|
432
|
+
.replace("_", " ")
|
|
433
|
+
.replace(/(^\w{1})|(\s+\w{1})/g, (letter) => letter.toUpperCase());
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
module.exports = {
|
|
437
|
+
connect,
|
|
438
|
+
get,
|
|
439
|
+
list,
|
|
440
|
+
where,
|
|
441
|
+
qcount,
|
|
442
|
+
remove,
|
|
443
|
+
upsert,
|
|
444
|
+
change: upsert,
|
|
445
|
+
insert,
|
|
446
|
+
disconnect,
|
|
447
|
+
close: disconnect,
|
|
448
|
+
};
|
package/src/serve.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
require("dotenv").config();
|
|
2
|
+
let express;
|
|
3
|
+
try {
|
|
4
|
+
express = require("ultimate-express");
|
|
5
|
+
} catch (_) {
|
|
6
|
+
express = require("express");
|
|
7
|
+
}
|
|
8
|
+
const app = express();
|
|
9
|
+
const bodyParser = require("body-parser");
|
|
10
|
+
app.use(bodyParser.json({ limit: "128mb" }));
|
|
11
|
+
app.use(
|
|
12
|
+
bodyParser.urlencoded({
|
|
13
|
+
extended: true,
|
|
14
|
+
}),
|
|
15
|
+
);
|
|
16
|
+
app.use((err, req, res, next) => {
|
|
17
|
+
if (err instanceof SyntaxError && err.status === 400 && "body" in err) {
|
|
18
|
+
return res.status(400).send(err); // Bad request
|
|
19
|
+
}
|
|
20
|
+
next();
|
|
21
|
+
});
|
|
22
|
+
let port = 3000;
|
|
23
|
+
if (process.env.NODE_ENV === "TEST") {
|
|
24
|
+
port = process.env.TEST_PORT;
|
|
25
|
+
} else {
|
|
26
|
+
port = process.env.port;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const { db, model, route } = require("./index");
|
|
30
|
+
db.connect({
|
|
31
|
+
connectionLimit: 100,
|
|
32
|
+
host: process.env.DB_HOST,
|
|
33
|
+
user: process.env.DB_USER,
|
|
34
|
+
password: process.env.DB_PASS,
|
|
35
|
+
database: process.env.DB_NAME,
|
|
36
|
+
port: process.env.DB_PORT,
|
|
37
|
+
charset: "utf8mb4",
|
|
38
|
+
});
|
|
39
|
+
const test = model(
|
|
40
|
+
db,
|
|
41
|
+
"test",
|
|
42
|
+
{
|
|
43
|
+
test_id: "required|integer",
|
|
44
|
+
user_id: "required|integer",
|
|
45
|
+
name: "required|string",
|
|
46
|
+
description: "string",
|
|
47
|
+
type: "required|integer",
|
|
48
|
+
info: "object",
|
|
49
|
+
is_deleted: "boolean",
|
|
50
|
+
},
|
|
51
|
+
"test_id",
|
|
52
|
+
[],
|
|
53
|
+
{ safeDelete: "is_deleted" },
|
|
54
|
+
);
|
|
55
|
+
app.use((req, res, next) => {
|
|
56
|
+
req.user = { user_id: "2" };
|
|
57
|
+
next();
|
|
58
|
+
});
|
|
59
|
+
app.use("/test", route(test, { user_id: "user.user_id" }));
|
|
60
|
+
app.use("*", (req, res) => {
|
|
61
|
+
res.send({ message: "Not Found" });
|
|
62
|
+
});
|
|
63
|
+
app.listen(port, () => {
|
|
64
|
+
console.log(`Example app listening at http://localhost:${port}`);
|
|
65
|
+
});
|
|
66
|
+
function authenticate(param) {
|
|
67
|
+
return function (req, res, next) {
|
|
68
|
+
// Is Loggedin
|
|
69
|
+
if (
|
|
70
|
+
!req.hasOwnProperty("session") ||
|
|
71
|
+
!req.session.hasOwnProperty("user_id")
|
|
72
|
+
) {
|
|
73
|
+
res.status(401);
|
|
74
|
+
res.send({ message: "user not loggedin" });
|
|
75
|
+
} else {
|
|
76
|
+
// Is Role permitting the usage of this api
|
|
77
|
+
if (!param.role.includes(req.session.role_selected.role)) {
|
|
78
|
+
res.status(401);
|
|
79
|
+
res.send({ message: "user not allowed to access this endpoint" });
|
|
80
|
+
}
|
|
81
|
+
// Is Account Offering permitting the usage of this api
|
|
82
|
+
if (!req.session.role_selected.offering.includes(param.offering)) {
|
|
83
|
+
res.status(401);
|
|
84
|
+
res.send({ message: "user not allowed to access this endpoint" });
|
|
85
|
+
}
|
|
86
|
+
//TODO: fine grain control needs to be written
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
module.exports = app;
|