diff --git a/src/infra/mail/mail.service.ts b/src/infra/mail/mail.service.ts index 1358f54..b5dc95d 100644 --- a/src/infra/mail/mail.service.ts +++ b/src/infra/mail/mail.service.ts @@ -19,4 +19,13 @@ export class MailService { html }) } + + public async sendEmailChange(email: string, code: string) { + const html = this.templateService.render('email-change', { code }) + await this.transporter.sendMail({ + to: email, + subject: 'Подтверждение смены почты', + html + }) + } } diff --git a/src/infra/mail/templates/email-change.hbs b/src/infra/mail/templates/email-change.hbs new file mode 100644 index 0000000..ecdb205 --- /dev/null +++ b/src/infra/mail/templates/email-change.hbs @@ -0,0 +1,14 @@ + + +
+ + + +Ваш код подтверждения для смены почты: {{code}}
+ + diff --git a/src/modules/notifications/notifications.controller.ts b/src/modules/notifications/notifications.controller.ts index cf18a9e..d933d2d 100644 --- a/src/modules/notifications/notifications.controller.ts +++ b/src/modules/notifications/notifications.controller.ts @@ -1,6 +1,10 @@ -import { Controller } from '@nestjs/common' +import { Controller, Logger } from '@nestjs/common' import { Ctx, EventPattern, Payload, RmqContext } from '@nestjs/microservices' -import type { OtpRequestedEvent } from '@teacinema/contracts' +import type { + EmailChangedEvent, + OtpRequestedEvent, + PhoneChangedEvent +} from '@teacinema/contracts' import { RmqService } from '../../infra/rmq/rmq.service' @@ -8,6 +12,8 @@ import { NotificationsService } from './notifications.service' @Controller() export class NotificationsController { + private readonly logger = new Logger(NotificationsController.name) + constructor( private readonly notificationsService: NotificationsService, private readonly rmqService: RmqService @@ -22,7 +28,35 @@ export class NotificationsController { await this.notificationsService.sendOtp(data) this.rmqService.ack(ctx) } catch (e) { - console.log('OTP processing error', e.message ?? e) + this.logger.error(`OTP processing error ${e.message ?? e}}`) + this.rmqService.nack(ctx) + } + } + + @EventPattern('account.phone.changed') + public async phoneChangedRequested( + @Payload() data: PhoneChangedEvent, + @Ctx() ctx: RmqContext + ) { + try { + await this.notificationsService.phoneChanged(data) + this.rmqService.ack(ctx) + } catch (e) { + this.logger.error(`Phone changing processing error ${e.message ?? e}}`) + this.rmqService.nack(ctx) + } + } + + @EventPattern('account.email.changed') + public async emaileChangedRequested( + @Payload() data: EmailChangedEvent, + @Ctx() ctx: RmqContext + ) { + try { + await this.notificationsService.emailChanged(data) + this.rmqService.ack(ctx) + } catch (e) { + this.logger.error(`Email changing processing error ${e.message ?? e}}`) this.rmqService.nack(ctx) } } diff --git a/src/modules/notifications/notifications.service.ts b/src/modules/notifications/notifications.service.ts index 537f95e..12f6c20 100644 --- a/src/modules/notifications/notifications.service.ts +++ b/src/modules/notifications/notifications.service.ts @@ -1,20 +1,51 @@ -import { Injectable } from '@nestjs/common' -import { OtpRequestedEvent } from '@teacinema/contracts' +import { Injectable, Logger } from '@nestjs/common' +import { + EmailChangedEvent, + OtpRequestedEvent, + PhoneChangedEvent +} from '@teacinema/contracts' import { MailService } from '../../infra/mail/mail.service' +import { SmsService } from '../../infra/sms/sms.service' @Injectable() export class NotificationsService { - constructor(private readonly mailService: MailService) {} + private readonly logger = new Logger(NotificationsService.name) + + constructor( + private readonly mailService: MailService, + private readonly smsService: SmsService + ) {} public async sendOtp(data: OtpRequestedEvent) { const { identifier, type, code } = data - if (type === 'email') { - console.log('SEND EMAIL', data) - await this.mailService.sendOtp(identifier, code) - } else { - console.log('SMS') + this.logger.log(`Send OTP to ${identifier} via ${type}`) + + switch (type) { + case 'email': + await this.mailService.sendOtp(identifier, code) + break + case 'phone': + await this.smsService.sendOtp(identifier, code) + break + default: + this.logger.error(`Unknown notification type: ${type}`) + throw new Error(`Unknown type: ${type}`) } } + + public async phoneChanged(data: PhoneChangedEvent) { + const { phone, code } = data + + this.logger.log(`Change phone to ${phone} via phone`) + return await this.smsService.sendPhoneChanged(phone, code) + } + + public async emailChanged(data: EmailChangedEvent) { + const { email, code } = data + + this.logger.log(`Change email to ${email} via email`) + return await this.mailService.sendEmailChange(email, code) + } }