From d9bc17db0255aa6794a4b2950767baca53cd8a9f Mon Sep 17 00:00:00 2001 From: xl1034 Date: Tue, 11 Mar 2025 13:09:44 +0700 Subject: [PATCH] Moved auth logic to service --- README.md | 3 + app.js | 4 +- modules/Auth/AuthController.js | 100 ++++++++++++--------------------- modules/Auth/AuthService.js | 86 ++++++++++++++++++++++++++++ 4 files changed, 126 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index e789bdf..9fd0e93 100644 --- a/README.md +++ b/README.md @@ -59,3 +59,6 @@ The following environment variables are required: | `JWT_SECRET` | The secret for the JWT token | | `VITE_API_URL` | The URL of the API | +## Useful information + +You can use `/api/v1/auth/generatePasswordHash?password=123456` to generate a password hash for development purposes \ No newline at end of file diff --git a/app.js b/app.js index 3d7ca37..997c325 100644 --- a/app.js +++ b/app.js @@ -15,7 +15,7 @@ import spaRouter from "./routers/spaRouter.js"; import api_v1_Router from "./routers/api_v1_Router.js"; import expressListRoutes from "express-list-routes"; -import AuthController from "./modules/Auth/AuthController"; +import AuthService from "./modules/Auth/AuthService"; /** * The port the server will listen on. @@ -53,7 +53,7 @@ if (process.env.NODE_ENV === "production") { * Authentication middlewares */ app.use(cors()); -passport.use(new BearerStrategy(AuthController.auth)) +passport.use(new BearerStrategy(AuthService.auth)) diff --git a/modules/Auth/AuthController.js b/modules/Auth/AuthController.js index 1e11c7b..61fd637 100644 --- a/modules/Auth/AuthController.js +++ b/modules/Auth/AuthController.js @@ -1,56 +1,20 @@ -import jwt from "jsonwebtoken"; -import {User} from "../../models/index"; import Controller from "../Controller"; -import bcrypt from "bcrypt"; +import AuthService from "./AuthService"; class AuthController extends Controller { - async auth(token, done) { - try { - const decoded = jwt.verify(token, process.env.JWT_SECRET); - const user = await User.findByPk(decoded.userId); - if (!user) { - return done(null, false); - } else { - return done(null, user); - } - } catch (e) { - return done(null, false); - } - } + /** + * @desc Login user + * @param req + * @param res + * @returns {Promise} + */ async login(req, res) { try { - // Получаем email и пароль из тела запроса - const {username, password} = req.body; - - // Находим пользователя по username - const user = await User.scope('withPassword').findOne({where: {username}}); - - // Если пользователь не найден, возвращаем ошибку - if (!user) { - console.log(`User not found ${username}`); - return res.status(401).json({message: 'Неверное имя пользователя или пароль'}); - } - - - // Сравниваем пароль из запроса с хешированным паролем пользователя - const isPasswordValid = await bcrypt.compare(password, user.password); - - // Если пароль неверный, возвращаем ошибку - if (!isPasswordValid) { - return res.status(401).json({message: 'Неверное имя пользователя или пароль'}); - } - - // Создаем JWT-токен - const token = jwt.sign({userId: user.id}, process.env.JWT_SECRET, { - expiresIn: '1h', - }); - - // Возвращаем токен - res.json({token}); + await AuthService.login(req, res) } catch (error) { console.error('Internal server error', error); res.status(500).json({message: 'Internal server error'}); @@ -58,6 +22,13 @@ class AuthController extends Controller { } + /** + * @desc Get current user + * @param req + * @param res + * @returns {Promise<*>} + */ + async user(req, res) { try { return res.json(req.user); @@ -65,42 +36,41 @@ class AuthController extends Controller { console.error(error); res.status(500).json({message: 'Internal server error'}); } - - } + /** + * @desc Logout user + * @param req + * @param res + * @returns {Promise} + */ + async logout(req, res) { try { - // Удаляем токен из заголовка авторизации - res.clearCookie('token'); - res.json({message: 'Вы успешно вышли из системы'}); + await AuthService.logout(req, res) } catch (error) { console.error(error); res.status(500).json({message: 'Internal server error'}); } } + + /** + * @desc Maintenance endpoint to generate password hash + * @param req + * @param res + * @returns {Promise} + */ async generatePasswordHash(req, res) { - if (process.env.NODE_ENV === 'development') { - // Get passwort from get request - const password = req.query.password; - - // Hash password - bcrypt.hash(password, 10, (err, hash) => { - if (err) { - console.error(err); - return res.status(500).json({message: 'Internal server error'}); - } - console.log(hash) - return res.json({hash}); - }); - - + try { + await AuthService.generatePasswordHash(req, res) + } catch (error) { + console.error('Internal server error', error); + res.status(500).json({message: 'Internal server error'}); } } - } export default new AuthController() diff --git a/modules/Auth/AuthService.js b/modules/Auth/AuthService.js index 41c14b3..d06e2e4 100644 --- a/modules/Auth/AuthService.js +++ b/modules/Auth/AuthService.js @@ -1,5 +1,91 @@ import Service from "../Service"; +import jwt from "jsonwebtoken"; +import {User} from "../../models"; +import bcrypt from "bcrypt"; class AuthService extends Service { + async auth(token, done) { + try { + const decoded = jwt.verify(token, process.env.JWT_SECRET); + const user = await User.findByPk(decoded.userId); + if (!user) { + return done(null, false); + } else { + return done(null, user); + } + } catch (e) { + return done(null, false); + } + } + + + async login(req, res) { + try { + // Получаем email и пароль из тела запроса + const {username, password} = req.body; + + // Находим пользователя по username + const user = await User.scope('withPassword').findOne({where: {username}}); + + // Если пользователь не найден, возвращаем ошибку + if (!user) { + console.log(`User not found ${username}`); + return res.status(401).json({message: 'Неверное имя пользователя или пароль'}); + } + + + // Сравниваем пароль из запроса с хешированным паролем пользователя + const isPasswordValid = await bcrypt.compare(password, user.password); + + // Если пароль неверный, возвращаем ошибку + if (!isPasswordValid) { + return res.status(401).json({message: 'Неверное имя пользователя или пароль'}); + } + + // Создаем JWT-токен + const token = jwt.sign({userId: user.id}, process.env.JWT_SECRET, { + expiresIn: '1h', + }); + + // Возвращаем токен + res.json({token}); + } catch (error) { + console.error(error); + res.status(500).json({message: 'Internal server error'}); + } + } + + + async logout(req, res) { + try { + // Удаляем токен из заголовка авторизации + res.clearCookie('token'); + res.json({message: 'Вы успешно вышли из системы'}); + } catch (error) { + console.error(error); + res.status(500).json({message: 'Internal server error'}); + } + } + + + async generatePasswordHash(req, res) { + if (process.env.NODE_ENV === 'development') { + // Get passwort from get request + const password = req.query.password; + + // Hash password + bcrypt.hash(password, 10, (err, hash) => { + if (err) { + console.error(err); + return res.status(500).json({message: 'Internal server error'}); + } + console.log(hash) + return res.json({hash}); + }); + } + } + } + +export default new AuthService \ No newline at end of file