Skip to content

Commit

Permalink
feat: nodemailer added for create route
Browse files Browse the repository at this point in the history
  • Loading branch information
Mr-Emerald-Wolf committed Sep 20, 2023
1 parent 255bcce commit a4be19a
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 103 deletions.
4 changes: 3 additions & 1 deletion .example.env
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ DB_NAME=mydb
DB_URI = "mongodb://${DB_HOST}:${DB_PORT}/${DB_NAME}"
ACCESS_KEY_SECRET="abc"
REFRESH_KEY_SECRET="def"
JUDGE_URI = http://139.59.4.43:2358
JUDGE_URI=
CC_SENDER_MAIL=
CC_SENDER_PASS=
243 changes: 146 additions & 97 deletions api/controllers/authController.js
Original file line number Diff line number Diff line change
@@ -1,105 +1,154 @@
const bcrypt = require('bcrypt');
const User = require('../models/User');
const jwtController = require('../controllers/jwtController');
const bcrypt = require("bcrypt");
const User = require("../models/User");
const jwtController = require("../controllers/jwtController");
const generator = require("generate-password");
const { sendMail } = require("../utils/sendMail");

const authController = {
login: async (req, res) => {
const { email, password } = req.body;
try {
const user = await User.findOne({ email });
if (!user) {
return res.status(400).json({ message: 'User not found' });
}
if (!user.isActive) {
return res.status(403).json({ message: 'User is banned' });
}
if (await bcrypt.compare(password, user.password)) {
user.tokenVersion += 1;
await user.save();
const accessToken = jwtController.signAccessToken(user.regNo, user.userRole, user.tokenVersion);
const refreshToken = jwtController.signRefreshToken(user.regNo, user.userRole);
user.refreshToken = refreshToken;
await user.save();
res.header('Authorization', `Bearer ${accessToken}`);
res.json({ accessToken, refreshToken });
} else {
res.status(401).json({ message: 'Incorrect password' });
}
} catch (error) {
console.log(error);
res.status(500).json({ error: 'Internal server error' });
}
},
login: async (req, res) => {
const { email, password } = req.body;
try {
const user = await User.findOne({ email });
if (!user) {
return res.status(400).json({ message: "User not found" });
}
if (!user.isActive) {
return res.status(403).json({ message: "User is banned" });
}
if (await bcrypt.compare(password, user.password)) {
user.tokenVersion += 1;
await user.save();
const accessToken = jwtController.signAccessToken(
user.regNo,
user.userRole,
user.tokenVersion
);
const refreshToken = jwtController.signRefreshToken(
user.regNo,
user.userRole
);
user.refreshToken = refreshToken;
await user.save();
res.header("Authorization", `Bearer ${accessToken}`);
res.json({ accessToken, refreshToken });
} else {
res.status(401).json({ message: "Incorrect password" });
}
} catch (error) {
console.log(error);
res.status(500).json({ error: "Internal server error" });
}
},

signup: async (req, res) => {
try {
const { name, regNo, email, password } = req.body;
const user_exists = await User.findOne({ $or: [{ regNo }, { email }] });
if (user_exists) {
return res.status(400).json({ error: 'User with the same registration number or email already exists' });
}
const hash = await bcrypt.hash(password, 10);
const new_user = new User({ name, regNo, email, password: hash });
await new_user.save();
res.status(201).json({ message: 'Signup successful' });
} catch (error) {
res.status(400).json({ error: 'Error' });
}
},
create: async (req, res) => {
try {
const { name, regNo, email } = req.body;
const user_exists = await User.findOne({ $or: [{ regNo }, { email }] });
if (user_exists) {
return res.status(400).json({
error:
"User with the same registration number or email already exists",
});
}

dashboard: async (req, res) => {
try {
const decoded = req.user;
const user = await User.findOne({ regNo: decoded.regNo });
if (!user) {
return res.status(404).json({ message: 'User not found' });
}
res.status(201).json(user);
} catch (error) {
res.status(400).json({ error: 'Error' });
}
},
var password = generator.generate({
length: 10,
numbers: true,
strict: true,
});

refresh: async (req, res) => {
const { refreshToken } = req.body;
if (!refreshToken) {
return res.status(400).json({ message: 'refreshToken is required' });
}
try {
const user = await User.findOne({ refreshToken });
if (!user) {
return res.status(404).json({ message: 'Invalid refreshToken' });
}
const storedRefreshToken = user.refreshToken;
if (!storedRefreshToken) {
return res.status(400).json({ message: 'Invalid refreshToken' });
}
user.tokenVersion += 1;
await user.save();
const newAccessToken = jwtController.signAccessToken(user.regNo, user.userRole, user.tokenVersion);
res.header('Authorization', `Bearer ${newAccessToken}`);
res.json({ accessToken: newAccessToken });
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
},

logout: async (req, res) => {
try {
const decoded = req.user;
const user = await User.findOne({ regNo: decoded.regNo });
if (!user) {
return res.status(404).json({ message: 'User not found' });
}
user.tokenVersion = 0;
user.refreshToken = null;
await user.save();
res.status(200).json({ message: 'Logout successful' });
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
},
// Send Email with credentials
const subject = "Cookoff Credentials";
const body = `Your Password is: ${password}`;
const response = await sendMail(email, subject, body);

if (!response.status) return res.status(500).json(response);
// No error

const hash = await bcrypt.hash(password, 10);
const new_user = new User({ name, regNo, email, password: hash });
await new_user.save();
res.status(201).json({ message: "Signup successful" });
} catch (error) {
res.status(400).json({ error: "Error" });
}
},

signup: async (req, res) => {
try {
const { name, regNo, email, password } = req.body;
const user_exists = await User.findOne({ $or: [{ regNo }, { email }] });
if (user_exists) {
return res.status(400).json({
error:
"User with the same registration number or email already exists",
});
}
const hash = await bcrypt.hash(password, 10);
const new_user = new User({ name, regNo, email, password: hash });
await new_user.save();
res.status(201).json({ message: "Signup successful" });
} catch (error) {
res.status(400).json({ error: "Error" });
}
},

dashboard: async (req, res) => {
try {
const decoded = req.user;
const user = await User.findOne({ regNo: decoded.regNo });
if (!user) {
return res.status(404).json({ message: "User not found" });
}
res.status(201).json(user);
} catch (error) {
res.status(400).json({ error: "Error" });
}
},

refresh: async (req, res) => {
const { refreshToken } = req.body;
if (!refreshToken) {
return res.status(400).json({ message: "refreshToken is required" });
}
try {
const user = await User.findOne({ refreshToken });
if (!user) {
return res.status(404).json({ message: "Invalid refreshToken" });
}
const storedRefreshToken = user.refreshToken;
if (!storedRefreshToken) {
return res.status(400).json({ message: "Invalid refreshToken" });
}
user.tokenVersion += 1;
await user.save();
const newAccessToken = jwtController.signAccessToken(
user.regNo,
user.userRole,
user.tokenVersion
);
res.header("Authorization", `Bearer ${newAccessToken}`);
res.json({ accessToken: newAccessToken });
} catch (error) {
res.status(500).json({ error: "Internal server error" });
}
},

logout: async (req, res) => {
try {
const decoded = req.user;
const user = await User.findOne({ regNo: decoded.regNo });
if (!user) {
return res.status(404).json({ message: "User not found" });
}
user.tokenVersion = 0;
user.refreshToken = null;
await user.save();
res.status(200).json({ message: "Logout successful" });
} catch (error) {
res.status(500).json({ error: "Internal server error" });
}
},
};

module.exports = authController;
module.exports = authController;
12 changes: 7 additions & 5 deletions api/routes/auth.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
const express = require("express");
const { verifyRefreshToken, verifyAccessToken, verifyAdminToken } = require(
"../middleware/jwtMiddleware",
);
const {
verifyRefreshToken,
verifyAccessToken,
verifyAdminToken,
} = require("../middleware/jwtMiddleware");
const RateLimiter = require("../middleware/rateLimit");
const authController = require("../controllers/authController");
const router = express.Router();

router.get("/dashboard", verifyAccessToken, authController.dashboard);
router.post("/login", RateLimiter, authController.login);
router.post("/signup", authController.signup);
router.post("/create", authController.create);
router.post(
"/refresh",
RateLimiter,
verifyRefreshToken,
authController.refresh,
authController.refresh
);
router.post("/logout", verifyAccessToken, authController.logout);

module.exports = router;

40 changes: 40 additions & 0 deletions api/utils/sendMail.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const nodemailer = require("nodemailer");
require("dotenv").config();

const CC_SENDER_MAIL = process.env.CC_SENDER_MAIL;
const CC_SENDER_PASS = process.env.CC_SENDER_PASS;

async function sendMail(reciever, subject, body) {
try {
// Create a transporter object using your SMTP server details
const transporter = nodemailer.createTransport({
service: "Gmail", // or your email service provider
port: 25,
auth: {
user: CC_SENDER_MAIL,
pass: CC_SENDER_PASS,
},
});

// Create an email message
const mailOptions = {
from: CC_SENDER_MAIL,
to: reciever,
subject: subject,
text: body,
};

// Send the email
const info = await transporter.sendMail(mailOptions);

console.log("Email sent:", info.response);
return { status: true, message: "Email sent:" + info.response };
} catch (error) {
console.error("Error sending email:", error);
return { status: false, message: "Error sending email:" + error };
}
}

module.exports = {
sendMail,
};
15 changes: 15 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@
"dotenv": "^16.3.1",
"express": "^4.18.2",
"express-rate-limit": "^6.9.0",
"generate-password": "^1.7.0",
"jsonwebtoken": "^9.0.1",
"mongoose": "^7.4.4",
"morgan": "^1.10.0",
"nodemailer": "^6.9.5",
"nodemon": "^3.0.1",
"os": "^0.1.2"
}
Expand Down

0 comments on commit a4be19a

Please sign in to comment.