add create user and login user parts

This commit is contained in:
Isuru Bimsara
2026-08-21 02:20:57 +05:30
parent 621d348eb1
commit b2c5e198a1
15 changed files with 842 additions and 336 deletions
+112 -5
View File
@@ -12,12 +12,20 @@
const { checkPassword } = require("../utils/hashPassword.util");
const { sendMail } = require("../utils/mail.util");
const { generateOTP, validateOTP } = require("../utils/otp.util");
const {getCachedUser,clearUserCache} = require("../utils/cache.util");
const { getCachedUser, clearUserCache } = require("../utils/cache.util");
const { generateToken } = require("../utils/jwt.util");
const {
createRefreshSession,
validateRefreshSession,
deleteRefreshSession,
} = require("../utils/refreshSession.util");
const db = require("../models");
const { log } = require("../utils/consoleLog.utill");
const appName = process.env.APP_NAME || "Niolla";
const User = db.User;
// Login Step 1: Request OTP
exports.loginReq = async (req, res) => {
try {
@@ -47,7 +55,7 @@ exports.loginReq = async (req, res) => {
firstName: user.firstName,
otp: otp,
},
text: `Hello ${user.firstName}, your otp is ${otp}`,
text: `Hello ${user.firstName}, your otp is ${otp}`,
});
log(`OTP for ${email}: ${otp}`);
@@ -65,6 +73,12 @@ exports.login = async (req, res) => {
try {
const { email, otp } = req.body;
if (!email || !otp) {
return res
.status(400)
.send({ success: false, message: "Email and OTP are required" });
}
const user = await getCachedUser(email);
if (!user) {
@@ -73,7 +87,14 @@ exports.login = async (req, res) => {
.send({ success: false, message: "User Not Found" });
}
const isValidOTP = validateOTP(email, otp);
if (user.accountStatus !== "ACTIVE") {
return res.status(403).send({
success: false,
message: "Account is not active",
});
}
const isValidOTP = validateOTP(email, String(otp));
if (!isValidOTP) {
return res
@@ -87,16 +108,24 @@ exports.login = async (req, res) => {
firstName: user.firstName,
lastName: user.lastName,
email: user.email,
role: user.role,
accountType: user.accountType,
});
const { refreshToken } = createRefreshSession(user.id);
// 3. Set JWT as HttpOnly cookie
res.cookie("access_token", token, {
httpOnly: true, // JS cannot access
secure: process.env.NODE_ENV === "production", // HTTPS only in prod
sameSite: process.env.NODE_ENV === "production" ? "None" : "Lax",
maxAge: 24 * 60 * 60 * 1000, // 1 day
maxAge: 15 * 60 * 1000, // 1 day
});
res.cookie("refresh_token", refreshToken, {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
sameSite: process.env.NODE_ENV === "production" ? "None" : "Lax",
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
});
log(`JWT issued for ${email}`);
@@ -112,6 +141,7 @@ exports.login = async (req, res) => {
lastName: user.lastName,
role: user.role,
accountType: user.accountType,
accessToken: token,
},
});
} catch (error) {
@@ -120,6 +150,83 @@ exports.login = async (req, res) => {
}
};
exports.refreshToken = async (req, res) => {
try {
const refreshToken = req.cookies?.refresh_token;
if (!refreshToken) {
return res.status(401).send({
success: false,
message: "Refresh token is required",
});
}
const session = validateRefreshSession(refreshToken);
if (!session) {
res.clearCookie("refresh_token");
return res.status(401).send({
success: false,
message: "Invalid or expired session. Please login again.",
});
}
const user = await User.findByPk(session.userId);
if (!user || user.accountStatus !== "ACTIVE") {
deleteRefreshSession(session.sessionId);
return res.status(401).send({
success: false,
message: "Session is no longer valid",
});
}
// Generate new Access Token
const token = generateToken({
id: user.id,
firstName: user.firstName,
lastName: user.lastName,
email: user.email,
accountType: user.accountType,
});
// Generate new Refresh Token
const { refreshToken: newRefreshToken } = createRefreshSession(user.id);
deleteRefreshSession(session.sessionId);
// Replace access cookie
res.cookie("access_token", token, {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
sameSite: process.env.NODE_ENV === "production" ? "None" : "Lax",
maxAge: 15 * 60 * 1000,
});
// Replace refresh cookie
res.cookie("refresh_token", newRefreshToken, {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
sameSite: process.env.NODE_ENV === "production" ? "None" : "Lax",
maxAge: 7 * 24 * 60 * 60 * 1000,
});
return res.status(200).send({
success: true,
message: "Session refreshed successfully",
});
} catch (error) {
console.error("REFRESH ERROR:", error);
return res.status(401).send({
success: false,
message: "Invalid or expired session. Please login again.",
});
}
};
// Logout: Clear the JWT cookie
exports.logout = (req, res) => {
res.clearCookie("access_token", {