From ada73a52b6ded5807103c65b0974cc70b405d001 Mon Sep 17 00:00:00 2001 From: Szasza Palmer Date: Tue, 24 Sep 2024 20:42:21 +1000 Subject: [PATCH] feature: Adding Secure Tracking API support --- lib/Classes/MailgunClient.ts | 4 + lib/Classes/SecureTracking.ts | 30 ++++++++ .../MailgunClient/IMailgunClient.ts | 2 + .../SecureTracking/ISecureTracking.ts | 11 +++ lib/Interfaces/SecureTracking/index.ts | 1 + lib/Interfaces/index.ts | 1 + lib/Types/SecureTracking/SecureTracking.ts | 15 ++++ lib/Types/SecureTracking/index.ts | 1 + lib/Types/index.ts | 1 + test/secure-tracking.test.ts | 74 +++++++++++++++++++ 10 files changed, 140 insertions(+) create mode 100644 lib/Classes/SecureTracking.ts create mode 100644 lib/Interfaces/SecureTracking/ISecureTracking.ts create mode 100644 lib/Interfaces/SecureTracking/index.ts create mode 100644 lib/Types/SecureTracking/SecureTracking.ts create mode 100644 lib/Types/SecureTracking/index.ts create mode 100644 test/secure-tracking.test.ts diff --git a/lib/Classes/MailgunClient.ts b/lib/Classes/MailgunClient.ts index 19a483e..c4dca23 100644 --- a/lib/Classes/MailgunClient.ts +++ b/lib/Classes/MailgunClient.ts @@ -19,6 +19,7 @@ import MultipleValidationClient from './Validations/multipleValidation'; import DomainTemplatesClient from './Domains/domainsTemplates'; import DomainTagsClient from './Domains/domainsTags'; import SubaccountsClient from './Subaccounts'; +import SecureTrackingClient from './SecureTracking'; import { IDomainsClient, @@ -34,6 +35,7 @@ import { IIPsClient, IIPPoolsClient, ISubaccountsClient, + ISecureTrackingClient, } from '../Interfaces'; export default class MailgunClient implements IMailgunClient { @@ -51,6 +53,7 @@ export default class MailgunClient implements IMailgunClient { public ip_pools: IIPPoolsClient; public lists: IMailingListsClient; public subaccounts: ISubaccountsClient; + public secure_tracking: ISecureTrackingClient; constructor(options: MailgunClientOptions, formData: InputFormData) { const config: RequestOptions = { ...options } as RequestOptions; @@ -92,6 +95,7 @@ export default class MailgunClient implements IMailgunClient { this.lists = new MailingListsClient(this.request, mailListsMembers); this.validate = new ValidateClient(this.request, multipleValidationClient); this.subaccounts = new SubaccountsClient(this.request); + this.secure_tracking = new SecureTrackingClient(this.request); } setSubaccount(subaccountId: string): void { diff --git a/lib/Classes/SecureTracking.ts b/lib/Classes/SecureTracking.ts new file mode 100644 index 0000000..461cfd1 --- /dev/null +++ b/lib/Classes/SecureTracking.ts @@ -0,0 +1,30 @@ +import { ISecureTrackingClient } from '../Interfaces'; +import { + GenerateSecureTrackingCertificateResponse, + GetSecureTrackingCertificateResponse, + RegenerateSecureTrackingCertificateResponse, +} from '../Types'; +import Request from './common/Request'; + +export default class SecureTrackingClient implements ISecureTrackingClient { + request: Request; + + constructor(request: Request) { + this.request = request; + } + + get(domain: string): Promise { + return this.request.get(`/v2/x509/${domain}/status`) + .then((response) => response.body); + } + + generate(domain: string): Promise { + return this.request.post(`/v2/x509/${domain}`) + .then((response) => response.body); + } + + regenerate(domain: string): Promise { + return this.request.put(`/v2/x509/${domain}`) + .then((response) => response.body); + } +} diff --git a/lib/Interfaces/MailgunClient/IMailgunClient.ts b/lib/Interfaces/MailgunClient/IMailgunClient.ts index 8b95e6c..401abee 100644 --- a/lib/Interfaces/MailgunClient/IMailgunClient.ts +++ b/lib/Interfaces/MailgunClient/IMailgunClient.ts @@ -11,6 +11,7 @@ import { IIPsClient } from '../IPs'; import { IIPPoolsClient } from '../IPPools'; import { IMailingListsClient } from '../MailingLists'; import { ISubaccountsClient } from '../Subaccounts'; +import { ISecureTrackingClient } from '../SecureTracking'; export interface IMailgunClient { domains: IDomainsClient; @@ -25,6 +26,7 @@ export interface IMailgunClient { ip_pools: IIPPoolsClient; lists: IMailingListsClient; subaccounts: ISubaccountsClient; + secure_tracking: ISecureTrackingClient; setSubaccount(subaccountId: string): void; resetSubaccount(): void; } diff --git a/lib/Interfaces/SecureTracking/ISecureTracking.ts b/lib/Interfaces/SecureTracking/ISecureTracking.ts new file mode 100644 index 0000000..ffb4bfe --- /dev/null +++ b/lib/Interfaces/SecureTracking/ISecureTracking.ts @@ -0,0 +1,11 @@ +import { + GenerateSecureTrackingCertificateResponse, + GetSecureTrackingCertificateResponse, + RegenerateSecureTrackingCertificateResponse, +} from '../../Types'; + +export interface ISecureTrackingClient { + get(domain: string): Promise + generate(domain: string): Promise + regenerate(domain: string): Promise +} diff --git a/lib/Interfaces/SecureTracking/index.ts b/lib/Interfaces/SecureTracking/index.ts new file mode 100644 index 0000000..0383813 --- /dev/null +++ b/lib/Interfaces/SecureTracking/index.ts @@ -0,0 +1 @@ +export * from './ISecureTracking'; diff --git a/lib/Interfaces/index.ts b/lib/Interfaces/index.ts index d328757..2995f63 100644 --- a/lib/Interfaces/index.ts +++ b/lib/Interfaces/index.ts @@ -12,3 +12,4 @@ export * from './Routes'; export * from './IPs'; export * from './IPPools'; export * from './Subaccounts'; +export * from './SecureTracking'; diff --git a/lib/Types/SecureTracking/SecureTracking.ts b/lib/Types/SecureTracking/SecureTracking.ts new file mode 100644 index 0000000..4ad51f4 --- /dev/null +++ b/lib/Types/SecureTracking/SecureTracking.ts @@ -0,0 +1,15 @@ +export type GetSecureTrackingCertificateResponse = { + status: string; + error: string; + certificate: string; +} + +export type GenerateSecureTrackingCertificateResponse = { + message: string; + location: string; +} + +export type RegenerateSecureTrackingCertificateResponse = { + message: string; + location: string; +} diff --git a/lib/Types/SecureTracking/index.ts b/lib/Types/SecureTracking/index.ts new file mode 100644 index 0000000..bfc41ad --- /dev/null +++ b/lib/Types/SecureTracking/index.ts @@ -0,0 +1 @@ +export * from './SecureTracking'; diff --git a/lib/Types/index.ts b/lib/Types/index.ts index 1a001e1..988afed 100644 --- a/lib/Types/index.ts +++ b/lib/Types/index.ts @@ -7,6 +7,7 @@ export * from './MailgunClient'; export * from './MailingLists'; export * from './Messages'; export * from './Routes'; +export * from './SecureTracking'; export * from './Stats'; export * from './Subaccounts'; export * from './Suppressions'; diff --git a/test/secure-tracking.test.ts b/test/secure-tracking.test.ts new file mode 100644 index 0000000..26e1c02 --- /dev/null +++ b/test/secure-tracking.test.ts @@ -0,0 +1,74 @@ +/* eslint-disable camelcase */ +import formData from 'form-data'; +import nock from 'nock'; +import { expect } from 'chai'; +import { ISecureTrackingClient } from '../lib/Interfaces'; +import Request from '../lib/Classes/common/Request'; +import SecureTrackingClient from '../lib/Classes/SecureTracking'; +import { InputFormData, RequestOptions } from '../lib/Types/Common'; +import { + GetSecureTrackingCertificateResponse, + GenerateSecureTrackingCertificateResponse, + RegenerateSecureTrackingCertificateResponse, +} from '../lib/Types/SecureTracking'; + +describe('SecureTrackingClient', function () { + let client: ISecureTrackingClient; + let api: nock.Scope; + let trackingDomain: string; + + beforeEach(function () { + client = new SecureTrackingClient(new Request({ url: 'https://api.mailgun.net' } as RequestOptions, formData as InputFormData)); + api = nock('https://api.mailgun.net'); + trackingDomain = 'email.testing.example.com'; + }); + + afterEach(function () { + api.done(); + }); + + describe('get', async () => { + it('fetches single secure tracking certificate by domain', async () => { + const data = { + status: 'expired', + error: 'x509 certificate has expired', + certificate: 'sample', + }; + + api.get(`/v2/x509/${trackingDomain}/status`).reply(200, data); + + const response: GetSecureTrackingCertificateResponse = await client.get(trackingDomain); + expect(response).eql(data); + }); + }); + + describe('generate', async () => { + it('generates a secure tracking certificate by domain', async () => { + const data = { + message: 'Initiated x509 key pair generation', + location: `/v2/x509/${trackingDomain}/status`, + }; + + api.post(`/v2/x509/${trackingDomain}`).reply(202, data); + + const response: GenerateSecureTrackingCertificateResponse = await client + .generate(trackingDomain); + expect(response).eql(data); + }); + }); + + describe('regenerate', async () => { + it('regenerates a secure tracking certificate by domain', async () => { + const data = { + message: 'Initiated x509 key pair generation', + location: `/v2/x509/${trackingDomain}/status`, + }; + + api.put(`/v2/x509/${trackingDomain}`).reply(202, data); + + const response: RegenerateSecureTrackingCertificateResponse = await client + .regenerate(trackingDomain); + expect(response).eql(data); + }); + }); +});