Finish password reset (hopefully)
This commit is contained in:
parent
b9a7f9aa8e
commit
27d8c7cff6
@ -26,6 +26,19 @@ class PasswordResetTokenRepository {
|
|||||||
throw new Error(`Failed to get password reset token by user ID: ${error.message}`)
|
throw new Error(`Failed to get password reset token by user ID: ${error.message}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getByToken(token: string): Promise<any> {
|
||||||
|
try {
|
||||||
|
return await prisma.passwordResetToken.findFirst({
|
||||||
|
where: {
|
||||||
|
token
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (error: any) {
|
||||||
|
// Handle error
|
||||||
|
throw new Error(`Failed to get password reset token by token: ${error.message}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new PasswordResetTokenRepository()
|
export default new PasswordResetTokenRepository()
|
||||||
|
@ -77,9 +77,15 @@ class UserService {
|
|||||||
const isTokenExpired = latestToken.createdAt < tokenExpiryDate
|
const isTokenExpired = latestToken.createdAt < tokenExpiryDate
|
||||||
|
|
||||||
if (!isTokenExpired) return false
|
if (!isTokenExpired) return false
|
||||||
|
|
||||||
|
await prisma.passwordResetToken.delete({
|
||||||
|
where: {
|
||||||
|
id: latestToken.id
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
prisma.passwordResetToken.create({
|
await prisma.passwordResetToken.create({
|
||||||
data: {
|
data: {
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
token: token,
|
token: token,
|
||||||
@ -101,8 +107,8 @@ class UserService {
|
|||||||
from: config.SMTP_USER,
|
from: config.SMTP_USER,
|
||||||
to: email,
|
to: email,
|
||||||
subject: "Reset your password",
|
subject: "Reset your password",
|
||||||
text: "A password reset has been requested, reset your password here: " + config.CLIENT_URL + "/#" + token, // Plain text body
|
text: "A password reset has been requested, reset your password here: " + config.CLIENT_URL + "#" + token, // Plain text body
|
||||||
html: "<p>A password reset has been requested, reset your password here: <a href='" + config.CLIENT_URL + "/#" + token + "'>" + config.CLIENT_URL + "/#token=" + token + "</a></p>", // Html body
|
html: "<p>A password reset has been requested, reset your password here: <a href='" + config.CLIENT_URL + "#" + token + "'>" + config.CLIENT_URL + "#" + token + "</a></p>", // Html body
|
||||||
});
|
});
|
||||||
|
|
||||||
return true
|
return true
|
||||||
@ -110,6 +116,26 @@ class UserService {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set new password
|
||||||
|
* @param urlToken
|
||||||
|
* @param password
|
||||||
|
*/
|
||||||
|
async newPassword(urlToken: string, password: string): Promise<boolean | User> {
|
||||||
|
const tokenData = await PasswordResetTokenRepository.getByToken(urlToken)
|
||||||
|
if (!tokenData) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const hashedPassword = await bcrypt.hash(password, 10)
|
||||||
|
return prisma.user.update({
|
||||||
|
where: { id: tokenData.userId },
|
||||||
|
data: {
|
||||||
|
password: hashedPassword
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default UserService
|
export default UserService
|
||||||
|
@ -2,7 +2,7 @@ import { Application, Request, Response } from 'express'
|
|||||||
import UserService from '../services/userService'
|
import UserService from '../services/userService'
|
||||||
import jwt from 'jsonwebtoken'
|
import jwt from 'jsonwebtoken'
|
||||||
import config from './config'
|
import config from './config'
|
||||||
import { loginAccountSchema, registerAccountSchema, resetPasswordSchema } from './zodTypes'
|
import { loginAccountSchema, registerAccountSchema, resetPasswordSchema, newPasswordSchema } from './zodTypes'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import { httpLogger } from './logger'
|
import { httpLogger } from './logger'
|
||||||
import { getPublicPath } from './storage'
|
import { getPublicPath } from './storage'
|
||||||
@ -85,6 +85,30 @@ async function addHttpRoutes(app: Application) {
|
|||||||
return res.status(400).json({ message: 'Failed to send password reset request' })
|
return res.status(400).json({ message: 'Failed to send password reset request' })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New password
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
*/
|
||||||
|
app.post('/new-password', async (req: Request, res: Response) => {
|
||||||
|
const { urlToken, password } = req.body
|
||||||
|
|
||||||
|
try {
|
||||||
|
newPasswordSchema.parse({ password })
|
||||||
|
} catch (error: any) {
|
||||||
|
return res.status(400).json({ message: error.errors[0]?.message })
|
||||||
|
}
|
||||||
|
|
||||||
|
const userService = new UserService()
|
||||||
|
const resetPassword = await userService.newPassword( urlToken, password )
|
||||||
|
|
||||||
|
if (resetPassword) {
|
||||||
|
return res.status(200).json({ message: 'Password has been reset' })
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(400).json({ message: 'Failed to set new password' })
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all tiles from a zone as an array of ids
|
* Get all tiles from a zone as an array of ids
|
||||||
* @param req
|
* @param req
|
||||||
|
@ -41,6 +41,15 @@ export const resetPasswordSchema = z.object({
|
|||||||
.regex(/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/, { message: 'Email must be valid' })
|
.regex(/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/, { message: 'Email must be valid' })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const newPasswordSchema = z.object({
|
||||||
|
password: z
|
||||||
|
.string()
|
||||||
|
.min(8, {
|
||||||
|
message: 'Password must be at least 8 characters long'
|
||||||
|
})
|
||||||
|
.max(255)
|
||||||
|
})
|
||||||
|
|
||||||
export const ZCharacterCreate = z.object({
|
export const ZCharacterCreate = z.object({
|
||||||
name: z
|
name: z
|
||||||
.string()
|
.string()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user