39647-vm/backend/controllers/authController.js
2026-04-08 14:28:58 +04:00

186 lines
4.8 KiB
JavaScript

const jwt = require('jsonwebtoken');
const User = require('../models/userModel');
const { validateEmail, validatePassword } = require('../middleware/validationMiddleware');
// Generate JWT Token
const generateToken = (id) => {
return jwt.sign({ id }, process.env.JWT_SECRET || 'your_secret_key', {
expiresIn: process.env.JWT_EXPIRE || '7d',
});
};
// @desc Register user
// @route POST /api/auth/register
// @access Public
exports.register = async (req, res) => {
try {
const { firstName, lastName, email, password, passwordConfirm } = req.body;
// Validation
if (!firstName || !lastName || !email || !password || !passwordConfirm) {
return res.status(400).json({ message: 'All fields are required' });
}
if (!validateEmail(email)) {
return res.status(400).json({ message: 'Invalid email format' });
}
if (!validatePassword(password)) {
return res.status(400).json({
message: 'Password must be at least 8 characters with uppercase, lowercase, and number',
});
}
if (password !== passwordConfirm) {
return res.status(400).json({ message: 'Passwords do not match' });
}
// Check if user already exists
let user = await User.findOne({ email });
if (user) {
return res.status(400).json({ message: 'Email already in use' });
}
// Create user
user = await User.create({
firstName,
lastName,
email,
password,
});
// Create token
const token = generateToken(user._id);
res.status(201).json({
success: true,
message: 'User registered successfully',
token,
user: user.getPublicData(),
});
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
};
// @desc Login user
// @route POST /api/auth/login
// @access Public
exports.login = async (req, res) => {
try {
const { email, password } = req.body;
// Validation
if (!email || !password) {
return res.status(400).json({ message: 'Email and password are required' });
}
if (!validateEmail(email)) {
return res.status(400).json({ message: 'Invalid email format' });
}
// Check if user exists and get password field
const user = await User.findOne({ email });
if (!user) {
return res.status(401).json({ message: 'Invalid email or password' });
}
// Check if password matches
const isPasswordMatch = await user.matchPassword(password);
if (!isPasswordMatch) {
return res.status(401).json({ message: 'Invalid email or password' });
}
// Check if user account is active
if (!user.isActive) {
return res.status(403).json({ message: 'Your account has been deactivated' });
}
// Update last login
user.lastLogin = new Date();
await user.save();
// Create token
const token = generateToken(user._id);
res.status(200).json({
success: true,
message: 'Login successful',
token,
user: user.getPublicData(),
});
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
};
// @desc Logout user (client-side)
// @route POST /api/auth/logout
// @access Private
exports.logout = async (req, res) => {
try {
// Token removal is handled on client-side
// This endpoint can be used for server-side session cleanup if needed
res.status(200).json({
success: true,
message: 'Logout successful',
});
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
};
// @desc Refresh token
// @route POST /api/auth/refresh-token
// @access Private
exports.refreshToken = async (req, res) => {
try {
const { token } = req.body;
if (!token) {
return res.status(400).json({ message: 'Token is required' });
}
// Verify token
let decoded;
try {
decoded = jwt.verify(token, process.env.JWT_SECRET || 'your_secret_key');
} catch (error) {
return res.status(401).json({ message: 'Invalid or expired token' });
}
// Get user
const user = await User.findById(decoded.id);
if (!user) {
return res.status(404).json({ message: 'User not found' });
}
// Generate new token
const newToken = generateToken(user._id);
res.status(200).json({
success: true,
message: 'Token refreshed successfully',
token: newToken,
});
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
};
// @desc Get current logged in user
// @route GET /api/auth/me
// @access Private
exports.getMe = async (req, res) => {
try {
const user = await User.findById(req.user.id);
res.status(200).json({
success: true,
user: user.getPublicData(),
});
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
};