Skip to content

Commit

Permalink
fix(api-service): Remove team member invitation nudge logic (#7397)
Browse files Browse the repository at this point in the history
  • Loading branch information
SokratisVidros authored Dec 27, 2024
1 parent 5fa6d4a commit 9d20fb8
Show file tree
Hide file tree
Showing 6 changed files with 2 additions and 222 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,6 @@ export class ParseEventRequest {
// eslint-disable-next-line no-param-reassign
command.payload = merge({}, defaultPayload, command.payload);

await this.sendInAppNudgeForTeamMemberInvite(command);

return await this.dispatchEvent(command, transactionId);
}

Expand Down Expand Up @@ -308,113 +306,4 @@ export class ParseEventRequest {

return reservedVariables?.map((reservedVariable) => reservedVariable.type) || [];
}

@Instrument()
@CachedEntity({
builder: (command: ParseEventRequestCommand) =>
buildHasNotificationKey({
_organizationId: command.organizationId,
}),
})
private async getNotificationCount(command: ParseEventRequestCommand): Promise<number> {
return await this.notificationRepository.count(
{
_organizationId: command.organizationId,
},
1
);
}

@Instrument()
private async sendInAppNudgeForTeamMemberInvite(command: ParseEventRequestCommand): Promise<void> {
try {
const isEnabled = await this.getFeatureFlag.execute(
GetFeatureFlagCommand.create({
key: FeatureFlagsKeysEnum.IS_TEAM_MEMBER_INVITE_NUDGE_ENABLED,
organizationId: command.organizationId,
userId: 'system',
environmentId: 'system',
})
);

if (!isEnabled) return;

// check if this is first trigger
const notificationCount = await this.getNotificationCount(command);

if (notificationCount > 0) return;

/*
* After the first trigger, we invalidate the cache to ensure the next event trigger
* will update the cache with a count of 1.
*/
this.invalidateCacheService.invalidateByKey({
key: buildHasNotificationKey({
_organizationId: command.organizationId,
}),
});

// check if user is using personal email
const user = await this.userRepository.findById(command.userId);

if (!user) throw new ApiException('User not found');

if (this.isBlockedEmail(user.email)) return;

// check if organization has more than 1 member
const membersCount = await this.memberRepository.count(
{
_organizationId: command.organizationId,
},
2
);

if (membersCount > 1) return;

Logger.log('No notification found', LOG_CONTEXT);

if (process.env.NOVU_API_KEY) {
if (!command.payload[INVITE_TEAM_MEMBER_NUDGE_PAYLOAD_KEY]) {
const novu = new Novu({ apiKey: process.env.NOVU_API_KEY });

await novu.trigger({
name: process.env.NOVU_INVITE_TEAM_MEMBER_NUDGE_TRIGGER_IDENTIFIER,
to: [
{
subscriberId: command.userId,
email: user?.email as string,
},
],
payload: {
[INVITE_TEAM_MEMBER_NUDGE_PAYLOAD_KEY]: true,
webhookUrl: `${process.env.API_ROOT_URL}/v1/invites/webhook`,
organizationId: command.organizationId,
},
});

this.analyticsService.track('Invite Nudge Sent', command.userId, {
_organization: command.organizationId,
});
}
}
} catch (error) {
Logger.error(error, 'Invite nudge failed', LOG_CONTEXT);
}
}

private isBlockedEmail(email: string): boolean {
return BLOCKED_DOMAINS.some((domain) => email.includes(domain));
}
}

const BLOCKED_DOMAINS = [
'@gmail',
'@outlook',
'@yahoo',
'@icloud',
'@mail',
'@hotmail',
'@protonmail',
'@gmx',
'@novu',
];
16 changes: 1 addition & 15 deletions apps/api/src/app/invites/invites.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ import { ResendInviteCommand } from './usecases/resend-invite/resend-invite.comm
import { ResendInvite } from './usecases/resend-invite/resend-invite.usecase';
import { ThrottlerCost } from '../rate-limiting/guards';
import { ApiCommonResponses } from '../shared/framework/response.decorator';
import { InviteNudgeWebhookCommand } from './usecases/invite-nudge/invite-nudge.command';
import { InviteNudgeWebhook } from './usecases/invite-nudge/invite-nudge.usecase';
import { UserAuthentication } from '../shared/framework/swagger/api.key.security';

@UseInterceptors(ClassSerializerInterceptor)
Expand All @@ -47,8 +45,7 @@ export class InvitesController {
private bulkInviteUsecase: BulkInvite,
private acceptInviteUsecase: AcceptInvite,
private getInvite: GetInvite,
private resendInviteUsecase: ResendInvite,
private inviteNudgeWebhookUsecase: InviteNudgeWebhook
private resendInviteUsecase: ResendInvite
) {}

@Get('/:inviteToken')
Expand Down Expand Up @@ -130,15 +127,4 @@ export class InvitesController {

return response;
}

@Post('/webhook')
async inviteCheckWebhook(@Headers('nv-hmac-256') hmacHeader: string, @Body() body: InviteWebhookDto) {
const command = InviteNudgeWebhookCommand.create({
hmacHeader,
subscriber: body.subscriber,
organizationId: body.payload.organizationId,
});

return await this.inviteNudgeWebhookUsecase.execute(command);
}
}
3 changes: 1 addition & 2 deletions apps/api/src/app/invites/usecases/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@ import { GetInvite } from './get-invite/get-invite.usecase';
import { BulkInvite } from './bulk-invite/bulk-invite.usecase';
import { InviteMember } from './invite-member/invite-member.usecase';
import { ResendInvite } from './resend-invite/resend-invite.usecase';
import { InviteNudgeWebhook } from './invite-nudge/invite-nudge.usecase';

export const USE_CASES = [AcceptInvite, GetInvite, BulkInvite, InviteMember, ResendInvite, InviteNudgeWebhook];
export const USE_CASES = [AcceptInvite, GetInvite, BulkInvite, InviteMember, ResendInvite];

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,7 @@ export class MarkMessageAs {
$in: command.messageIds,
},
});
const isEnabled = await this.getFeatureFlag.execute(
GetFeatureFlagCommand.create({
key: FeatureFlagsKeysEnum.IS_TEAM_MEMBER_INVITE_NUDGE_ENABLED,
organizationId: command.organizationId,
userId: 'system',
environmentId: 'system',
})
);
if (command.mark.seen != null) {
if (isEnabled && (process.env.NODE_ENV === 'dev' || process.env.NODE_ENV === 'production')) {
await this.sendAnalyticsEventForInviteTeamNudge(messages);
}
await this.updateServices(command, subscriber, messages, MarkEnum.SEEN);
}

Expand Down

0 comments on commit 9d20fb8

Please sign in to comment.