162 lines
3.8 KiB
JavaScript
162 lines
3.8 KiB
JavaScript
const bcrypt = require('bcrypt');
|
|
const { Admin, LoginHistory } = require('../models');
|
|
const { generateToken, generateRefreshToken, verifyToken } = require('../utils/jwt');
|
|
const logger = require('../config/logger');
|
|
|
|
/**
|
|
* Admin Authentication Service
|
|
* Handles admin login and authentication logic
|
|
*/
|
|
|
|
/**
|
|
* Authenticate admin and generate token
|
|
* @param {string} username - Admin username
|
|
* @param {string} password - Admin password
|
|
* @param {Object} loginInfo - Login metadata (IP, user agent, device info)
|
|
* @returns {Object} Admin data and token
|
|
*/
|
|
const loginAdmin = async (username, password, loginInfo = {}) => {
|
|
try {
|
|
// Find admin by username
|
|
const admin = await Admin.findOne({
|
|
where: { username },
|
|
});
|
|
|
|
if (!admin) {
|
|
throw new Error('Invalid username or password');
|
|
}
|
|
|
|
// Check if admin is active
|
|
if (admin.status === 'inactive') {
|
|
throw new Error('Admin account is inactive');
|
|
}
|
|
|
|
// Verify password
|
|
const isPasswordValid = await bcrypt.compare(password, admin.password);
|
|
|
|
if (!isPasswordValid) {
|
|
throw new Error('Invalid username or password');
|
|
}
|
|
|
|
// Generate JWT token and refresh token
|
|
const tokenPayload = {
|
|
userId: admin.id,
|
|
type: 'admin',
|
|
role: admin.role,
|
|
};
|
|
|
|
const token = generateToken(tokenPayload);
|
|
const refreshToken = generateRefreshToken(tokenPayload);
|
|
|
|
// Update last login time
|
|
await admin.update({
|
|
lastLoginAt: new Date(),
|
|
});
|
|
|
|
// Record login history
|
|
await LoginHistory.create({
|
|
userId: admin.id,
|
|
userType: 'admin',
|
|
ipAddress: loginInfo.ipAddress,
|
|
userAgent: loginInfo.userAgent,
|
|
deviceInfo: loginInfo.deviceInfo,
|
|
loginAt: new Date(),
|
|
});
|
|
|
|
logger.info(`Admin login successful: ${admin.username} (${admin.id})`);
|
|
|
|
// Return admin data (excluding password)
|
|
return {
|
|
admin: {
|
|
id: admin.id,
|
|
username: admin.username,
|
|
email: admin.email,
|
|
role: admin.role,
|
|
status: admin.status,
|
|
lastLoginAt: admin.lastLoginAt,
|
|
},
|
|
token,
|
|
refreshToken,
|
|
};
|
|
} catch (error) {
|
|
logger.error('Admin login error:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Refresh admin access token
|
|
* @param {string} refreshToken - Refresh token
|
|
* @returns {Object} New tokens
|
|
*/
|
|
const refreshAdminToken = async (refreshToken) => {
|
|
try {
|
|
// Verify refresh token
|
|
const decoded = verifyToken(refreshToken);
|
|
|
|
// Ensure it's an admin token
|
|
if (decoded.type !== 'admin') {
|
|
throw new Error('Invalid refresh token');
|
|
}
|
|
|
|
// Find admin to ensure they still exist and are active
|
|
const admin = await Admin.findByPk(decoded.userId);
|
|
|
|
if (!admin) {
|
|
throw new Error('Admin not found');
|
|
}
|
|
|
|
if (admin.status === 'inactive') {
|
|
throw new Error('Admin account is inactive');
|
|
}
|
|
|
|
// Generate new tokens
|
|
const tokenPayload = {
|
|
userId: admin.id,
|
|
type: 'admin',
|
|
role: admin.role,
|
|
};
|
|
|
|
const newToken = generateToken(tokenPayload);
|
|
const newRefreshToken = generateRefreshToken(tokenPayload);
|
|
|
|
logger.info(`Admin token refreshed: ${admin.username} (${admin.id})`);
|
|
|
|
return {
|
|
token: newToken,
|
|
refreshToken: newRefreshToken,
|
|
};
|
|
} catch (error) {
|
|
logger.error('Admin token refresh error:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Get admin profile by ID
|
|
* @param {string} adminId - Admin ID
|
|
* @returns {Object} Admin profile
|
|
*/
|
|
const getAdminProfile = async (adminId) => {
|
|
try {
|
|
const admin = await Admin.findByPk(adminId, {
|
|
attributes: { exclude: ['password'] },
|
|
});
|
|
|
|
if (!admin) {
|
|
throw new Error('Admin not found');
|
|
}
|
|
|
|
return admin;
|
|
} catch (error) {
|
|
logger.error('Get admin profile error:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
module.exports = {
|
|
loginAdmin,
|
|
getAdminProfile,
|
|
refreshAdminToken,
|
|
};
|