From a7979c22daee6f94b026266f836ad516c7fe4fd6 Mon Sep 17 00:00:00 2001 From: Anand Chowdhary Date: Thu, 22 Oct 2020 23:15:55 +0530 Subject: [PATCH] :sparkles: Add resend email verification endpoint --- src/config/configuration.ts | 1 + src/modules/auth/auth.controller.ts | 10 +++++----- src/modules/auth/auth.dto.ts | 6 ++++++ src/modules/auth/auth.module.ts | 3 ++- src/modules/auth/auth.service.ts | 27 ++++++++++++++++++++++++++- 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/config/configuration.ts b/src/config/configuration.ts index c6514ac5c..bb441c20e 100644 --- a/src/config/configuration.ts +++ b/src/config/configuration.ts @@ -1,4 +1,5 @@ export default () => ({ + frontendUrl: process.env.FRONTEND_URL ?? 'http://localhost:3000', email: { name: process.env.EMAIL_NAME ?? 'Staart', from: process.env.EMAIL_FROM, diff --git a/src/modules/auth/auth.controller.ts b/src/modules/auth/auth.controller.ts index ae68c11d3..89c59443d 100644 --- a/src/modules/auth/auth.controller.ts +++ b/src/modules/auth/auth.controller.ts @@ -2,7 +2,7 @@ import { Body, Controller, Post } from '@nestjs/common'; import { users } from '@prisma/client'; import { RateLimit } from 'nestjs-rate-limiter'; import { OmitSecrets } from 'src/modules/prisma/prisma.interface'; -import { RegisterDto } from './auth.dto'; +import { RegisterDto, ResendEmailVerificationDto } from './auth.dto'; import { AuthService } from './auth.service'; @Controller('auth') @@ -21,11 +21,11 @@ export class AuthController { @Post('resend-email-verification') @RateLimit({ - points: 10, + points: 1, duration: 60, - errorMessage: 'Wait for 60 seconds before trying to create an account', + errorMessage: 'Wait for 60 seconds before requesting another email', }) - async resendVerify() { - return this.authService.resentEmailVerification(); + async resendVerify(@Body() data: ResendEmailVerificationDto) { + return this.authService.sendEmailVerification(data.email, true); } } diff --git a/src/modules/auth/auth.dto.ts b/src/modules/auth/auth.dto.ts index fae502c79..1b25f4409 100644 --- a/src/modules/auth/auth.dto.ts +++ b/src/modules/auth/auth.dto.ts @@ -74,3 +74,9 @@ export class RegisterDto { @IsOptional() attributes: Record; } + +export class ResendEmailVerificationDto { + @IsEmail() + @IsNotEmpty() + email: string; +} diff --git a/src/modules/auth/auth.module.ts b/src/modules/auth/auth.module.ts index 65fe86d34..280b955a3 100644 --- a/src/modules/auth/auth.module.ts +++ b/src/modules/auth/auth.module.ts @@ -1,4 +1,5 @@ import { Module } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; import { EmailModule } from '../email/email.module'; import { PrismaModule } from '../prisma/prisma.module'; import { UsersService } from '../user/user.service'; @@ -6,7 +7,7 @@ import { AuthController } from './auth.controller'; import { AuthService } from './auth.service'; @Module({ - imports: [PrismaModule, EmailModule], + imports: [PrismaModule, EmailModule, ConfigModule], controllers: [AuthController], providers: [AuthService, UsersService], }) diff --git a/src/modules/auth/auth.service.ts b/src/modules/auth/auth.service.ts index 2d3bd4e13..f821480c7 100644 --- a/src/modules/auth/auth.service.ts +++ b/src/modules/auth/auth.service.ts @@ -1,4 +1,5 @@ import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; import { users } from '@prisma/client'; import { EmailService } from '../email/email.service'; import { OmitSecrets } from '../prisma/prisma.interface'; @@ -12,6 +13,7 @@ export class AuthService { private prisma: PrismaService, private users: UsersService, private email: EmailService, + private configService: ConfigService, ) {} async register(data: RegisterDto): Promise> { @@ -37,10 +39,33 @@ export class AuthService { }, }, }); + await this.sendEmailVerification(email); return this.prisma.expose(user); } - async resentEmailVerification() { + async sendEmailVerification(email: string, resend = false) { + const emailSafe = this.users.getSafeEmail(email); + const emailDetails = await this.prisma.emails.findFirst({ + where: { emailSafe }, + include: { user: true }, + }); + if (!emailDetails) + throw new HttpException( + 'There is no user for this email', + HttpStatus.NOT_FOUND, + ); + this.email.send({ + to: `"${emailDetails.user.name}" <${email}>`, + template: resend + ? 'auth/resend-email-verification' + : 'auth/email-verification', + data: { + name: emailDetails.user.name, + link: `${this.configService.get( + 'frontendUrl', + )}/auth/verify-email?token=`, + }, + }); return { queued: true }; } }