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' }); | |
| } | |
| } | |