beech-api 3.8.0 → 3.9.0-beta.8-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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "beech-api",
3
- "version": "3.8.0",
3
+ "version": "3.9.0-beta.8-rc",
4
4
  "description": "Command line interface for rapid Beech API development",
5
5
  "keywords": [
6
6
  "api",
@@ -18,9 +18,9 @@
18
18
  },
19
19
  "authors": "bombkiml",
20
20
  "bin": {
21
- "beech-app": "./packages/cli/bin/beech-app.js",
22
- "beech-service": "./packages/cli/bin/beech-service.js",
23
- "beech": "./packages/cli/core/generator/index.js"
21
+ "beech-app": "packages/cli/bin/beech-app.js",
22
+ "beech-service": "packages/cli/bin/beech-service.js",
23
+ "beech": "packages/cli/core/generator/index.js"
24
24
  },
25
25
  "bugs": {
26
26
  "url": "https://github.com/bombkiml/beech-api/issues"
@@ -28,20 +28,20 @@
28
28
  "homepage": "https://github.com/bombkiml/beech-api/blob/master/README.md",
29
29
  "deprecated": false,
30
30
  "engines": {
31
- "node": ">=14.19"
31
+ "node": ">=16.20"
32
32
  },
33
33
  "dependencies": {
34
34
  "app-root-path": "^3.0.0",
35
- "axios": "^0.26.1",
35
+ "axios": "^1.8.4",
36
36
  "child-process-promise": "^2.2.1",
37
37
  "cli-clear": "^1.0.4",
38
38
  "compression": "^1.7.5",
39
- "cookie-parser": "1.4.3",
39
+ "cookie-parser": "^1.4.7",
40
40
  "cors": "^2.8.1",
41
41
  "crypto-js": "^4.2.0",
42
42
  "cryptr": "^6.3.0",
43
- "express": "4.19.2",
44
- "express-duplicate-request": "^1.0.3",
43
+ "express": "^4.20.0",
44
+ "express-duplicate-request": "^1.0.5",
45
45
  "express-rate-limit": "^7.4.0",
46
46
  "express-session": "^1.17.1",
47
47
  "express-slow-down": "^2.0.3",
@@ -49,14 +49,14 @@
49
49
  "fs": "0.0.1-security",
50
50
  "helmet": "^8.1.0",
51
51
  "inquirer": "8.2.4",
52
- "jsonwebtoken": "^8.5.1",
52
+ "jsonwebtoken": "^9.0.2",
53
53
  "log-update": "^4.0.0",
54
54
  "md5": "^2.3.0",
55
55
  "method-override": "^3.0.0",
56
56
  "mkdirp": "^2.1.6",
57
57
  "module-alias": "^2.2.2",
58
58
  "mysql": "^2.18.1",
59
- "mysql2": "^2.3.3",
59
+ "mysql2": "^3.14.0",
60
60
  "node-cmd": "^3.0.0",
61
61
  "node-emoji": "^1.11.0",
62
62
  "node-notifier": "^10.0.1",
@@ -72,7 +72,7 @@
72
72
  "walk": "^2.3.14"
73
73
  },
74
74
  "devDependencies": {
75
- "jest": "^28.1.3",
75
+ "jest": "^29.7.0",
76
76
  "nodemon": "^3.1.0",
77
77
  "sequelize-cli": "^5.5.1"
78
78
  },
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  const logUpdate = require("log-update");
3
3
  const clear = require("cli-clear");
4
4
  const inquirer = require('inquirer');
@@ -52,8 +52,8 @@ class Beech {
52
52
  inquirer.prompt([ {
53
53
  type: "list",
54
54
  name: "sql",
55
- message: "Please pick a SQL structure base:",
56
- choices: [ "Basic (mysql only)", "Sequelize (mysql, sqlite, mariadb, postgres, mssql)" ],
55
+ message: "Please pick a pool base engine:",
56
+ choices: [ "Basic (mysql only)", "Sequelize ORM tool (mysql, sqlite, mariadb, postgres, mssql)" ],
57
57
  } ]).then(async resSql => {
58
58
  if (resSql.sql.split(' ')[ 0 ] != "Basic") {
59
59
  tmpGloablConfigFile = await __dirname + '/../core/configure/global.config-sequelize.js';
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  const logUpdate = require("log-update");
3
3
  const notifier = require("node-notifier");
4
4
  const path = require("path");
@@ -20,6 +20,14 @@ class Beech {
20
20
  return new Promise(async (resolve, reject) => {
21
21
  try {
22
22
  if (this.option == "serve") {
23
+ // Show comiling msg
24
+ const frames = ['\n[-] Compiling', '\n[\\] Compiling.', '\n[|] Compiling..', '\n[/] Compiling...'];
25
+ let i = 0;
26
+ var refreshCompileIntervalId = setInterval(() => {
27
+ const frame = frames[i = ++i % frames.length];
28
+ logUpdate(`${frame}`);
29
+ }, 300);
30
+ // option logic for silent notify
23
31
  let turnNoti = true;
24
32
  if (this.argument == "--silent" || this.argument == "-S") {
25
33
  turnNoti = false;
@@ -30,15 +38,32 @@ class Beech {
30
38
  testServ.listen(this._config_.main_config.app_port, async () => {
31
39
  await testServ.close();
32
40
  // Start real service.
33
- await this.serviceDevStart(this.argument);
34
- // check turn on nofi
35
- if (turnNoti) {
36
- this.notiCompile();
37
- }
41
+ this.serviceDevStart(this.argument, (err, run) => {
42
+ if(!err && run) {
43
+ // Check turn on noti
44
+ if (turnNoti) {
45
+ this.notiCompile();
46
+ }
47
+ // Delay for new replace Compiling msg to Running
48
+ setTimeout(() => {
49
+ clearInterval(refreshCompileIntervalId);
50
+ logUpdate("\n[OK] Running...");
51
+ }, 2500);
52
+ } else {
53
+ setTimeout(() => {
54
+ clearInterval(refreshCompileIntervalId);
55
+ logUpdate("\n[ERR] Failed... ", err);
56
+ reject();
57
+ }, 2500);
58
+ }
59
+ });
38
60
  }).on('error', (err) => {
61
+ clearInterval(refreshCompileIntervalId);
39
62
  console.log("\n Faltal ", err);
63
+ reject();
40
64
  })
41
65
  } else {
66
+ clearInterval(refreshCompileIntervalId);
42
67
  resolve("\n Faltal  The app.conifg.js file is not found.");
43
68
  }
44
69
  } else if (!this.option || this.option == "-h" || this.option == "?" || this.option == "--help") {
@@ -60,28 +85,39 @@ class Beech {
60
85
  });
61
86
  }
62
87
 
63
- serviceDevStart(argument) {
64
- logUpdate("Compiling...");
88
+ serviceDevStart(argument, cb) {
65
89
  let promise = null;
66
- // check Dev. run service
67
- const spawnData = new Promise((resolve) => {
68
- if(argument == "-D" || argument == "--dev") {
69
- promise = this.spawn('npx', ['nodemon', '-q', './cli/beech']); // For Dev.
70
- } else {
71
- promise = this.spawn('npx', ['nodemon', '-q', './node_modules/beech-api/packages/cli/beech']); // For Prd.
72
- }
73
- resolve(promise.childProcess);
74
- });
75
- Promise.all([spawnData]).then((childProcess) => {
76
- childProcess[0].stdout.on('data', (data) => {
77
- console.log(data.toString().slice(0, -1));
78
- });
79
- childProcess[0].stderr.on('data', (data) => {
80
- if(data.toString().slice(0, 8) != "Ignoring" && data.toString().match(/\[SEQUELIZE0006\]/g) != "[SEQUELIZE0006]") {
81
- console.log(data.toString());
90
+ try {
91
+ const spawnData = new Promise((resolve) => {
92
+ // check Dev. run service
93
+ if(argument == "-D" || argument == "--dev") {
94
+ promise = this.spawn('npx', ['nodemon', '-q', './cli/beech']); // For Dev.
95
+ } else {
96
+ promise = this.spawn('npx', ['nodemon', '-q', './node_modules/beech-api/packages/cli/beech']); // For Prd.
82
97
  }
98
+ resolve(promise.childProcess);
83
99
  });
84
- });
100
+ Promise.all([spawnData]).then((childProcess) => {
101
+ childProcess[0].stdout.on('data', (data) => {
102
+ console.log(data.toString().slice(0, -1));
103
+ });
104
+ // Check process error
105
+ childProcess[0].stderr.on('data', (data) => {
106
+ // Check Error from std Allow for Mysql version error
107
+ if(data.toString().slice(0, 8) != "Ignoring" && data.toString().match(/\[SEQUELIZE0006\]/g) != "[SEQUELIZE0006]") {
108
+ if(data.toString().slice(0, 13) == "node:internal") {
109
+ cb(data.toString(), false);
110
+ } else {
111
+ console.log(data.toString());
112
+ }
113
+ }
114
+ });
115
+ // Callback first
116
+ cb(null, true);
117
+ });
118
+ } catch (error) {
119
+ cb(error, false);
120
+ }
85
121
  }
86
122
 
87
123
  notiCompile() {
@@ -11,7 +11,9 @@ const byPassCredentials = (options, _res = {}, _next = () => {}) => {
11
11
  if(!options.length) {
12
12
  if(passport_config.jwt_broken_role ? passport_config.jwt_broken_role.length > 0 : false) {
13
13
  // CASE: jwt_broken_role DEFUALT is set
14
- return [credentials, checkRoleMiddleware(passport_config.jwt_broken_role)(options, _res, _next)];
14
+ return credentials(options, _res, () => {
15
+ return checkRoleMiddleware(passport_config.jwt_broken_role)(options, _res, _next);
16
+ });
15
17
  } else {
16
18
  if(!Object.keys(options).length) {
17
19
  return [credentials];
@@ -34,78 +36,95 @@ const byPassCredentials = (options, _res = {}, _next = () => {}) => {
34
36
  const credentials = (req, res, next) => {
35
37
  if (passport_config.jwt_allow === true) {
36
38
  const auth_endpoint = (passport_config.auth_endpoint) ? (passport_config.auth_endpoint[ 0 ] === "/" ? passport_config.auth_endpoint : "/" + passport_config.auth_endpoint) : "/authentication";
37
- if(auth_endpoint.split("/")[1] == req.params.hash) {
39
+ const slashOneIsHash = auth_endpoint.split("/")[1];
40
+ // Check first HASH equal Authentication
41
+ if(slashOneIsHash == req.params.hash) {
42
+ // Bypass authentication for auth endpoint
38
43
  return next();
39
- }
40
- }
41
-
42
- return passport.authenticate("jwt", {
43
- session: false,
44
- }, (err, user, info) => {
45
- // error check
46
- if (err) {
47
- console.log(err, info);
48
- return res.status(401).json({
49
- code: 401,
50
- error: "UNAUTHORIZED",
51
- message: {
52
- name: "WrongTokenError",
53
- message: "token error.",
54
- },
55
- /* dev: { err, info }, */ // for dev info
56
- });
57
- }
58
- // anything token check
59
- if (!user) {
60
- if (info) {
61
- if (info.name == "TokenExpiredError") {
62
- return res.status(401).json({
63
- code: 401,
64
- status: "TOKEN_EXPIRED",
65
- message: info,
66
- });
67
- }
68
- if (info.name == "Error") {
69
- return res.status(401).json({
70
- code: 401,
71
- status: "NO_AUTH_TOKEN",
72
- message: {
73
- name: "NoTokenError",
74
- message: "No auth token",
75
- },
76
- });
77
- }
78
- if (info.name == "SyntaxError") {
79
- return res.status(401).json({
80
- code: 401,
81
- status: "PAYLOAD_SYNTAX_ERROR",
82
- message: {
83
- name: "SyntaxError",
84
- message: "Unexpected token < in JSON at position 0",
85
- },
86
- });
87
- }
88
- }
89
- return res.status(401).json({
90
- code: 401,
91
- status: "UNAUTHORIZED_USER",
92
- message: info || {
93
- name: "TokenError",
94
- message: "Unauthorized token."
95
- },
96
- });
97
44
  } else {
98
- // Perfectly user jwt
99
- return next();
45
+ return passport.authenticate("jwt", {
46
+ session: false,
47
+ }, (err, user, info) => {
48
+ // error check
49
+ if (err) {
50
+ console.log(err, info);
51
+ return res.status(401).json({
52
+ code: 401,
53
+ error: "UNAUTHORIZED",
54
+ message: {
55
+ name: "WrongTokenError",
56
+ message: "token error.",
57
+ },
58
+ /* dev: { err, info }, */ // for dev info
59
+ });
60
+ } else {
61
+ // anything token check
62
+ if (!user) {
63
+ if (info) {
64
+ if (info.name == "TokenExpiredError") {
65
+ return res.status(401).json({
66
+ code: 401,
67
+ status: "TOKEN_EXPIRED",
68
+ message: info,
69
+ });
70
+ }
71
+ if (info.name == "Error") {
72
+ return res.status(401).json({
73
+ code: 401,
74
+ status: "NO_AUTH_TOKEN",
75
+ message: {
76
+ name: "NoTokenError",
77
+ message: "No auth token",
78
+ },
79
+ });
80
+ }
81
+ if (info.name == "SyntaxError") {
82
+ return res.status(401).json({
83
+ code: 401,
84
+ status: "PAYLOAD_SYNTAX_ERROR",
85
+ message: {
86
+ name: "SyntaxError",
87
+ message: "Unexpected token < in JSON at position 0",
88
+ },
89
+ });
90
+ }
91
+ } else {
92
+ return res.status(401).json({
93
+ code: 401,
94
+ status: "UNAUTHORIZED_USER",
95
+ message: info || {
96
+ name: "TokenError",
97
+ message: "Unauthorized token."
98
+ },
99
+ });
100
+ }
101
+ } else {
102
+ // Perfectly user jwt
103
+ return next();
104
+ }
105
+ }
106
+ }
107
+ )(req, res, next);
100
108
  }
101
- })(req, res, next);
109
+ } else {
110
+ // Bypass authentication
111
+ return next();
112
+ }
102
113
  }
103
114
 
104
115
  const credentialsGuard = (req, res, next) => {
105
- checkAppKey(req, res, (checked) => {
106
- if (checked) {
116
+ checkAppKey(req, res, (err) => {
117
+ if (!err) {
107
118
  // Perfectly
108
119
  next();
120
+ } else {
121
+ // Bad Request
122
+ return res.status(400).json({
123
+ code: 400,
124
+ status: 'BAD_REQUEST',
125
+ message: "Bad request.",
126
+ info: err,
127
+ });
109
128
  }
110
129
  });
111
130
  }
@@ -114,33 +133,19 @@ function checkAppKey(req, res, cb) {
114
133
  if (_passport_config_.app_key_allow) {
115
134
  if (req.headers.app_key) {
116
135
  if (_config_.main_config.app_key == req.headers.app_key) {
117
- return cb(true);
136
+ // Perfectly
137
+ cb(null, true);
118
138
  } else {
119
- res.status(400).json({
120
- code: 400,
121
- status: 'BAD_REQUEST',
122
- message: "Bad request.",
123
- info: {
124
- status: "BAD_VALUE",
125
- message: "Bad with wrong key."
126
- },
127
- });
128
- return cb(false);
139
+ // Wrong App key
140
+ cb({ status: "BAD_VALUE", message: "Bad with wrong key." }, false);
129
141
  }
130
142
  } else {
131
- res.status(400).json({
132
- code: 400,
133
- status: 'BAD_REQUEST',
134
- message: "Bad request.",
135
- info: {
136
- status: "BAD_ENTITY",
137
- message: "Bad with app entity key.",
138
- },
139
- });
140
- return cb(false);
143
+ // No App key
144
+ cb({ status: "BAD_ENTITY", message: "Bad with app entity key." }, false);
141
145
  }
142
146
  } else {
143
- return cb(true);
147
+ // App key not allow, bypass
148
+ cb(null, true);
144
149
  }
145
150
  }
146
151
 
@@ -24,9 +24,38 @@ module.exports = {
24
24
  if (passport_config.jwt_allow === true) {
25
25
  // Check if the APP_KEY is allow
26
26
  if(passport_config.app_key_allow) {
27
- global.Credentials = (_options = {}, _res, _next) => [credentialsGuard, byPassCredentials(_options, _res, _next)];
27
+ // All allow JWT & APP_KEY
28
+ //global.Credentials = [credentialsGuard, byPassCredentials]; // perfect
29
+ global.Credentials = (..._options) => {
30
+ const [option_or_req, res, next] = _options;
31
+ if (_options.length === 3) {
32
+ // Used as: app.use(Credentials)
33
+ return credentialsGuard(option_or_req, res, () => {
34
+ return byPassCredentials(option_or_req, res, next);
35
+ });
36
+ } else if (_options.length === 0) {
37
+ // Used as: app.use(Credentials())
38
+ return [credentialsGuard, byPassCredentials];
39
+ } else {
40
+ // Used as: app.use(Credentials([...] ))
41
+ return [credentialsGuard, byPassCredentials(option_or_req)];
42
+ }
43
+ };
28
44
  } else {
29
- global.Credentials = (_options = {}, _res, _next) => [byPassCredentials(_options, _res, _next)];
45
+ // Only allow JWT
46
+ global.Credentials = (..._options) => {
47
+ const [option_or_req, res, next] = _options;
48
+ if (_options.length === 3) {
49
+ // Used as: app.use(Credentials)
50
+ return byPassCredentials(option_or_req, res, next);
51
+ } else if (_options.length === 0) {
52
+ // Used as: app.use(Credentials())
53
+ return byPassCredentials;
54
+ } else {
55
+ // Used as: app.use(Credentials([...]))
56
+ return byPassCredentials(option_or_req);
57
+ }
58
+ };
30
59
  }
31
60
  // loop check db connect is true
32
61
  fs.readFile("./app.config.js", "utf-8", (err, data) => {
@@ -52,16 +81,61 @@ module.exports = {
52
81
  }
53
82
  });
54
83
  } else if (passport_config.app_key_allow === true) {
55
- global.Credentials = (_options = {}, _res, _next) => [credentialsGuard];
84
+ // Only allow APP_KEY
85
+ global.Credentials = (..._options) => {
86
+ const [option_or_req, res, next] = _options;
87
+ if (_options.length === 3) {
88
+ // Used as: app.use(Credentials)
89
+ return credentialsGuard(option_or_req, res, () => {
90
+ return next();
91
+ });
92
+ } else if (_options.length === 0) {
93
+ // Used as: app.use(Credentials())
94
+ return [credentialsGuard];
95
+
96
+ } else {
97
+ // Used as: app.use(Credentials([...] ))
98
+ return [credentialsGuard];
99
+ }
100
+ };
101
+ // Resolve it
56
102
  resolve([true, false, null]);
57
103
  } else {
58
- global.Credentials = (_options = {}, _res, _next) => [];
104
+ // Neither APP_KEY nor JWT allow
105
+ global.Credentials = (..._options) => {
106
+ const [option_or_req, res, next] = _options;
107
+ if (_options.length === 3) {
108
+ // Used as: app.use(Credentials)
109
+ return next();
110
+ } else if (_options.length === 0) {
111
+ // Used as: app.use(Credentials())
112
+ return [];
113
+ } else {
114
+ // Used as: app.use(Credentials([...] ))
115
+ return [];
116
+ }
117
+ };
118
+ // Resolve it
59
119
  resolve([true, false, null]);
60
120
  }
61
121
  } else {
62
- global.Credentials = (_options = {}, _res, _next) => [];
122
+ // Passport config file not found
123
+ global.Credentials = (..._options) => {
124
+ const [option_or_req, res, next] = _options;
125
+ if (_options.length === 3) {
126
+ // Used as: app.use(Credentials)
127
+ return next();
128
+ } else {
129
+ // Used as: app.use(Credentials() or Credentials([...] ))
130
+ return [];
131
+ }
132
+ };
133
+
134
+ // Old logic
63
135
  //const Requests = require("./_Request");
64
- //global.Credentials = (_options = {}, _res, _next) => [Requests.requests]; ----> // [Closed] TODO check passport.config file if not exists show error when file src/ using the JWT (maybe for show JWT is ON/OFF)
136
+ //global.Credentials = (_options = {}, _res, _next) => [Requests.requests]; // ----> [Closed] TODO check passport.config file if not exists show error when file src/ using the JWT (maybe for show JWT is ON/OFF)
137
+
138
+ // Resolve it
65
139
  resolve([false, null, null]);
66
140
  }
67
141
  });
@@ -80,10 +154,12 @@ module.exports = {
80
154
  var passportPasswordField = passport_config.model.password_field || "password";
81
155
  var passportTable = passport_config.model.table || "users";
82
156
  var pool = eval("sql." + passport_config.model.name);
157
+ // Check your assign auth fields
83
158
  checkAuthFields(pool_base, pool, passportTable, passport_config.model.fields, (err, msg) => {
84
159
  if(err) {
85
- console.error("\n Error ", err);
160
+ console.log("\n Error ", err);
86
161
  return;
162
+ //throw err;
87
163
  } else {
88
164
  // find passport primary key
89
165
  findPassportPk(pool_base, pool, passportTable, passport_config.model.fields, (err, passportFields) => {
@@ -163,42 +239,38 @@ module.exports = {
163
239
  } else if (pool_base == "sequelize") {
164
240
  // pool base is Sequelize
165
241
  try {
166
- pool.query("SHOW KEYS FROM " + passportTable + " WHERE Key_name = 'PRIMARY'", { type: QueryTypes.SELECT }).then((pk) => {
167
- let fieldPk = pk[0].Column_name;
168
- pool.query("SELECT " + passportFields + " FROM " + passportTable + " WHERE " + fieldPk + " = :pk", {
169
- replacements: {
170
- pk: + jwtPayload[fieldPk]
171
- },
172
- type: QueryTypes.SELECT,
173
- }).then((result) => {
174
- return done(null, JSON.parse(JSON.stringify(result[ 0 ] || null)));
175
- }).catch((error) => {
176
- if(pool.options.logging) {
177
- return done(error, null);
178
- } else {
179
- if(error.sql) {
180
- delete error.sql;
181
- if(error.errors) {
182
- delete error.errors;
183
- }
184
- if(error.parent) {
185
- delete error.parent;
186
- }
187
- if(error.original) {
188
- delete error.original.sql;
189
- }
190
- if(error.parameters) {
191
- delete error.parameters;
192
- }
193
- return done(error, null);
242
+ // Function Find table primaryKey
243
+ const findPkOfTable = () => {
244
+ return new Promise(async (resolve, reject) => {
245
+ try {
246
+ const tableInfo = await pool.getQueryInterface().describeTable(String(passportTable));
247
+ const primaryKeys = Object.entries(tableInfo).filter(([columnName, columnInfo]) => columnInfo.primaryKey).map(([columnName]) => columnName);
248
+ if(primaryKeys.length) {
249
+ resolve(primaryKeys);
194
250
  } else {
195
- return done(String(error), null);
251
+ resolve([Object.keys(tableInfo)[0]]);
196
252
  }
253
+ } catch (error) {
254
+ reject(`Query Interface ${error}`);
197
255
  }
198
256
  });
199
- }).catch((err) => {
200
- return done(err, null);
201
- });
257
+ }
258
+ // Find table primaryKey
259
+ findPkOfTable()
260
+ .then((fieldPk) => {
261
+ pool.query("SELECT " + passportFields + " FROM " + passportTable + " WHERE " + fieldPk + " = :pk", {
262
+ replacements: {
263
+ pk: + jwtPayload[fieldPk]
264
+ },
265
+ type: QueryTypes.SELECT,
266
+ }).then((result) => {
267
+ return done(null, JSON.parse(JSON.stringify(result[ 0 ] || null)));
268
+ }).catch((err) => {
269
+ return done(err, null);
270
+ });
271
+ }).catch(err => {
272
+ return done(err, null);
273
+ });
202
274
  } catch (error) {
203
275
  return done(error, null);
204
276
  }
@@ -24,7 +24,7 @@ module.exports = {
24
24
  // The fields for authenticate, default fields: (`username` and `password`)
25
25
  username_field: "",
26
26
  password_field: "",
27
- // JWT playload data
27
+ // JWT playload data, You can add it. Example: ["name", "email", ...]
28
28
  fields: [],
29
29
  // Other fields add for authentication.
30
30
  guard: {
@@ -27,7 +27,7 @@ mysqlInProcess = (database_config, headDbShow, cb) => {
27
27
  // check hash ?
28
28
  if(val.username && val.password) {
29
29
  if(val.username.length < 55 || val.password < 55) {
30
- return cb("Error: No Hash access for connect to database.\n", null);
30
+ return cb("Error: Incorrect Hash access for connect to database.\n", null);
31
31
  }
32
32
  let accessDb = [];
33
33
  [val.username, val.password].map((e, k) => {