tafil-node-api 1.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of tafil-node-api might be problematic. Click here for more details.

package/.env ADDED
@@ -0,0 +1,3 @@
1
+ PORT=8080
2
+ MONGO_URL=mongodb+srv://tafil:sEtMDtM3SxD89BLZ@cluster0.7tqjz.mongodb.net/SubUsers?retryWrites=true&w=majority
3
+ AUTH_SECRET=qwertyuiop789456123
package/app.js ADDED
@@ -0,0 +1,28 @@
1
+ const express = require(`express`);
2
+ const app = express();
3
+ const mongoose = require(`mongoose`);
4
+ const cors = require(`cors`);
5
+ require(`dotenv`).config();
6
+
7
+ const routes = require(`./routes/routes`);
8
+ const { notFound, errorHandler } = require(`./middlewares/error`);
9
+
10
+ app.use(cors());
11
+ app.use(express.json());
12
+ app.set("view engine", "ejs");
13
+ app.use(`/`, routes);
14
+ app.use(notFound);
15
+ app.use(errorHandler);
16
+
17
+ const port = process.env.PORT || 8080;
18
+ const url = process.env.MONGO_URL;
19
+
20
+ app.listen(port, async () => {
21
+ try {
22
+ const conn = await mongoose.connect(url);
23
+ console.log(`Server has started on port :: ${port}`);
24
+ console.log(`MongoDB :: ${conn.connection.host}`);
25
+ } catch (error) {
26
+ console.log(error);
27
+ }
28
+ });
@@ -0,0 +1,71 @@
1
+ const { execSync } = require("child_process");
2
+
3
+ const runCommand = (command) => {
4
+ try {
5
+ execSync(`${command}`, { stdio: "inherit" });
6
+ } catch (error) {
7
+ console.log(error);
8
+ return false;
9
+ }
10
+ return true;
11
+ };
12
+
13
+ const projectName = process.argv[2];
14
+ const git_checkout_repo = `git clone --depth 1 https://github.com/taffil/node-api.git ${projectName}`;
15
+ const installDepsCommand = `cd ${projectName} && npm install`;
16
+
17
+ console.log(`Cloning repo ${projectName}`);
18
+ const checkedOut = runCommand(git_checkout_repo);
19
+ if (!checkedOut) process.exit(-1);
20
+
21
+ console.log(`Installing dependencies for ${projectName}`);
22
+ const installDeps = runCommand(installDepsCommand);
23
+
24
+ if (!installDeps) process.exit(-1);
25
+
26
+ console.log(`cd ${projectName} && npm start`);
27
+
28
+ // const path = require("path");
29
+ // const fs = require("fs");
30
+
31
+ // const currentPath = process.cwd();
32
+ // const projectPath = path.join(currentPath, projectName);
33
+
34
+ // if (process.argv.length < 3) {
35
+ // console.log("npx create-my-boilerplate node-api");
36
+ // process.exit(1);
37
+ // }
38
+
39
+ // try {
40
+ // fs.mkdirSync(projectPath);
41
+ // } catch (err) {
42
+ // if (err.code === "EEXIST") {
43
+ // console.log(
44
+ // `The file ${projectName} already exist in the current directory, please give it another name.`
45
+ // );
46
+ // } else {
47
+ // console.log(error);
48
+ // }
49
+ // process.exit(1);
50
+ // }
51
+
52
+ // const main = async () => {
53
+ // try {
54
+ // console.log("Downloading files...");
55
+ // execSync(`git clone --depth 1 ${git_repo} ${projectPath}`);
56
+
57
+ // process.chdir(projectPath);
58
+
59
+ // console.log("Installing dependencies...");
60
+ // execSync("npm install");
61
+
62
+ // console.log("Removing useless files");
63
+ // execSync("npx rimraf ./.git");
64
+ // fs.rmdirSync(path.join(projectPath, "bin"), { recursive: true });
65
+
66
+ // console.log("The installation is done, this is ready to use !");
67
+ // } catch (error) {
68
+ // console.log(error);
69
+ // }
70
+ // };
71
+ // main();
@@ -0,0 +1,113 @@
1
+ const UserService = require(`../services/AuthService`);
2
+
3
+ exports.signup = (req, res, next) => {
4
+ UserService.signup(req.body)
5
+ .then((result) => {
6
+ res.json({ msg: "User Registred", ...result });
7
+ console.log({ msg: "User Registered", ...result });
8
+ })
9
+ .catch((error) => {
10
+ next(error);
11
+ });
12
+ };
13
+
14
+ exports.signin = (req, res, next) => {
15
+ UserService.signin(req.body)
16
+ .then((result) => {
17
+ res.json({ msg: "Loged In", ...result });
18
+ console.log({ msg: "Loged In", ...result });
19
+ })
20
+ .catch((error) => {
21
+ next(error);
22
+ });
23
+ };
24
+
25
+ exports.verifyEmail = (req, res, next) => {
26
+ const { email, token } = req.params;
27
+ authService
28
+ .verifyEmail(email, token)
29
+ .then((result) => {
30
+ console.log(result);
31
+ res.render(`verified-email`, null, (error, data) => {
32
+ if (error) {
33
+ res.status(404).json({ status: "failed", message: "file not found" });
34
+ } else {
35
+ res.write(data);
36
+ }
37
+ });
38
+ })
39
+ .catch((err) => {
40
+ console.log(err);
41
+ res.render(`unverified-email`, null, (error, data) => {
42
+ if (error) {
43
+ res.status(404).json({ status: "failed", message: "file not found" });
44
+ } else {
45
+ res.write(data);
46
+ }
47
+ });
48
+ });
49
+ };
50
+
51
+ exports.forgotPassword = (req, res, next) => {
52
+ const { email } = req.body;
53
+ authService
54
+ .forgotPassword(email)
55
+ .then((result) => {
56
+ console.log(result);
57
+ res.status(201).json({
58
+ success: true,
59
+ message: `Reset link has been sent to your email`,
60
+ });
61
+ })
62
+ .catch((err) => {
63
+ console.log(err);
64
+ if (!err.statusCode) {
65
+ err.statusCode = 500;
66
+ }
67
+ next(err);
68
+ });
69
+ };
70
+
71
+ exports.resetPassword = (req, res, next) => {
72
+ const { id, token } = req.params;
73
+ authService
74
+ .resetPassword(id, token)
75
+ .then((result) => {
76
+ res.render(`reset-password`, null, (error, data) => {
77
+ if (error) {
78
+ res.write(`file not found`);
79
+ } else {
80
+ res.write(data);
81
+ }
82
+ res.end();
83
+ });
84
+ })
85
+ .catch((err) => {
86
+ res.render(`reset-failed`, null, (error, data) => {
87
+ if (error) {
88
+ res.write(`file not found`);
89
+ } else {
90
+ res.write(data);
91
+ }
92
+ res.end();
93
+ });
94
+ });
95
+ };
96
+
97
+ exports.newPassword = (req, res, next) => {
98
+ const { id, token } = req.params;
99
+ const { password } = req.body;
100
+ authService
101
+ .newPassword(id, token, password)
102
+ .then((result) => {
103
+ console.log(result);
104
+ res.json({ success: true, message: "Your password has been updated" });
105
+ })
106
+ .catch((err) => {
107
+ console.log(err);
108
+ if (!err.statusCode) {
109
+ err.statusCode = 500;
110
+ }
111
+ next(err);
112
+ });
113
+ };
@@ -0,0 +1,34 @@
1
+ const UserService = require(`../services/UserService`);
2
+
3
+ exports.getUserProfile = (req, res, next) => {
4
+ UserService.getUserProfile(req.body)
5
+ .then((user) => {
6
+ res.json({ success: true, user });
7
+ console.log(user)
8
+ })
9
+ .catch((error) => {
10
+ next(error);
11
+ });
12
+ };
13
+
14
+ exports.updateUserProfile = (req, res, next) => {
15
+ UserService.updateUserProfile(req.body)
16
+ .then((updatedUser) => {
17
+ res.json({ updated: true, ...updatedUser });
18
+ console.log(updatedUser)
19
+ })
20
+ .catch((error) => {
21
+ next(error);
22
+ });
23
+ };
24
+
25
+ exports.updatePasswod = (req, res, next) => {
26
+ UserService.updatePasswod(req.body)
27
+ .then((updatedPassword) => {
28
+ res.json({ updated: true, ...updatedPassword });
29
+ console.log(updatedPassword)
30
+ })
31
+ .catch((error) => {
32
+ next(error);
33
+ });
34
+ };
@@ -0,0 +1,28 @@
1
+ const nodemailer = require("nodemailer");
2
+
3
+ const sendEmail = ({ emailPassword, email, text, subject }) => {
4
+ const transporter = nodemailer.createTransport({
5
+ service: "hotmail",
6
+ auth: {
7
+ user: "ourservice@email.com",
8
+ pass: `${emailPassword}`,
9
+ },
10
+ });
11
+
12
+ const options = {
13
+ from: "ourservice@email.com",
14
+ to: `${email}`,
15
+ subject: `${subject}`,
16
+ html: `${text}`,
17
+ };
18
+
19
+ transporter.sendMail(options, (error, info) => {
20
+ if (error) {
21
+ console.log(error);
22
+ } else {
23
+ console.log("Email sent: " + info.response);
24
+ }
25
+ });
26
+ };
27
+
28
+ module.exports = sendEmail;
@@ -0,0 +1,28 @@
1
+ const jwt = require("jsonwebtoken");
2
+
3
+ module.exports = (req, res, next) => {
4
+ const authHeader = req.get("Authorization");
5
+ if (!authHeader) {
6
+ const error = new Error("Not Authorized.");
7
+ error.statusCode = 403;
8
+ throw error;
9
+ } else {
10
+ try {
11
+ const token = authHeader.split(" ")[1];
12
+ const authSecret = process.env.AUTH_SECRET;
13
+ let decodedToken = jwt.verify(token, authSecret);
14
+ if (!decodedToken) {
15
+ const error = new Error("Not Authenticated.");
16
+ error.statusCode = 401;
17
+ throw error;
18
+ }
19
+ req.body.userId = decodedToken.loadedUser._id;
20
+ req.body.isAdmin = decodedToken.loadedUser.isAdmin;
21
+ next();
22
+ } catch (err) {
23
+ err.message = "Invalid token";
24
+ err.statusCode = 401;
25
+ throw err;
26
+ }
27
+ }
28
+ };
@@ -0,0 +1,17 @@
1
+ const notFound = (req, res, next) => {
2
+ const error = new Error(`Not found - ${req.originalUrl}`);
3
+ res.status(404);
4
+ next(error);
5
+ };
6
+
7
+ const errorHandler = (error, req, res, next) => {
8
+ const status = error.statusCode || 500;
9
+ const message = error.message;
10
+ const data = error.data;
11
+ console.log(`================================================`);
12
+ console.log({ success: false, message, data, status });
13
+ console.log(`================================================`);
14
+ res.status(status).json({ success: false, message, data, status });
15
+ };
16
+
17
+ module.exports = { notFound, errorHandler };
@@ -0,0 +1,36 @@
1
+ const mongoose = require(`mongoose`);
2
+ const Schema = mongoose.Schema;
3
+
4
+ const userSchema = new Schema(
5
+ {
6
+ firstname: {
7
+ type: String,
8
+ required: [true, `Name must be provided`],
9
+ trim: true,
10
+ maxlength: [15, `Name cannot be more than 15 characters`],
11
+ },
12
+ lastname: {
13
+ type: String,
14
+ required: [true, `Lastname must be provided`],
15
+ trim: true,
16
+ maxlength: [15, `Lastname cannot be more than 15 characters`],
17
+ },
18
+ email: {
19
+ type: String,
20
+ required: [true, "Email must be provided"],
21
+ trim: true,
22
+ unique: [true, "Email already in use"],
23
+ },
24
+ password: {
25
+ type: String,
26
+ required: [true, `Password must be provided`],
27
+ },
28
+ isAdmin: {
29
+ type: Boolean,
30
+ default: false,
31
+ },
32
+ },
33
+ { timestamps: true }
34
+ );
35
+
36
+ module.exports = mongoose.model(`User`, userSchema);
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "tafil-node-api",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "app.js",
6
+ "bin": "./bin/generate-app.js",
7
+ "scripts": {
8
+ "start": "nodemon app.js",
9
+ "postinstall": "npx husky install"
10
+ },
11
+ "keywords": [],
12
+ "author": "Tafil Osmani",
13
+ "license": "ISC",
14
+ "dependencies": {
15
+ "bcryptjs": "^2.4.3",
16
+ "cors": "^2.8.5",
17
+ "dotenv": "^10.0.0",
18
+ "ejs": "^3.1.6",
19
+ "express": "^4.17.2",
20
+ "jsonwebtoken": "^8.5.1",
21
+ "mongodb": "^4.4.1",
22
+ "mongoose": "^6.1.3",
23
+ "nodemailer": "^6.7.3",
24
+ "nodemon": "^2.0.15"
25
+ }
26
+ }
@@ -0,0 +1,16 @@
1
+ const express = require(`express`)
2
+ const router = express.Router()
3
+ const AuthControllers = require(`../controllers/AuthControllers`)
4
+
5
+ router.post(`/signup`, AuthControllers.signup)
6
+ router.post(`/signin`, AuthControllers.signin)
7
+
8
+ // Verify Email
9
+ router.get(`/verification/:email/:token`, AuthControllers.verifyEmail);
10
+
11
+ // Password Reset
12
+ router.post(`/forgot-password`, AuthControllers.forgotPassword);
13
+ router.get(`/reset-password/:id/:token`, AuthControllers.resetPassword);
14
+ router.post(`/reset-password/:id/:token`, AuthControllers.newPassword);
15
+
16
+ module.exports = router
@@ -0,0 +1,10 @@
1
+ const express = require(`express`);
2
+ const router = express.Router();
3
+ const UserControllers = require(`../controllers/UserControllers`);
4
+ const auth = require("../middlewares/authMiddlware");
5
+
6
+ router.get(`/profile`, auth, UserControllers.getUserProfile)
7
+ router.post(`/profile`, auth, UserControllers.updateUserProfile);
8
+ router.post(`/password`, auth, UserControllers.updatePasswod);
9
+
10
+ module.exports = router;
@@ -0,0 +1,9 @@
1
+ const express = require(`express`);
2
+ const router = express.Router();
3
+ const UserRoute = require(`./UserRoutes`);
4
+ const AuthRoute = require(`./AuthRoutes`);
5
+
6
+ router.use(`/auth`, AuthRoute);
7
+ router.use(`/user`, UserRoute);
8
+
9
+ module.exports = router;
@@ -0,0 +1,237 @@
1
+ const User = require("../models/userModel");
2
+ const bcrypt = require(`bcryptjs`);
3
+ const generateToken = require(`../utils/generateToken`);
4
+ const regex =
5
+ /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
6
+
7
+ exports.signup = ({ firstname, lastname, email, password }) => {
8
+ return new Promise((resolve, reject) => {
9
+ if (!firstname || !lastname || !email.match(regex) || !password) {
10
+ const error = new Error("Please provide all required fields");
11
+ error.statusCode = 400;
12
+ reject(error);
13
+ }
14
+ let lowerCaseEmail = email.trim().toLowerCase();
15
+ User.find({ email: lowerCaseEmail })
16
+ .then((user) => {
17
+ if (user?.length) {
18
+ const error = new Error("User Already Exists");
19
+ throw error;
20
+ } else {
21
+ bcrypt.hash(password, 12).then((hashed) => {
22
+ User.create({
23
+ firstname,
24
+ lastname,
25
+ email: lowerCaseEmail,
26
+ password: hashed,
27
+ })
28
+ .then((result) => {
29
+ resolve({
30
+ success: true,
31
+ token: generateToken(result),
32
+ id: result._id.toString(),
33
+ email: result.email,
34
+ firstname: result.firstname,
35
+ lastname: result.lastname,
36
+ });
37
+ })
38
+ .catch((error) => {
39
+ reject(error);
40
+ });
41
+ });
42
+ }
43
+ })
44
+ .catch((error) => {
45
+ reject(error);
46
+ });
47
+ });
48
+ };
49
+
50
+ exports.signin = ({ email, password }) => {
51
+ return new Promise((resolve, reject) => {
52
+ if (!email.match(regex) || !password) {
53
+ const error = new Error("Please provide all required fields");
54
+ error.statusCode = 400;
55
+ reject(error);
56
+ }
57
+ let lowerCaseEmail = email.trim().toLowerCase();
58
+ let loadedUser;
59
+ User.find({ email: lowerCaseEmail })
60
+ .then((user) => {
61
+ if (!user?.length) {
62
+ const error = new Error("User Does Not Exist");
63
+ error.statusCode = 404;
64
+ throw error;
65
+ } else {
66
+ loadedUser = user[0];
67
+ return bcrypt.compare(password, user[0].password);
68
+ }
69
+ })
70
+ .then((isEqual) => {
71
+ if (!isEqual) {
72
+ const error = new Error("Wrong Email or Password");
73
+ error.statusCode = 401;
74
+ throw error;
75
+ } else {
76
+ resolve({
77
+ success: true,
78
+ token: generateToken(loadedUser),
79
+ id: loadedUser._id.toString(),
80
+ email: loadedUser.email,
81
+ firstname: loadedUser.firstname,
82
+ lastname: loadedUser.lastname,
83
+ });
84
+ }
85
+ })
86
+ .catch((error) => {
87
+ reject(error);
88
+ });
89
+ });
90
+ };
91
+
92
+ exports.verifyEmail = (email, token) => {
93
+ return new Promise((resolve, reject) => {
94
+ User.find({ email: email })
95
+ .then((user) => {
96
+ if (!user?.length) {
97
+ const error = new Error(`A user with this email could not be found`);
98
+ error.statusCode = 401;
99
+ throw error;
100
+ }
101
+ if (user[0].verified) {
102
+ const error = new Error(`E-Mail address already verified`);
103
+ error.statusCode = 401;
104
+ throw error;
105
+ }
106
+
107
+ const secret = process.env.VERIFICATION + email;
108
+ try {
109
+ jwt.verify(token, secret);
110
+ User.findByIdAndUpdate(
111
+ { _id: user[0].id },
112
+ {
113
+ verified: true,
114
+ }
115
+ )
116
+ .then((user) => {
117
+ resolve({ success: true, message: "E-Mail has been verified" });
118
+ })
119
+ .catch((error) => {
120
+ reject(error);
121
+ });
122
+ } catch (error) {
123
+ const newError = new Error(`${error.message}`);
124
+ throw newError;
125
+ }
126
+ })
127
+ .catch((error) => {
128
+ reject(error);
129
+ });
130
+ });
131
+ };
132
+
133
+ exports.forgotPassword = (email) => {
134
+ return new Promise((resolve, reject) => {
135
+ User.find({ email: email })
136
+ .then((user) => {
137
+ if (!user?.length) {
138
+ const error = new Error(`A user with this email could not be found`);
139
+ error.statusCode = 401;
140
+ throw error;
141
+ }
142
+ const name = user[0].firstname;
143
+ const email = user[0].email;
144
+ const password = user[0].password;
145
+ const id = user[0]._id;
146
+ const emailPassword = process.env.emailPassword;
147
+ const secret = process.env.FORGOT_PASSWORD + password;
148
+ const payload = {
149
+ email: email,
150
+ id: id,
151
+ };
152
+
153
+ const token = jwt.sign(payload, secret, { expiresIn: `15m` });
154
+
155
+ const link = `http://localhost:8888/auth/reset-password/${id}/${token}`;
156
+ const data = {
157
+ emailPassword,
158
+ email,
159
+ text: `<p>Hi ${name},<br><br>Trouble signing in?<br>Resetting your password is easy.<br><br>We received a request to reset the password for your account.<br>Just press the button below and follow the instructions. We&#8217;ll have you up and running in no time.<br></p><br><a style="color:white; padding: 10px; background-color: grey; border-radius: 3px;" href="${link}">Reset password</a><br><br><p>If you did not make this request then please ignore this email.
160
+ <br>
161
+ Notice! This reset link expires in 15 minutes<br><br>
162
+ Kind Regards, Paws</p>`,
163
+ subject: `Reset Password`,
164
+ };
165
+ sendEmail(data);
166
+ console.log(link);
167
+ resolve(user);
168
+ })
169
+ .catch((error) => {
170
+ reject(error);
171
+ });
172
+ });
173
+ };
174
+
175
+ exports.resetPassword = (id, token) => {
176
+ return new Promise((resolve, reject) => {
177
+ User.find({ _id: id })
178
+ .then((user) => {
179
+ if (!user?.length) {
180
+ const error = new Error(`A user with this email could not be found`);
181
+ error.statusCode = 401;
182
+ throw error;
183
+ }
184
+ const email = user[0].email;
185
+ const secret = process.env.FORGOT_PASSWORD + user[0].password;
186
+ try {
187
+ const payload = jwt.verify(token, secret);
188
+ resolve({ email });
189
+ } catch (error) {
190
+ const newError = new Error(`${error.message}`);
191
+ throw newError;
192
+ }
193
+ })
194
+ .catch((error) => {
195
+ reject(error);
196
+ });
197
+ });
198
+ };
199
+
200
+ exports.newPassword = (id, token, password) => {
201
+ return new Promise((resolve, reject) => {
202
+ User.find({ _id: id })
203
+ .then((user) => {
204
+ if (!user?.length) {
205
+ const error = new Error(`A user with this email could not be found`);
206
+ error.statusCode = 401;
207
+ throw error;
208
+ }
209
+
210
+ const secret = process.env.FORGOT_PASSWORD + user[0].password;
211
+ try {
212
+ jwt.verify(token, secret);
213
+ bcrypt.hash(password, 12).then((hashedPassword) => {
214
+ const newPassword = hashedPassword;
215
+ User.findByIdAndUpdate(
216
+ { _id: id },
217
+ {
218
+ password: newPassword,
219
+ }
220
+ )
221
+ .then((user) => {
222
+ resolve(user);
223
+ })
224
+ .catch((error) => {
225
+ reject(error);
226
+ });
227
+ });
228
+ } catch (error) {
229
+ const newError = new Error(`${error.message}`);
230
+ throw newError;
231
+ }
232
+ })
233
+ .catch((error) => {
234
+ reject(error);
235
+ });
236
+ });
237
+ };