tafil-node-api 1.0.0

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 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
+ };