beech-api 3.8.0 → 3.9.75
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/LICENSE +21 -21
- package/README.md +1715 -1244
- package/index.js +2 -2
- package/package.json +92 -83
- package/packages/cli/beech +9 -10
- package/packages/cli/bin/beech-app.js +389 -389
- package/packages/cli/bin/beech-service.js +262 -132
- package/packages/cli/core/auth/Credentials.js +174 -147
- package/packages/cli/core/auth/Passport.js +664 -592
- package/packages/cli/core/auth/_Request.js +12 -12
- package/packages/cli/core/configure/_gitignore +16 -15
- package/packages/cli/core/configure/_sequelizerc +9 -9
- package/packages/cli/core/configure/app.config-basic.js +55 -55
- package/packages/cli/core/configure/app.config-sequelize.js +88 -88
- package/packages/cli/core/configure/beech.config.js +9 -9
- package/packages/cli/core/configure/global.config-basic.js +8 -8
- package/packages/cli/core/configure/global.config-sequelize.js +8 -8
- package/packages/cli/core/configure/jest.config.js +6 -6
- package/packages/cli/core/configure/jsconfig.json +8 -7
- package/packages/cli/core/configure/passport.config.js +97 -97
- package/packages/cli/core/databases/mysql.js +94 -95
- package/packages/cli/core/databases/sequelize.js +187 -179
- package/packages/cli/core/databases/test.js +251 -170
- package/packages/cli/core/file-walk/file-walk.js +35 -35
- package/packages/cli/core/generator/_endpoints +15 -15
- package/packages/cli/core/generator/_endpoints_basic +42 -42
- package/packages/cli/core/generator/_help +26 -18
- package/packages/cli/core/generator/_help_create +10 -10
- package/packages/cli/core/generator/_help_service +10 -10
- package/packages/cli/core/generator/_helpers +9 -9
- package/packages/cli/core/generator/_helpers_basic +22 -22
- package/packages/cli/core/generator/_models +6 -29
- package/packages/cli/core/generator/_models_basic +13 -22
- package/packages/cli/core/generator/_package +23 -20
- package/packages/cli/core/generator/_scheduler +32 -22
- package/packages/cli/core/generator/_spec +29 -29
- package/packages/cli/core/generator/index.js +1081 -738
- package/packages/cli/core/helpers/2fa.js +106 -85
- package/packages/cli/core/helpers/math.js +115 -103
- package/packages/cli/core/helpers/poolEntity.js +103 -59
- package/packages/cli/core/index.js +264 -188
- package/packages/cli/core/middleware/express/duplicateRequest.js +16 -12
- package/packages/cli/core/middleware/express/jwtCheckAllow.js +86 -68
- package/packages/cli/core/middleware/express/rateLimit.js +29 -17
- package/packages/cli/core/middleware/express/slowDown.js +2 -2
- package/packages/cli/core/middleware/index.js +6 -6
- package/packages/cli/core/middleware/origin/guard/advance.js +75 -74
- package/packages/cli/core/middleware/origin/whitelist/cors.js +94 -94
- package/packages/cli/core/services/http.express.js +481 -441
- package/packages/cli/core/test/check-node.js +21 -0
- package/packages/cli/core/test/utils.js +7 -7
- package/packages/cli/entry +10 -0
- package/packages/lib/index.js +6 -6
- package/packages/lib/src/endpoint.js +947 -532
- package/packages/lib/src/guard.js +60 -60
- package/packages/lib/src/salt.js +3 -3
- package/packages/lib/src/schema.js +96 -93
- package/packages/lib/src/specificExpress.js +7 -7
- package/packages/lib/src/user.js +271 -271
|
@@ -1,188 +1,264 @@
|
|
|
1
|
-
global.appRoot = require("app-root-path");
|
|
2
|
-
const moment = require("moment");
|
|
3
|
-
const { performance } = require("perf_hooks");
|
|
4
|
-
const moduleAlias = require("module-alias");
|
|
5
|
-
moduleAlias.addAlias("@", appRoot + "/src");
|
|
6
|
-
const _express_ = require("express");
|
|
7
|
-
global._app_ = _express_();
|
|
8
|
-
// Compression
|
|
9
|
-
const compression = require("compression");
|
|
10
|
-
_app_.use(compression());
|
|
11
|
-
// Helmet
|
|
12
|
-
const helmet = require("helmet");
|
|
13
|
-
_app_.use(helmet());
|
|
14
|
-
// CORS
|
|
15
|
-
const cors = require("cors");
|
|
16
|
-
global.endpoint = _express_.Router();
|
|
17
|
-
const cookieParser = require("cookie-parser");
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
global.
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
//
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
_app_.use((
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
//
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
1
|
+
global.appRoot = require("app-root-path");
|
|
2
|
+
const moment = require("moment");
|
|
3
|
+
const { performance } = require("perf_hooks");
|
|
4
|
+
const moduleAlias = require("module-alias");
|
|
5
|
+
moduleAlias.addAlias("@", appRoot + "/src");
|
|
6
|
+
const _express_ = require("express");
|
|
7
|
+
global._app_ = _express_();
|
|
8
|
+
// Compression
|
|
9
|
+
const compression = require("compression");
|
|
10
|
+
_app_.use(compression());
|
|
11
|
+
// Helmet
|
|
12
|
+
const helmet = require("helmet");
|
|
13
|
+
_app_.use(helmet());
|
|
14
|
+
// CORS
|
|
15
|
+
const cors = require("cors");
|
|
16
|
+
global.endpoint = _express_.Router();
|
|
17
|
+
const cookieParser = require("cookie-parser");
|
|
18
|
+
const methodOverride = require("method-override");
|
|
19
|
+
const expressSession = require("express-session");
|
|
20
|
+
const globalVariable = require(appRoot + "/global.config.js");
|
|
21
|
+
globalVariable.init();
|
|
22
|
+
// Local environments
|
|
23
|
+
global._config_ = require(appRoot + "/app.config");
|
|
24
|
+
const _beech_ = require(appRoot + "/beech.config.js").defineConfig;
|
|
25
|
+
global._publicPath_ = _beech_.base;
|
|
26
|
+
const mySqlDbConnect = require("./databases/mysql");
|
|
27
|
+
const SequelizeDbConnect = require("./databases/sequelize");
|
|
28
|
+
// Set limit payload for request body & multipart/form-data (multer)
|
|
29
|
+
const multer = require("multer");
|
|
30
|
+
const uploadAllowMethod = _beech_?.payload?.file?.uploadAllowMethod || ["POST", "PATCH", "PUT"];
|
|
31
|
+
const allowedTypes = _beech_?.payload?.file?.allowedTypes || []; // default: no allowed type
|
|
32
|
+
const fileLimitSize = _beech_?.payload?.file?.limit || 5 * 1024 * 1024; // 5MB
|
|
33
|
+
const uploadStrategy = multer({
|
|
34
|
+
limits: { fileSize: fileLimitSize },
|
|
35
|
+
fileFilter: (req, file, cb) => {
|
|
36
|
+
if (allowedTypes.length === 0) {
|
|
37
|
+
cb(new Error("INVALID_FILE_TYPE_ALLOW"), false); // Allow all file types if no allowed types specified
|
|
38
|
+
} else if (allowedTypes.includes(file.mimetype)) {
|
|
39
|
+
cb(null, true);
|
|
40
|
+
} else {
|
|
41
|
+
cb(new Error("INVALID_FILE_TYPE"), false);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}).any();
|
|
45
|
+
const jsonLimitSize = _beech_?.payload?.json?.limit || "100KB"; // json payload
|
|
46
|
+
const urlencodedLimitSize = _beech_?.payload?.urlencoded?.limit || "100KB"; // urlencoded payload (multipart/form-data)
|
|
47
|
+
const urlencodedExtended = !!(_beech_?.payload?.urlencoded?.extended ?? true);
|
|
48
|
+
_app_.use(_express_.urlencoded({ limit: urlencodedLimitSize, extended: urlencodedExtended })); // application/x-www-form-urlencoded payload
|
|
49
|
+
_app_.use(_express_.json({ limit: jsonLimitSize }));
|
|
50
|
+
_app_.use((req, res, next) => {
|
|
51
|
+
const isUploadMethod = uploadAllowMethod.includes(req.method);
|
|
52
|
+
const isMultipart = req.headers["content-type"]?.includes("multipart/form-data");
|
|
53
|
+
// Handle file upload for allowed methods
|
|
54
|
+
if (isUploadMethod) {
|
|
55
|
+
return uploadStrategy(req, res, (err) => {
|
|
56
|
+
if (err) return next(err);
|
|
57
|
+
next();
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
// Handle method not allowed for file upload
|
|
61
|
+
if (!isUploadMethod && isMultipart) {
|
|
62
|
+
return res.status(405).json({
|
|
63
|
+
code: 405,
|
|
64
|
+
status: "METHOD_NOT_ALLOWED_FOR_UPLOAD",
|
|
65
|
+
message: _config_.main_config?.dev ? `File upload is not allowed for ${req.method} method.` : "Method Not Allowed for file upload.",
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
// next to next middleware
|
|
69
|
+
next();
|
|
70
|
+
});
|
|
71
|
+
_app_.use((err, req, res, next) => {
|
|
72
|
+
// Handle payload too large error for JSON and URL-encoded
|
|
73
|
+
if (err.type === "entity.too.large") {
|
|
74
|
+
const isJson = req.headers["content-type"]?.includes("application/json");
|
|
75
|
+
const limitUsed = isJson ? jsonLimitSize : urlencodedLimitSize;
|
|
76
|
+
return res.status(413).json({
|
|
77
|
+
code: 413,
|
|
78
|
+
status: "PAYLOAD_TOO_LARGE",
|
|
79
|
+
message:_config_.main_config?.dev ? `${isJson ? 'JSON' : 'Form data'} too large, Max limit is ${limitUsed}` : "Payload Too Large.",
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
if (err.message === "INVALID_FILE_TYPE_ALLOW") {
|
|
83
|
+
return res.status(400).json({
|
|
84
|
+
code: 400,
|
|
85
|
+
status: "INVALID_FILE_TYPE_ALLOW",
|
|
86
|
+
message: "Invalid file type, No file types allowed.",
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
// Handle invalid file type error from multer
|
|
90
|
+
if (err.message === "INVALID_FILE_TYPE") {
|
|
91
|
+
return res.status(400).json({
|
|
92
|
+
code: 400,
|
|
93
|
+
status: "INVALID_FILE_TYPE",
|
|
94
|
+
message: _config_.main_config?.dev ? `Invalid file type, Allowed: ${allowedTypes.join(', ')}` : "Invalid file type.",
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// Handle multer file size limit error
|
|
98
|
+
if (err.code === "LIMIT_FILE_SIZE") {
|
|
99
|
+
return res.status(413).json({
|
|
100
|
+
code: 413,
|
|
101
|
+
status: "PAYLOAD_TOO_LARGE",
|
|
102
|
+
message: _config_.main_config?.dev ? `File size too large, Max limit is ${fileLimitSize / 1024 / 1024}MB` : "Payload Too Large.",
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
// next to general error handler
|
|
106
|
+
next(err);
|
|
107
|
+
});
|
|
108
|
+
// Database test
|
|
109
|
+
const {
|
|
110
|
+
testConnectInProcess,
|
|
111
|
+
filterDbIsTrue,
|
|
112
|
+
disConnectTestDB,
|
|
113
|
+
} = require("./databases/test");
|
|
114
|
+
// create global sequelize object
|
|
115
|
+
const { QueryTypes, DataTypes, Op } = require("sequelize");
|
|
116
|
+
global.QueryTypes = QueryTypes;
|
|
117
|
+
global.DataTypes = DataTypes;
|
|
118
|
+
global.Op = Op;
|
|
119
|
+
// Allow whitelist cors
|
|
120
|
+
const { whitelist, sign, avg } = require("./middleware/index");
|
|
121
|
+
_app_.use(cors({ origin: true, credentials: true }));
|
|
122
|
+
_app_.use((req, res, next) => {
|
|
123
|
+
whitelist(async (lists, originSensitive) => {
|
|
124
|
+
sign(req, res, lists, originSensitive, (err) => {
|
|
125
|
+
if (!err) {
|
|
126
|
+
next();
|
|
127
|
+
} else {
|
|
128
|
+
throw err;
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
// View engine
|
|
134
|
+
_app_.use(methodOverride());
|
|
135
|
+
_app_.use(cookieParser());
|
|
136
|
+
_app_.use(expressSession({
|
|
137
|
+
secret: "surprise you mother f*cker",
|
|
138
|
+
resave: true,
|
|
139
|
+
saveUninitialized: true,
|
|
140
|
+
}));
|
|
141
|
+
// Dev. activity
|
|
142
|
+
global._requestTime_ = moment(new Date()).format("YYYY-MM-DD HH:mm:ss");
|
|
143
|
+
_app_.use((req, res, next) => {
|
|
144
|
+
console.log(`[${_requestTime_}] : Request ${req.method} ${req.originalUrl}`);
|
|
145
|
+
const t0 = performance.now();
|
|
146
|
+
res.on('finish', () => {
|
|
147
|
+
const responseTime = moment(new Date()).format("YYYY-MM-DD HH:mm:ss");
|
|
148
|
+
const t1 = performance.now();
|
|
149
|
+
const duration = (t1 - t0).toFixed(0);
|
|
150
|
+
console.log(`[${responseTime}] : Response ${res.statusCode} (${duration}ms)`);
|
|
151
|
+
});
|
|
152
|
+
next();
|
|
153
|
+
});
|
|
154
|
+
// Check Syntax error.
|
|
155
|
+
_app_.use((error, req, res, next) => {
|
|
156
|
+
if (error instanceof SyntaxError) {
|
|
157
|
+
res.status(400).json({
|
|
158
|
+
...error,
|
|
159
|
+
status: "BAD_REQUEST",
|
|
160
|
+
message: "Bad Request.",
|
|
161
|
+
body: error.body,
|
|
162
|
+
});
|
|
163
|
+
} else {
|
|
164
|
+
next();
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
// Advance Guard
|
|
168
|
+
_app_.use(avg);
|
|
169
|
+
// Engine import
|
|
170
|
+
const httpExpress = require("./services/http.express");
|
|
171
|
+
const fileWalk = require("./file-walk/file-walk");
|
|
172
|
+
// Passport initialization
|
|
173
|
+
const authPassport = require("./auth/Passport");
|
|
174
|
+
const passport = require("passport");
|
|
175
|
+
_app_.use(passport.initialize());
|
|
176
|
+
_app_.use(passport.session());
|
|
177
|
+
passport.serializeUser((user, done) => {
|
|
178
|
+
done(null, user);
|
|
179
|
+
});
|
|
180
|
+
passport.deserializeUser((user, done) => {
|
|
181
|
+
done(null, user);
|
|
182
|
+
});
|
|
183
|
+
// Endpoint magic
|
|
184
|
+
const { Base } = require("../../lib/index");
|
|
185
|
+
// Read folder in ./src/endpoints/*
|
|
186
|
+
const walk = require("walk");
|
|
187
|
+
let jsfiles = [];
|
|
188
|
+
let walker = walk.walk(appRoot + "/src/endpoints", { followLinks: false });
|
|
189
|
+
// Walk file on push
|
|
190
|
+
walker.on("file", (root, stat, next) => {
|
|
191
|
+
jsfiles.push(root + "/" + stat.name);
|
|
192
|
+
next();
|
|
193
|
+
});
|
|
194
|
+
// Walking
|
|
195
|
+
walker.on("end", () => {
|
|
196
|
+
init(jsfiles);
|
|
197
|
+
});
|
|
198
|
+
// Initialize the application
|
|
199
|
+
init = async (jsfiles) => {
|
|
200
|
+
try {
|
|
201
|
+
const testConnectToDB = new Promise((resolve) => {
|
|
202
|
+
filterDbIsTrue(_config_.database_config, (err, dbTruthy) => {
|
|
203
|
+
if (err) {
|
|
204
|
+
throw ("Config file crash.", err);
|
|
205
|
+
}
|
|
206
|
+
// leave data to disconnect database
|
|
207
|
+
let leaveDataForDisconnect = dbTruthy.slice(0);
|
|
208
|
+
// check db connect truthy length ?
|
|
209
|
+
if (dbTruthy.length > 0) {
|
|
210
|
+
testConnectInProcess(dbTruthy, dbTruthy.length, (err, result, dbs) => {
|
|
211
|
+
if (err) {
|
|
212
|
+
throw ("[101m Failed [0m Database connect failed.", err);
|
|
213
|
+
}
|
|
214
|
+
if (result) {
|
|
215
|
+
// Disconnect database
|
|
216
|
+
disConnectTestDB(leaveDataForDisconnect, dbs, (err, disResult) => {
|
|
217
|
+
if (err) {
|
|
218
|
+
throw ("[101m Failed [0m Testing Database connect failed.", err);
|
|
219
|
+
}
|
|
220
|
+
if (disResult) {
|
|
221
|
+
// Disconnect and Next to real
|
|
222
|
+
resolve(true);
|
|
223
|
+
} else {
|
|
224
|
+
throw err;
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
} else {
|
|
230
|
+
// Not ON connect, Next to real
|
|
231
|
+
resolve(true);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
Promise.all([testConnectToDB]).then(async (x) => {
|
|
236
|
+
if (x[0]) {
|
|
237
|
+
await (pool_base == "basic" ? new Promise((resolve) => resolve(mySqlDbConnect.connect())) : new Promise((resolve) => resolve(SequelizeDbConnect.connect())));
|
|
238
|
+
await authPassport.init().then(async (p) => {
|
|
239
|
+
if (p[0]) {
|
|
240
|
+
console.log("\n[101m Init failed [0m", p[0]);
|
|
241
|
+
return;
|
|
242
|
+
//throw p[0];
|
|
243
|
+
} else {
|
|
244
|
+
await new Promise((resolve) => resolve(fileWalk.fileWalk(jsfiles)));
|
|
245
|
+
await (pool_base == "basic" ? new Promise((resolve) => resolve()) : new Promise((resolve) => resolve(Base())));
|
|
246
|
+
await new Promise((resolve) => {
|
|
247
|
+
httpExpress.expressStart().then((expss) => {
|
|
248
|
+
resolve(expss);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}).catch((err) => {
|
|
253
|
+
console.log("[101m Catch init failed [0m", err);
|
|
254
|
+
throw err;
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
} catch (error) {
|
|
259
|
+
console.log("[101m Compile failed [0m", error);
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
// Use router
|
|
264
|
+
_app_.use(_publicPath_, endpoint);
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
const _beech_ = require(appRoot + "/beech.config.js");
|
|
2
|
-
const { duplicateRequest } = require("express-duplicate-request");
|
|
3
|
-
const nextDuplicater = (req, res, next) =>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
const _beech_ = require(appRoot + "/beech.config.js");
|
|
2
|
+
const { duplicateRequest } = require("express-duplicate-request");
|
|
3
|
+
const nextDuplicater = (req, res, next) => next();
|
|
4
|
+
const defaultConfigure = {
|
|
5
|
+
expiration: _beech_.defineConfig.server.duplicateRequest ? _beech_.defineConfig.server.duplicateRequest.expiration : 0,
|
|
6
|
+
};
|
|
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
|
+
};
|
|
15
|
+
|
|
16
|
+
module.exports = { Duplicater, duplicateRequest };
|
|
@@ -1,68 +1,86 @@
|
|
|
1
|
-
const passport = require("passport");
|
|
2
|
-
|
|
3
|
-
const checkRoleMiddleware = (options) => {
|
|
4
|
-
return
|
|
5
|
-
if(!Array.isArray(options)) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
options.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
1
|
+
const passport = require("passport");
|
|
2
|
+
|
|
3
|
+
const checkRoleMiddleware = (options) => {
|
|
4
|
+
return (req, res, next) => {
|
|
5
|
+
if(!Array.isArray(options)) {
|
|
6
|
+
// Perfectly with options is not type Array
|
|
7
|
+
return next();
|
|
8
|
+
} else {
|
|
9
|
+
passport.authenticate("jwt", {
|
|
10
|
+
session: false,
|
|
11
|
+
}, (err, user, info) => {
|
|
12
|
+
// error check
|
|
13
|
+
if (err) {
|
|
14
|
+
//console.log(err, info);
|
|
15
|
+
return res.status(403).json({
|
|
16
|
+
code: 403,
|
|
17
|
+
status: "FORBIDDEN",
|
|
18
|
+
message: "Forbidden: Insufficient role",
|
|
19
|
+
info: {
|
|
20
|
+
error: err,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
} else {
|
|
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();
|
|
36
|
+
} else {
|
|
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
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
})(req, res, next);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
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
|
+
|
|
80
|
+
const checkRoleMiddlewareWithDefaultProject = (options) => {
|
|
81
|
+
return function (req, res, next) {
|
|
82
|
+
return checkRoleMiddleware(options)(req, res, next);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
module.exports = { checkRoleMiddleware, checkRoleMiddlewareWithDefaultProject };
|