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 +3 -0
- package/app.js +28 -0
- package/bin/generate-app.js +71 -0
- package/controllers/AuthControllers.js +113 -0
- package/controllers/UserControllers.js +34 -0
- package/helpers/SendEmail.js +28 -0
- package/middlewares/authMiddlware.js +28 -0
- package/middlewares/error.js +17 -0
- package/models/userModel.js +36 -0
- package/package.json +26 -0
- package/routes/AuthRoutes.js +16 -0
- package/routes/UserRoutes.js +10 -0
- package/routes/routes.js +9 -0
- package/services/AuthService.js +237 -0
- package/services/UserService.js +116 -0
- package/utils/generateToken.js +11 -0
- package/views/reset-failed.ejs +340 -0
- package/views/reset-password.ejs +482 -0
- package/views/unverified-email.ejs +342 -0
- package/views/verified-email.ejs +362 -0
package/.env
ADDED
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;
|
package/routes/routes.js
ADDED
@@ -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’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
|
+
};
|