beech-api 3.8.0 → 3.9.0-beta.9-rc

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.
@@ -2,6 +2,7 @@
2
2
  const logUpdate = require("log-update");
3
3
  const inquirer = require('inquirer');
4
4
  const walk = require("walk");
5
+ const { connectForGenerateModel } = require("../databases/test");
5
6
 
6
7
  class Generator {
7
8
  constructor() {
@@ -178,6 +179,18 @@ class Generator {
178
179
  resolve("\n Faltal  commnad it's not available.");
179
180
  }
180
181
  }
182
+ } else if (this.option == 'update') {
183
+ console.log('------------------------------');
184
+ if(this.argument == 'model') {
185
+ // this.special = model name
186
+ // if (!this.special) {
187
+ // resolve("\n [103m [90m Warning [0m [0m Please specify model name to update.");
188
+ // } else {
189
+ // this.updateModel()
190
+ // .then(res => resolve(res))
191
+ // .catch(err => reject(err));
192
+ // }
193
+ }
181
194
  } else if (this.option == 'passport') {
182
195
  if (this.argument == "init") {
183
196
  this.makePassportInit()
@@ -190,21 +203,42 @@ class Generator {
190
203
  this.generateKeyConfigFile()
191
204
  .then(resGenKey => resolve(resGenKey))
192
205
  .catch(err => reject(err));
193
- } else if (this.option && this.option.slice(0, 5) == 'hash:') {
206
+ } else if (this.option && this.option.slice(0, 5) == "hash:") {
207
+ const { HashIt, Z } = require(__dirname + "/../helpers/math");
194
208
  if(this.option.length > 5) {
195
- const { HashIt, Z } = require(__dirname + "/../helpers/math");
196
209
  Z((err, ak) => {
197
210
  if(err) {
198
211
  logUpdate(err);
199
212
  } else {
200
213
  let txt = this.option.split(":");
201
214
  HashIt(txt, ak, null, (5).toString().length, (hashed) => {
202
- logUpdate(hashed);
215
+ logUpdate("\n" + hashed);
203
216
  });
204
217
  }
205
218
  });
206
219
  } else {
207
- resolve("\n Info.  No text to hash.");
220
+ inquirer.prompt([ {
221
+ type: "confirm",
222
+ name: "confirmHashNoText",
223
+ message: "No text to hash, Do you want to continue ?:",
224
+ } ]).then(confirm => {
225
+ if(confirm.confirmHashNoText) {
226
+ Z((err, ak) => {
227
+ if(err) {
228
+ logUpdate(err);
229
+ } else {
230
+ let txt = this.option.split(":");
231
+ HashIt(txt, ak, null, (5).toString().length, (hashed) => {
232
+ logUpdate("\n" + hashed);
233
+ });
234
+ }
235
+ });
236
+ } else {
237
+ // no text to hash say no.
238
+ resolve(": Say no.");
239
+ }
240
+ });
241
+
208
242
  }
209
243
  } else if (this.option == "skd") {
210
244
  if (this.argument == "init") {
@@ -404,12 +438,12 @@ class Generator {
404
438
  // check pool_base
405
439
  if (pool_base[ 1 ] == "basic") {
406
440
  tmpModelsPath += '/_models_basic';
407
- this.generateModel(tmpModelsPath, dbSelected.selectDbConnect)
441
+ this.generateModel(tmpModelsPath, dbSelected.selectDbConnect, appBuf2eval, pool_base[1])
408
442
  .then(console.log)
409
443
  .catch(console.log);
410
444
  } else if (pool_base[ 1 ] == "sequelize") {
411
445
  tmpModelsPath += '/_models';
412
- this.generateModel(tmpModelsPath, dbSelected.selectDbConnect)
446
+ this.generateModel(tmpModelsPath, dbSelected.selectDbConnect, appBuf2eval, pool_base[1])
413
447
  .then(console.log)
414
448
  .catch(console.log);
415
449
  } else {
@@ -429,35 +463,182 @@ class Generator {
429
463
  });
430
464
  }
431
465
 
432
- generateModel(tmpModelsPath, dbSelected) {
466
+ updateModel() {
467
+ return new Promise((resolve, reject) => {
468
+ try {
469
+ // 1. อ่านการตั้งค่าจาก global.config และ app.config เหมือนตอนสร้าง Model
470
+ this.fs.readFile("./global.config.js", 'utf8', (err, globalData) => {
471
+ if (err) return resolve("\n [101m Faltal [0m Can't read `global.config.js` file.");
472
+
473
+ this.fs.readFile("./app.config.js", 'utf8', (appErr, appData) => {
474
+ if (appErr) return resolve("\n [101m Faltal [0m Can't read `app.config.js` file.");
475
+
476
+ let appBuf2eval = eval(appData);
477
+ let modelName = this.special; // <table_name>
478
+ let modelPath = `./src/models/${modelName.charAt(0).toUpperCase() + modelName.slice(1)}.js`;
479
+
480
+ // ตรวจสอบว่ามีไฟล์ Model เดิมอยู่หรือไม่
481
+ if (!this.fs.existsSync(modelPath)) {
482
+ return resolve(`\n [103m [90m Warning [0m [0m Model file \`${modelName}\` not found to update.`);
483
+ }
484
+
485
+ // ให้ผู้ใช้เลือก Connection ที่ต้องการดึง Schema ใหม่
486
+ inquirer.prompt([{
487
+ type: "list",
488
+ name: "selectDbConnect",
489
+ message: " [93mSelect database connection to sync schema: [0m",
490
+ choices: appBuf2eval.database_config.map(e => e.name),
491
+ }]).then(dbSelected => {
492
+
493
+ // 2. ดึง Schema ใหม่จาก DB
494
+ const { connectForGenerateModel } = require("../databases/test");
495
+ let newModelClassName = modelName.split("_").map(e => e.charAt(0).toUpperCase() + e.slice(1)).join("");
496
+
497
+ connectForGenerateModel(dbSelected.selectDbConnect, modelName, appBuf2eval.database_config, (err, tableSchema, tableName) => {
498
+ if (err) return reject(err);
499
+
500
+ // 3. แปลง Schema เป็น Code String
501
+ this.rawSchemaTable(dbSelected.selectDbConnect, newModelClassName, tableName, tableSchema, (SchemaErr, rawSchema) => {
502
+ if (SchemaErr) return reject(SchemaErr);
503
+
504
+ // 4. อ่านไฟล์เดิมและทำการ Replace เฉพาะส่วน Schema
505
+ this.fs.readFile(modelPath, 'utf8', (readErr, currentContent) => {
506
+ if (readErr) return reject(readErr);
507
+
508
+ // ใช้ Regex เพื่อหาช่วงของ Schema(...).define(...) และเปลี่ยนเฉพาะข้างใน
509
+ // โดยจะหาตั้งแต่ Schema(sql.db).define("table", { จนถึง });
510
+ const regex = /const\s+\w+\s+=\s+Schema\(sql\.\w+\)\.define\([\s\S]*?\}\);/;
511
+
512
+ if (regex.test(currentContent)) {
513
+ let updatedContent = currentContent.replace(regex, rawSchema);
514
+
515
+ this.fs.writeFile(modelPath, updatedContent, 'utf8', (writeErr) => {
516
+ if (writeErr) return reject(writeErr);
517
+ resolve(`\n [102m [90m Passed [0m [0m The model \`${modelName}\` schema has been updated.`);
518
+ });
519
+ } else {
520
+ resolve("\n [101m Faltal [0m Could not find Schema definition pattern in the file.");
521
+ }
522
+ });
523
+ });
524
+ });
525
+ });
526
+ });
527
+ });
528
+ } catch (error) {
529
+ reject(error);
530
+ }
531
+ });
532
+ }
533
+
534
+ generateModel(tmpModelsPath, dbSelected, appBuf2eval, pool_base) {
433
535
  return new Promise((resolve, reject) => {
434
536
  try {
537
+ // Show generating msg
538
+ const frames = [
539
+ '\n[-] Generating',
540
+ '\n[\\] Generating.',
541
+ '\n[|] Generating..',
542
+ '\n[/] Generating...'
543
+ ];
544
+ let i = 0;
545
+ var refreshGenerateIntervalId = null;
546
+ // Save model folder
435
547
  let modelPath = './src/models/';
436
- // argument join `slash`
548
+ // Argument join `slash`
437
549
  let arg = this.argument.replace(/^\/+|\/+$/g, '');
438
550
  arg = arg.split('/');
439
551
  let models = arg.pop();
552
+ let oriModelsName = models.slice(0);
440
553
  models = models.charAt(0).toUpperCase() + models.slice(1);
441
554
  let newModel = models.split("_").map(e => e.charAt(0).toUpperCase() + e.slice(1)).join("");
442
555
  let subFolder = arg.join('/');
443
- // models
556
+ // Declare models
444
557
  let fullModels = modelPath + subFolder.concat('/') + models.concat('.js');
445
558
 
446
- // check file exists
559
+ /**
560
+ * All properties
561
+ *
562
+ * @tmpModelPath String : path to keep generate model file
563
+ * @dbSelect String : database connection name
564
+ * @appBug2eval Object : database connection object
565
+ * @pool_base Object : pool base connection
566
+ *
567
+ * @i Number : loop count running...
568
+ * @refreshGenerateIntervalId Object : for clear interval id
569
+ *
570
+ * @arg String : argument from typing
571
+ * @models String : model name
572
+ * @oriModelsName String : original model name from typing
573
+ * @newModel String : model first upper case
574
+ * @subFolder String : agument sub folder
575
+ * @fullModels String : full model path and model file name
576
+ *
577
+ */
578
+ // Check file exists
447
579
  if (!this.fs.existsSync(fullModels)) {
448
- // generater model
449
- this.makeFolder(modelPath + subFolder)
450
- .then(this.copy.bind(this, tmpModelsPath, fullModels))
451
- .then(this.modelContentReplace.bind(this, fullModels, {
452
- 'modelNameUppercase': newModel,
453
- 'modelName': models.toLowerCase(),
454
- 'dbSelected': dbSelected,
455
- }))
456
- .then(logUpdate("\n Processing  The model `" + models + "` it's generating..."))
457
- .then(generated => logUpdate(generated))
458
- .catch(err => {
459
- throw err;
580
+ // Check pool base is basic|sequelize
581
+ if(pool_base == "basic") {
582
+ // Generate basic model
583
+ this.makeFolder(modelPath + subFolder)
584
+ .then(this.copy.bind(this, tmpModelsPath, fullModels))
585
+ .then(this.modelContentReplace.bind(this, fullModels, {
586
+ 'modelName': oriModelsName,
587
+ 'dbSelected': dbSelected,
588
+ }))
589
+ .then(
590
+ refreshGenerateIntervalId = setInterval(() => {
591
+ const frame = frames[i = ++i % frames.length];
592
+ logUpdate(`${frame}`);
593
+ }, 300)
594
+ )
595
+ .then(generated => {
596
+ logUpdate(generated);
597
+ clearInterval(refreshGenerateIntervalId);
598
+ })
599
+ .catch(err => {
600
+ throw err;
601
+ });
602
+ } else if(pool_base == "sequelize") {
603
+ // Gether table schema
604
+ connectForGenerateModel(dbSelected, oriModelsName, appBuf2eval.database_config, (err, tableSchema, tableName) => {
605
+ if(err) {
606
+ throw logUpdate("\n Faltal ", String(err), "\n");
607
+ } else {
608
+ // Raw model schema
609
+ this.rawSchemaTable(dbSelected, newModel, tableName, tableSchema, (SchemaErr, rawSchema) => {
610
+ if(err) {
611
+ throw logUpdate("\n Faltal  RAW Schema ERR:", String(SchemaErr), "\n");
612
+ } else {
613
+ // Generate sequelize model
614
+ this.makeFolder(modelPath + subFolder)
615
+ .then(this.copy.bind(this, tmpModelsPath, fullModels))
616
+ .then(this.modelContentReplace.bind(this, fullModels, {
617
+ 'modelName': oriModelsName,
618
+ 'modelNameUppercase': newModel,
619
+ 'modelStructure': rawSchema,
620
+ }))
621
+ .then(
622
+ refreshGenerateIntervalId = setInterval(() => {
623
+ const frame = frames[i = ++i % frames.length];
624
+ logUpdate(`${frame}`);
625
+ }, 300)
626
+ )
627
+ .then(generated => {
628
+ logUpdate(generated);
629
+ clearInterval(refreshGenerateIntervalId);
630
+ })
631
+ .catch(err => {
632
+ throw err;
633
+ });
634
+ }
635
+ });
636
+ }
460
637
  });
638
+ } else {
639
+ // Fallback (When Accident)
640
+ resolve("\n Faltal  The pool_base in `global.config.js` file does not match the specific.");
641
+ }
461
642
  } else {
462
643
  resolve("\n Warning  The model `" + models + "` it's duplicated.");
463
644
  }
@@ -467,6 +648,78 @@ class Generator {
467
648
  });
468
649
  }
469
650
 
651
+ rawSchemaTable(dbNameSelected, newModelName, tableName, modelSchema, cb) {
652
+ try {
653
+ // Function map type
654
+ const mapToSequelizeType = (rawType) => {
655
+ const type = rawType.toUpperCase();
656
+ // Assign all conditions
657
+ if (type.includes('INT')) return 'DataTypes.INTEGER';
658
+ if (type.includes('BIGINT')) return 'DataTypes.BIGINT';
659
+ if (type.includes('FLOAT')) return 'DataTypes.FLOAT';
660
+ if (type.includes('DOUBLE')) return 'DataTypes.DOUBLE';
661
+ if (type.includes('DECIMAL')) return 'DataTypes.DECIMAL';
662
+ if (type.includes('BOOLEAN') || type === 'TINYINT(1)') return 'DataTypes.BOOLEAN';
663
+ if (type.includes('CHAR')) {
664
+ const match = type.match(/\((\d+)\)/);
665
+ const length = match ? match[1] : '255';
666
+ return `DataTypes.STRING(${length})`;
667
+ }
668
+ if (type.includes('VARCHAR')) {
669
+ const match = type.match(/\((\d+)\)/);
670
+ const length = match ? match[1] : '255';
671
+ return `DataTypes.STRING(${length})`;
672
+ }
673
+ if (type.includes('TEXT')) return 'DataTypes.TEXT';
674
+ if (type.includes('DATE')) return 'DataTypes.DATE';
675
+ if (type.includes('TIME')) return 'DataTypes.TIME';
676
+ if (type.includes('JSON')) return 'DataTypes.JSON';
677
+ if (type.includes('UUID')) return 'DataTypes.UUID';
678
+ if (type.includes('BLOB')) return 'DataTypes.BLOB';
679
+ if (type.includes('ENUM')) return 'DataTypes.ENUM'; // Needs manual values
680
+ if (type.includes('GEOMETRY')) return 'DataTypes.GEOMETRY';
681
+ // Fallback
682
+ return `DataTypes.STRING`;
683
+ };
684
+ // Looping key fields
685
+ const fields = Object.entries(modelSchema).map(([name, props]) => {
686
+ // Declare line
687
+ const lines = [];
688
+ // Push line and assign space for beautiful
689
+ lines.push(` type: ${mapToSequelizeType(props.type)},`);
690
+ lines.push(` allowNull: ${props.allowNull},`);
691
+ // Check is primary key
692
+ if (props.primaryKey) lines.push(` primaryKey: true,`);
693
+ if (props.autoIncrement) lines.push(` autoIncrement: true,`);
694
+ //if (props.comment) lines.push(` comment: '${props.comment}',`);
695
+
696
+ // Handle defaultValue
697
+ if (props.defaultValue !== null && props.defaultValue !== undefined) {
698
+ const defaultVal = String(props.defaultValue).toUpperCase();
699
+ if (
700
+ defaultVal === 'CURRENT_TIMESTAMP' ||
701
+ defaultVal === 'NOW()' ||
702
+ defaultVal.includes('CURRENT_TIMESTAMP')
703
+ ) {
704
+ lines.push(` defaultValue: DataTypes.NOW,`);
705
+ } else if (defaultVal === 'UUID()' || defaultVal === 'uuid()' || defaultVal === 'UUID') {
706
+ lines.push(` defaultValue: DataTypes.UUIDV4,`);
707
+ } else if (typeof props.defaultValue === 'string') {
708
+ lines.push(` defaultValue: '${props.defaultValue}',`);
709
+ } else {
710
+ lines.push(` defaultValue: ${props.defaultValue},`);
711
+ }
712
+ }
713
+ // Finally
714
+ return ` ${name}: {\n${lines.join('\n')}\n }`;
715
+ });
716
+ // Callback
717
+ cb(null, `const ${newModelName} = Schema(sql.${dbNameSelected}).define("${tableName}", {\n${fields.join(',\n')}\n});`);
718
+ } catch (error) {
719
+ cb(error, null);
720
+ }
721
+ }
722
+
470
723
  makeHelper() {
471
724
  return new Promise((resolve, reject) => {
472
725
  try {
@@ -632,6 +885,7 @@ class Generator {
632
885
  text = text.replace(new RegExp('{{dbSelected}}', 'g'), textCondition.dbSelected);
633
886
  // check add model name text uppercase
634
887
  if (Object.keys(textCondition).length > 1) {
888
+ text = text.replace(new RegExp('{{modelStructure}}', 'g'), textCondition.modelStructure);
635
889
  text = text.replace(new RegExp('{{modelNameUppercase}}', 'g'), textCondition.modelNameUppercase);
636
890
  }
637
891
  // writing the file
@@ -644,7 +898,7 @@ class Generator {
644
898
  });
645
899
  }
646
900
  })
647
- }, 1000);
901
+ }, 2000);
648
902
  } catch (error) {
649
903
  reject(error);
650
904
  }
@@ -1,5 +1,9 @@
1
+ const fs = require("fs");
1
2
  const { FindOne } = require("../../../lib/src/user");
2
3
  const { findPassportPk } = require("./poolEntity");
4
+ const passport_config_file = appRoot + "/passport.config.js";
5
+ const md5 = require("md5");
6
+ const secret = require("../../../lib/src/salt").salt;
3
7
 
4
8
  function TwoFactor(user, reqBody, guard_field, cb) {
5
9
  try {
@@ -8,6 +12,22 @@ function TwoFactor(user, reqBody, guard_field, cb) {
8
12
  cb(true, err);
9
13
  } else {
10
14
  if(userId.length) {
15
+ if (fs.existsSync(passport_config_file)) {
16
+ passport_config = require(passport_config_file);
17
+ } else {
18
+ cb(true, {
19
+ code: 500,
20
+ status: "INTERNAL_SERVER_ERR",
21
+ error: {
22
+ code: 404,
23
+ status: "ERROR_FILE_NOT_EXISTS",
24
+ message: "The file passport.config.js not exists!",
25
+ }
26
+ });
27
+ return;
28
+ }
29
+ let usrField = passport_config.model.username_field || "username";
30
+ let pwdField = passport_config.model.password_field || "password"
11
31
  // filter without base user, pass
12
32
  let without_base = Object.keys(reqBody).map((k) => {
13
33
  return guard_field.filter((e) => e == k)[0];
@@ -19,7 +39,8 @@ function TwoFactor(user, reqBody, guard_field, cb) {
19
39
  // check length match ?
20
40
  if(x.length == guard_field.length) {
21
41
  let z = {};
22
- z[userId[0]] = user.id;
42
+ z[usrField] = reqBody[usrField];
43
+ z[pwdField] = md5(reqBody[pwdField] + secret);
23
44
  x.map((guard) => {
24
45
  z[guard] = reqBody[guard];
25
46
  });
@@ -34,7 +34,19 @@ function getAppKey(cb) {
34
34
 
35
35
  function HashIt(txt, app_key, iteration = 10000, len = 10, cb) {
36
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))));
37
+ let result = "";
38
+ let loop = 0;
39
+ const maxLoop = 10;
40
+ do {
41
+ const payload = txt.concat(md5(secret).toString().slice(0, len + 1));
42
+ result = crypIt.encrypt(payload);
43
+ loop++;
44
+ if (loop >= maxLoop) {
45
+ console.log("\n FAIL  Hash loop limit exceeded, Try again.");
46
+ return;
47
+ }
48
+ } while (/[+-]/.test(result)); // reject -, +
49
+ cb(result);
38
50
  }
39
51
 
40
52
  function DeHashIt(txtHashed, iteration = 10000, len = 10, cb) {
@@ -43,7 +55,7 @@ function DeHashIt(txtHashed, iteration = 10000, len = 10, cb) {
43
55
  if(err) {
44
56
  cb(err, null);
45
57
  } else {
46
- const crypIt = new Cryptr(secret.toString().concat(app_key.toString()), { encoding: "base64url", pbkdf2Iterations: iteration, saltLength: len, });
58
+ const crypIt = new Cryptr(secret.toString().concat(app_key.toString()), { encoding: "base64", pbkdf2Iterations: iteration, saltLength: len, });
47
59
  let decryped = crypIt.decrypt(txtHashed);
48
60
  cb(false, decryped.concat(md5(secret).toString()));
49
61
  }
@@ -1,34 +1,60 @@
1
- function findPassportPk(pool_base, pool, passportTable, passportConfigField, cb) {
1
+ async function findPassportPk(pool_base, pool, passportTable, passportConfigField, cb) {
2
2
  try {
3
- if(passportConfigField.length) {
4
- cb(null, passportConfigField);
5
- } else {
6
- if(pool_base == "basic") {
7
- // pool base is Basic
8
- pool.query("SHOW KEYS FROM " + passportTable + " WHERE Key_name = 'PRIMARY'", (err, pk) => {
9
- if(err) {
10
- throw "Authentication table: " + err;
3
+ let finalPassportField = [];
4
+ // Push and Replace it
5
+ const pushOrReplace = (arr, value) => {
6
+ arr = arr.filter(v => !value.includes(v));
7
+ arr = [...value, ...arr];
8
+ return arr;
9
+ }
10
+ // Check pool engine
11
+ if(pool_base == "basic") {
12
+ // pool base is Basic
13
+ pool.query("SHOW KEYS FROM " + passportTable + " WHERE Key_name = 'PRIMARY'", (err, pk) => {
14
+ if(err) {
15
+ throw "Authentication table: " + err;
16
+ } else {
17
+ if(passportConfigField.length) {
18
+ finalPassportField = pushOrReplace(passportConfigField, [pk[0].Column_name]);
19
+ cb(null, finalPassportField);
11
20
  } else {
12
21
  cb(null, [pk[0].Column_name]);
13
22
  }
14
- });
15
- } else if (pool_base == "sequelize") {
16
- // pool base is Sequelize
17
- pool.query("SHOW KEYS FROM " + passportTable + " WHERE Key_name = 'PRIMARY'", { type: QueryTypes.SELECT }).then((pk) => {
18
- cb(null, [pk[0].Column_name]);
19
- }).catch((err) => {
20
- throw "Authentication table: " + err;
21
- });
22
- } else {
23
- throw "The Base pool error. UNKNOWN pool_base = '"+ pool_base +"'";
23
+ }
24
+ });
25
+ } else if (pool_base == "sequelize") {
26
+ // pool base is Sequelize
27
+ // Find table primaryKey
28
+ try {
29
+ const tableInfo = await pool.getQueryInterface().describeTable(String(passportTable));
30
+ const primaryKeys = Object.entries(tableInfo).filter(([columnName, columnInfo]) => columnInfo.primaryKey).map(([columnName]) => columnName);
31
+ if(primaryKeys.length) {
32
+ if(passportConfigField.length) {
33
+ finalPassportField = pushOrReplace(passportConfigField, primaryKeys);
34
+ cb(null, finalPassportField);
35
+ } else {
36
+ cb(null, primaryKeys);
37
+ }
38
+ } else {
39
+ if(passportConfigField.length) {
40
+ finalPassportField = pushOrReplace(passportConfigField, [Object.keys(tableInfo)[0]]);
41
+ cb(null, finalPassportField);
42
+ } else {
43
+ cb(null, [Object.keys(tableInfo)[0]]);
44
+ }
45
+ }
46
+ } catch (error) {
47
+ throw `Query Interface ${error}`;
24
48
  }
49
+ } else {
50
+ throw "The Base pool error. UNKNOWN pool_base = '"+ pool_base +"'";
25
51
  }
26
52
  } catch (error) {
27
53
  cb(error, null);
28
54
  }
29
55
  }
30
56
 
31
- function checkAuthFields(pool_base, pool, passportTable, passportConfigField, cb) {
57
+ async function checkAuthFields(pool_base, pool, passportTable, passportConfigField, cb) {
32
58
  try {
33
59
  if(passportConfigField.length) {
34
60
  if(pool_base == "basic") {
@@ -42,18 +68,36 @@ function checkAuthFields(pool_base, pool, passportTable, passportConfigField, cb
42
68
  });
43
69
  } else if (pool_base == "sequelize") {
44
70
  // 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
- });
71
+ // Check assing fields exists
72
+ const checkColumnsExist = async (tableName, fields = []) => {
73
+ const queryInterface = pool.getQueryInterface();
74
+ try {
75
+ const tableDescription = await queryInterface.describeTable(tableName);
76
+ const result = {};
77
+ for (const column of fields) {
78
+ result[column] = tableDescription.hasOwnProperty(column);
79
+ }
80
+ return result;
81
+ } catch (error) {
82
+ throw `Query Interface ${error}`;
83
+ }
84
+ }
85
+ const openFields = await checkColumnsExist(passportTable, passportConfigField);
86
+ const assignFieldsIsWhitelist = Object.values(openFields).includes(false) ? false : true;
87
+ if(assignFieldsIsWhitelist) {
88
+ cb(null, openFields);
89
+ } else {
90
+ cb(`Authentication table fields error: '${passportTable}' => [${passportConfigField}]`, null);
91
+ }
50
92
  } else {
51
93
  cb("The Base pool error. UNKNOWN pool_base = '"+ pool_base +"'", null);
52
94
  }
95
+ } else {
96
+ cb(null, []);
53
97
  }
54
98
  } catch (error) {
55
99
  cb(error, null);
56
100
  }
57
101
  }
58
102
 
59
- module.exports = { findPassportPk, checkAuthFields }
103
+ module.exports = { findPassportPk, checkAuthFields };