dss-server / src /controllers /authController.js
yeshwanth-kr's picture
Upload 43 files
8c7b7ca verified
const bcrypt = require('bcryptjs');
const dayjs = require('dayjs');
const jwt = require('jsonwebtoken');
const { body } = require('express-validator');
const { User } = require('../models');
const env = require('../config/env');
const validate = require('../utils/validation');
const PASSWORD_ROTATION_ROLES = new Set(['Admin', 'HR', 'Safety_Officer']);
const PASSWORD_ROTATION_DAYS = 90;
const loginValidators = [
body('email').isEmail().withMessage('Valid email is required'),
body('password').isLength({ min: 6 }).withMessage('Password is required'),
validate
];
const changePasswordValidators = [
body('current_password').isLength({ min: 6 }).withMessage('current_password is required'),
body('new_password').isLength({ min: 8 }).withMessage('new_password must be at least 8 characters'),
validate
];
function getPasswordDueDate(role, passwordChangedAt) {
if (!PASSWORD_ROTATION_ROLES.has(role)) return null;
return dayjs(passwordChangedAt).add(PASSWORD_ROTATION_DAYS, 'day').format('DD/MM/YYYY');
}
function isPasswordRotationExpired(role, passwordChangedAt) {
if (!PASSWORD_ROTATION_ROLES.has(role)) return false;
if (!passwordChangedAt) return true;
return dayjs().startOf('day').diff(dayjs(passwordChangedAt).startOf('day'), 'day') >= PASSWORD_ROTATION_DAYS;
}
async function login(req, res, next) {
try {
const { email, password } = req.body;
const user = await User.findOne({ email: String(email).toLowerCase() }).lean();
if (!user || !user.is_active) {
return res.status(401).json({ message: 'Invalid credentials' });
}
const isMatch = await bcrypt.compare(password, user.password_hash);
if (!isMatch) {
return res.status(401).json({ message: 'Invalid credentials' });
}
const mustResetPassword = Boolean(user.must_reset_password);
const passwordRotationExpired = isPasswordRotationExpired(user.role, user.password_changed_at);
const mustChangePassword = mustResetPassword || passwordRotationExpired;
const token = jwt.sign(
{
id: String(user._id),
full_name: user.full_name,
email: user.email,
role: user.role,
vendor_id: user.vendor_id ? String(user.vendor_id) : null
},
env.jwtSecret,
{ expiresIn: '12h' }
);
return res.json({
token,
user: {
id: user.id,
full_name: user.full_name,
email: user.email,
role: user.role,
vendor_id: user.vendor_id ? String(user.vendor_id) : null,
must_reset_password: mustResetPassword,
must_change_password: mustChangePassword,
password_due_date: getPasswordDueDate(user.role, user.password_changed_at)
}
});
} catch (error) {
return next(error);
}
}
async function changePassword(req, res, next) {
try {
const { current_password, new_password } = req.body;
if (current_password === new_password) {
return res.status(400).json({ message: 'New password must be different from current password' });
}
const user = await User.findOne({ _id: req.user.id, is_active: true });
if (!user) {
return res.status(404).json({ message: 'User not found' });
}
const isMatch = await bcrypt.compare(current_password, user.password_hash);
if (!isMatch) {
return res.status(401).json({ message: 'Current password is incorrect' });
}
user.password_hash = await bcrypt.hash(new_password, 10);
user.must_reset_password = false;
user.password_changed_at = new Date();
await user.save();
return res.json({
message: 'Password changed successfully',
user: {
must_reset_password: false,
must_change_password: false,
password_due_date: getPasswordDueDate(user.role, new Date())
}
});
} catch (error) {
return next(error);
}
}
module.exports = {
loginValidators,
changePasswordValidators,
login,
changePassword
};