Skip to content

Commit

Permalink
COM-990: Allow configuration of redirect url (#65)
Browse files Browse the repository at this point in the history
* include allowedRedirectUrl in resolveConfig to allow configuration of redirectUrl for different scopes

* add changeset

* add scope type to IsValidRedirectUrl

* add check for scope in redirect-url validator

* correct changeset

* throw error when scope is not supported

* correct defaultMessage

---------

Co-authored-by: Julia Wegmayr <[email protected]>
  • Loading branch information
juliawegmayr and Julia Wegmayr authored Aug 6, 2024
1 parent d21db92 commit 6b5b9a4
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 12 deletions.
34 changes: 34 additions & 0 deletions .changeset/flat-ads-know.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
"@comet/brevo-api": major
---

The `allowedRedirectUrl` must now be configured within the resolveConfig for each specific scope, instead of being set once for all scopes in the brevo config.

```diff
BrevoModule.register({
brevo: {
resolveConfig: (scope: EmailCampaignContentScope) => {
// change config based on scope - for example different sender email
// this is just to show you can use the scope to change the config but it has no real use in this example
if (scope.domain === "main") {
return {
apiKey: config.brevo.apiKey,
doubleOptInTemplateId: config.brevo.doubleOptInTemplateId,
sender: { name: config.brevo.sender.name, email: config.brevo.sender.email },
+ allowedRedirectUrl: config.brevo.allowedRedirectUrl,
};
} else {
return {
apiKey: config.brevo.apiKey,
doubleOptInTemplateId: config.brevo.doubleOptInTemplateId,
sender: { name: config.brevo.sender.name, email: config.brevo.sender.email },
+ allowedRedirectUrl: config.brevo.allowedRedirectUrl,
};
}
},
BrevoContactAttributes,
BrevoContactFilterAttributes,
- allowedRedirectUrl: config.brevo.allowedRedirectUrl,
},
})
```
3 changes: 2 additions & 1 deletion demo/api/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,18 +145,19 @@ export class AppModule {
apiKey: config.brevo.apiKey,
doubleOptInTemplateId: config.brevo.doubleOptInTemplateId,
sender: { name: config.brevo.sender.name, email: config.brevo.sender.email },
allowedRedirectUrl: config.brevo.allowedRedirectUrl,
};
} else {
return {
apiKey: config.brevo.apiKey,
doubleOptInTemplateId: config.brevo.doubleOptInTemplateId,
sender: { name: config.brevo.sender.name, email: config.brevo.sender.email },
allowedRedirectUrl: config.brevo.allowedRedirectUrl,
};
}
},
BrevoContactAttributes,
BrevoContactFilterAttributes,
allowedRedirectUrl: config.brevo.allowedRedirectUrl,
},
ecgRtrList: {
apiKey: config.ecgRtrList.apiKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class BrevoContactSubscribeInput {
email: string;

@IsUrl({ require_tld: process.env.NODE_ENV === "production" })
@IsValidRedirectURL()
@IsValidRedirectURL(EmailContactSubscribeScope)
redirectionUrl: string;

@ValidateNested()
Expand Down
2 changes: 1 addition & 1 deletion packages/api/src/brevo-contact/brevo-contact.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export class BrevoContactModule {
static register({ BrevoContactAttributes, Scope, TargetGroup }: BrevoContactModuleConfig): DynamicModule {
const BrevoContact = BrevoContactFactory.create({ BrevoContactAttributes });
const BrevoContactSubscribeInput = SubscribeInputFactory.create({ BrevoContactAttributes, Scope });
const [BrevoContactInput, BrevoContactUpdateInput] = BrevoContactInputFactory.create({ BrevoContactAttributes });
const [BrevoContactInput, BrevoContactUpdateInput] = BrevoContactInputFactory.create({ BrevoContactAttributes, Scope });
const BrevoContactResolver = createBrevoContactResolver({
BrevoContact,
BrevoContactSubscribeInput,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Field, InputType } from "@nestjs/graphql";
import { Type as TypeTransformer } from "class-transformer";
import { IsBoolean, IsNotEmpty, IsOptional, IsString, IsUrl, ValidateNested } from "class-validator";

import { BrevoContactAttributesInterface } from "../../types";
import { BrevoContactAttributesInterface, EmailCampaignScopeInterface } from "../../types";
import { IsValidRedirectURL } from "../validator/redirect-url.validator";

export interface BrevoContactInputInterface {
Expand All @@ -22,8 +22,10 @@ export interface BrevoContactUpdateInputInterface {
export class BrevoContactInputFactory {
static create({
BrevoContactAttributes,
Scope,
}: {
BrevoContactAttributes?: Type<BrevoContactAttributesInterface>;
Scope: Type<EmailCampaignScopeInterface>;
}): [Type<BrevoContactInputInterface>, Type<Partial<BrevoContactUpdateInputInterface>>] {
@InputType({
isAbstract: true,
Expand All @@ -41,7 +43,7 @@ export class BrevoContactInputFactory {

@Field()
@IsUrl({ require_tld: process.env.NODE_ENV === "production" })
@IsValidRedirectURL()
@IsValidRedirectURL(Scope)
redirectionUrl: string;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class SubscribeInputFactory {

@Field()
@IsUrl({ require_tld: process.env.NODE_ENV === "production" })
@IsValidRedirectURL()
@IsValidRedirectURL(Scope)
redirectionUrl: string;
}

Expand Down
19 changes: 14 additions & 5 deletions packages/api/src/brevo-contact/validator/redirect-url.validator.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { Inject, Injectable } from "@nestjs/common";
import { registerDecorator, ValidationOptions, ValidatorConstraint, ValidatorConstraintInterface } from "class-validator";
import { registerDecorator, ValidationArguments, ValidationOptions, ValidatorConstraint, ValidatorConstraintInterface } from "class-validator";
import { EmailCampaignScopeInterface } from "src/types";

import { BrevoModuleConfig } from "../../config/brevo-module.config";
import { BREVO_MODULE_CONFIG } from "../../config/brevo-module.constants";

export const IsValidRedirectURL = (validationOptions?: ValidationOptions) => {
export const IsValidRedirectURL = (scope: EmailCampaignScopeInterface, validationOptions?: ValidationOptions) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (object: Record<string, any>, propertyName: string): void => {
registerDecorator({
target: object.constructor,
propertyName,
options: validationOptions,
validator: IsValidRedirectURLConstraint,
constraints: [],
constraints: [scope],
});
};
};
Expand All @@ -22,10 +23,18 @@ export const IsValidRedirectURL = (validationOptions?: ValidationOptions) => {
export class IsValidRedirectURLConstraint implements ValidatorConstraintInterface {
constructor(@Inject(BREVO_MODULE_CONFIG) private readonly config: BrevoModuleConfig) {}

async validate(urlToValidate: string): Promise<boolean> {
if (urlToValidate?.startsWith(this.config.brevo.allowedRedirectUrl)) {
async validate(urlToValidate: string, args: ValidationArguments): Promise<boolean> {
const [scope] = args.constraints;
const configForScope = this.config.brevo.resolveConfig(scope);

if (!configForScope) {
throw Error("Scope does not exist");
}

if (urlToValidate?.startsWith(configForScope.allowedRedirectUrl)) {
return true;
}

return false;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/api/src/config/brevo-module.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ export interface BrevoModuleConfig {
name: string;
email: string;
};
allowedRedirectUrl: string;
};
BrevoContactAttributes?: Type<BrevoContactAttributesInterface>;
BrevoContactFilterAttributes?: Type<BrevoContactFilterAttributesInterface>;
allowedRedirectUrl: string;
};
ecgRtrList: {
apiKey: string;
Expand Down

0 comments on commit 6b5b9a4

Please sign in to comment.