nodejs-backpack 0.0.1-security → 2.0.22
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.
Potentially problematic release.
This version of nodejs-backpack might be problematic. Click here for more details.
- package/.sample-env +3 -0
- package/helper.js +76 -0
- package/index.js +131 -0
- package/package.json +53 -6
- package/readme.md +155 -0
- package/sample-app.js +41 -0
- package/sample-auth-controller.js +217 -0
- package/sample-auth-middleware.js +44 -0
- package/sample-auth-route.js +19 -0
- package/sample-config-mailer.js +10 -0
- package/sample-controller.js +174 -0
- package/sample-env +4 -0
- package/sample-file-uploader.js +27 -0
- package/sample-form-parser.js +5 -0
- package/sample-helper.js +138 -0
- package/sample-index-route.js +7 -0
- package/sample-package.json +29 -0
- package/sample-route.js +20 -0
- package/sample-schema-ResetToken.js +26 -0
- package/sample-schema-User.js +51 -0
- package/sample-schema.js +49 -0
- package/sample-validation.js +4 -0
- package/typing.gif +0 -0
- package/README.md +0 -5
@@ -0,0 +1,217 @@
|
|
1
|
+
const User = require("../models/User"); //
|
2
|
+
const ResetToken = require("../models/ResetToken");
|
3
|
+
const bcrypt = require("bcryptjs");
|
4
|
+
const jwt = require("jsonwebtoken");
|
5
|
+
const dotenv = require("dotenv").config().parsed;
|
6
|
+
const crypto = require("crypto");
|
7
|
+
const {
|
8
|
+
successResponse,
|
9
|
+
checkValidationResult,
|
10
|
+
customResponse,
|
11
|
+
errorResponse,
|
12
|
+
} = require("rest-api-response-npm");
|
13
|
+
const nodemailer = require("../config/mailtrap");
|
14
|
+
|
15
|
+
const AuthController = {
|
16
|
+
signUp: (req, res, next) => {
|
17
|
+
const response = checkValidationResult(res, req);
|
18
|
+
if (response["status_code"] === 422) {
|
19
|
+
return errorResponse(
|
20
|
+
res,
|
21
|
+
response["data"],
|
22
|
+
response["message"],
|
23
|
+
response["status_code"]
|
24
|
+
);
|
25
|
+
}
|
26
|
+
const password = req.body.password;
|
27
|
+
bcrypt
|
28
|
+
.hash(password, 12)
|
29
|
+
.then((hashPw) => {
|
30
|
+
req.body.password = hashPw;
|
31
|
+
const user = new User(req.body);
|
32
|
+
return user.save();
|
33
|
+
})
|
34
|
+
.then((result) => {
|
35
|
+
return successResponse(res, result, "User Registerd Successfully");
|
36
|
+
})
|
37
|
+
.catch((err) => {
|
38
|
+
next(err);
|
39
|
+
});
|
40
|
+
},
|
41
|
+
login: (req, res, next) => {
|
42
|
+
const response = checkValidationResult(res, req);
|
43
|
+
if (response["status_code"] === 422) {
|
44
|
+
return errorResponse(
|
45
|
+
res,
|
46
|
+
response["data"],
|
47
|
+
response["message"],
|
48
|
+
response["status_code"]
|
49
|
+
);
|
50
|
+
}
|
51
|
+
const email = req.body.email;
|
52
|
+
const password = req.body.password;
|
53
|
+
let loadedUser;
|
54
|
+
User.findOne({ email: email })
|
55
|
+
.then((user) => {
|
56
|
+
loadedUser = user;
|
57
|
+
return bcrypt.compare(password, user.password);
|
58
|
+
})
|
59
|
+
.then((isEqual) => {
|
60
|
+
if (!isEqual) {
|
61
|
+
data = {
|
62
|
+
password: ["Wrong Password"],
|
63
|
+
};
|
64
|
+
return customResponse(res, data, "Wrong Password", 422);
|
65
|
+
}
|
66
|
+
// create new token using sign
|
67
|
+
return jwt.sign(
|
68
|
+
{
|
69
|
+
userId: loadedUser._id,
|
70
|
+
},
|
71
|
+
dotenv.JWT_SIGNATURE,
|
72
|
+
{ expiresIn: "365d" }
|
73
|
+
);
|
74
|
+
})
|
75
|
+
.then((token) => {
|
76
|
+
loadedUser.token = token;
|
77
|
+
loadedUser.save();
|
78
|
+
return successResponse(
|
79
|
+
res,
|
80
|
+
{ access_token: token, user_data: loadedUser },
|
81
|
+
"Login Successfully"
|
82
|
+
);
|
83
|
+
})
|
84
|
+
.catch((err) => {
|
85
|
+
next(err);
|
86
|
+
});
|
87
|
+
},
|
88
|
+
logout: (req, res, next) => {
|
89
|
+
const filter = { _id: req.userId };
|
90
|
+
const update = { token: "" };
|
91
|
+
User.findOneAndUpdate(filter, update)
|
92
|
+
.then(() => {
|
93
|
+
return successResponse(res, null, "You have been Logged Out");
|
94
|
+
})
|
95
|
+
.catch((err) => {
|
96
|
+
next(err);
|
97
|
+
});
|
98
|
+
},
|
99
|
+
forgotPassword: (req, res, next) => {
|
100
|
+
const response = checkValidationResult(res, req);
|
101
|
+
if (response["status_code"] === 422) {
|
102
|
+
return errorResponse(
|
103
|
+
res,
|
104
|
+
response["data"],
|
105
|
+
response["message"],
|
106
|
+
response["status_code"]
|
107
|
+
);
|
108
|
+
}
|
109
|
+
crypto.randomBytes(32, (err, buffer) => {
|
110
|
+
if (err) {
|
111
|
+
return customResponse(res, null, "Something went wrong", 400);
|
112
|
+
}
|
113
|
+
const token = buffer.toString("hex");
|
114
|
+
User.findOne({ email: req.body.email })
|
115
|
+
.then((user) => {
|
116
|
+
const reset_token = new ResetToken({
|
117
|
+
reset_token: token,
|
118
|
+
email: user.email,
|
119
|
+
});
|
120
|
+
return reset_token.save();
|
121
|
+
})
|
122
|
+
.then((result) => {
|
123
|
+
nodemailer.sendMail({
|
124
|
+
to: req.body.email,
|
125
|
+
from: "ats@technomarktest.io",
|
126
|
+
subject: "Password reset",
|
127
|
+
html: `
|
128
|
+
<p>You requested a password reset</p>
|
129
|
+
<p>Click this <a href="${dotenv?.HOST}/reset/?token=${token}&email=${req.body.email}">link</a> to set a new password.</p>
|
130
|
+
`,
|
131
|
+
});
|
132
|
+
return successResponse(
|
133
|
+
res,
|
134
|
+
null,
|
135
|
+
"Reset password link send your registerd email address"
|
136
|
+
);
|
137
|
+
})
|
138
|
+
.catch((err) => {
|
139
|
+
next(err);
|
140
|
+
});
|
141
|
+
});
|
142
|
+
},
|
143
|
+
resetPassword: (req, res, next) => {
|
144
|
+
const response = checkValidationResult(res, req);
|
145
|
+
if (response["status_code"] === 422) {
|
146
|
+
return errorResponse(
|
147
|
+
res,
|
148
|
+
response["data"],
|
149
|
+
response["message"],
|
150
|
+
response["status_code"]
|
151
|
+
);
|
152
|
+
}
|
153
|
+
const new_password = req.body.password;
|
154
|
+
const r_token = req.body.reset_token;
|
155
|
+
const email = req.body.email;
|
156
|
+
let resetUser;
|
157
|
+
ResetToken.findOne({
|
158
|
+
email: email,
|
159
|
+
reset_token: r_token,
|
160
|
+
})
|
161
|
+
.then((result) => {
|
162
|
+
if (!result) {
|
163
|
+
return customResponse(
|
164
|
+
res,
|
165
|
+
null,
|
166
|
+
`Reset token has expired. Please try the 'forgot password' option again to get a new reset token!`,
|
167
|
+
401
|
168
|
+
);
|
169
|
+
}
|
170
|
+
return User.findOne({
|
171
|
+
email: email,
|
172
|
+
});
|
173
|
+
})
|
174
|
+
.then((user) => {
|
175
|
+
resetUser = user;
|
176
|
+
return bcrypt.hash(new_password, 12);
|
177
|
+
})
|
178
|
+
.then((hashedPassword) => {
|
179
|
+
resetUser.password = hashedPassword;
|
180
|
+
return resetUser.save();
|
181
|
+
})
|
182
|
+
.then((result1) => {
|
183
|
+
return ResetToken.findOneAndDelete({
|
184
|
+
email: email,
|
185
|
+
reset_token: r_token,
|
186
|
+
});
|
187
|
+
})
|
188
|
+
.then((result1) => {
|
189
|
+
return successResponse(res, null, "Your Password Change Successfully");
|
190
|
+
})
|
191
|
+
.catch((err) => {
|
192
|
+
next(err);
|
193
|
+
});
|
194
|
+
},
|
195
|
+
profile: (req, res, next) => {
|
196
|
+
const usertoken = req.headers.authorization;
|
197
|
+
const token = usertoken.split(" ");
|
198
|
+
const user = jwt.verify(token[1], dotenv.JWT_SIGNATURE);
|
199
|
+
User.findOne({ _id: user.userId })
|
200
|
+
.then((userData) => {
|
201
|
+
if (!userData) {
|
202
|
+
return customResponse(
|
203
|
+
res,
|
204
|
+
null,
|
205
|
+
"A user with this email could not be found",
|
206
|
+
400
|
207
|
+
);
|
208
|
+
}
|
209
|
+
return successResponse(res, userData);
|
210
|
+
})
|
211
|
+
.catch((err) => {
|
212
|
+
next(err);
|
213
|
+
});
|
214
|
+
},
|
215
|
+
};
|
216
|
+
|
217
|
+
module.exports = AuthController;
|
@@ -0,0 +1,44 @@
|
|
1
|
+
const jwt = require("jsonwebtoken");
|
2
|
+
const dotenv = require("dotenv").config().parsed;
|
3
|
+
const User = require("../models/User"); //
|
4
|
+
const { customResponse } = require("rest-api-response-npm");
|
5
|
+
|
6
|
+
function authenticateToken(req, res, next) {
|
7
|
+
const authHeader = req.headers["authorization"];
|
8
|
+
|
9
|
+
if (authHeader) {
|
10
|
+
const token = authHeader.split(" ")[1];
|
11
|
+
|
12
|
+
if (token) {
|
13
|
+
try {
|
14
|
+
const jwt_secret_key = dotenv?.JWT_SIGNATURE;
|
15
|
+
const decoded = jwt.verify(token, jwt_secret_key);
|
16
|
+
// Token is valid, you can access the decoded payload
|
17
|
+
console.log("decoded?.data?.token", decoded?.userId);
|
18
|
+
if (decoded?.userId) {
|
19
|
+
User.findOne({ _id: decoded?.userId })
|
20
|
+
.then((userData) => {
|
21
|
+
console.log("token", token);
|
22
|
+
console.log("userData", userData);
|
23
|
+
if (userData && token === userData?.token) {
|
24
|
+
req.user = decoded.data;
|
25
|
+
req.userId = decoded.userId;
|
26
|
+
next();
|
27
|
+
} else {
|
28
|
+
return customResponse(res, null, "Token is expired", 401);
|
29
|
+
}
|
30
|
+
})
|
31
|
+
.catch((err) => {});
|
32
|
+
}
|
33
|
+
} catch (err) {
|
34
|
+
return customResponse(res, null, "Token is invalid or expired", 401);
|
35
|
+
}
|
36
|
+
} else {
|
37
|
+
return customResponse(res, null, "No token found", 401);
|
38
|
+
}
|
39
|
+
} else {
|
40
|
+
return customResponse(res, null, "No authorization header", 401);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
module.exports = authenticateToken;
|
@@ -0,0 +1,19 @@
|
|
1
|
+
const express = require('express');
|
2
|
+
const router = express.Router();
|
3
|
+
const AuthController = require('../controllers/AuthController');
|
4
|
+
const signUpRequestValidationRequest = require('./validationRequest/Auth/signUpRequestValidationRequest');
|
5
|
+
const signInValidationRequest = require('./validationRequest/Auth/signInValidationRequest');
|
6
|
+
const forgotPasswordValidationRequest = require('./validationRequest/Auth/forgotPasswordValidationRequest');
|
7
|
+
const resetPasswordValidationRequest = require('./validationRequest/Auth/resetPasswordValidationRequest');
|
8
|
+
const formParser = require('../helpers/formParser');
|
9
|
+
const isAuth = require("../middleware/AuthMiddleware");
|
10
|
+
|
11
|
+
|
12
|
+
router.post(`/register`,formParser,signUpRequestValidationRequest, AuthController.signUp);
|
13
|
+
router.post(`/login`,formParser,signInValidationRequest, AuthController.login);
|
14
|
+
router.post(`/forgot-password`,formParser,forgotPasswordValidationRequest, AuthController.forgotPassword);
|
15
|
+
router.post(`/reset-password`,formParser,resetPasswordValidationRequest, AuthController.resetPassword);
|
16
|
+
router.get(`/logout`,formParser,isAuth, AuthController.logout);
|
17
|
+
router.get(`/get-profile`,formParser,isAuth, AuthController.profile);
|
18
|
+
|
19
|
+
module.exports = router;
|
@@ -0,0 +1,174 @@
|
|
1
|
+
const {
|
2
|
+
successResponse,
|
3
|
+
checkValidationResult,
|
4
|
+
errorResponse,
|
5
|
+
} = require("rest-api-response-npm");
|
6
|
+
const ${schemaName} = require("../models/${schemaName}");
|
7
|
+
const {
|
8
|
+
generatePaginationLinks,
|
9
|
+
searchableFields,
|
10
|
+
mergerFilesAndBody,
|
11
|
+
filterMissingFields,
|
12
|
+
} = require("../helpers/helper.js");
|
13
|
+
|
14
|
+
const ${fileName}Controller = {
|
15
|
+
list: async (req, res) => {
|
16
|
+
var currentPage = parseInt(req?.query?.page_no) || 1;
|
17
|
+
var perPage = parseInt(req?.query?.page_limit) || 10;
|
18
|
+
var searchInput = req?.query?.search || "";
|
19
|
+
|
20
|
+
const rgx = (pattern) => new RegExp(`.*${pattern}.*`);
|
21
|
+
const searchRgx = rgx(searchInput);
|
22
|
+
|
23
|
+
var SearchFieldArray = ${___SearchFieldArray___};
|
24
|
+
|
25
|
+
const count = await ${schemaName}.countDocuments({
|
26
|
+
$or: SearchFieldArray,
|
27
|
+
});
|
28
|
+
|
29
|
+
const totalPages = Math.ceil(count / perPage);
|
30
|
+
|
31
|
+
await ${schemaName}.find({
|
32
|
+
$or: SearchFieldArray,
|
33
|
+
})
|
34
|
+
.skip((currentPage - 1) * perPage)
|
35
|
+
.limit(perPage)
|
36
|
+
.sort({ createdAt: -1 })
|
37
|
+
.then((results) => {
|
38
|
+
const response = {
|
39
|
+
totalRecords: count,
|
40
|
+
totalPages: totalPages,
|
41
|
+
currentPage: currentPage,
|
42
|
+
perPage: perPage,
|
43
|
+
results: results,
|
44
|
+
};
|
45
|
+
|
46
|
+
generatePaginationLinks(
|
47
|
+
req,
|
48
|
+
response,
|
49
|
+
currentPage,
|
50
|
+
perPage,
|
51
|
+
totalPages,
|
52
|
+
searchInput
|
53
|
+
);
|
54
|
+
return successResponse(
|
55
|
+
res,
|
56
|
+
response,
|
57
|
+
"${fileName} list fetched successfully!"
|
58
|
+
);
|
59
|
+
})
|
60
|
+
.catch((err) => {
|
61
|
+
return errorResponse(res, err, "Opps something went wrong!", 500);
|
62
|
+
});
|
63
|
+
},
|
64
|
+
getDetail: async (req, res) => {
|
65
|
+
const response = checkValidationResult(res, req);
|
66
|
+
if (response["status_code"] === 422) {
|
67
|
+
return errorResponse(
|
68
|
+
res,
|
69
|
+
response["data"],
|
70
|
+
response["message"],
|
71
|
+
response["status_code"]
|
72
|
+
);
|
73
|
+
}
|
74
|
+
await ${schemaName}.findById(req.params.id)
|
75
|
+
.then((result) => {
|
76
|
+
if (result) {
|
77
|
+
return successResponse(res, result, "${fileName} detail fetched successfully!");
|
78
|
+
} else {
|
79
|
+
data = {
|
80
|
+
id: ["Record doesn't exist!"],
|
81
|
+
};
|
82
|
+
return validationResponse(res, data, "Record doesn't exist!");
|
83
|
+
}
|
84
|
+
})
|
85
|
+
.catch((err) =>
|
86
|
+
{
|
87
|
+
return errorResponse(res, err, "Opps something went wrong!", 500)
|
88
|
+
}
|
89
|
+
);
|
90
|
+
},
|
91
|
+
store: async (req, res) => {
|
92
|
+
const response = checkValidationResult(res, req);
|
93
|
+
if (response["status_code"] === 422) {
|
94
|
+
return errorResponse(
|
95
|
+
res,
|
96
|
+
response["data"],
|
97
|
+
response["message"],
|
98
|
+
response["status_code"]
|
99
|
+
);
|
100
|
+
}
|
101
|
+
/*File values into body*/
|
102
|
+
mergerFilesAndBody(req);
|
103
|
+
var storeData = ${___StoreFieldArray___};
|
104
|
+
var ${schemaName}Store = new ${schemaName}(storeData);
|
105
|
+
await ${schemaName}Store.save()
|
106
|
+
.then((result) => {
|
107
|
+
return successResponse(res, result, "${fileName} created successfully!");
|
108
|
+
})
|
109
|
+
.catch((err) => {
|
110
|
+
return errorResponse(res, err, "Opps something went wrong!", 500);
|
111
|
+
});
|
112
|
+
},
|
113
|
+
update: async (req, res) => {
|
114
|
+
const response = checkValidationResult(res, req);
|
115
|
+
if (response["status_code"] === 422) {
|
116
|
+
return errorResponse(
|
117
|
+
res,
|
118
|
+
response["data"],
|
119
|
+
response["message"],
|
120
|
+
response["status_code"]
|
121
|
+
);
|
122
|
+
}
|
123
|
+
/*File values into body*/
|
124
|
+
mergerFilesAndBody(req);
|
125
|
+
|
126
|
+
var updateData = ${___StoreFieldArray___};
|
127
|
+
|
128
|
+
updateData = filterMissingFields(updateData); // Removes fields with null values
|
129
|
+
|
130
|
+
await ${schemaName}.findByIdAndUpdate(req.params.id, updateData, { new: true })
|
131
|
+
.then((result) => {
|
132
|
+
if (result) {
|
133
|
+
successResponse(res, result, "${fileName} updated successfully!");
|
134
|
+
} else {
|
135
|
+
data = {
|
136
|
+
id: ["Record doesn't exist!"],
|
137
|
+
};
|
138
|
+
validationResponse(res, data, "Record doesn't exist!");
|
139
|
+
}
|
140
|
+
})
|
141
|
+
.catch((err) =>
|
142
|
+
errorResponse(res, err, "Opps something went wrong!", 500)
|
143
|
+
);
|
144
|
+
},
|
145
|
+
destroy: async (req, res) => {
|
146
|
+
const response = checkValidationResult(res, req);
|
147
|
+
if (response["status_code"] === 422) {
|
148
|
+
return errorResponse(
|
149
|
+
res,
|
150
|
+
response["data"],
|
151
|
+
response["message"],
|
152
|
+
response["status_code"]
|
153
|
+
);
|
154
|
+
}
|
155
|
+
await ${schemaName}.findByIdAndDelete(req.params.id)
|
156
|
+
.then((result) => {
|
157
|
+
if (result) {
|
158
|
+
return successResponse(res, result, "Deleted successfully!");
|
159
|
+
} else {
|
160
|
+
data = {
|
161
|
+
id: ["Record doesn't exist!"],
|
162
|
+
};
|
163
|
+
return validationResponse(res, data, "Record doesn't exist!");
|
164
|
+
}
|
165
|
+
})
|
166
|
+
.catch((err) =>
|
167
|
+
{
|
168
|
+
return errorResponse(res, err, "Opps something went wrong!", 500)
|
169
|
+
}
|
170
|
+
);
|
171
|
+
}
|
172
|
+
};
|
173
|
+
|
174
|
+
module.exports = ${fileName}Controller;
|
package/sample-env
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
const multer = require("multer");
|
2
|
+
const fs = require("fs");
|
3
|
+
const path = require("path");
|
4
|
+
|
5
|
+
// Create a Multer instance with destination for uploaded files
|
6
|
+
const storage = (routeName) =>
|
7
|
+
multer.diskStorage({
|
8
|
+
destination: function (req, file, cb) {
|
9
|
+
const folder = `./public/${routeName}`;
|
10
|
+
|
11
|
+
// Check if the folder exists, create it if it doesn't
|
12
|
+
if (!fs.existsSync(folder)) {
|
13
|
+
fs.mkdirSync(folder, { recursive: true });
|
14
|
+
}
|
15
|
+
|
16
|
+
cb(null, folder);
|
17
|
+
},
|
18
|
+
filename: function (req, file, cb) {
|
19
|
+
let fileExt = path.extname(file.originalname);
|
20
|
+
cb(null, `${routeName}-${Date.now()}${fileExt}`);
|
21
|
+
},
|
22
|
+
});
|
23
|
+
|
24
|
+
// Enable file upload middleware using Multer
|
25
|
+
const upload = (routeName) => multer({ storage: storage(routeName) });
|
26
|
+
|
27
|
+
module.exports = upload;
|
package/sample-helper.js
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
function extractRouteName(req) {
|
2
|
+
const path = req.originalUrl.split("?")[0]; // Remove query parameters
|
3
|
+
const parts = path.split("/").filter(Boolean); // Remove empty parts
|
4
|
+
return parts[parts.length - 1];
|
5
|
+
}
|
6
|
+
|
7
|
+
function generatePaginationLinks(
|
8
|
+
req,
|
9
|
+
response,
|
10
|
+
currentPage,
|
11
|
+
perPage,
|
12
|
+
totalPages,
|
13
|
+
searchInput
|
14
|
+
) {
|
15
|
+
const routeName = extractRouteName(req);
|
16
|
+
|
17
|
+
// add first page link
|
18
|
+
const firstLink = `${req.protocol}://${req.get("host")}${
|
19
|
+
req.baseUrl
|
20
|
+
}/${routeName}?page_no=1&page_limit=${perPage}&search=${searchInput}`;
|
21
|
+
response.firstLink = firstLink;
|
22
|
+
|
23
|
+
// add previous page link if exist
|
24
|
+
if (currentPage > 1) {
|
25
|
+
const previousPage = currentPage - 1;
|
26
|
+
const previousLink = `${req.protocol}://${req.get("host")}${
|
27
|
+
req.baseUrl
|
28
|
+
}/${routeName}?page_no=${previousPage}&page_limit=${perPage}&search=${searchInput}`;
|
29
|
+
response.previousLink = previousLink;
|
30
|
+
} else {
|
31
|
+
response.previousLink = null;
|
32
|
+
}
|
33
|
+
|
34
|
+
// add current page link if exist
|
35
|
+
if (currentPage >= 1 || currentPage <= totalPages) {
|
36
|
+
const currentLink = `${req.protocol}://${req.get("host")}${
|
37
|
+
req.baseUrl
|
38
|
+
}/${routeName}?page_no=${currentPage}&page_limit=${perPage}&search=${searchInput}`;
|
39
|
+
response.currentLink = currentLink;
|
40
|
+
} else {
|
41
|
+
response.currentLink = null;
|
42
|
+
}
|
43
|
+
|
44
|
+
// add next page link if exist
|
45
|
+
if (currentPage < totalPages) {
|
46
|
+
const nextPage = currentPage + 1;
|
47
|
+
const nextLink = `${req.protocol}://${req.get("host")}${
|
48
|
+
req.baseUrl
|
49
|
+
}/${routeName}?page_no=${nextPage}&page_limit=${perPage}&search=${searchInput}`;
|
50
|
+
response.nextLink = nextLink;
|
51
|
+
} else {
|
52
|
+
response.nextLink = null;
|
53
|
+
}
|
54
|
+
|
55
|
+
// add last page link
|
56
|
+
const lastPage = totalPages ? totalPages : 1;
|
57
|
+
const lastLink = `${req.protocol}://${req.get("host")}${
|
58
|
+
req.baseUrl
|
59
|
+
}/${routeName}?page_no=${lastPage}&page_limit=${perPage}&search=${searchInput}`;
|
60
|
+
response.lastLink = lastLink;
|
61
|
+
|
62
|
+
return response;
|
63
|
+
}
|
64
|
+
|
65
|
+
function modelsParams(Schema) {
|
66
|
+
// Obtain the schema parameters object
|
67
|
+
const paths = Schema?.schema?.paths;
|
68
|
+
let parameters = [];
|
69
|
+
let all = [];
|
70
|
+
let required = [];
|
71
|
+
let optional = [];
|
72
|
+
// Loop over the paths and log each field's name and type
|
73
|
+
for (const path in paths) {
|
74
|
+
let isRequired = paths[path]?.options?.required ? true : false;
|
75
|
+
parameters.push({
|
76
|
+
field: path,
|
77
|
+
is_required: isRequired,
|
78
|
+
});
|
79
|
+
if (isRequired) {
|
80
|
+
required.push(path);
|
81
|
+
} else {
|
82
|
+
optional.push(path);
|
83
|
+
}
|
84
|
+
all.push(path);
|
85
|
+
}
|
86
|
+
const unwantedProps = ["_id", "createdAt", "updatedAt", "__v"];
|
87
|
+
const filteredFormData = all.filter((prop) => !unwantedProps.includes(prop));
|
88
|
+
return {
|
89
|
+
parameters: parameters,
|
90
|
+
allFields: all,
|
91
|
+
requiredFields: required,
|
92
|
+
optionalFields: optional,
|
93
|
+
filteredFormFields: filteredFormData,
|
94
|
+
};
|
95
|
+
}
|
96
|
+
|
97
|
+
function searchableFields(Model) {
|
98
|
+
var formFields = modelsParams(Model);
|
99
|
+
var uploadFieldArray = [];
|
100
|
+
var searchFields = [];
|
101
|
+
if (
|
102
|
+
formFields &&
|
103
|
+
formFields?.filteredFormFields &&
|
104
|
+
formFields?.filteredFormFields.length
|
105
|
+
) {
|
106
|
+
searchFields = formFields?.filteredFormFields;
|
107
|
+
return searchFields;
|
108
|
+
}
|
109
|
+
}
|
110
|
+
function mergerFilesAndBody(req) {
|
111
|
+
if (req.files && Object.keys(req.files).length > 0) {
|
112
|
+
Object.keys(req.files).forEach(function (key) {
|
113
|
+
if (req.files[key] && req.files[key] !== undefined) {
|
114
|
+
var file = req.files[key];
|
115
|
+
if (file && file?.path && file?.fieldname)
|
116
|
+
req.body[file?.fieldname] = file?.path.replace(/\public\\/g, "");
|
117
|
+
}
|
118
|
+
});
|
119
|
+
req.files = [];
|
120
|
+
return req;
|
121
|
+
}
|
122
|
+
}
|
123
|
+
function filterMissingFields(data) {
|
124
|
+
for (var key in data) {
|
125
|
+
if (data[key] === null) {
|
126
|
+
delete data[key];
|
127
|
+
}
|
128
|
+
}
|
129
|
+
return data;
|
130
|
+
}
|
131
|
+
|
132
|
+
module.exports = {
|
133
|
+
generatePaginationLinks,
|
134
|
+
modelsParams,
|
135
|
+
searchableFields,
|
136
|
+
mergerFilesAndBody,
|
137
|
+
filterMissingFields,
|
138
|
+
};
|
@@ -0,0 +1,29 @@
|
|
1
|
+
{
|
2
|
+
"name": "my-node-project",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"description": "",
|
5
|
+
"main": "index.js",
|
6
|
+
"scripts": {
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
8
|
+
"dev": "nodemon app.js"
|
9
|
+
},
|
10
|
+
"author": "",
|
11
|
+
"license": "ISC",
|
12
|
+
"dependencies": {
|
13
|
+
"bcryptjs": "^2.4.3",
|
14
|
+
"body-parser": "^1.20.2",
|
15
|
+
"dotenv": "^16.3.1",
|
16
|
+
"express": "^4.18.2",
|
17
|
+
"express-validator": "^7.0.1",
|
18
|
+
"jsonwebtoken": "^9.0.1",
|
19
|
+
"mongoose": "^7.3.1",
|
20
|
+
"mongoose-backpack": "^0.2.7",
|
21
|
+
"multer": "^1.4.5-lts.1",
|
22
|
+
"node-backpack": "^0.0.427",
|
23
|
+
"nodemailer": "^6.9.3",
|
24
|
+
"rest-api-response-npm": "^0.1.4"
|
25
|
+
},
|
26
|
+
"devDependencies": {
|
27
|
+
"nodemon": "^3.0.1"
|
28
|
+
}
|
29
|
+
}
|