Spaces:
Runtime error
Runtime error
import { Request, Response } from 'express'; | |
import User from '../models/users'; | |
import { comparePassword, hashPassword } from '../utils/passwordUtils'; | |
import { generateToken } from '../utils/jwtUtils'; | |
import { logger } from '../utils/logger'; | |
import { sendMail } from '../utils/mailer'; | |
import { generateResetToken } from '../utils/tokenUtils'; | |
import { Op } from 'sequelize'; | |
import { AuthenticatedRequest } from 'shared/interfaces/user.interface'; | |
export const login = async (req: Request, res: Response) => { | |
try { | |
const { email, password } = req.body; | |
const user = await User.findOne({ | |
where: { | |
email: email, | |
}, | |
}) | |
if (!user) { | |
return res.status(401).json({ error: 'Invalid Credentials' }); | |
} | |
const passwordMatch = await comparePassword(password, user.password); | |
if (!passwordMatch) { | |
return res.status(401).json({ error: 'Invalid Credentials' }); | |
} | |
if (user.status === 'inactive') { | |
return res.status(403).json({ error: 'Forbidden' }); | |
} | |
const payload = { | |
id: user.id, | |
name: user.name, | |
email: user.email, | |
role_id: user.role_id | |
} | |
const token = generateToken(payload); | |
return res.status(200).json({ token: token }); | |
} catch (error) { | |
logger.error("Error logging in: "); | |
logger.error(error); | |
return res.status(500).json({ error: 'Internal server error' }); | |
} | |
} | |
export const forgotPassword = async (req: Request, res: Response) => { | |
try { | |
const { email } = req.body; | |
const user = await User.findOne({ | |
where: { email } | |
}); | |
if (!user) { | |
return res.status(404).json({ error: 'User not found' }); | |
} | |
const resetToken = generateResetToken(); | |
const resetTokenExpiry = new Date(Date.now() + 3600000); | |
await user.update({ | |
reset_token: resetToken, | |
reset_token_expiry: resetTokenExpiry | |
}); | |
const resetLink = `${process.env.APP_URL}reset-password?token=${resetToken}`; | |
sendMail({ | |
subject: 'Your password reset link', | |
to: email, | |
content: `<p><b>Dear ${user.name},</b></p> | |
<p>Click the link below to reset your password:</p> | |
<p><a href="${resetLink}">Reset Your Password</a></p> | |
<p>Link will expire within 1 hour.</p> | |
<p>Best regards,<br>Team Fusion Bills</p>` | |
}) | |
return res.status(200).json({ message: 'Password reset email sent successfully' }); | |
} catch (error) { | |
logger.error("Error in forgot password: "); | |
logger.error(error); | |
return res.status(500).json({ error: 'Internal server error' }); | |
} | |
} | |
export const resetPassword = async (req: Request, res: Response) => { | |
try { | |
const { token, newPassword } = req.body; | |
const user = await User.findOne({ | |
where: { | |
reset_token: token, | |
reset_token_expiry: { [Op.gt]: new Date() } | |
} | |
}); | |
if (!user) { | |
return res.status(400).json({ error: 'Invalid or expired token' }); | |
} | |
const hashedPassword = await hashPassword(newPassword); | |
await user.update({ | |
password: hashedPassword, | |
reset_token: null, | |
reset_token_expiry: null | |
}); | |
return res.status(200).json({ message: 'Password reset successfully' }); | |
} catch (error) { | |
logger.error("Error in reset password: "); | |
logger.error(error); | |
return res.status(500).json({ error: 'Internal server error' }); | |
} | |
} | |
export const changePassword = async (req: AuthenticatedRequest, res: Response) => { | |
try { | |
const { currentPassword, newPassword, confirmPassword } = req.body; | |
const userId = req.user?.id; | |
if (!userId) { | |
return res.status(401).json({ error: 'Unauthorized' }); | |
} | |
const user = await User.findByPk(userId); | |
if (!user) { | |
return res.status(404).json({ error: 'User not found' }); | |
} | |
const isPasswordCorrect = await comparePassword(currentPassword, user.password); | |
if (!isPasswordCorrect) { | |
return res.status(400).json({ error: 'Invalid current password' }); | |
} | |
if (newPassword !== confirmPassword) { | |
return res.status(400).json({ error: 'New passwords do not match' }); | |
} | |
if (newPassword.length < 8) { | |
return res.status(400).json({ error: 'Password must be at least 8 characters long.' }); | |
} | |
const hashedPassword = await hashPassword(newPassword); | |
user.password = hashedPassword; | |
await user.save(); | |
return res.status(200).json({ message: 'Password changed successfully' }); | |
} catch (error) { | |
logger.error("Error changing password: "); | |
logger.error(error); | |
return res.status(500).json({ error: 'Internal server error' }); | |
} | |
} | |