diff --git a/backend/src/modules/auth-module/auth.module.ts b/backend/src/modules/auth-module/auth.module.ts index dab6e0f..2d14cd7 100644 --- a/backend/src/modules/auth-module/auth.module.ts +++ b/backend/src/modules/auth-module/auth.module.ts @@ -3,6 +3,7 @@ import { JwtModule } from '@nestjs/jwt'; import { TypeOrmModule } from '@nestjs/typeorm'; import { UserCredentials } from 'src/entities'; +import { SendgridModule } from '../sendgrid-module/sendgrid.module'; import { UserModule } from '../user-module/user.module'; import { AuthController } from './controller/auth.controller'; @@ -15,6 +16,7 @@ import { AccessTokenStrategy, RefreshTokenStrategy } from './strategies'; @Module({ imports: [ UserModule, + SendgridModule, JwtModule.register({}), TypeOrmModule.forFeature([UserCredentials]), ], diff --git a/backend/src/modules/auth-module/services/auth.service.ts b/backend/src/modules/auth-module/services/auth.service.ts index 9416bba..fec3d69 100644 --- a/backend/src/modules/auth-module/services/auth.service.ts +++ b/backend/src/modules/auth-module/services/auth.service.ts @@ -1,5 +1,6 @@ import { ForbiddenException, Injectable } from '@nestjs/common'; +import { PasswordConfirmationMailService } from '../../sendgrid-module/services/password-confirmation.mail.service'; import { UserDataRepository } from '../../user-module/repositories/user-data.repository'; import { TokensDto, UserCredentialsDto } from '../models/dto'; import { UserCredentialsRepository } from '../repositories/user-credentials.repository'; @@ -13,7 +14,8 @@ export class AuthService { private readonly userCredentialsRepository: UserCredentialsRepository, private readonly userDataRepository: UserDataRepository, private readonly tokenManagementService: TokenManagementService, - private readonly encryptionService: EncryptionService + private readonly encryptionService: EncryptionService, + private readonly passwordConfirmationMailService: PasswordConfirmationMailService ) {} public async signup(userCredentials: UserCredentialsDto): Promise { @@ -27,6 +29,11 @@ export class AuthService { await this.userDataRepository.createInitialUserData(user); + // TODO Send email confirmation + // await this.passwordConfirmationMailService.sendPasswordConfirmationMail( + // user.email + // ); + return this.generateAndPersistTokens(user.id, user.email); } diff --git a/backend/src/modules/sendgrid-module/sendgrid.module.ts b/backend/src/modules/sendgrid-module/sendgrid.module.ts index 1c0a2f9..feadf31 100644 --- a/backend/src/modules/sendgrid-module/sendgrid.module.ts +++ b/backend/src/modules/sendgrid-module/sendgrid.module.ts @@ -1,20 +1,22 @@ import { Module } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; -import { MailService } from './services/mail.service'; +import { PasswordConfirmationMailService } from './services/password-confirmation.mail.service'; +import { TemplateConfigService } from './services/template-config.service'; @Module({ imports: [ConfigModule], providers: [ - MailService, { provide: 'SEND_GRID_API_KEY', useFactory: (configService: ConfigService): string => configService.get('SEND_GRID_API_KEY'), inject: [ConfigService], }, + PasswordConfirmationMailService, + TemplateConfigService, ], controllers: [], - exports: [MailService], + exports: [PasswordConfirmationMailService], }) export class SendgridModule {} diff --git a/backend/src/modules/sendgrid-module/services/base.mail.service.ts b/backend/src/modules/sendgrid-module/services/base.mail.service.ts new file mode 100644 index 0000000..3aac170 --- /dev/null +++ b/backend/src/modules/sendgrid-module/services/base.mail.service.ts @@ -0,0 +1,19 @@ +import { Inject, Injectable } from '@nestjs/common'; +import * as SendGridMailApi from '@sendgrid/mail'; + +// API: https://www.twilio.com/docs/sendgrid/api-reference/mail-send/mail-send#request-body + +@Injectable() +export abstract class BaseMailService { + public constructor( + @Inject('SEND_GRID_API_KEY') protected readonly sendGridApiKey: string + ) { + SendGridMailApi.setApiKey(this.sendGridApiKey); + } + + protected async sendMail( + mailOptions: SendGridMailApi.MailDataRequired + ): Promise<[SendGridMailApi.ClientResponse, object]> { + return SendGridMailApi.send(mailOptions); + } +} diff --git a/backend/src/modules/sendgrid-module/services/mail.service.ts b/backend/src/modules/sendgrid-module/services/mail.service.ts deleted file mode 100644 index 37aa601..0000000 --- a/backend/src/modules/sendgrid-module/services/mail.service.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import * as SendGridMailApi from '@sendgrid/mail'; - -@Injectable() -export class MailService { - public constructor( - @Inject('SEND_GRID_API_KEY') private readonly apiKey: string - ) { - SendGridMailApi.setApiKey(this.apiKey); - } -} diff --git a/backend/src/modules/sendgrid-module/services/password-confirmation.mail.service.ts b/backend/src/modules/sendgrid-module/services/password-confirmation.mail.service.ts new file mode 100644 index 0000000..53af5aa --- /dev/null +++ b/backend/src/modules/sendgrid-module/services/password-confirmation.mail.service.ts @@ -0,0 +1,36 @@ +import { Inject, Injectable } from '@nestjs/common'; +import * as SendGridMailApi from '@sendgrid/mail'; + +import { BaseMailService } from './base.mail.service'; +import { TemplateConfigService } from './template-config.service'; + +@Injectable() +export class PasswordConfirmationMailService extends BaseMailService { + private readonly PASSWORD_CONFIRMATION_EMAIL: string = + 'PASSWORD_CONFIRMATION_EMAIL'; + + public constructor( + @Inject('SEND_GRID_API_KEY') protected readonly sendGridApiKey: string, + private readonly templateConfigService: TemplateConfigService + ) { + super(sendGridApiKey); + } + + public async sendPasswordConfirmationMail(to: string): Promise { + const templateId: string = this.templateConfigService.getTemplateId( + this.PASSWORD_CONFIRMATION_EMAIL + ); + + const mailoptions: SendGridMailApi.MailDataRequired = { + to, + from: { email: 'info@igor-propisnov.com', name: 'Ticket App' }, + templateId: templateId, + dynamicTemplateData: { + name: 'Mara', + buttonUrl: 'https://igor-propisnov.com', + }, + }; + + await this.sendMail(mailoptions); + } +} diff --git a/backend/src/modules/sendgrid-module/services/template-config.service.ts b/backend/src/modules/sendgrid-module/services/template-config.service.ts new file mode 100644 index 0000000..1328f2e --- /dev/null +++ b/backend/src/modules/sendgrid-module/services/template-config.service.ts @@ -0,0 +1,11 @@ +import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; + +@Injectable() +export class TemplateConfigService { + public constructor(private configService: ConfigService) {} + + public getTemplateId(key: string): string { + return this.configService.get(`SENDGRID_TEMPLATE_${key}`); + } +}