feat: event emitter added

This commit is contained in:
mirarifhasan
2024-05-20 23:20:27 +06:00
parent 1e860c3535
commit 742eca6d10
10 changed files with 16082 additions and 18273 deletions

View File

@@ -30,6 +30,7 @@
"@nestjs/common": "10.2.7",
"@nestjs/config": "3.1.1",
"@nestjs/core": "10.2.7",
"@nestjs/event-emitter": "2.0.4",
"@nestjs/graphql": "12.0.9",
"@nestjs/jwt": "10.1.1",
"@nestjs/passport": "10.0.2",

View File

@@ -19,7 +19,6 @@ import {
USER_IS_ADMIN,
USER_NOT_FOUND,
} from '../errors';
import { MailerService } from '../mailer/mailer.service';
import { InvitedUser } from './invited-user.model';
import { TeamService } from '../team/team.service';
import { TeamCollectionService } from '../team-collection/team-collection.service';
@@ -31,6 +30,8 @@ import { ShortcodeService } from 'src/shortcode/shortcode.service';
import { ConfigService } from '@nestjs/config';
import { OffsetPaginationArgs } from 'src/types/input-types.args';
import { UserDeletionResult } from 'src/user/user.model';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { Events } from 'src/types/EventEmitter';
@Injectable()
export class AdminService {
@@ -43,9 +44,9 @@ export class AdminService {
private readonly teamInvitationService: TeamInvitationService,
private readonly pubsub: PubSubService,
private readonly prisma: PrismaService,
private readonly mailerService: MailerService,
private readonly shortcodeService: ShortcodeService,
private readonly configService: ConfigService,
private readonly eventEmitter: EventEmitter2,
) {}
/**
@@ -99,17 +100,16 @@ export class AdminService {
});
if (alreadyInvitedUser != null) return E.left(USER_ALREADY_INVITED);
try {
await this.mailerService.sendUserInvitationEmail(inviteeEmail, {
this.eventEmitter.emit(Events.MAILER_SEND_USER_INVITATION_EMAIL, {
to: inviteeEmail,
mailDesc: {
template: 'user-invitation',
variables: {
inviteeEmail: inviteeEmail,
magicLink: `${this.configService.get('VITE_BASE_URL')}`,
},
});
} catch (e) {
return E.left(EMAIL_FAILED);
}
},
});
// Add invitee email to the list of invited users by admin
const dbInvitedUser = await this.prisma.invitedUsers.create({

View File

@@ -27,9 +27,11 @@ import { MailerModule } from './mailer/mailer.module';
import { PosthogModule } from './posthog/posthog.module';
import { ScheduleModule } from '@nestjs/schedule';
import { HealthModule } from './health/health.module';
import { EventEmitterModule } from '@nestjs/event-emitter';
@Module({
imports: [
EventEmitterModule.forRoot(),
ConfigModule.forRoot({
isGlobal: true,
load: [async () => loadInfraConfiguration()],

View File

@@ -1,5 +1,4 @@
import { HttpStatus, Injectable } from '@nestjs/common';
import { MailerService } from 'src/mailer/mailer.service';
import { PrismaService } from 'src/prisma/prisma.service';
import { UserService } from 'src/user/user.service';
import { VerifyMagicDto } from './dto/verify-magic.dto';
@@ -30,6 +29,8 @@ import { VerificationToken } from '@prisma/client';
import { Origin } from './helper';
import { ConfigService } from '@nestjs/config';
import { InfraConfigService } from 'src/infra-config/infra-config.service';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { Events } from 'src/types/EventEmitter';
@Injectable()
export class AuthService {
@@ -37,9 +38,9 @@ export class AuthService {
private usersService: UserService,
private prismaService: PrismaService,
private jwtService: JwtService,
private readonly mailerService: MailerService,
private readonly configService: ConfigService,
private infraConfigService: InfraConfigService,
private eventEmitter: EventEmitter2,
) {}
/**
@@ -234,11 +235,14 @@ export class AuthService {
url = this.configService.get('VITE_BASE_URL');
}
await this.mailerService.sendEmail(email, {
template: 'user-invitation',
variables: {
inviteeEmail: email,
magicLink: `${url}/enter?token=${generatedTokens.token}`,
this.eventEmitter.emit(Events.MAILER_SEND_EMAIL, {
to: email,
mailDesc: {
template: 'user-invitation',
variables: {
inviteeEmail: email,
magicLink: `${url}/enter?token=${generatedTokens.token}`,
},
},
});

View File

@@ -0,0 +1,30 @@
import { Injectable } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';
import { Events } from 'src/types/EventEmitter';
import {
AdminUserInvitationMailDescription,
MailDescription,
UserMagicLinkMailDescription,
} from './MailDescriptions';
import { MailerService } from './mailer.service';
@Injectable()
export class MailerEventListener {
constructor(private mailerService: MailerService) {}
@OnEvent(Events.MAILER_SEND_EMAIL, { async: true })
async handleSendEmailEvent(data: {
to: string;
mailDesc: MailDescription | UserMagicLinkMailDescription;
}) {
await this.mailerService.sendEmail(data.to, data.mailDesc);
}
@OnEvent(Events.MAILER_SEND_USER_INVITATION_EMAIL, { async: true })
async handleSendUserInvitationEmailEvent(data: {
to: string;
mailDesc: AdminUserInvitationMailDescription;
}) {
await this.mailerService.sendUserInvitationEmail(data.to, data.mailDesc);
}
}

View File

@@ -9,17 +9,21 @@ import {
} from 'src/errors';
import { ConfigService } from '@nestjs/config';
import { loadInfraConfiguration } from 'src/infra-config/helper';
import { MailerEventListener } from './mailer.listener';
@Global()
@Module({
imports: [],
providers: [MailerService],
exports: [MailerService],
})
@Module({})
export class MailerModule {
static async register() {
const env = await loadInfraConfiguration();
// If mailer SMTP is DISABLED, return the module without any configuration
if (env.INFRA.MAILER_SMTP_ENABLE !== 'true') {
console.log('Mailer SMTP is disabled');
return { module: MailerModule };
}
// If mailer is ENABLED, return the module with configuration
let mailerSmtpUrl = env.INFRA.MAILER_SMTP_URL;
let mailerAddressFrom = env.INFRA.MAILER_ADDRESS_FROM;
@@ -31,6 +35,7 @@ export class MailerModule {
return {
module: MailerModule,
providers: [MailerService, MailerEventListener],
imports: [
NestMailerModule.forRoot({
transport: mailerSmtpUrl ?? throwErr(MAILER_SMTP_URL_UNDEFINED),

View File

@@ -7,10 +7,14 @@ import {
import { throwErr } from 'src/utils';
import { EMAIL_FAILED } from 'src/errors';
import { MailerService as NestMailerService } from '@nestjs-modules/mailer';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class MailerService {
constructor(private readonly nestMailerService: NestMailerService) {}
constructor(
private readonly nestMailerService: NestMailerService,
private readonly configService: ConfigService,
) {}
/**
* Takes an input mail description and spits out the Email subject required for it
@@ -42,6 +46,8 @@ export class MailerService {
to: string,
mailDesc: MailDescription | UserMagicLinkMailDescription,
) {
if (this.configService.get('INFRA.MAILER_SMTP_ENABLE') !== 'true') return;
try {
await this.nestMailerService.sendMail({
to,
@@ -64,6 +70,8 @@ export class MailerService {
to: string,
mailDesc: AdminUserInvitationMailDescription,
) {
if (this.configService.get('INFRA.MAILER_SMTP_ENABLE') !== 'true') return;
try {
const res = await this.nestMailerService.sendMail({
to,

View File

@@ -15,12 +15,13 @@ import {
TEAM_MEMBER_NOT_FOUND,
} from 'src/errors';
import { TeamInvitation } from './team-invitation.model';
import { MailerService } from 'src/mailer/mailer.service';
import { UserService } from 'src/user/user.service';
import { PubSubService } from 'src/pubsub/pubsub.service';
import { validateEmail } from '../utils';
import { AuthUser } from 'src/types/AuthUser';
import { ConfigService } from '@nestjs/config';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { Events } from 'src/types/EventEmitter';
@Injectable()
export class TeamInvitationService {
@@ -28,9 +29,9 @@ export class TeamInvitationService {
private readonly prisma: PrismaService,
private readonly userService: UserService,
private readonly teamService: TeamService,
private readonly mailerService: MailerService,
private readonly pubsub: PubSubService,
private readonly configService: ConfigService,
private eventEmitter: EventEmitter2,
) {}
/**
@@ -147,14 +148,17 @@ export class TeamInvitationService {
},
});
await this.mailerService.sendEmail(inviteeEmail, {
template: 'team-invitation',
variables: {
invitee: creator.displayName ?? 'A Hoppscotch User',
action_url: `${this.configService.get('VITE_BASE_URL')}/join-team?id=${
dbInvitation.id
}`,
invite_team_name: team.name,
this.eventEmitter.emit(Events.MAILER_SEND_EMAIL, {
to: inviteeEmail,
mailDesc: {
template: 'team-invitation',
variables: {
invitee: creator.displayName ?? 'A Hoppscotch User',
action_url: `${this.configService.get(
'VITE_BASE_URL',
)}/join-team?id=${dbInvitation.id}`,
invite_team_name: team.name,
},
},
});

View File

@@ -0,0 +1,4 @@
export enum Events {
MAILER_SEND_EMAIL = 'mailer.sendEmail',
MAILER_SEND_USER_INVITATION_EMAIL = 'mailer.sendUserInvitationEmail',
}

34235
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff