add html and subject to password recovery props

This commit is contained in:
2023-07-18 12:53:39 +02:00
parent f38a019429
commit 75361abc82
4 changed files with 33 additions and 6 deletions

View File

@@ -208,7 +208,7 @@ export class AuthController {
@HttpCode(HttpStatus.NO_CONTENT) @HttpCode(HttpStatus.NO_CONTENT)
@Post('recover-password') @Post('recover-password')
async recoverPassword(@Body() body: RecoverPasswordDto): Promise<void> { async recoverPassword(@Body() body: RecoverPasswordDto): Promise<void> {
return await this.commandBus.execute(new SendPasswordRecoveryEmailCommand(body.email)) return await this.commandBus.execute(new SendPasswordRecoveryEmailCommand(body))
} }
@ApiOperation({ description: 'Reset password', summary: 'Reset password' }) @ApiOperation({ description: 'Reset password', summary: 'Reset password' })

View File

@@ -1,6 +1,22 @@
import { IsEmail } from 'class-validator' import { ApiProperty } from '@nestjs/swagger'
import { IsEmail, IsOptional, IsString } from 'class-validator'
export class RecoverPasswordDto { export class RecoverPasswordDto {
/** User's email address */
@IsEmail() @IsEmail()
email: string email: string
@ApiProperty({
description: `HTML template to be sent in the email;\n ##name## will be replaced with the user's name; \n ##token## will be replaced with the password recovery token`,
example:
'<h1>Hi, ##name#</h1><p>Click <a href="##token##">here</a> to recover your password</p>',
})
@IsString()
@IsOptional()
html?: string
/** Email subject */
@IsString()
@IsOptional()
subject?: string
} }

View File

@@ -4,9 +4,10 @@ import { v4 as uuidv4 } from 'uuid'
import { UsersRepository } from '../../users/infrastructure/users.repository' import { UsersRepository } from '../../users/infrastructure/users.repository'
import { UsersService } from '../../users/services/users.service' import { UsersService } from '../../users/services/users.service'
import { RecoverPasswordDto } from '../dto'
export class SendPasswordRecoveryEmailCommand { export class SendPasswordRecoveryEmailCommand {
constructor(public readonly email: string) {} constructor(public readonly body: RecoverPasswordDto) {}
} }
@CommandHandler(SendPasswordRecoveryEmailCommand) @CommandHandler(SendPasswordRecoveryEmailCommand)
@@ -19,7 +20,7 @@ export class SendPasswordRecoveryEmailHandler
) {} ) {}
async execute(command: SendPasswordRecoveryEmailCommand) { async execute(command: SendPasswordRecoveryEmailCommand) {
const user = await this.usersRepository.findUserByEmail(command.email) const user = await this.usersRepository.findUserByEmail(command.body.email)
if (!user) { if (!user) {
throw new NotFoundException('User not found') throw new NotFoundException('User not found')
@@ -30,7 +31,9 @@ export class SendPasswordRecoveryEmailHandler
await this.usersService.sendPasswordRecoveryEmail({ await this.usersService.sendPasswordRecoveryEmail({
email: updatedUser.user.email, email: updatedUser.user.email,
name: updatedUser.user.name, name: updatedUser.user.name,
html: command.body.html,
passwordRecoveryToken: updatedUser.resetPasswordToken, passwordRecoveryToken: updatedUser.resetPasswordToken,
subject: command.body.subject,
}) })
if (!updatedUser) { if (!updatedUser) {
throw new NotFoundException('User not found') throw new NotFoundException('User not found')

View File

@@ -56,17 +56,25 @@ export class UsersService {
email, email,
name, name,
passwordRecoveryToken, passwordRecoveryToken,
html,
subject,
}: { }: {
email: string email: string
name: string name: string
html?: string
subject?: string
passwordRecoveryToken: string passwordRecoveryToken: string
}) { }) {
const htmlFinal =
html.replace('##token##', passwordRecoveryToken).replace('##name##', name) ||
`<b>Hello ${name}!</b><br/>To recover your password follow this link:<br/><a href="http://localhost:3000/confirm-email/${passwordRecoveryToken}">Confirm email</a>. If it doesn't work, copy and paste the following link in your browser:<br/>http://localhost:3000/confirm-email/${passwordRecoveryToken} `
try { try {
await this.emailService.sendMail({ await this.emailService.sendMail({
from: 'Andrii <andrii@andrii.es>', from: 'Andrii <andrii@andrii.es>',
to: email, to: email,
html: `<b>Hello ${name}!</b><br/>To recover your password follow this link:<br/><a href="http://localhost:3000/confirm-email/${passwordRecoveryToken}">Confirm email</a>. If it doesn't work, copy and paste the following link in your browser:<br/>http://localhost:3000/confirm-email/${passwordRecoveryToken} `, html: htmlFinal,
subject: 'Password recovery', subject: subject || 'Password recovery',
}) })
} catch (e) { } catch (e) {
this.logger.error(e?.message || e) this.logger.error(e?.message || e)