Skip to content

Commit

Permalink
Add check for valid folderId (#269)
Browse files Browse the repository at this point in the history
  • Loading branch information
juliawegmayr authored Feb 17, 2025
1 parent c15195c commit 53d8f20
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 2 deletions.
47 changes: 47 additions & 0 deletions packages/api/src/brevo-api/brevo-api-folders.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as Brevo from "@getbrevo/brevo";
import { Inject, Injectable } from "@nestjs/common";
import { EmailCampaignScopeInterface } from "src/types";

import { BrevoModuleConfig } from "../config/brevo-module.config";
import { BREVO_MODULE_CONFIG } from "../config/brevo-module.constants";
import { handleBrevoError } from "./brevo-api.utils";
import { BrevoApiFolder } from "./dto/brevo-api-folder";

@Injectable()
export class BrevoApiFoldersService {
private readonly contactsApi: Brevo.ContactsApi;

constructor(@Inject(BREVO_MODULE_CONFIG) private readonly config: BrevoModuleConfig) {
this.contactsApi = new Brevo.ContactsApi();
}

async *getAllBrevoFolders(scope: EmailCampaignScopeInterface): AsyncGenerator<BrevoApiFolder, void, undefined> {
const apiKey = this.config.brevo.resolveConfig(scope).apiKey;
this.contactsApi.setApiKey(Brevo.ContactsApiApiKeys.apiKey, apiKey);

// Limit set by Brevo
const limit = 50;
let offset = 0;

while (true) {
try {
const { response, body } = await this.contactsApi.getFolders(limit, offset);

if (response.statusCode !== 200) {
throw new Error("Failed to get folders");
}

const folders = body.folders ?? [];
if (folders.length === 0) {
break;
}

yield* folders;

offset += limit;
} catch (error) {
handleBrevoError(error);
}
}
}
}
5 changes: 3 additions & 2 deletions packages/api/src/brevo-api/brevo-api.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import { Module } from "@nestjs/common";
import { ConfigModule } from "../config/config.module";
import { BrevoApiCampaignsService } from "./brevo-api-campaigns.service";
import { BrevoApiContactsService } from "./brevo-api-contact.service";
import { BrevoApiFoldersService } from "./brevo-api-folders.service";
import { BrevoApiSenderService } from "./brevo-api-sender.service";
import { BrevoTransactionalMailsService } from "./brevo-api-transactional-mails.service";

@Module({
imports: [ConfigModule, CacheModule.register({ ttl: 1000 * 60 }), MikroOrmModule.forFeature(["BrevoConfig"])],
providers: [BrevoApiContactsService, BrevoApiCampaignsService, BrevoTransactionalMailsService, BrevoApiSenderService],
exports: [BrevoApiContactsService, BrevoApiCampaignsService, BrevoTransactionalMailsService, BrevoApiSenderService],
providers: [BrevoApiContactsService, BrevoApiCampaignsService, BrevoTransactionalMailsService, BrevoApiSenderService, BrevoApiFoldersService],
exports: [BrevoApiContactsService, BrevoApiCampaignsService, BrevoTransactionalMailsService, BrevoApiSenderService, BrevoApiFoldersService],
})
export class BrevoApiModule {}
10 changes: 10 additions & 0 deletions packages/api/src/brevo-api/dto/brevo-api-folder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Field, ID, ObjectType } from "@nestjs/graphql";

@ObjectType()
export class BrevoApiFolder {
@Field(() => ID)
id: number;

@Field(() => String)
name: string;
}
21 changes: 21 additions & 0 deletions packages/api/src/brevo-config/brevo-config.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { InjectRepository } from "@mikro-orm/nestjs";
import { Type } from "@nestjs/common";
import { Args, ID, Mutation, Query, Resolver } from "@nestjs/graphql";

import { BrevoApiFoldersService } from "../brevo-api/brevo-api-folders.service";
import { BrevoApiSenderService } from "../brevo-api/brevo-api-sender.service";
import { BrevoTransactionalMailsService } from "../brevo-api/brevo-api-transactional-mails.service";
import { BrevoApiEmailTemplate } from "../brevo-api/dto/brevo-api-email-templates-list";
Expand All @@ -26,6 +27,7 @@ export function createBrevoConfigResolver({
constructor(
private readonly entityManager: EntityManager,
private readonly brevoSenderApiService: BrevoApiSenderService,
private readonly brevoFolderIdService: BrevoApiFoldersService,
private readonly brevoTransactionalEmailsApiService: BrevoTransactionalMailsService,
@InjectRepository(BrevoConfig) private readonly repository: EntityRepository<BrevoConfigInterface>,
) {}
Expand All @@ -50,6 +52,15 @@ export function createBrevoConfigResolver({
return false;
}

private async isValidFolderId({ folderId }: { folderId: number }): Promise<boolean> {
for await (const folder of this.brevoFolderIdService.getAllBrevoFolders(Scope)) {
if (folder.id === folderId) {
return true;
}
}
return false;
}

@RequiredPermission(["brevo-newsletter-config"], { skipScopeCheck: true })
@Query(() => [BrevoApiSender], { nullable: true })
async senders(
Expand Down Expand Up @@ -91,6 +102,10 @@ export function createBrevoConfigResolver({
throw new Error("Template ID is not valid. ");
}

if (!(await this.isValidFolderId({ folderId: input.folderId }))) {
throw new Error("Folder ID is not valid. ");
}

const brevoConfig = this.repository.create({
...input,
scope,
Expand Down Expand Up @@ -121,6 +136,12 @@ export function createBrevoConfigResolver({
}
}

if (input.folderId) {
if (!(await this.isValidFolderId({ folderId: input.folderId }))) {
throw new Error("Folder ID is not valid. ");
}
}

if (lastUpdatedAt) {
validateNotModified(brevoConfig, lastUpdatedAt);
}
Expand Down

0 comments on commit 53d8f20

Please sign in to comment.