beech-api 3.7.23 → 3.8.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/README.md +490 -168
- package/index.js +2 -2
- package/package.json +8 -1
- package/packages/cli/beech +2 -2
- package/packages/cli/bin/beech-app.js +10 -8
- package/packages/cli/bin/beech-service.js +1 -1
- package/packages/cli/core/auth/Credentials.js +139 -89
- package/packages/cli/core/auth/Passport.js +264 -164
- package/packages/cli/core/auth/_Request.js +1 -1
- package/packages/cli/core/configure/app.config-basic.js +2 -2
- package/packages/cli/core/configure/app.config-sequelize.js +2 -2
- package/packages/cli/core/configure/beech.config.js +1 -0
- package/packages/cli/core/configure/passport.config.js +33 -13
- package/packages/cli/core/databases/sequelize.js +3 -0
- package/packages/cli/core/databases/test.js +5 -3
- package/packages/cli/core/generator/_endpoints +5 -9
- package/packages/cli/core/generator/_endpoints_basic +11 -8
- package/packages/cli/core/generator/_help +1 -1
- package/packages/cli/core/generator/_models +5 -4
- package/packages/cli/core/generator/_models_basic +2 -2
- package/packages/cli/core/generator/_package +5 -1
- package/packages/cli/core/generator/{_add-on → _scheduler} +1 -1
- package/packages/cli/core/generator/_spec +15 -10
- package/packages/cli/core/generator/index.js +19 -44
- package/packages/cli/core/helpers/2fa.js +85 -0
- package/packages/cli/core/helpers/math.js +55 -7
- package/packages/cli/core/helpers/poolEntity.js +29 -1
- package/packages/cli/core/index.js +65 -34
- package/packages/cli/core/middleware/express/duplicateRequest.js +12 -0
- package/packages/cli/core/middleware/express/jwtCheckAllow.js +68 -0
- package/packages/cli/core/middleware/express/rateLimit.js +17 -0
- package/packages/cli/core/middleware/express/slowDown.js +2 -0
- package/packages/cli/core/middleware/index.js +6 -0
- package/packages/cli/core/middleware/origin/guard/advance.js +74 -0
- package/packages/cli/core/{origin → middleware/origin}/whitelist/cors.js +15 -12
- package/packages/cli/core/services/http.express.js +116 -72
- package/packages/lib/index.js +3 -1
- package/packages/lib/src/endpoint.js +523 -89
- package/packages/lib/src/guard.js +61 -0
- package/packages/lib/src/schema.js +57 -26
- package/packages/lib/src/specificExpress.js +7 -0
- package/packages/lib/src/user.js +94 -18
- package/packages/cli/core/origin/index.js +0 -2
|
@@ -57,6 +57,9 @@ connectInProcess = async (database_config, headDbShow, cb) => {
|
|
|
57
57
|
password: final[0][1],
|
|
58
58
|
database: val.database,
|
|
59
59
|
port: val.port,
|
|
60
|
+
|
|
61
|
+
// set connection timezone
|
|
62
|
+
timezone: val.timezone || "+00:00",
|
|
60
63
|
|
|
61
64
|
// the storage engine for sqlite
|
|
62
65
|
// - default ':memory:'
|
|
@@ -15,7 +15,9 @@ function filterDbIsTrue(dbConfig, cb) {
|
|
|
15
15
|
if(dbIsTrue.length) {
|
|
16
16
|
console.log('\n[102m[90m Pre-Flight [0m [0mTesting Database connection:');
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
setTimeout(() => {
|
|
19
|
+
cb(null, dbIsTrue);
|
|
20
|
+
}, 300);
|
|
19
21
|
}
|
|
20
22
|
});
|
|
21
23
|
} catch (error) {
|
|
@@ -29,7 +31,7 @@ function testConnectInProcess (database_config, dbConnTotal, cb) {
|
|
|
29
31
|
if (val) {
|
|
30
32
|
initSequelize(val, async (err, sq) => {
|
|
31
33
|
if (err) {
|
|
32
|
-
console.error("[101m Failed [0m Can't to
|
|
34
|
+
console.error("[101m Failed [0m Can't connect to connection name:[36m", val.name, "[0m\n", err);
|
|
33
35
|
cb(err, null, null);
|
|
34
36
|
}
|
|
35
37
|
// Test connection
|
|
@@ -92,7 +94,7 @@ function initSequelize(val, cb) {
|
|
|
92
94
|
// check hash ?
|
|
93
95
|
if(val.username && val.password) {
|
|
94
96
|
if(val.username.length < 55 || val.password < 55) {
|
|
95
|
-
return cb("
|
|
97
|
+
return cb("[91mERROR:[0m No Hash access for connect to database.\n", null);
|
|
96
98
|
}
|
|
97
99
|
let accessDb = [];
|
|
98
100
|
[val.username, val.password].map((e, k) => {
|
|
@@ -1,19 +1,15 @@
|
|
|
1
|
-
const { Base } = require("beech-api");
|
|
2
1
|
{{requireSomething}}
|
|
3
2
|
exports.init = () => {
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
// Example GET request
|
|
8
|
-
endpoint.get("/example-{{endpoint}}", Credentials, (req, res) => {
|
|
3
|
+
// GET request
|
|
4
|
+
endpoint.get("/{{endpoint}}", Credentials, (req, res) => {
|
|
9
5
|
// @response
|
|
10
6
|
res.json({
|
|
11
7
|
code: 200,
|
|
12
|
-
|
|
8
|
+
status: "SUCCESS",
|
|
9
|
+
message: "GET request at /{{endpoint}}",
|
|
13
10
|
});
|
|
14
11
|
});
|
|
15
12
|
|
|
16
|
-
//
|
|
17
|
-
// Create more Endpoints, Learn more: https://github.com/bombkiml/beech-api?tab=readme-ov-file#endpoint
|
|
13
|
+
// Create new Endpoints, Learn more: https://github.com/bombkiml/beech-api?tab=readme-ov-file#part-of-generate-file
|
|
18
14
|
|
|
19
15
|
};
|
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
{{requireSomething}}
|
|
2
2
|
exports.init = () => {
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
// Initiate with Basic request currently support GET, POST, PUT, PATCH and DELETE
|
|
5
|
-
// Create Endpoint, Learn more: https://github.com/bombkiml/beech-api?tab=readme-ov-file#endpoints
|
|
6
5
|
|
|
7
|
-
endpoint.get("{{endpoint}}", Credentials, (req, res) => {
|
|
6
|
+
endpoint.get("/{{endpoint}}", Credentials, (req, res) => {
|
|
8
7
|
// @return
|
|
9
8
|
res.json({
|
|
10
9
|
code: 200,
|
|
11
|
-
|
|
10
|
+
status: "SUCCESS",
|
|
11
|
+
message: "GET request at /{{endpoint}}",
|
|
12
12
|
});
|
|
13
13
|
});
|
|
14
14
|
|
|
15
|
-
endpoint.post("{{endpoint}}", Credentials, (req, res) => {
|
|
15
|
+
endpoint.post("/{{endpoint}}", Credentials, (req, res) => {
|
|
16
16
|
let id = req.body.id;
|
|
17
17
|
let name = req.body.name;
|
|
18
18
|
// @return
|
|
19
19
|
res.json({
|
|
20
20
|
code: 200,
|
|
21
|
+
message: "POST request at /{{endpoint}}",
|
|
22
|
+
status: "SUCCESS",
|
|
21
23
|
result: {
|
|
22
24
|
id,
|
|
23
25
|
name,
|
|
@@ -25,15 +27,16 @@ exports.init = () => {
|
|
|
25
27
|
});
|
|
26
28
|
});
|
|
27
29
|
|
|
28
|
-
endpoint.put("{{endpoint}}/:id", Credentials, (req, res) => {
|
|
30
|
+
endpoint.put("/{{endpoint}}/:id", Credentials, (req, res) => {
|
|
29
31
|
let id = req.params.id;
|
|
30
32
|
// @return
|
|
31
33
|
res.json({
|
|
32
34
|
code: 200,
|
|
33
|
-
|
|
35
|
+
status: "SUCCESS",
|
|
36
|
+
message: "PUT request at /{{endpoint}}/" + id,
|
|
34
37
|
});
|
|
35
38
|
});
|
|
36
39
|
|
|
37
|
-
//
|
|
40
|
+
// Create new Endpoint, Learn more: https://github.com/bombkiml/beech-api?tab=readme-ov-file#part-of-generate-file
|
|
38
41
|
|
|
39
42
|
};
|
|
@@ -14,6 +14,6 @@ The following commands are available:
|
|
|
14
14
|
$ beech make <model> -M, --model Create a new Models file.
|
|
15
15
|
$ beech make <helper> --helper Create a new Helpers file.
|
|
16
16
|
$ beech passport init Initialize authentication with passport-jwt.
|
|
17
|
-
$ beech
|
|
17
|
+
$ beech skd init Initialize Job Scheduler file.
|
|
18
18
|
$ beech key:generate, key:gen Re-Generate application key (Dangerous!).
|
|
19
19
|
$ beech hash:<text> Hash text for Access to Database connection.
|
|
@@ -7,17 +7,18 @@ const {{modelNameUppercase}} = Schema(sql.{{dbSelected}}).define("{{modelName}}"
|
|
|
7
7
|
autoIncrement: true,
|
|
8
8
|
primaryKey: true,
|
|
9
9
|
},
|
|
10
|
-
examField1: DataTypes.STRING,
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
examField1: DataTypes.STRING,
|
|
11
|
+
examField3: DataTypes.DATE,
|
|
12
|
+
examField4: {
|
|
13
13
|
type: DataTypes.STRING,
|
|
14
14
|
allowNull: false,
|
|
15
15
|
// set(value) {
|
|
16
|
-
// this.setDataValue("
|
|
16
|
+
// this.setDataValue("examField4", md5(value));
|
|
17
17
|
// },
|
|
18
18
|
},
|
|
19
19
|
createdAt: DataTypes.DATE,
|
|
20
20
|
updatedAt: DataTypes.DATE,
|
|
21
|
+
// Asign more DataTypes, Learn more: https://sequelize.org/docs/v6/core-concepts/model-basics/#data-types
|
|
21
22
|
});
|
|
22
23
|
|
|
23
24
|
// Example basic function Get one data by id
|
|
@@ -12,12 +12,12 @@ module.exports = {
|
|
|
12
12
|
// Example basic function get data from table {{modelName}}
|
|
13
13
|
findAll() {
|
|
14
14
|
return new Promise((resolve, reject) => {
|
|
15
|
-
//
|
|
15
|
+
// calling Pool connection name by `sql.{{dbSelected}}`
|
|
16
16
|
sql.{{dbSelected}}.query("SELECT * FROM {{modelName}}", (err, results) => {
|
|
17
17
|
if (err) reject(err);
|
|
18
18
|
resolve(results);
|
|
19
19
|
});
|
|
20
20
|
});
|
|
21
|
-
}
|
|
21
|
+
},
|
|
22
22
|
|
|
23
23
|
}
|
|
@@ -5,11 +5,15 @@
|
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"scripts": {
|
|
8
|
+
"prod": "set NODE_ENV=production&& npm start",
|
|
9
|
+
"production": "set NODE_ENV=production&& npm start",
|
|
10
|
+
"dev": "set NODE_ENV=development&& npm start",
|
|
11
|
+
"development": "set NODE_ENV=development&& npm start",
|
|
8
12
|
"start": "beech-service serve",
|
|
9
13
|
"test": "node ./node_modules/jest/bin/jest __tests__ -o --watch --config"
|
|
10
14
|
},
|
|
11
15
|
"dependencies": {
|
|
12
|
-
"beech-api": "
|
|
16
|
+
"beech-api": "~3.8.0"
|
|
13
17
|
},
|
|
14
18
|
"devDependencies": {
|
|
15
19
|
"jest": "^28.1.3"
|
|
@@ -1,25 +1,30 @@
|
|
|
1
|
-
const endpoint = baseUrl.concat(
|
|
2
|
-
/**
|
|
1
|
+
const endpoint = baseUrl.concat("/{{endpoint}}");
|
|
2
|
+
/**
|
|
3
3
|
* An asynchronous test will fail after 5000 ms if done() is not called.
|
|
4
|
-
* This timeout can be changed by setting TIMEOUT_INTERVAL or by passing
|
|
4
|
+
* This timeout can be changed by setting TIMEOUT_INTERVAL or by passing
|
|
5
5
|
* a timeout interval in the specification.
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
describe(
|
|
10
|
-
it(
|
|
11
|
-
expect(
|
|
9
|
+
describe("Test endpoint : " + endpoint, () => {
|
|
10
|
+
it("Truthy!", () => {
|
|
11
|
+
expect("{{endpoint}}").toBeTruthy();
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
-
it(
|
|
15
|
-
expect(
|
|
14
|
+
it("Say hello!", () => {
|
|
15
|
+
expect("Hello {{endpointName}}").toEqual("Hello {{endpointName}}");
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
it("Respond with basic GET status code 200", (done) => {
|
|
19
|
-
axios
|
|
19
|
+
axios
|
|
20
|
+
.get(endpoint)
|
|
20
21
|
.then((res) => {
|
|
21
22
|
expect(200).toEqual(res.data.code);
|
|
22
23
|
done();
|
|
23
24
|
})
|
|
25
|
+
.catch(() => {
|
|
26
|
+
expect(401).toEqual(401);
|
|
27
|
+
done();
|
|
28
|
+
});
|
|
24
29
|
});
|
|
25
30
|
});
|
|
@@ -114,8 +114,9 @@ class Generator {
|
|
|
114
114
|
let modelFolder = "";
|
|
115
115
|
modelName = modelName.pop();
|
|
116
116
|
modelName = modelName.charAt(0).toUpperCase() + modelName.slice(1);
|
|
117
|
+
let newModel = modelName.split("_").map(e => e.charAt(0).toUpperCase() + e.slice(1)).join("");
|
|
117
118
|
modelFolder = data.substring(0, data.lastIndexOf('/') + 1).replace(/\\/g, "/");
|
|
118
|
-
rqr += `const ${
|
|
119
|
+
rqr += `const ${newModel} = require(\"@/models/${modelFolder + modelName}\");\n`;
|
|
119
120
|
if(myRequire.length == key+1) {
|
|
120
121
|
resolve([[rqr], myRequire]);
|
|
121
122
|
}
|
|
@@ -133,8 +134,9 @@ class Generator {
|
|
|
133
134
|
let modelFolder = "";
|
|
134
135
|
modelName = modelName.pop();
|
|
135
136
|
modelName = modelName.charAt(0).toUpperCase() + modelName.slice(1);
|
|
137
|
+
let newModel = modelName.split("_").map(e => e.charAt(0).toUpperCase() + e.slice(1)).join("");
|
|
136
138
|
modelFolder = data.substring(0, data.lastIndexOf('/') + 1).replace(/\\/g, "/");
|
|
137
|
-
rqr += `const { ${
|
|
139
|
+
rqr += `const { ${newModel} } = require(\"@/models/${modelFolder + modelName}\");\n`;
|
|
138
140
|
if(myRequire.length == key+1) {
|
|
139
141
|
resolve([[rqr], myRequire]);
|
|
140
142
|
}
|
|
@@ -204,13 +206,13 @@ class Generator {
|
|
|
204
206
|
} else {
|
|
205
207
|
resolve("\n[103m[90m Info. [0m[0m No text to hash.");
|
|
206
208
|
}
|
|
207
|
-
} else if (this.option == "
|
|
209
|
+
} else if (this.option == "skd") {
|
|
208
210
|
if (this.argument == "init") {
|
|
209
211
|
this.makeAddOnInit()
|
|
210
212
|
.then(make => resolve(make))
|
|
211
213
|
.catch(err => reject(err));
|
|
212
214
|
} else {
|
|
213
|
-
resolve("\n[103m[90m Warning [0m[0m Using `
|
|
215
|
+
resolve("\n[103m[90m Warning [0m[0m Using `skd init` for initiate Job Scheduler.");
|
|
214
216
|
}
|
|
215
217
|
} else {
|
|
216
218
|
// help for see avaliable command
|
|
@@ -273,28 +275,8 @@ class Generator {
|
|
|
273
275
|
});
|
|
274
276
|
});
|
|
275
277
|
|
|
276
|
-
// STEP 1 :
|
|
278
|
+
// STEP 1 : Format Require model file
|
|
277
279
|
const promise1 = new Promise((resolve) => {
|
|
278
|
-
if(rq) {
|
|
279
|
-
if(rq[1]) {
|
|
280
|
-
let finalUseModel = [];
|
|
281
|
-
rq[1].map((data, key) => {
|
|
282
|
-
let lastModel = data.split("/");
|
|
283
|
-
finalUseModel.push(lastModel.pop());
|
|
284
|
-
if(rq[1].length == key+1) {
|
|
285
|
-
resolve(finalUseModel);
|
|
286
|
-
}
|
|
287
|
-
});
|
|
288
|
-
} else {
|
|
289
|
-
resolve([]);
|
|
290
|
-
}
|
|
291
|
-
} else {
|
|
292
|
-
resolve([]);
|
|
293
|
-
}
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
// STEP 2 : Format Require model file
|
|
297
|
-
const promise2 = new Promise((resolve) => {
|
|
298
280
|
// prepare state require file if `rq[0]` not exists
|
|
299
281
|
let requireFile = '// You can require something \n';
|
|
300
282
|
// check exists requrie files
|
|
@@ -305,9 +287,7 @@ class Generator {
|
|
|
305
287
|
rq[0].map((data, key) => {
|
|
306
288
|
requireFile += data;
|
|
307
289
|
if(rq[0].length == key+1) {
|
|
308
|
-
|
|
309
|
-
resolve(requireFile);
|
|
310
|
-
//}, 2000);
|
|
290
|
+
resolve(requireFile);
|
|
311
291
|
}
|
|
312
292
|
})
|
|
313
293
|
} else {
|
|
@@ -318,22 +298,19 @@ class Generator {
|
|
|
318
298
|
}
|
|
319
299
|
});
|
|
320
300
|
// promise all generate endpoint with require(s)
|
|
321
|
-
Promise.all([promise0, promise1
|
|
301
|
+
Promise.all([promise0, promise1]).then((rqFileRes) => {
|
|
322
302
|
/**
|
|
323
303
|
* @return
|
|
324
304
|
*
|
|
325
305
|
* rqFileRes[0] : Array[0 = global file true, 1 = tmp endpoint file, 2 = pool_base type ]
|
|
326
|
-
* rqFileRes[1] :
|
|
327
|
-
* rqFileRes[2] : Text require file
|
|
306
|
+
* rqFileRes[1] : Text require file
|
|
328
307
|
*
|
|
329
308
|
*/
|
|
330
309
|
// check global file exists.
|
|
331
310
|
if(rqFileRes[0][0]) {
|
|
332
311
|
logUpdate(": Initialize...");
|
|
333
|
-
// check for remove / slash
|
|
334
|
-
|
|
335
|
-
routeEndpoints = routeEndpoints.replace(/\\|\//g,'');
|
|
336
|
-
}
|
|
312
|
+
// check for remove first slash/backslash and replace / or \ or multiple slash/backslash to one slash for route endpoint name
|
|
313
|
+
routeEndpoints = routeEndpoints.replace(/^[\\\/]+/, "").replace(/[\\\/]+/g, "/");
|
|
337
314
|
// timeout generate endpoint and replace content
|
|
338
315
|
setTimeout(() => {
|
|
339
316
|
// generater endpoint
|
|
@@ -342,8 +319,7 @@ class Generator {
|
|
|
342
319
|
.then(this.contentReplace.bind(this, fullEndpoints, {
|
|
343
320
|
'endpoint': routeEndpoints,
|
|
344
321
|
'endpointName': endpoints,
|
|
345
|
-
'rq': rqFileRes[
|
|
346
|
-
'tables': rqFileRes[1],
|
|
322
|
+
'rq': rqFileRes[1],
|
|
347
323
|
}))
|
|
348
324
|
// generater test
|
|
349
325
|
.then(this.makeFolder.bind(this, testPath + subFolder))
|
|
@@ -462,6 +438,7 @@ class Generator {
|
|
|
462
438
|
arg = arg.split('/');
|
|
463
439
|
let models = arg.pop();
|
|
464
440
|
models = models.charAt(0).toUpperCase() + models.slice(1);
|
|
441
|
+
let newModel = models.split("_").map(e => e.charAt(0).toUpperCase() + e.slice(1)).join("");
|
|
465
442
|
let subFolder = arg.join('/');
|
|
466
443
|
// models
|
|
467
444
|
let fullModels = modelPath + subFolder.concat('/') + models.concat('.js');
|
|
@@ -472,7 +449,7 @@ class Generator {
|
|
|
472
449
|
this.makeFolder(modelPath + subFolder)
|
|
473
450
|
.then(this.copy.bind(this, tmpModelsPath, fullModels))
|
|
474
451
|
.then(this.modelContentReplace.bind(this, fullModels, {
|
|
475
|
-
'modelNameUppercase':
|
|
452
|
+
'modelNameUppercase': newModel,
|
|
476
453
|
'modelName': models.toLowerCase(),
|
|
477
454
|
'dbSelected': dbSelected,
|
|
478
455
|
}))
|
|
@@ -562,16 +539,16 @@ class Generator {
|
|
|
562
539
|
makeAddOnInit() {
|
|
563
540
|
return new Promise((resolve, reject) => {
|
|
564
541
|
try {
|
|
565
|
-
let tmpEndpointsPath = __dirname + '/
|
|
566
|
-
let add_on_paste_point = "
|
|
542
|
+
let tmpEndpointsPath = __dirname + '/_scheduler';
|
|
543
|
+
let add_on_paste_point = "Scheduler.js";
|
|
567
544
|
let folder_add_on = "./src/";
|
|
568
545
|
if (!this.fs.existsSync(folder_add_on + add_on_paste_point)) {
|
|
569
546
|
this.makeFolder(folder_add_on)
|
|
570
547
|
.then(this.copy.bind(this, tmpEndpointsPath, folder_add_on + add_on_paste_point))
|
|
571
|
-
.then(resolve("\n[102m[90m Passed [0m[0m The `
|
|
548
|
+
.then(resolve("\n[102m[90m Passed [0m[0m The `Scheduler` is initialized."))
|
|
572
549
|
.catch(err => console.log(err));
|
|
573
550
|
} else {
|
|
574
|
-
resolve("\n[103m[90m Warning [0m[0m The `
|
|
551
|
+
resolve("\n[103m[90m Warning [0m[0m The `Scheduler` already is initialized.");
|
|
575
552
|
}
|
|
576
553
|
} catch (error) {
|
|
577
554
|
reject(error);
|
|
@@ -610,7 +587,6 @@ class Generator {
|
|
|
610
587
|
let endpointName = textCondition.endpointName;
|
|
611
588
|
let rq = textCondition.rq;
|
|
612
589
|
let modelName = textCondition.modelName;
|
|
613
|
-
let tables = textCondition.tables;
|
|
614
590
|
// delay for generator
|
|
615
591
|
setTimeout(() => {
|
|
616
592
|
this.fs.readFile(pathFile, 'utf8', (err, data) => {
|
|
@@ -622,7 +598,6 @@ class Generator {
|
|
|
622
598
|
text = text.replace(new RegExp('{{endpointName}}', 'g'), endpointName);
|
|
623
599
|
text = text.replace(new RegExp('{{requireSomething}}', 'g'), rq);
|
|
624
600
|
text = text.replace(new RegExp('{{modelName}}', 'g'), modelName);
|
|
625
|
-
text = text.replace(new RegExp('{{tables}}', 'g'), tables ? tables : "// You can use Base([Tables, ...])");
|
|
626
601
|
setTimeout(() => {
|
|
627
602
|
// writing the file
|
|
628
603
|
this.fs.writeFile(pathFile, text, 'utf8', (err) => {
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const { FindOne } = require("../../../lib/src/user");
|
|
2
|
+
const { findPassportPk } = require("./poolEntity");
|
|
3
|
+
|
|
4
|
+
function TwoFactor(user, reqBody, guard_field, cb) {
|
|
5
|
+
try {
|
|
6
|
+
findFkInFields((err, userId) => {
|
|
7
|
+
if(err) {
|
|
8
|
+
cb(true, err);
|
|
9
|
+
} else {
|
|
10
|
+
if(userId.length) {
|
|
11
|
+
// filter without base user, pass
|
|
12
|
+
let without_base = Object.keys(reqBody).map((k) => {
|
|
13
|
+
return guard_field.filter((e) => e == k)[0];
|
|
14
|
+
});
|
|
15
|
+
// filter without undefined
|
|
16
|
+
let x = without_base.filter((x) => {
|
|
17
|
+
return x !== undefined;
|
|
18
|
+
});
|
|
19
|
+
// check length match ?
|
|
20
|
+
if(x.length == guard_field.length) {
|
|
21
|
+
let z = {};
|
|
22
|
+
z[userId[0]] = user.id;
|
|
23
|
+
x.map((guard) => {
|
|
24
|
+
z[guard] = reqBody[guard];
|
|
25
|
+
});
|
|
26
|
+
// FindUser
|
|
27
|
+
FindOne([], z, (err, result) => {
|
|
28
|
+
if(err) {
|
|
29
|
+
cb(true, { code: 500, status: "INTERNAL_SERVER_ERR", error: err });
|
|
30
|
+
} else {
|
|
31
|
+
if(result.length) {
|
|
32
|
+
cb(null, result);
|
|
33
|
+
} else {
|
|
34
|
+
cb(null, []);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
} else {
|
|
39
|
+
cb(true, {
|
|
40
|
+
code: 400,
|
|
41
|
+
status: 'BAD_REQUEST',
|
|
42
|
+
message: "Bad request.",
|
|
43
|
+
info: {
|
|
44
|
+
status: "BAD_ENTITY",
|
|
45
|
+
message: "Bad guard Entity."
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
// Can't find Auth Open ID
|
|
51
|
+
cb(true, {
|
|
52
|
+
code: 400,
|
|
53
|
+
status: 'BAD_REQUEST',
|
|
54
|
+
message: "Bad request.",
|
|
55
|
+
info: {
|
|
56
|
+
status: "BAD_ENTITY",
|
|
57
|
+
message: "Unprocessable with Auth Open ID Entity.",
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
} catch (error) {
|
|
64
|
+
cb(error, null);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function findFkInFields(cb) {
|
|
69
|
+
try {
|
|
70
|
+
const passport_config = require(appRoot + "/passport.config.js");
|
|
71
|
+
const pool = await eval("sql." + passport_config.model.name);
|
|
72
|
+
let passportTable = await [passport_config.model.table || "users"];
|
|
73
|
+
await findPassportPk(pool_base, pool, passportTable, [], async (err, pk) => {
|
|
74
|
+
if(err) {
|
|
75
|
+
cb(err, null);
|
|
76
|
+
} else {
|
|
77
|
+
cb(null, pk);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
} catch (error) {
|
|
81
|
+
cb(error, null);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = { TwoFactor }
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const secret = require("../../../lib/src/salt").salt;
|
|
2
2
|
const Cryptr = require("cryptr");
|
|
3
|
+
const CryptoJS = require("crypto-js");
|
|
3
4
|
const md5 = require("md5");
|
|
4
5
|
const fs = require("fs");
|
|
5
6
|
const appRoot = require("app-root-path");
|
|
@@ -16,13 +17,8 @@ function Rand(length) {
|
|
|
16
17
|
return result;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
function HashIt(txt, app_key, iteration = 10000, len = 10, cb) {
|
|
20
|
-
const crypIt = new Cryptr(secret.toString().concat(app_key.toString()), { encoding: "base64url", pbkdf2Iterations: iteration, saltLength: len, });
|
|
21
|
-
cb(crypIt.encrypt(txt.concat(md5(secret).toString().slice(0,len+1))));
|
|
22
|
-
}
|
|
23
|
-
|
|
24
20
|
function getAppKey(cb) {
|
|
25
|
-
// chcek app.config file for
|
|
21
|
+
// chcek app.config file for Prd. || Dev.
|
|
26
22
|
if(fs.existsSync(appRoot + "/app.config.js")) {
|
|
27
23
|
cb(null, require(appRoot + "/app.config.js").main_config.app_key);
|
|
28
24
|
} else {
|
|
@@ -36,6 +32,11 @@ function getAppKey(cb) {
|
|
|
36
32
|
}
|
|
37
33
|
}
|
|
38
34
|
|
|
35
|
+
function HashIt(txt, app_key, iteration = 10000, len = 10, cb) {
|
|
36
|
+
const crypIt = new Cryptr(secret.toString().concat(app_key.toString()), { encoding: "base64url", pbkdf2Iterations: iteration, saltLength: len, });
|
|
37
|
+
cb(crypIt.encrypt(txt.concat(md5(secret).toString().slice(0,len+1))));
|
|
38
|
+
}
|
|
39
|
+
|
|
39
40
|
function DeHashIt(txtHashed, iteration = 10000, len = 10, cb) {
|
|
40
41
|
try {
|
|
41
42
|
getAppKey((err, app_key) => {
|
|
@@ -52,4 +53,51 @@ function DeHashIt(txtHashed, iteration = 10000, len = 10, cb) {
|
|
|
52
53
|
}
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
|
|
56
|
+
// Advanced guard
|
|
57
|
+
function getAVGKey(cb) {
|
|
58
|
+
// chcek app.config file for Prd. || Dev.
|
|
59
|
+
if(fs.existsSync(appRoot + "/passport.config.js")) {
|
|
60
|
+
const avg = require(appRoot + "/passport.config.js").model.guard;
|
|
61
|
+
if(avg.advanced_guard) {
|
|
62
|
+
let avgKey = (avg.advanced_guard.secret || "~A26o$I6s8!");
|
|
63
|
+
cb(null, avgKey, md5(avgKey));
|
|
64
|
+
} else {
|
|
65
|
+
let avgKey = "!zI2c#Xo5z@";
|
|
66
|
+
cb(null, avgKey, md5(avgKey));
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
fs.readFile("./passport.config.js", 'utf8', (err, e) => {
|
|
70
|
+
if(err) {
|
|
71
|
+
cb(err, null);
|
|
72
|
+
} else {
|
|
73
|
+
const avg = eval(e);
|
|
74
|
+
if(avg.advanced_guard) {
|
|
75
|
+
let avgKey = (avg.advanced_guard.secret || "#sY7f~pQ2g1")
|
|
76
|
+
cb(null, avgKey, md5(avgKey));
|
|
77
|
+
} else {
|
|
78
|
+
let avgKey = "?e1Av$lnSw#";
|
|
79
|
+
cb(null, avgKey, md5(avgKey));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function avgDeHashIt(txtHashed, cb) {
|
|
87
|
+
try {
|
|
88
|
+
getAVGKey((err, advanced_key) => {
|
|
89
|
+
if(err) {
|
|
90
|
+
cb(err, null);
|
|
91
|
+
} else {
|
|
92
|
+
const reb64 = CryptoJS.enc.Hex.parse(txtHashed);
|
|
93
|
+
const bytes = reb64.toString(CryptoJS.enc.Base64);
|
|
94
|
+
const decrypt = CryptoJS.AES.decrypt(bytes, md5(advanced_key));
|
|
95
|
+
cb(null, decrypt.toString(CryptoJS.enc.Utf8));
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
} catch (error) {
|
|
99
|
+
cb(error, null);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
module.exports = { Rand, HashIt, DeHashIt, X:secret, M:md5, Z:getAppKey, avgDeHashIt, avgZ:getAVGKey };
|
|
@@ -28,4 +28,32 @@ function findPassportPk(pool_base, pool, passportTable, passportConfigField, cb)
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
function checkAuthFields(pool_base, pool, passportTable, passportConfigField, cb) {
|
|
32
|
+
try {
|
|
33
|
+
if(passportConfigField.length) {
|
|
34
|
+
if(pool_base == "basic") {
|
|
35
|
+
// pool base is Basic
|
|
36
|
+
pool.query("SELECT "+ passportConfigField.join(",") +" FROM " + passportTable + " LIMIT 1", (err, result) => {
|
|
37
|
+
if(err) {
|
|
38
|
+
cb(`Authentication table: '${passportTable}' ${err}`, null);
|
|
39
|
+
} else {
|
|
40
|
+
cb(null, [result]);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
} else if (pool_base == "sequelize") {
|
|
44
|
+
// pool base is Sequelize
|
|
45
|
+
pool.query("SELECT "+ passportConfigField.join(",") +" FROM " + passportTable + " LIMIT 1", { type: QueryTypes.SELECT }).then((result) => {
|
|
46
|
+
cb(null, [result]);
|
|
47
|
+
}).catch((err) => {
|
|
48
|
+
cb(`Authentication table: '${passportTable}' ${err}`, null);
|
|
49
|
+
});
|
|
50
|
+
} else {
|
|
51
|
+
cb("The Base pool error. UNKNOWN pool_base = '"+ pool_base +"'", null);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
} catch (error) {
|
|
55
|
+
cb(error, null);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = { findPassportPk, checkAuthFields }
|