forked from noxious/server
Improved error message to client for password reset request, delete PasswordTokenReset after changing password
This commit is contained in:
parent
881e3375ab
commit
44cfbd6ee8
32
src/services/passwordResetTokenService.ts
Normal file
32
src/services/passwordResetTokenService.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import prisma from '../utilities/prisma'
|
||||||
|
import passwordResetTokenRepository from '../repositories/passwordResetTokenRepository'
|
||||||
|
import { appLogger } from '../utilities/logger'
|
||||||
|
|
||||||
|
class PasswordResetTokenService {
|
||||||
|
/**
|
||||||
|
* Delete token
|
||||||
|
* @param token
|
||||||
|
*/
|
||||||
|
public async delete(token: string): Promise<boolean> {
|
||||||
|
|
||||||
|
try {
|
||||||
|
const tokenData = await passwordResetTokenRepository.getByToken(token)
|
||||||
|
if (!tokenData) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
prisma.passwordResetToken.delete({
|
||||||
|
where: {
|
||||||
|
token
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return true
|
||||||
|
} catch (error: any) {
|
||||||
|
appLogger.error(`Error deleting password reset token: ${error instanceof Error ? error.message : String(error)}`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PasswordResetTokenService
|
@ -6,6 +6,7 @@ import { User } from '@prisma/client'
|
|||||||
import config from '../utilities/config'
|
import config from '../utilities/config'
|
||||||
import NodeMailer from 'nodemailer'
|
import NodeMailer from 'nodemailer'
|
||||||
import { httpLogger } from '../utilities/logger'
|
import { httpLogger } from '../utilities/logger'
|
||||||
|
import PasswordResetTokenService from './passwordResetTokenService'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User service
|
* User service
|
||||||
@ -76,6 +77,7 @@ class UserService {
|
|||||||
* @param email
|
* @param email
|
||||||
*/
|
*/
|
||||||
async requestPasswordReset(email: string): Promise<boolean> {
|
async requestPasswordReset(email: string): Promise<boolean> {
|
||||||
|
try {
|
||||||
const user = await UserRepository.getByEmail(email)
|
const user = await UserRepository.getByEmail(email)
|
||||||
if (!user) return false
|
if (!user) return false
|
||||||
|
|
||||||
@ -84,7 +86,7 @@ class UserService {
|
|||||||
|
|
||||||
// Check if password reset has been requested recently
|
// Check if password reset has been requested recently
|
||||||
if (latestToken) {
|
if (latestToken) {
|
||||||
const tokenExpiryDate = new Date(Date.now() - 24 * 60 * 60 * 1000)
|
const tokenExpiryDate = new Date(Date.now() - 24 * 60 * 60 * 1000) // 24 hours
|
||||||
const isTokenExpired = latestToken.createdAt < tokenExpiryDate
|
const isTokenExpired = latestToken.createdAt < tokenExpiryDate
|
||||||
|
|
||||||
if (!isTokenExpired) return false
|
if (!isTokenExpired) return false
|
||||||
@ -113,7 +115,6 @@ class UserService {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
try {
|
|
||||||
await transporter.sendMail({
|
await transporter.sendMail({
|
||||||
from: config.SMTP_USER,
|
from: config.SMTP_USER,
|
||||||
to: email,
|
to: email,
|
||||||
@ -134,7 +135,7 @@ class UserService {
|
|||||||
* @param urlToken
|
* @param urlToken
|
||||||
* @param password
|
* @param password
|
||||||
*/
|
*/
|
||||||
async resetPassword(urlToken: string, password: string): Promise<boolean | User> {
|
async resetPassword(urlToken: string, password: string): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const tokenData = await PasswordResetTokenRepository.getByToken(urlToken)
|
const tokenData = await PasswordResetTokenRepository.getByToken(urlToken)
|
||||||
if (!tokenData) {
|
if (!tokenData) {
|
||||||
@ -142,12 +143,18 @@ class UserService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const hashedPassword = await bcrypt.hash(password, 10)
|
const hashedPassword = await bcrypt.hash(password, 10)
|
||||||
return prisma.user.update({
|
prisma.user.update({
|
||||||
where: { id: tokenData.userId },
|
where: { id: tokenData.userId },
|
||||||
data: {
|
data: {
|
||||||
password: hashedPassword
|
password: hashedPassword
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Delete the token
|
||||||
|
const passwordResetTokenService = new PasswordResetTokenService()
|
||||||
|
await passwordResetTokenService.delete(urlToken)
|
||||||
|
|
||||||
|
return true
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
httpLogger.error(`Error setting new password: ${error instanceof Error ? error.message : String(error)}`)
|
httpLogger.error(`Error setting new password: ${error instanceof Error ? error.message : String(error)}`)
|
||||||
return false
|
return false
|
||||||
|
@ -82,7 +82,7 @@ async function addHttpRoutes(app: Application) {
|
|||||||
return res.status(200).json({ message: 'Email has been sent' })
|
return res.status(200).json({ message: 'Email has been sent' })
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(400).json({ message: 'Failed to send password reset request' })
|
return res.status(400).json({ message: 'Failed to send password reset request. Perhaps one has already been sent recently, check your spam folder.' })
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user