This commit is contained in:
silverpro89
2026-01-19 20:32:23 +07:00
parent 70838a4bc1
commit 97e2e8402e
14 changed files with 10115 additions and 686 deletions

View File

@@ -1,7 +1,9 @@
const { UsersAuth, UserProfile } = require('../models');
const { UsersAuth, UserProfile, Role, Permission, UserAssignment, School, Class, Grade } = require('../models');
const roleHelperService = require('../services/roleHelperService');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const { Op } = require('sequelize');
// JWT Secret - nên lưu trong environment variable
const JWT_SECRET = process.env.JWT_SECRET || 'sena-secret-key-2026';
@@ -12,7 +14,36 @@ const JWT_EXPIRES_IN = '24h';
*/
class AuthController {
/**
* Login - Xác thực người dùng
* @swagger
* /api/auth/login:
* post:
* tags: [Authentication]
* summary: Đăng nhập vào hệ thống
* description: Xác thực người dùng bằng username/email và password
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - username
* - password
* properties:
* username:
* type: string
* example: student001
* password:
* type: string
* format: password
* example: password123
* responses:
* 200:
* description: Đăng nhập thành công
* 401:
* description: Username hoặc password không đúng
* 403:
* description: Tài khoản bị khóa
*/
async login(req, res, next) {
try {
@@ -25,7 +56,6 @@ class AuthController {
message: 'Username và password là bắt buộc',
});
}
// Tìm user theo username hoặc email
const user = await UsersAuth.findOne({
where: {
@@ -107,6 +137,9 @@ class AuthController {
current_session_id: sessionId,
});
// Load role và permissions bằng helper service
const { roleInfo, permissions } = await roleHelperService.getUserRoleAndPermissions(user.id);
// Tạo JWT token
const token = jwt.sign(
{
@@ -114,6 +147,7 @@ class AuthController {
username: user.username,
email: user.email,
sessionId: sessionId,
roleCode: roleInfo?.role_code,
},
JWT_SECRET,
{ expiresIn: JWT_EXPIRES_IN }
@@ -130,6 +164,8 @@ class AuthController {
username: user.username,
email: user.email,
profile: user.profile,
role: roleInfo,
permissions: permissions,
last_login: user.last_login,
login_count: user.login_count,
},
@@ -141,7 +177,74 @@ class AuthController {
}
/**
* Register - Tạo tài khoản mới
* @swagger
* /api/auth/register:
* post:
* tags: [Authentication]
* summary: Đăng ký tài khoản mới
* description: Tạo tài khoản người dùng mới với username, email và password. Tự động tạo profile nếu có thông tin.
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - username
* - email
* - password
* properties:
* username:
* type: string
* minLength: 3
* maxLength: 50
* example: newuser123
* email:
* type: string
* format: email
* example: user@example.com
* password:
* type: string
* format: password
* minLength: 6
* example: password123
* full_name:
* type: string
* example: Nguyễn Văn A
* phone:
* type: string
* example: "0901234567"
* school_id:
* type: string
* format: uuid
* responses:
* 201:
* description: Đăng ký tài khoản thành công
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* message:
* type: string
* example: Đăng ký tài khoản thành công
* data:
* type: object
* properties:
* id:
* type: string
* format: uuid
* username:
* type: string
* email:
* type: string
* 400:
* description: Thiếu thông tin bắt buộc
* 409:
* description: Username hoặc email đã tồn tại
*/
async register(req, res, next) {
try {
@@ -155,13 +258,10 @@ class AuthController {
});
}
// Kiểm tra username đã tồn tại
// Check if user exists
const existingUser = await UsersAuth.findOne({
where: {
[require('sequelize').Op.or]: [
{ username },
{ email },
],
[Op.or]: [{ username }, { email }],
},
});
@@ -173,25 +273,23 @@ class AuthController {
}
// Hash password
const salt = crypto.randomBytes(16).toString('hex');
const passwordHash = await bcrypt.hash(password + salt, 10);
const hashedPassword = await bcrypt.hash(password, 10);
// Tạo user mới
const newUser = await UsersAuth.create({
// Create user auth
const user = await UsersAuth.create({
username,
email,
password_hash: passwordHash,
salt,
qr_secret: crypto.randomBytes(32).toString('hex'),
password_hash: hashedPassword,
status: 'active',
});
// Tạo profile nếu có thông tin
if (full_name || phone || school_id) {
// Create user profile if we have additional info
if (full_name || phone) {
await UserProfile.create({
user_id: newUser.id,
full_name: full_name || username,
phone,
school_id,
user_id: user.id,
full_name: full_name || null,
phone: phone || null,
school_id: school_id || null,
});
}
@@ -199,18 +297,31 @@ class AuthController {
success: true,
message: 'Đăng ký tài khoản thành công',
data: {
id: newUser.id,
username: newUser.username,
email: newUser.email,
id: user.id,
username: user.username,
email: user.email,
},
});
} catch (error) {
console.error('Register error:', error);
next(error);
}
}
/**
* Verify Token - Xác thực JWT token
* @swagger
* /api/auth/verify-token:
* post:
* tags: [Authentication]
* summary: Xác thực JWT token
* description: Kiểm tra tính hợp lệ của JWT token
* security:
* - bearerAuth: []
* responses:
* 200:
* description: Token hợp lệ
* 401:
* description: Token không hợp lệ
*/
async verifyToken(req, res, next) {
try {
@@ -271,7 +382,19 @@ class AuthController {
}
/**
* Logout - Đăng xuất
* @swagger
* /api/auth/logout:
* post:
* tags: [Authentication]
* summary: Đăng xuất
* description: Xóa session hiện tại
* security:
* - bearerAuth: []
* responses:
* 200:
* description: Đăng xuất thành công
* 401:
* description: Token không hợp lệ
*/
async logout(req, res, next) {
try {
@@ -332,9 +455,16 @@ class AuthController {
});
}
// Load role và permissions bằng helper service
const { roleInfo, permissions } = await roleHelperService.getUserRoleAndPermissions(user.id);
res.json({
success: true,
data: user,
data: {
...user.toJSON(),
role: roleInfo,
permissions: permissions,
},
});
} catch (error) {
if (error.name === 'JsonWebTokenError' || error.name === 'TokenExpiredError') {
@@ -348,4 +478,4 @@ class AuthController {
}
}
module.exports = new AuthController();
module.exports = new AuthController();