feat: event emitter added
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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()],
|
||||
|
||||
@@ -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}`,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
30
packages/hoppscotch-backend/src/mailer/mailer.listener.ts
Normal file
30
packages/hoppscotch-backend/src/mailer/mailer.listener.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
4
packages/hoppscotch-backend/src/types/EventEmitter.ts
Normal file
4
packages/hoppscotch-backend/src/types/EventEmitter.ts
Normal 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
34235
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user