From 53f2934a24ac205dd4128a44e002b106bda1947b Mon Sep 17 00:00:00 2001 From: elangptra Date: Thu, 3 Oct 2024 10:32:34 +0700 Subject: [PATCH] refactor: auth login and refresh token API --- controllers/auth/auth.js | 68 +++++++++++++++++++++++-- controllers/contentControllers/topic.js | 14 ++--- index.js | 1 - models/usersModels/userModel.js | 3 ++ routes/auth/auth.js | 4 +- 5 files changed, 77 insertions(+), 13 deletions(-) diff --git a/controllers/auth/auth.js b/controllers/auth/auth.js index 0e09121..b93ce40 100644 --- a/controllers/auth/auth.js +++ b/controllers/auth/auth.js @@ -253,11 +253,20 @@ export const loginUser = async (req, res) => { } const accessToken = jwt.sign( - { ID: user.ID, - ROLE: user.ROLE - }, + { ID: user.ID, ROLE: user.ROLE }, process.env.ACCESS_TOKEN_SECRET, - { expiresIn: "6h" } + { expiresIn: "3h" } + ); + + const refreshToken = jwt.sign( + { ID: user.ID, ROLE: user.ROLE }, + process.env.REFRESH_TOKEN_SECRET, + { expiresIn: "7d" } + ); + + await models.User.update( + { REFRESH_TOKEN: refreshToken }, + { where: { ID: user.ID } } ); const userResponse = { @@ -266,6 +275,7 @@ export const loginUser = async (req, res) => { EMAIL: user.EMAIL, ROLE: user.ROLE, TOKEN: `Bearer ${accessToken}`, + REFRESH_TOKEN: refreshToken, }; response(200, userResponse, "Login successful", res); @@ -275,6 +285,56 @@ export const loginUser = async (req, res) => { } }; +export const refreshToken = async (req, res) => { + const { REFRESH_TOKEN } = req.body; + + if (!REFRESH_TOKEN) { + return response(400, null, "Refresh token is required!", res); + } + + try { + const user = await models.User.findOne({ where: { REFRESH_TOKEN } }); + + if (!user) { + return response(403, null, "Invalid refresh token!", res); + } + + jwt.verify( + REFRESH_TOKEN, + process.env.REFRESH_TOKEN_SECRET, + (err, decoded) => { + if (err) { + if (err.name === "TokenExpiredError") { + return response( + 401, + null, + "Refresh token expired. Please login again.", + res + ); + } + return response(403, null, "Invalid refresh token!", res); + } + + const newAccessToken = jwt.sign( + { ID: user.ID, ROLE: user.ROLE }, + process.env.ACCESS_TOKEN_SECRET, + { expiresIn: "3h" } + ); + + response( + 200, + { TOKEN: `Bearer ${newAccessToken}` }, + "Token refreshed successfully", + res + ); + } + ); + } catch (error) { + console.log(error); + response(500, null, "Internal Server Error", res); + } +}; + export const logoutUser = (req, res) => { response(200, null, "You have successfully logged out.", res); }; diff --git a/controllers/contentControllers/topic.js b/controllers/contentControllers/topic.js index 10da6a6..7d58e67 100644 --- a/controllers/contentControllers/topic.js +++ b/controllers/contentControllers/topic.js @@ -32,17 +32,17 @@ export const getTopicBySectionId = async (req, res) => { const { sectionId } = req.params; const sectionExists = await models.Section.findByPk(sectionId); - // if (!sectionExists) { - // return response(404, null, "Section not found", res); - // } + if (!sectionExists) { + return response(404, null, "Section not found", res); + } const topics = await models.Topic.findAll({ where: { ID_SECTION: sectionId }, }); - // if (!topics || topics.length === 0) { - // return response(404, null, "No topics found for this section", res); - // } + if (!topics || topics.length === 0) { + return response(404, null, "No topics found for this section", res); + } response(200, topics, "Success", res); } catch (error) { @@ -218,7 +218,7 @@ export const getCompletedTopicsBySection = async (req, res) => { const result = Object.values(completedSections); // if (!result.length) { - // return response(404, null, "No completed topics for Level 6 found", res); + // return response(404, null, "No section with completed topics found", res); // } response( diff --git a/index.js b/index.js index f1ec28e..b1f4ca1 100644 --- a/index.js +++ b/index.js @@ -22,7 +22,6 @@ app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(router); -// Serve static files from the uploads directory app.use(express.static("public")); app.listen(process.env.APP_PORT, () => { diff --git a/models/usersModels/userModel.js b/models/usersModels/userModel.js index abf4b9d..7d3cb60 100644 --- a/models/usersModels/userModel.js +++ b/models/usersModels/userModel.js @@ -41,6 +41,9 @@ const UserModel = (DataTypes) => { type: DataTypes.STRING, allowNull: true, }, + REFRESH_TOKEN: { + type: DataTypes.STRING, + }, TIME_USERS: { type: DataTypes.DATE, allowNull: true, diff --git a/routes/auth/auth.js b/routes/auth/auth.js index d98f4c1..aec5376 100644 --- a/routes/auth/auth.js +++ b/routes/auth/auth.js @@ -1,5 +1,5 @@ import express from "express"; -import { registerTeacher, registerStudent, registerAdmin, loginUser, logoutUser, forgotPassword, resetPassword } from "../../controllers/auth/auth.js"; +import { registerTeacher, registerStudent, registerAdmin, loginUser, refreshToken, logoutUser, forgotPassword, resetPassword } from "../../controllers/auth/auth.js"; import { verifyLoginUser, adminOnly } from "../../middlewares/User/authUser.js"; const router = express.Router(); @@ -12,6 +12,8 @@ router.post("/register/admin", verifyLoginUser, adminOnly, registerAdmin); router.post("/login", loginUser); +router.post("/refreshToken", refreshToken); + router.post("/logout", logoutUser); router.post("/forgotPassword", forgotPassword)