diff --git a/src/admin-portal/admin-portal.spec.ts b/src/admin-portal/admin-portal.spec.ts new file mode 100644 index 000000000..921bf1a24 --- /dev/null +++ b/src/admin-portal/admin-portal.spec.ts @@ -0,0 +1,203 @@ +import fetch from 'jest-fetch-mock'; +import { fetchBody, fetchOnce } from '../common/utils/test-utils'; +import { WorkOS } from '../workos'; +import portalLinkResponse from './fixtures/portal-link-response.fixture.json'; +import generateLinkInvalid from './fixtures/generate-link-invalid.fixture.json'; + +const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); + +describe('AdminPortal', () => { + beforeEach(() => fetch.resetMocks()); + + describe('generateLink', () => { + describe('with the sso intent', () => { + it('returns an Admin Portal link', async () => { + fetchOnce(portalLinkResponse, { status: 201 }); + + const { link } = await workos.adminPortal.generateLink({ + intent: 'sso', + organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', + returnUrl: 'https://www.example.com', + }); + + expect(fetchBody()).toEqual({ + intent: 'sso', + organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', + return_url: 'https://www.example.com', + }); + expect(link).toBeDefined(); + }); + }); + + describe('with the dsync intent', () => { + it('returns an Admin Portal link', async () => { + fetchOnce(portalLinkResponse, { status: 201 }); + + const { link } = await workos.adminPortal.generateLink({ + intent: 'dsync', + organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', + returnUrl: 'https://www.example.com', + }); + + expect(fetchBody()).toEqual({ + intent: 'dsync', + organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', + return_url: 'https://www.example.com', + }); + expect(link).toBeDefined(); + }); + }); + + describe('with the audit_logs intent', () => { + it('returns an Admin Portal link', async () => { + fetchOnce(portalLinkResponse, { status: 201 }); + + const { link } = await workos.adminPortal.generateLink({ + intent: 'audit_logs', + organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', + returnUrl: 'https://www.example.com', + }); + + expect(fetchBody()).toEqual({ + intent: 'audit_logs', + organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', + return_url: 'https://www.example.com', + }); + expect(link).toBeDefined(); + }); + }); + + describe('with the log_streams intent', () => { + it('returns an Admin Portal link', async () => { + fetchOnce(portalLinkResponse, { status: 201 }); + + const { link } = await workos.adminPortal.generateLink({ + intent: 'log_streams', + organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', + returnUrl: 'https://www.example.com', + }); + + expect(fetchBody()).toEqual({ + intent: 'log_streams', + organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', + return_url: 'https://www.example.com', + }); + expect(link).toBeDefined(); + }); + }); + + describe('with the domain_verification intent', () => { + it('returns an Admin Portal link', async () => { + fetchOnce(portalLinkResponse, { status: 201 }); + + const { link } = await workos.adminPortal.generateLink({ + intent: 'domain_verification', + organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', + returnUrl: 'https://www.example.com', + }); + + expect(fetchBody()).toEqual({ + intent: 'domain_verification', + organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', + return_url: 'https://www.example.com', + }); + expect(link).toBeDefined(); + }); + }); + + describe('with the certificate_renewal intent', () => { + it('returns an Admin Portal link', async () => { + fetchOnce(portalLinkResponse, { status: 201 }); + + const { link } = await workos.adminPortal.generateLink({ + intent: 'certificate_renewal', + organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', + returnUrl: 'https://www.example.com', + }); + + expect(fetchBody()).toEqual({ + intent: 'certificate_renewal', + organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', + return_url: 'https://www.example.com', + }); + expect(link).toBeDefined(); + }); + }); + + describe('with the bring_your_own_key intent', () => { + it('returns an Admin Portal link', async () => { + fetchOnce(portalLinkResponse, { status: 201 }); + + const { link } = await workos.adminPortal.generateLink({ + intent: 'bring_your_own_key', + organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', + returnUrl: 'https://www.example.com', + }); + + expect(fetchBody()).toEqual({ + intent: 'bring_your_own_key', + organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', + return_url: 'https://www.example.com', + }); + expect(link).toBeDefined(); + }); + }); + + describe('with intentOptions and adminEmails', () => { + it('serializes the new parameters correctly', async () => { + fetchOnce(portalLinkResponse, { status: 201 }); + + const { link } = await workos.adminPortal.generateLink({ + intent: 'sso', + organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', + returnUrl: 'https://www.example.com', + intentOptions: { + sso: { + bookmarkSlug: 'chatgpt', + providerType: 'GoogleSAML', + }, + }, + adminEmails: ['admin@example.com'], + }); + + expect(fetchBody()).toEqual({ + intent: 'sso', + organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', + return_url: 'https://www.example.com', + intent_options: { + sso: { + bookmark_slug: 'chatgpt', + provider_type: 'GoogleSAML', + }, + }, + admin_emails: ['admin@example.com'], + }); + expect(link).toBeDefined(); + }); + }); + + describe('with an invalid organization', () => { + it('throws an error', async () => { + fetchOnce(generateLinkInvalid, { + status: 400, + headers: { 'X-Request-ID': 'a-request-id' }, + }); + + await expect( + workos.adminPortal.generateLink({ + intent: 'sso', + organization: 'bogus-id', + returnUrl: 'https://www.example.com', + }), + ).rejects.toThrow( + 'Could not find an organization with the id, bogus-id.', + ); + expect(fetchBody()).toEqual({ + intent: 'sso', + organization: 'bogus-id', + return_url: 'https://www.example.com', + }); + }); + }); + }); +}); diff --git a/src/admin-portal/admin-portal.ts b/src/admin-portal/admin-portal.ts new file mode 100644 index 000000000..6f1881ef0 --- /dev/null +++ b/src/admin-portal/admin-portal.ts @@ -0,0 +1,33 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { WorkOS } from '../workos'; +import type { + PortalLinkResponse, + PortalLinkResponseWire, +} from './interfaces/portal-link-response.interface'; +import type { GenerateLink } from './interfaces/generate-link.interface'; +import { deserializePortalLinkResponse } from './serializers/portal-link-response.serializer'; +import { serializeGenerateLink } from './serializers/generate-link.serializer'; + +export class AdminPortal { + constructor(private readonly workos: WorkOS) {} + + /** + * Generate a Portal Link + * + * Generate a Portal Link scoped to an Organization. + * @param payload - Admin Portal link generation parameters. + * @returns {Promise} + * @throws {BadRequestException} 400 + * @throws {UnauthorizedException} 401 + * @throws {NotFoundException} 404 + * @throws {UnprocessableEntityException} 422 + */ + async generateLink(payload: GenerateLink): Promise { + const { data } = await this.workos.post( + '/portal/generate_link', + serializeGenerateLink(payload), + ); + return deserializePortalLinkResponse(data); + } +} diff --git a/src/admin-portal/fixtures/generate-link-invalid.fixture.json b/src/admin-portal/fixtures/generate-link-invalid.fixture.json new file mode 100644 index 000000000..fc3a2f1cd --- /dev/null +++ b/src/admin-portal/fixtures/generate-link-invalid.fixture.json @@ -0,0 +1,3 @@ +{ + "message": "Could not find an organization with the id, bogus-id." +} diff --git a/src/admin-portal/fixtures/generate-link.fixture.json b/src/admin-portal/fixtures/generate-link.fixture.json new file mode 100644 index 000000000..63bd14d7c --- /dev/null +++ b/src/admin-portal/fixtures/generate-link.fixture.json @@ -0,0 +1,13 @@ +{ + "return_url": "https://example.com/admin-portal/return", + "success_url": "https://example.com/admin-portal/success", + "organization": "org_01EHZNVPK3SFK441A1RGBFSHRT", + "intent": "sso", + "intent_options": { + "sso": { + "bookmark_slug": "chatgpt", + "provider_type": "GoogleSAML" + } + }, + "admin_emails": ["admin@example.com"] +} diff --git a/src/admin-portal/fixtures/intent-options.fixture.json b/src/admin-portal/fixtures/intent-options.fixture.json new file mode 100644 index 000000000..31bad9130 --- /dev/null +++ b/src/admin-portal/fixtures/intent-options.fixture.json @@ -0,0 +1,6 @@ +{ + "sso": { + "bookmark_slug": "chatgpt", + "provider_type": "GoogleSAML" + } +} diff --git a/src/admin-portal/fixtures/portal-link-response.fixture.json b/src/admin-portal/fixtures/portal-link-response.fixture.json new file mode 100644 index 000000000..811f32a96 --- /dev/null +++ b/src/admin-portal/fixtures/portal-link-response.fixture.json @@ -0,0 +1,3 @@ +{ + "link": "https://setup.workos.com?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." +} diff --git a/src/admin-portal/fixtures/sso-intent-options.fixture.json b/src/admin-portal/fixtures/sso-intent-options.fixture.json new file mode 100644 index 000000000..79ab315ed --- /dev/null +++ b/src/admin-portal/fixtures/sso-intent-options.fixture.json @@ -0,0 +1,4 @@ +{ + "bookmark_slug": "chatgpt", + "provider_type": "GoogleSAML" +} diff --git a/src/admin-portal/interfaces/generate-link.interface.ts b/src/admin-portal/interfaces/generate-link.interface.ts new file mode 100644 index 000000000..b76720bf4 --- /dev/null +++ b/src/admin-portal/interfaces/generate-link.interface.ts @@ -0,0 +1,41 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + IntentOptions, + IntentOptionsResponse, +} from './intent-options.interface'; +import type { GenerateLinkIntent } from '../../common/interfaces/generate-link-intent.interface'; + +export interface GenerateLink { + /** The URL to go to when an admin clicks on your logo in the Admin Portal. If not specified, the return URL configured on the [Redirects](https://dashboard.workos.com/redirects) page will be used. */ + returnUrl?: string; + /** The URL to redirect the admin to when they finish setup. If not specified, the success URL configured on the [Redirects](https://dashboard.workos.com/redirects) page will be used. */ + successUrl?: string; + /** An [Organization](https://workos.com/docs/reference/organization) identifier. */ + organization: string; + /** + * + * The intent of the Admin Portal. + * - `sso` - Launch Admin Portal for creating SSO connections + * - `dsync` - Launch Admin Portal for creating Directory Sync connections + * - `audit_logs` - Launch Admin Portal for viewing Audit Logs + * - `log_streams` - Launch Admin Portal for creating Log Streams + * - `domain_verification` - Launch Admin Portal for Domain Verification + * - `certificate_renewal` - Launch Admin Portal for renewing SAML Certificates + * - `bring_your_own_key` - Launch Admin Portal for configuring Bring Your Own Key + */ + intent?: GenerateLinkIntent; + /** Options to configure the Admin Portal based on the intent. */ + intentOptions?: IntentOptions; + /** The email addresses of the IT admins to grant access to the Admin Portal for the given organization. Accepts up to 20 emails. */ + adminEmails?: string[]; +} + +export interface GenerateLinkResponse { + return_url?: string; + success_url?: string; + organization: string; + intent?: GenerateLinkIntent; + intent_options?: IntentOptionsResponse; + admin_emails?: string[]; +} diff --git a/src/admin-portal/interfaces/index.ts b/src/admin-portal/interfaces/index.ts new file mode 100644 index 000000000..eafac3f0c --- /dev/null +++ b/src/admin-portal/interfaces/index.ts @@ -0,0 +1,6 @@ +// This file is auto-generated by oagen. Do not edit. + +export * from './generate-link.interface'; +export * from './intent-options.interface'; +export * from './portal-link-response.interface'; +export * from './sso-intent-options.interface'; diff --git a/src/admin-portal/interfaces/intent-options.interface.ts b/src/admin-portal/interfaces/intent-options.interface.ts new file mode 100644 index 000000000..229e9e1af --- /dev/null +++ b/src/admin-portal/interfaces/intent-options.interface.ts @@ -0,0 +1,15 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + SSOIntentOptions, + SSOIntentOptionsResponse, +} from './sso-intent-options.interface'; + +export interface IntentOptions { + /** SSO-specific options for the Admin Portal. */ + sso: SSOIntentOptions; +} + +export interface IntentOptionsResponse { + sso: SSOIntentOptionsResponse; +} diff --git a/src/admin-portal/interfaces/portal-link-response.interface.ts b/src/admin-portal/interfaces/portal-link-response.interface.ts new file mode 100644 index 000000000..a7ea95f54 --- /dev/null +++ b/src/admin-portal/interfaces/portal-link-response.interface.ts @@ -0,0 +1,10 @@ +// This file is auto-generated by oagen. Do not edit. + +export interface PortalLinkResponse { + /** An ephemeral link to initiate the Admin Portal. */ + link: string; +} + +export interface PortalLinkResponseWire { + link: string; +} diff --git a/src/admin-portal/interfaces/sso-intent-options.interface.ts b/src/admin-portal/interfaces/sso-intent-options.interface.ts new file mode 100644 index 000000000..6450eabb9 --- /dev/null +++ b/src/admin-portal/interfaces/sso-intent-options.interface.ts @@ -0,0 +1,13 @@ +// This file is auto-generated by oagen. Do not edit. + +export interface SSOIntentOptions { + /** The bookmark slug to use for SSO. */ + bookmarkSlug?: string; + /** The SSO provider type to configure. */ + providerType?: 'GoogleSAML'; +} + +export interface SSOIntentOptionsResponse { + bookmark_slug?: string; + provider_type?: 'GoogleSAML'; +} diff --git a/src/admin-portal/serializers.spec.ts b/src/admin-portal/serializers.spec.ts new file mode 100644 index 000000000..418598d8f --- /dev/null +++ b/src/admin-portal/serializers.spec.ts @@ -0,0 +1,62 @@ +// This file is auto-generated by oagen. Do not edit. + +import { + deserializeSSOIntentOptions, + serializeSSOIntentOptions, +} from './serializers/sso-intent-options.serializer'; +import { + deserializeIntentOptions, + serializeIntentOptions, +} from './serializers/intent-options.serializer'; +import { + deserializeGenerateLink, + serializeGenerateLink, +} from './serializers/generate-link.serializer'; +import { + deserializePortalLinkResponse, + serializePortalLinkResponse, +} from './serializers/portal-link-response.serializer'; +import type { SSOIntentOptionsResponse } from './interfaces/sso-intent-options.interface'; +import type { IntentOptionsResponse } from './interfaces/intent-options.interface'; +import type { GenerateLinkResponse } from './interfaces/generate-link.interface'; +import type { PortalLinkResponseWire } from './interfaces/portal-link-response.interface'; +import sSOIntentOptionsFixture from './fixtures/sso-intent-options.fixture.json'; +import intentOptionsFixture from './fixtures/intent-options.fixture.json'; +import generateLinkFixture from './fixtures/generate-link.fixture.json'; +import portalLinkResponseFixture from './fixtures/portal-link-response.fixture.json'; + +describe('SSOIntentOptionsSerializer', () => { + it('round-trips through serialize/deserialize', () => { + const fixture = sSOIntentOptionsFixture as SSOIntentOptionsResponse; + const deserialized = deserializeSSOIntentOptions(fixture); + const reserialized = serializeSSOIntentOptions(deserialized); + expect(reserialized).toEqual(expect.objectContaining(fixture)); + }); +}); + +describe('IntentOptionsSerializer', () => { + it('round-trips through serialize/deserialize', () => { + const fixture = intentOptionsFixture as IntentOptionsResponse; + const deserialized = deserializeIntentOptions(fixture); + const reserialized = serializeIntentOptions(deserialized); + expect(reserialized).toEqual(expect.objectContaining(fixture)); + }); +}); + +describe('GenerateLinkSerializer', () => { + it('round-trips through serialize/deserialize', () => { + const fixture = generateLinkFixture as GenerateLinkResponse; + const deserialized = deserializeGenerateLink(fixture); + const reserialized = serializeGenerateLink(deserialized); + expect(reserialized).toEqual(expect.objectContaining(fixture)); + }); +}); + +describe('PortalLinkResponseSerializer', () => { + it('round-trips through serialize/deserialize', () => { + const fixture = portalLinkResponseFixture as PortalLinkResponseWire; + const deserialized = deserializePortalLinkResponse(fixture); + const reserialized = serializePortalLinkResponse(deserialized); + expect(reserialized).toEqual(expect.objectContaining(fixture)); + }); +}); diff --git a/src/admin-portal/serializers/generate-link.serializer.ts b/src/admin-portal/serializers/generate-link.serializer.ts new file mode 100644 index 000000000..c76688537 --- /dev/null +++ b/src/admin-portal/serializers/generate-link.serializer.ts @@ -0,0 +1,38 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + GenerateLink, + GenerateLinkResponse, +} from '../interfaces/generate-link.interface'; +import { + deserializeIntentOptions, + serializeIntentOptions, +} from './intent-options.serializer'; + +export const deserializeGenerateLink = ( + response: GenerateLinkResponse, +): GenerateLink => ({ + returnUrl: response.return_url, + successUrl: response.success_url, + organization: response.organization, + intent: response.intent, + intentOptions: + response.intent_options != null + ? deserializeIntentOptions(response.intent_options) + : undefined, + adminEmails: response.admin_emails, +}); + +export const serializeGenerateLink = ( + model: GenerateLink, +): GenerateLinkResponse => ({ + return_url: model.returnUrl, + success_url: model.successUrl, + organization: model.organization, + intent: model.intent, + intent_options: + model.intentOptions != null + ? serializeIntentOptions(model.intentOptions) + : undefined, + admin_emails: model.adminEmails, +}); diff --git a/src/admin-portal/serializers/intent-options.serializer.ts b/src/admin-portal/serializers/intent-options.serializer.ts new file mode 100644 index 000000000..a7d16e1df --- /dev/null +++ b/src/admin-portal/serializers/intent-options.serializer.ts @@ -0,0 +1,22 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + IntentOptions, + IntentOptionsResponse, +} from '../interfaces/intent-options.interface'; +import { + deserializeSSOIntentOptions, + serializeSSOIntentOptions, +} from './sso-intent-options.serializer'; + +export const deserializeIntentOptions = ( + response: IntentOptionsResponse, +): IntentOptions => ({ + sso: deserializeSSOIntentOptions(response.sso), +}); + +export const serializeIntentOptions = ( + model: IntentOptions, +): IntentOptionsResponse => ({ + sso: serializeSSOIntentOptions(model.sso), +}); diff --git a/src/admin-portal/serializers/portal-link-response.serializer.ts b/src/admin-portal/serializers/portal-link-response.serializer.ts new file mode 100644 index 000000000..75a96c945 --- /dev/null +++ b/src/admin-portal/serializers/portal-link-response.serializer.ts @@ -0,0 +1,18 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + PortalLinkResponse, + PortalLinkResponseWire, +} from '../interfaces/portal-link-response.interface'; + +export const deserializePortalLinkResponse = ( + response: PortalLinkResponseWire, +): PortalLinkResponse => ({ + link: response.link, +}); + +export const serializePortalLinkResponse = ( + model: PortalLinkResponse, +): PortalLinkResponseWire => ({ + link: model.link, +}); diff --git a/src/admin-portal/serializers/sso-intent-options.serializer.ts b/src/admin-portal/serializers/sso-intent-options.serializer.ts new file mode 100644 index 000000000..5c36252fa --- /dev/null +++ b/src/admin-portal/serializers/sso-intent-options.serializer.ts @@ -0,0 +1,20 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + SSOIntentOptions, + SSOIntentOptionsResponse, +} from '../interfaces/sso-intent-options.interface'; + +export const deserializeSSOIntentOptions = ( + response: SSOIntentOptionsResponse, +): SSOIntentOptions => ({ + bookmarkSlug: response.bookmark_slug, + providerType: response.provider_type, +}); + +export const serializeSSOIntentOptions = ( + model: SSOIntentOptions, +): SSOIntentOptionsResponse => ({ + bookmark_slug: model.bookmarkSlug, + provider_type: model.providerType, +}); diff --git a/src/common/interfaces/generate-link-intent.interface.ts b/src/common/interfaces/generate-link-intent.interface.ts new file mode 100644 index 000000000..696d9d318 --- /dev/null +++ b/src/common/interfaces/generate-link-intent.interface.ts @@ -0,0 +1,10 @@ +// This file is auto-generated by oagen. Do not edit. + +export type GenerateLinkIntent = + | 'sso' + | 'dsync' + | 'audit_logs' + | 'log_streams' + | 'domain_verification' + | 'certificate_renewal' + | 'bring_your_own_key'; diff --git a/src/common/interfaces/index.ts b/src/common/interfaces/index.ts index c9abe5235..ef8cefcfa 100644 --- a/src/common/interfaces/index.ts +++ b/src/common/interfaces/index.ts @@ -1,4 +1,5 @@ export * from './event.interface'; +export * from './generate-link-intent.interface'; export * from './get-options.interface'; export * from './list.interface'; export * from './patch-options.interface'; diff --git a/src/index.ts b/src/index.ts index 6a7e8d1d5..877c3ba6f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,5 @@ +// This file is auto-generated by oagen. Do not edit. + import { SubtleCryptoProvider } from './common/crypto/subtle-crypto-provider'; import { CryptoProvider } from './common/crypto/crypto-provider'; @@ -23,7 +25,7 @@ export { FeatureFlagsRuntimeClient } from './feature-flags/runtime-client'; export * from './organizations/interfaces'; export * from './organization-domains/interfaces'; export * from './passwordless/interfaces'; -export * from './portal/interfaces'; +export * from './admin-portal/interfaces'; export * from './roles/interfaces'; export * from './sso/interfaces'; export * from './user-management/interfaces'; diff --git a/src/index.worker.ts b/src/index.worker.ts index aeaab70bc..747bda6c5 100644 --- a/src/index.worker.ts +++ b/src/index.worker.ts @@ -18,7 +18,7 @@ export * from './events/interfaces'; export * from './organizations/interfaces'; export * from './organization-domains/interfaces'; export * from './passwordless/interfaces'; -export * from './portal/interfaces'; +export * from './admin-portal/interfaces'; export * from './sso/interfaces'; export * from './user-management/interfaces'; export * from './roles/interfaces'; diff --git a/src/portal/fixtures/generate-link-invalid.json b/src/portal/fixtures/generate-link-invalid.json deleted file mode 100644 index 6a3264374..000000000 --- a/src/portal/fixtures/generate-link-invalid.json +++ /dev/null @@ -1 +0,0 @@ -{ "message": "Could not find an organization with the id, bogus-id."} diff --git a/src/portal/fixtures/generate-link.json b/src/portal/fixtures/generate-link.json deleted file mode 100644 index 9cb389f3e..000000000 --- a/src/portal/fixtures/generate-link.json +++ /dev/null @@ -1 +0,0 @@ -{ "link": "https://id.workos.com/portal/launch?secret=secret" } diff --git a/src/portal/interfaces/generate-portal-link-intent.interface.ts b/src/portal/interfaces/generate-portal-link-intent.interface.ts deleted file mode 100644 index 5b1dc2e98..000000000 --- a/src/portal/interfaces/generate-portal-link-intent.interface.ts +++ /dev/null @@ -1,9 +0,0 @@ -export enum GeneratePortalLinkIntent { - AuditLogs = 'audit_logs', - DomainVerification = 'domain_verification', - DSync = 'dsync', - LogStreams = 'log_streams', - SSO = 'sso', - CertificateRenewal = 'certificate_renewal', - BringYourOwnKey = 'bring_your_own_key', -} diff --git a/src/portal/interfaces/index.ts b/src/portal/interfaces/index.ts deleted file mode 100644 index d7e1d0aa1..000000000 --- a/src/portal/interfaces/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { GeneratePortalLinkIntent } from './generate-portal-link-intent.interface'; diff --git a/src/portal/portal.spec.ts b/src/portal/portal.spec.ts deleted file mode 100644 index cc61be9f7..000000000 --- a/src/portal/portal.spec.ts +++ /dev/null @@ -1,209 +0,0 @@ -import fetch from 'jest-fetch-mock'; -import { fetchBody, fetchOnce } from '../common/utils/test-utils'; -import { WorkOS } from '../workos'; -import generateLinkInvalid from './fixtures/generate-link-invalid.json'; -import generateLink from './fixtures/generate-link.json'; -import { GeneratePortalLinkIntent } from './interfaces/generate-portal-link-intent.interface'; - -const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); - -describe('Portal', () => { - beforeEach(() => fetch.resetMocks()); - - describe('generateLink', () => { - describe('with a valid organization', () => { - describe('with the sso intent', () => { - it('returns an Admin Portal link', async () => { - fetchOnce(generateLink, { status: 201 }); - - const { link } = await workos.portal.generateLink({ - intent: GeneratePortalLinkIntent.SSO, - organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', - returnUrl: 'https://www.example.com', - }); - - expect(fetchBody()).toEqual({ - intent: GeneratePortalLinkIntent.SSO, - organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', - return_url: 'https://www.example.com', - }); - expect(link).toEqual( - 'https://id.workos.com/portal/launch?secret=secret', - ); - }); - }); - - describe('with the domain_verification intent', () => { - it('returns an Admin Portal link', async () => { - fetchOnce(generateLink, { status: 201 }); - - const { link } = await workos.portal.generateLink({ - intent: GeneratePortalLinkIntent.DomainVerification, - organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', - returnUrl: 'https://www.example.com', - }); - - expect(fetchBody()).toEqual({ - intent: GeneratePortalLinkIntent.DomainVerification, - organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', - return_url: 'https://www.example.com', - }); - expect(link).toEqual( - 'https://id.workos.com/portal/launch?secret=secret', - ); - }); - }); - - describe('with the dsync intent', () => { - it('returns an Admin Portal link', async () => { - fetchOnce(generateLink, { status: 201 }); - - const { link } = await workos.portal.generateLink({ - intent: GeneratePortalLinkIntent.DSync, - organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', - returnUrl: 'https://www.example.com', - }); - - expect(fetchBody()).toEqual({ - intent: GeneratePortalLinkIntent.DSync, - organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', - return_url: 'https://www.example.com', - }); - expect(link).toEqual( - 'https://id.workos.com/portal/launch?secret=secret', - ); - }); - }); - - describe('with the `audit_logs` intent', () => { - it('returns an Admin Portal link', async () => { - fetchOnce(generateLink, { status: 201 }); - - const { link } = await workos.portal.generateLink({ - intent: GeneratePortalLinkIntent.AuditLogs, - organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', - returnUrl: 'https://www.example.com', - }); - - expect(fetchBody()).toEqual({ - intent: GeneratePortalLinkIntent.AuditLogs, - organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', - return_url: 'https://www.example.com', - }); - expect(link).toEqual( - 'https://id.workos.com/portal/launch?secret=secret', - ); - }); - }); - - describe('with the `log_streams` intent', () => { - it('returns an Admin Portal link', async () => { - fetchOnce(generateLink, { status: 201 }); - - const { link } = await workos.portal.generateLink({ - intent: GeneratePortalLinkIntent.LogStreams, - organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', - returnUrl: 'https://www.example.com', - }); - - expect(fetchBody()).toEqual({ - intent: GeneratePortalLinkIntent.LogStreams, - organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', - return_url: 'https://www.example.com', - }); - expect(link).toEqual( - 'https://id.workos.com/portal/launch?secret=secret', - ); - }); - }); - describe('with the `certificate_renewal` intent', () => { - it('returns an Admin Portal link', async () => { - fetchOnce(generateLink, { status: 201 }); - - const { link } = await workos.portal.generateLink({ - intent: GeneratePortalLinkIntent.CertificateRenewal, - organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', - returnUrl: 'https://www.example.com', - }); - - expect(fetchBody()).toEqual({ - intent: GeneratePortalLinkIntent.CertificateRenewal, - organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', - return_url: 'https://www.example.com', - }); - expect(link).toEqual( - 'https://id.workos.com/portal/launch?secret=secret', - ); - }); - }); - describe('with the `bring_your_own_key` intent', () => { - it('returns an Admin Portal link', async () => { - fetchOnce(generateLink, { status: 201 }); - - const { link } = await workos.portal.generateLink({ - intent: GeneratePortalLinkIntent.BringYourOwnKey, - organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', - returnUrl: 'https://www.example.com', - }); - - expect(fetchBody()).toEqual({ - intent: GeneratePortalLinkIntent.BringYourOwnKey, - organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3', - return_url: 'https://www.example.com', - }); - expect(link).toEqual( - 'https://id.workos.com/portal/launch?secret=secret', - ); - }); - }); - }); - - describe('with an invalid organization', () => { - it('throws an error', async () => { - fetchOnce(generateLinkInvalid, { - status: 400, - headers: { 'X-Request-ID': 'a-request-id' }, - }); - - await expect( - workos.portal.generateLink({ - intent: GeneratePortalLinkIntent.SSO, - organization: 'bogus-id', - returnUrl: 'https://www.example.com', - }), - ).rejects.toThrow( - 'Could not find an organization with the id, bogus-id.', - ); - expect(fetchBody()).toEqual({ - intent: GeneratePortalLinkIntent.SSO, - organization: 'bogus-id', - return_url: 'https://www.example.com', - }); - }); - }); - - describe('with an invalid organization', () => { - it('throws an error', async () => { - fetchOnce(generateLinkInvalid, { - status: 400, - headers: { 'X-Request-ID': 'a-request-id' }, - }); - - await expect( - workos.portal.generateLink({ - intent: GeneratePortalLinkIntent.SSO, - organization: 'bogus-id', - returnUrl: 'https://www.example.com', - }), - ).rejects.toThrow( - 'Could not find an organization with the id, bogus-id.', - ); - expect(fetchBody()).toEqual({ - intent: GeneratePortalLinkIntent.SSO, - organization: 'bogus-id', - return_url: 'https://www.example.com', - }); - }); - }); - }); -}); diff --git a/src/portal/portal.ts b/src/portal/portal.ts deleted file mode 100644 index fb466131f..000000000 --- a/src/portal/portal.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { WorkOS } from '../workos'; -import { GeneratePortalLinkIntent } from './interfaces/generate-portal-link-intent.interface'; - -export class Portal { - constructor(private readonly workos: WorkOS) {} - - async generateLink({ - intent, - organization, - returnUrl, - successUrl, - }: { - intent: GeneratePortalLinkIntent; - organization: string; - returnUrl?: string; - successUrl?: string; - }): Promise<{ link: string }> { - const { data } = await this.workos.post('/portal/generate_link', { - intent, - organization, - return_url: returnUrl, - success_url: successUrl, - }); - - return data; - } -} diff --git a/src/workos.ts b/src/workos.ts index 1014c4a5c..a0e1c95ae 100644 --- a/src/workos.ts +++ b/src/workos.ts @@ -1,3 +1,5 @@ +// This file is auto-generated by oagen. Do not edit. + import { ApiKeyRequiredException, GenericServerException, @@ -24,7 +26,7 @@ import { Organizations } from './organizations/organizations'; import { OrganizationDomains } from './organization-domains/organization-domains'; import { Passwordless } from './passwordless/passwordless'; import { Pipes } from './pipes/pipes'; -import { Portal } from './portal/portal'; +import { AdminPortal } from './admin-portal/admin-portal'; import { SSO } from './sso/sso'; import { Webhooks } from './webhooks/webhooks'; import { Mfa } from './mfa/mfa'; @@ -53,6 +55,7 @@ const HEADER_AUTHORIZATION = 'Authorization'; const HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key'; const HEADER_WARRANT_TOKEN = 'Warrant-Token'; +/** WorkOS REST API */ export class WorkOS { readonly baseURL: string; readonly client: HttpClient; @@ -75,7 +78,7 @@ export class WorkOS { readonly organizationDomains = new OrganizationDomains(this); readonly passwordless = new Passwordless(this); readonly pipes = new Pipes(this); - readonly portal = new Portal(this); + readonly adminPortal = new AdminPortal(this); readonly sso = new SSO(this); readonly userManagement: UserManagement; readonly vault = new Vault(this);