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.
- package/README.md +551 -146
- package/package.json +13 -12
- package/packages/cli/bin/beech-app.js +4 -4
- package/packages/cli/bin/beech-service.js +62 -25
- package/packages/cli/core/auth/Credentials.js +115 -88
- package/packages/cli/core/auth/Passport.js +111 -39
- package/packages/cli/core/configure/passport.config.js +1 -1
- package/packages/cli/core/databases/mysql.js +1 -1
- package/packages/cli/core/databases/sequelize.js +15 -6
- package/packages/cli/core/databases/test.js +125 -39
- package/packages/cli/core/generator/_models +3 -26
- package/packages/cli/core/generator/_models_basic +0 -9
- package/packages/cli/core/generator/_package +6 -7
- package/packages/cli/core/generator/_scheduler +16 -6
- package/packages/cli/core/generator/index.js +277 -23
- package/packages/cli/core/helpers/2fa.js +22 -1
- package/packages/cli/core/helpers/math.js +14 -2
- package/packages/cli/core/helpers/poolEntity.js +70 -26
- package/packages/cli/core/index.js +88 -10
- package/packages/cli/core/middleware/express/duplicateRequest.js +10 -6
- package/packages/cli/core/middleware/express/jwtCheckAllow.js +52 -34
- package/packages/cli/core/middleware/express/rateLimit.js +14 -2
- package/packages/cli/core/middleware/origin/guard/advance.js +5 -4
- package/packages/cli/core/services/http.express.js +49 -9
- package/packages/cli/core/test/check-node.js +21 -0
- package/packages/lib/src/endpoint.js +639 -286
- package/packages/lib/src/schema.js +4 -1
|
@@ -15,7 +15,6 @@ _app_.use(helmet());
|
|
|
15
15
|
const cors = require("cors");
|
|
16
16
|
global.endpoint = _express_.Router();
|
|
17
17
|
const cookieParser = require("cookie-parser");
|
|
18
|
-
const bodyParser = require("body-parser");
|
|
19
18
|
const methodOverride = require("method-override");
|
|
20
19
|
const expressSession = require("express-session");
|
|
21
20
|
const expressValidator = require("express-validator");
|
|
@@ -27,10 +26,86 @@ const _beech_ = require(appRoot + "/beech.config.js").defineConfig;
|
|
|
27
26
|
global._publicPath_ = _beech_.base;
|
|
28
27
|
const mySqlDbConnect = require("./databases/mysql");
|
|
29
28
|
const SequelizeDbConnect = require("./databases/sequelize");
|
|
30
|
-
//
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
// Set limit payload for request body & multipart/form-data (multer)
|
|
30
|
+
const multer = require("multer");
|
|
31
|
+
const uploadAllowMethod = _beech_?.payload?.file?.uploadAllowMethod || ["POST", "PATCH", "PUT"];
|
|
32
|
+
const allowedTypes = _beech_?.payload?.file?.allowedTypes || []; // default: no allowed type
|
|
33
|
+
const fileLimitSize = _beech_?.payload?.file?.limit || 5 * 1024 * 1024; // 5MB
|
|
34
|
+
const uploadStrategy = multer({
|
|
35
|
+
limits: { fileSize: fileLimitSize },
|
|
36
|
+
fileFilter: (req, file, cb) => {
|
|
37
|
+
if (allowedTypes.length === 0) {
|
|
38
|
+
cb(new Error("INVALID_FILE_TYPE_ALLOW"), false); // Allow all file types if no allowed types specified
|
|
39
|
+
} else if (allowedTypes.includes(file.mimetype)) {
|
|
40
|
+
cb(null, true);
|
|
41
|
+
} else {
|
|
42
|
+
cb(new Error("INVALID_FILE_TYPE"), false);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}).any();
|
|
46
|
+
const jsonLimitSize = _beech_?.payload.json?.limit || "100KB"; // json payload
|
|
47
|
+
const urlencodedLimitSize = _beech_?.payload?.urlencoded?.limit || "100KB"; // urlencoded payload (multipart/form-data)
|
|
48
|
+
const urlencodedExtended = !!(_beech_?.payload?.urlencoded?.extended ?? true);
|
|
49
|
+
_app_.use(_express_.urlencoded({ limit: urlencodedLimitSize, extended: urlencodedExtended })); // application/x-www-form-urlencoded payload
|
|
50
|
+
_app_.use(_express_.json({ limit: jsonLimitSize }));
|
|
51
|
+
_app_.use((req, res, next) => {
|
|
52
|
+
const isUploadMethod = uploadAllowMethod.includes(req.method);
|
|
53
|
+
const isMultipart = req.headers["content-type"]?.includes("multipart/form-data");
|
|
54
|
+
// Handle file upload for allowed methods
|
|
55
|
+
if (isUploadMethod) {
|
|
56
|
+
return uploadStrategy(req, res, (err) => {
|
|
57
|
+
if (err) return next(err);
|
|
58
|
+
next();
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// Handle method not allowed for file upload
|
|
62
|
+
if (!isUploadMethod && isMultipart) {
|
|
63
|
+
return res.status(405).json({
|
|
64
|
+
code: 405,
|
|
65
|
+
status: "METHOD_NOT_ALLOWED_FOR_UPLOAD",
|
|
66
|
+
message: _config_.main_config?.dev ? `File upload is not allowed for ${req.method} method.` : "Method Not Allowed for file upload.",
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
// next to next middleware
|
|
70
|
+
next();
|
|
71
|
+
});
|
|
72
|
+
_app_.use((err, req, res, next) => {
|
|
73
|
+
// Handle payload too large error for JSON and URL-encoded
|
|
74
|
+
if (err.type === "entity.too.large") {
|
|
75
|
+
const isJson = req.headers["content-type"]?.includes("application/json");
|
|
76
|
+
const limitUsed = isJson ? jsonLimitSize : urlencodedLimitSize;
|
|
77
|
+
return res.status(413).json({
|
|
78
|
+
code: 413,
|
|
79
|
+
status: "PAYLOAD_TOO_LARGE",
|
|
80
|
+
message:_config_.main_config?.dev ? `${isJson ? 'JSON' : 'Form data'} too large, Max limit is ${limitUsed}` : "Payload Too Large.",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (err.message === "INVALID_FILE_TYPE_ALLOW") {
|
|
84
|
+
return res.status(400).json({
|
|
85
|
+
code: 400,
|
|
86
|
+
status: "INVALID_FILE_TYPE_ALLOW",
|
|
87
|
+
message: "Invalid file type, No file types allowed.",
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
// Handle invalid file type error from multer
|
|
91
|
+
if (err.message === "INVALID_FILE_TYPE") {
|
|
92
|
+
return res.status(400).json({
|
|
93
|
+
code: 400,
|
|
94
|
+
status: "INVALID_FILE_TYPE",
|
|
95
|
+
message: _config_.main_config?.dev ? `Invalid file type, Allowed: ${allowedTypes.join(', ')}` : "Invalid file type.",
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
// Handle multer file size limit error
|
|
99
|
+
if (err.code === "LIMIT_FILE_SIZE") {
|
|
100
|
+
return res.status(413).json({
|
|
101
|
+
code: 413,
|
|
102
|
+
status: "PAYLOAD_TOO_LARGE",
|
|
103
|
+
message: _config_.main_config?.dev ? `File size too large, Max limit is ${fileLimitSize / 1024 / 1024}MB` : "Payload Too Large.",
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
// next to general error handler
|
|
107
|
+
next(err);
|
|
108
|
+
});
|
|
34
109
|
// Database test
|
|
35
110
|
const {
|
|
36
111
|
testConnectInProcess,
|
|
@@ -57,8 +132,6 @@ _app_.use((req, res, next) => {
|
|
|
57
132
|
});
|
|
58
133
|
});
|
|
59
134
|
// View engine
|
|
60
|
-
_app_.use(bodyParser.json());
|
|
61
|
-
_app_.use(bodyParser.urlencoded({ extended: true }));
|
|
62
135
|
_app_.use(methodOverride());
|
|
63
136
|
_app_.use(cookieParser());
|
|
64
137
|
_app_.use(expressSession({
|
|
@@ -164,9 +237,11 @@ init = async (jsfiles) => {
|
|
|
164
237
|
Promise.all([testConnectToDB]).then(async (x) => {
|
|
165
238
|
if (x[0]) {
|
|
166
239
|
await (pool_base == "basic" ? new Promise((resolve) => resolve(mySqlDbConnect.connect())) : new Promise((resolve) => resolve(SequelizeDbConnect.connect())));
|
|
167
|
-
await authPassport.init().then(async (
|
|
168
|
-
if (
|
|
169
|
-
|
|
240
|
+
await authPassport.init().then(async (p) => {
|
|
241
|
+
if (p[0]) {
|
|
242
|
+
console.log("\n[101m Init failed [0m", p[0]);
|
|
243
|
+
return;
|
|
244
|
+
//throw p[0];
|
|
170
245
|
} else {
|
|
171
246
|
await new Promise((resolve) => resolve(fileWalk.fileWalk(jsfiles)));
|
|
172
247
|
await (pool_base == "basic" ? new Promise((resolve) => resolve()) : new Promise((resolve) => resolve(Base())));
|
|
@@ -176,6 +251,9 @@ init = async (jsfiles) => {
|
|
|
176
251
|
});
|
|
177
252
|
});
|
|
178
253
|
}
|
|
254
|
+
}).catch((err) => {
|
|
255
|
+
console.log("[101m Catch init failed [0m", err);
|
|
256
|
+
throw err;
|
|
179
257
|
});
|
|
180
258
|
}
|
|
181
259
|
});
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
const _beech_ = require(appRoot + "/beech.config.js");
|
|
2
2
|
const { duplicateRequest } = require("express-duplicate-request");
|
|
3
|
-
const nextDuplicater = (req, res, next) =>
|
|
4
|
-
|
|
5
|
-
};
|
|
6
|
-
let configure = {
|
|
3
|
+
const nextDuplicater = (req, res, next) => next();
|
|
4
|
+
const defaultConfigure = {
|
|
7
5
|
expiration: _beech_.defineConfig.server.duplicateRequest ? _beech_.defineConfig.server.duplicateRequest.expiration : 0,
|
|
8
6
|
};
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
const baseConfigure = {
|
|
8
|
+
..._beech_.defineConfig.server.duplicateRequest, // Override default configure with user configure.
|
|
9
|
+
...defaultConfigure,
|
|
10
|
+
};
|
|
11
|
+
const Duplicater = (more_configure = {}) => {
|
|
12
|
+
const config = { ...baseConfigure, ...more_configure };
|
|
13
|
+
return config.expiration ? duplicateRequest(config) : nextDuplicater;
|
|
14
|
+
};
|
|
11
15
|
|
|
12
16
|
module.exports = { Duplicater, duplicateRequest };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
const passport = require("passport");
|
|
2
2
|
|
|
3
3
|
const checkRoleMiddleware = (options) => {
|
|
4
|
-
return
|
|
4
|
+
return (req, res, next) => {
|
|
5
5
|
if(!Array.isArray(options)) {
|
|
6
|
+
// Perfectly with options is not type Array
|
|
6
7
|
return next();
|
|
7
8
|
} else {
|
|
8
9
|
passport.authenticate("jwt", {
|
|
@@ -10,7 +11,7 @@ const checkRoleMiddleware = (options) => {
|
|
|
10
11
|
}, (err, user, info) => {
|
|
11
12
|
// error check
|
|
12
13
|
if (err) {
|
|
13
|
-
console.log(err, info);
|
|
14
|
+
//console.log(err, info);
|
|
14
15
|
return res.status(403).json({
|
|
15
16
|
code: 403,
|
|
16
17
|
status: "FORBIDDEN",
|
|
@@ -20,49 +21,66 @@ const checkRoleMiddleware = (options) => {
|
|
|
20
21
|
},
|
|
21
22
|
});
|
|
22
23
|
} else {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
} else {
|
|
36
|
-
if(isPerfectly) {
|
|
37
|
-
res.status(403).json({
|
|
38
|
-
code: 403,
|
|
39
|
-
status: "FORBIDDEN",
|
|
40
|
-
message: "Forbidden: Insufficient role",
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
isPerfectly = false;
|
|
44
|
-
}
|
|
24
|
+
if(!options.length) {
|
|
25
|
+
// Perfectly with no options
|
|
26
|
+
return next();
|
|
27
|
+
} else {
|
|
28
|
+
const allowed = options.some(rule => {
|
|
29
|
+
return Object.entries(rule).every(([key, condition]) => {
|
|
30
|
+
//console.log('----matchCondition(user?.[key], condition, user)-->>', matchCondition(user?.[key], condition, user));
|
|
31
|
+
return matchCondition(user?.[key], condition, user);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
if (allowed) {
|
|
35
|
+
return next();
|
|
45
36
|
} else {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
37
|
+
res.status(403).json({
|
|
38
|
+
code: 403,
|
|
39
|
+
status: "FORBIDDEN",
|
|
40
|
+
message: "Forbidden: Insufficient role",
|
|
41
|
+
info: {
|
|
42
|
+
status: "ROLE_NOT_ALLOWED",
|
|
43
|
+
error: "Insufficient role or User token does not have sufficient role.",
|
|
44
|
+
},
|
|
45
|
+
});
|
|
54
46
|
}
|
|
55
|
-
}
|
|
47
|
+
}
|
|
56
48
|
}
|
|
57
49
|
})(req, res, next);
|
|
58
50
|
}
|
|
59
51
|
}
|
|
60
52
|
}
|
|
61
53
|
|
|
54
|
+
const operators = {
|
|
55
|
+
$eq: (userValue, expected) => userValue === expected,
|
|
56
|
+
$ne: (userValue, expected) => userValue !== expected,
|
|
57
|
+
$in: (userValue, expected) => Array.isArray(expected) && expected.includes(userValue),
|
|
58
|
+
$not: (userValue, expected) => Array.isArray(expected) && !expected.includes(userValue),
|
|
59
|
+
$regex: (userValue, expected) =>
|
|
60
|
+
typeof userValue === 'string' && expected instanceof RegExp
|
|
61
|
+
? expected.test(userValue)
|
|
62
|
+
: false,
|
|
63
|
+
$fn: (userValue, fn, user) => typeof fn === 'function' && fn(userValue, user),
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const matchCondition = (userValue, condition, user) => {
|
|
67
|
+
if (typeof condition !== 'object' || condition instanceof RegExp || Array.isArray(condition)) {
|
|
68
|
+
return Array.isArray(condition)
|
|
69
|
+
? operators.$in(userValue, condition)
|
|
70
|
+
: operators.$eq(userValue, condition);
|
|
71
|
+
}
|
|
72
|
+
// operator object
|
|
73
|
+
return Object.entries(condition).every(([op, expected]) => {
|
|
74
|
+
const handler = operators[op];
|
|
75
|
+
if (!handler) return false;
|
|
76
|
+
return handler(userValue, expected, user);
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
|
|
62
80
|
const checkRoleMiddlewareWithDefaultProject = (options) => {
|
|
63
81
|
return function (req, res, next) {
|
|
64
82
|
return checkRoleMiddleware(options)(req, res, next);
|
|
65
83
|
}
|
|
66
84
|
}
|
|
67
85
|
|
|
68
|
-
module.exports = { checkRoleMiddleware, checkRoleMiddlewareWithDefaultProject }
|
|
86
|
+
module.exports = { checkRoleMiddleware, checkRoleMiddlewareWithDefaultProject };
|
|
@@ -11,7 +11,19 @@ let configure = {
|
|
|
11
11
|
legacyHeaders: (_beech_.defineConfig.server.rateLimit) ? (_beech_.defineConfig.server.rateLimit.legacyHeaders || false) : false,
|
|
12
12
|
message: (_beech_.defineConfig.server.rateLimit) ? (_beech_.defineConfig.server.rateLimit.message || tooManyMsg) : tooManyMsg,
|
|
13
13
|
};
|
|
14
|
-
configure = {
|
|
15
|
-
|
|
14
|
+
configure = {
|
|
15
|
+
..._beech_.defineConfig.server.rateLimit, // Override default configure with user configure.
|
|
16
|
+
...configure,
|
|
17
|
+
keyGenerator: (req) => `${req.ip}:${req.params.hash}${req.params['0']}`,
|
|
18
|
+
};
|
|
19
|
+
const Limiter = (more_configure = {}) => {
|
|
20
|
+
const middleware = rateLimit({
|
|
21
|
+
...configure,
|
|
22
|
+
...more_configure,
|
|
23
|
+
});
|
|
24
|
+
return (req, res, next) => {
|
|
25
|
+
middleware(req, res, next);
|
|
26
|
+
};
|
|
27
|
+
};
|
|
16
28
|
|
|
17
29
|
module.exports = { Limiter, rateLimit };
|
|
@@ -14,12 +14,13 @@ function avg(req, res, next) {
|
|
|
14
14
|
});
|
|
15
15
|
// promise all
|
|
16
16
|
Promise.all([checkPassport]).then((final) => {
|
|
17
|
-
let item = final[0];
|
|
18
|
-
let passport_config = item[1];
|
|
19
17
|
/**
|
|
20
18
|
* item[0] : Boolean = passport file found.
|
|
21
|
-
* item[1] : Object = passport object.
|
|
19
|
+
* item[1] : Object = passport object. (for check on/off)
|
|
22
20
|
*/
|
|
21
|
+
let item = final[0];
|
|
22
|
+
let passport_config = item[1];
|
|
23
|
+
// check passport file exists ?, when not exists go to next
|
|
23
24
|
if(item[0]) {
|
|
24
25
|
if ((passport_config.model.guard.advanced_guard) ? passport_config.model.guard.advanced_guard.allow : false) {
|
|
25
26
|
let advanced_guard_entity = req.headers[passport_config.model.guard.advanced_guard.entity || "timing"];
|
|
@@ -47,7 +48,7 @@ function avg(req, res, next) {
|
|
|
47
48
|
message: "Bad request.",
|
|
48
49
|
info: {
|
|
49
50
|
status: "BAD_VALUE",
|
|
50
|
-
message: "Bad with wrong Advance guard."
|
|
51
|
+
message: "Bad with wrong Advance guard key."
|
|
51
52
|
},
|
|
52
53
|
});
|
|
53
54
|
}
|
|
@@ -3,8 +3,7 @@ const fs = require("fs");
|
|
|
3
3
|
const passport_config_file = "/passport.config.js";
|
|
4
4
|
const auth = require("../auth/Credentials");
|
|
5
5
|
const { TwoFactor } = require("../helpers/2fa");
|
|
6
|
-
const {
|
|
7
|
-
const moment = require("moment");
|
|
6
|
+
const { Limiter, Duplicater } = require("../middleware");
|
|
8
7
|
|
|
9
8
|
module.exports = {
|
|
10
9
|
expressStart() {
|
|
@@ -144,7 +143,7 @@ module.exports = {
|
|
|
144
143
|
// declare authentication endpoint name with publicPath
|
|
145
144
|
let auth_endpoint = (passport_config.auth_endpoint) ? (passport_config.auth_endpoint[ 0 ] === "/" ? passport_config.auth_endpoint : "/" + passport_config.auth_endpoint) : "/authentication";
|
|
146
145
|
// authentication endpoints
|
|
147
|
-
endpoint.post(auth_endpoint, auth.credentialsGuard, (req, res, next) => {
|
|
146
|
+
endpoint.post(auth_endpoint, Duplicater(), Limiter(), auth.credentialsGuard, (req, res, next) => {
|
|
148
147
|
passport.authenticate('local', { session: false }, (err, user, opt) => {
|
|
149
148
|
if (err) {
|
|
150
149
|
res.status(502).json({ code: 502, status: "BAD_GATEWAY", message: String(err) });
|
|
@@ -196,8 +195,49 @@ module.exports = {
|
|
|
196
195
|
}
|
|
197
196
|
})(req, res, next);
|
|
198
197
|
});
|
|
198
|
+
// refresh token endpoints
|
|
199
|
+
endpoint.post(auth_endpoint + '/refresh', Duplicater(), Limiter(), auth.credentials, (req, res) => {
|
|
200
|
+
const refreshToken = req.headers.authorization.split("Bearer ")[1] || null;
|
|
201
|
+
if (!refreshToken) {
|
|
202
|
+
return res.status(400).json({
|
|
203
|
+
code: 400,
|
|
204
|
+
status: "BAD_REQUEST",
|
|
205
|
+
message: "Bad request.",
|
|
206
|
+
info: {
|
|
207
|
+
status: "BAD_ENTITY",
|
|
208
|
+
message: "Refresh token is required.",
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
} else {
|
|
212
|
+
jwt.verify(refreshToken, passport_config.secret, (err, user) => {
|
|
213
|
+
if (err) {
|
|
214
|
+
return res.status(401).json({
|
|
215
|
+
code: 401,
|
|
216
|
+
status: "UNAUTHORIZED",
|
|
217
|
+
message: "Unauthorized user.",
|
|
218
|
+
info: {
|
|
219
|
+
status: "TOKEN_INVALID_ERR",
|
|
220
|
+
message: "Invalid refresh token.",
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
} else {
|
|
224
|
+
delete user.iat;
|
|
225
|
+
delete user.exp;
|
|
226
|
+
const newAccessToken = jwt.sign(user, passport_config.secret, {
|
|
227
|
+
expiresIn: passport_config.token_expired
|
|
228
|
+
});
|
|
229
|
+
res.status(200).json({
|
|
230
|
+
code: 200,
|
|
231
|
+
status: "TOKEN_REFRESHED",
|
|
232
|
+
user: user,
|
|
233
|
+
accessToken: newAccessToken,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
});
|
|
199
239
|
// create auth data endpoints
|
|
200
|
-
endpoint.post(auth_endpoint + '/create', auth.credentialsGuard, (req, res) => {
|
|
240
|
+
endpoint.post(auth_endpoint + '/create', Duplicater(), Limiter(), auth.credentialsGuard, (req, res) => {
|
|
201
241
|
const promise = new Promise((resolve) => {
|
|
202
242
|
/**
|
|
203
243
|
*
|
|
@@ -251,7 +291,7 @@ module.exports = {
|
|
|
251
291
|
});
|
|
252
292
|
});
|
|
253
293
|
// patch auth data endpoints
|
|
254
|
-
endpoint.patch(auth_endpoint + '/update/:id', auth.credentials, (req, res) => {
|
|
294
|
+
endpoint.patch(auth_endpoint + '/update/:id', Duplicater(), Limiter(), auth.credentials, (req, res) => {
|
|
255
295
|
const promise = new Promise((resolve) => {
|
|
256
296
|
if (passport_config.app_key_allow) {
|
|
257
297
|
if (req.headers.app_key) {
|
|
@@ -305,7 +345,7 @@ module.exports = {
|
|
|
305
345
|
*
|
|
306
346
|
*/
|
|
307
347
|
if (passport_config.strategy.google.allow) {
|
|
308
|
-
endpoint.get(auth_endpoint + '/google', passport.authenticate('google', {
|
|
348
|
+
endpoint.get(auth_endpoint + '/google', Limiter(), passport.authenticate('google', {
|
|
309
349
|
scope: [
|
|
310
350
|
'https://www.googleapis.com/auth/userinfo.email',
|
|
311
351
|
'https://www.googleapis.com/auth/plus.login'
|
|
@@ -313,7 +353,7 @@ module.exports = {
|
|
|
313
353
|
}));
|
|
314
354
|
// google auth callback
|
|
315
355
|
const googleCallback = (passport_config.strategy.google.callbackURL) ? (passport_config.strategy.google.callbackURL[ 0 ] === "/" ? passport_config.strategy.google.callbackURL : "/" + passport_config.strategy.google.callbackURL) : "/google/callback";
|
|
316
|
-
endpoint.get(auth_endpoint + googleCallback, passport.authenticate('google', { failureRedirect: passport_config.strategy.google.failureRedirect, failureMessage: true }), (req, res) => {
|
|
356
|
+
endpoint.get(auth_endpoint + googleCallback, Limiter(), passport.authenticate('google', { failureRedirect: passport_config.strategy.google.failureRedirect, failureMessage: true }), (req, res) => {
|
|
317
357
|
if (typeof req.user.user !== 'undefined') {
|
|
318
358
|
// declare user for sign JWT
|
|
319
359
|
let user = JSON.parse(JSON.stringify(req.user.user));
|
|
@@ -362,10 +402,10 @@ module.exports = {
|
|
|
362
402
|
*
|
|
363
403
|
*/
|
|
364
404
|
if (passport_config.strategy.facebook.allow) {
|
|
365
|
-
endpoint.get(auth_endpoint + '/facebook', passport.authenticate('facebook', { scope: [ 'email', 'public_profile' ] }));
|
|
405
|
+
endpoint.get(auth_endpoint + '/facebook', Limiter(), passport.authenticate('facebook', { scope: [ 'email', 'public_profile' ] }));
|
|
366
406
|
// facebook callback
|
|
367
407
|
const facebookCallback = (passport_config.strategy.facebook.callbackURL) ? (passport_config.strategy.facebook.callbackURL[ 0 ] === "/" ? passport_config.strategy.facebook.callbackURL : "/" + passport_config.strategy.facebook.callbackURL) : "/facebook/callback";
|
|
368
|
-
endpoint.get(auth_endpoint + facebookCallback, passport.authenticate('facebook', { failureRedirect: passport_config.strategy.facebook.failureRedirect, failureMessage: true }), (req, res) => {
|
|
408
|
+
endpoint.get(auth_endpoint + facebookCallback, Limiter(), passport.authenticate('facebook', { failureRedirect: passport_config.strategy.facebook.failureRedirect, failureMessage: true }), (req, res) => {
|
|
369
409
|
if (typeof req.user.user !== 'undefined') {
|
|
370
410
|
// declare user for sign JWT
|
|
371
411
|
let user = JSON.parse(JSON.stringify(req.user.user));
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const current = process.versions.node;
|
|
2
|
+
|
|
3
|
+
const required = {
|
|
4
|
+
min16: "16.20.0",
|
|
5
|
+
min22: "22.18.0",
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const semver = (a, b) => {
|
|
9
|
+
const pa = a.split(".").map(Number);
|
|
10
|
+
const pb = b.split(".").map(Number);
|
|
11
|
+
for (let i = 0; i < 3; i++) {
|
|
12
|
+
if (pa[i] > pb[i]) return 1;
|
|
13
|
+
if (pa[i] < pb[i]) return -1;
|
|
14
|
+
}
|
|
15
|
+
return 0;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
if (semver(current, required.min16) < 0 && semver(current, required.min22) < 0) {
|
|
19
|
+
console.error(`\n❌ You are using Node.js ${current}.\n` + `Beech requires Node.js version ${required.min16}+ or ${required.min22}+.\n` + `Please upgrade your Node.js version.\n`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|