Moved auth logic to service

This commit is contained in:
xl1034 2025-03-11 13:09:44 +07:00
parent 372a7a5dee
commit d9bc17db02
4 changed files with 126 additions and 67 deletions

View File

@ -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

4
app.js
View File

@ -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))

View File

@ -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<void>}
*/
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<void>}
*/
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<void>}
*/
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()

View File

@ -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