diff --git a/playground/handlers.ts b/playground/handlers.ts index 3b6bb33c1..687222553 100644 --- a/playground/handlers.ts +++ b/playground/handlers.ts @@ -1,4 +1,5 @@ import { program } from 'commander'; +import fetch from 'node-fetch'; import { Connection, GetOrganizationMemberRoles200ResponseOneOfInner, @@ -16,7 +17,10 @@ import fs from 'fs'; import { fileURLToPath } from 'url'; import nock from 'nock'; -process.env.RECORD && nock.recorder.rec({ output_objects: true }); +if (process.env.RECORD) { + (globalThis as any).fetch = fetch; + nock.recorder.rec({ output_objects: true }); +} const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -151,6 +155,7 @@ export async function attackProtection() { revertedSuspiciousIpThrottlingConfig.enabled ); } + export async function anomaly() { const mgmntClient = new ManagementClient(program.opts()); try { @@ -296,6 +301,7 @@ export async function clientGrants() { const { data: clientGrant } = await mgmntClient.clientGrants.create({ client_id: program.opts().clientId, audience: api?.identifier as string, + organization_usage: 'allow', scope: ['openid'], }); console.log(`Created client grant ${clientGrant.id}`); @@ -310,11 +316,35 @@ export async function clientGrants() { { id: clientGrant.id as string }, { scope: ['openid', 'profile'] } ); - console.log(`Updated client grant to use scopes '${updatedClientGrant.scope?.join(', ')}'`); + const { data: organization } = await mgmntClient.organizations.create({ + name: 'test-org', + }); + + await mgmntClient.organizations.addClientGrant( + { id: organization.id }, + { grant_id: clientGrant.id } + ); + + const { data: orgsByClientGrant } = await mgmntClient.clientGrants.getOrganizations({ + id: clientGrant.id, + }); + console.log(`got orgs by ${clientGrant.id} ${orgsByClientGrant.map((org) => org.name)}`); + const { data: clientGrantsByOrg } = await mgmntClient.organizations.getClientGrants({ + id: organization.id, + }); + console.log(`got client grants by ${organization.name} ${clientGrantsByOrg.map((cg) => cg.id)}`); + + await mgmntClient.organizations.deleteClientGrant({ + id: organization.id, + grant_id: clientGrant.id, + }); + console.log(`Removed ${clientGrant.id} from ${organization.id}`); + // Delete API for testing await mgmntClient.resourceServers.delete({ id: api?.id as string }); + await mgmntClient.organizations.delete({ id: organization.id }); await mgmntClient.clientGrants.delete({ id: clientGrant.id as string }); console.log('Removed the client grant: ' + clientGrant.id); diff --git a/src/auth/oauth.ts b/src/auth/oauth.ts index 02c6a8462..8d7a60e3b 100644 --- a/src/auth/oauth.ts +++ b/src/auth/oauth.ts @@ -89,6 +89,11 @@ export interface ClientCredentialsGrantRequest extends ClientCredentials { * The unique identifier of the target API you want to access. */ audience: string; + + /** + * An Organization Name or ID. When included, the access token returned will include the org_id and org_name claims + */ + organization?: string; } export interface PasswordGrantRequest extends ClientCredentials { diff --git a/src/management/__generated/managers/client-grants-manager.ts b/src/management/__generated/managers/client-grants-manager.ts index 1217f9202..8d53459e0 100644 --- a/src/management/__generated/managers/client-grants-manager.ts +++ b/src/management/__generated/managers/client-grants-manager.ts @@ -4,10 +4,14 @@ import type { ClientGrant, ClientGrantCreate, GetClientGrants200Response, + GetClientGrantsOrganizations200Response, PatchClientGrantsByIdRequest, GetClientGrants200ResponseOneOf, + GetClientGrantsOrganizations200ResponseOneOf, + GetClientGrantsOrganizations200ResponseOneOfInner, DeleteClientGrantsByIdRequest, GetClientGrantsRequest, + GetClientGrantsOrganizationsRequest, PatchClientGrantsByIdOperationRequest, } from '../models/index.js'; @@ -83,6 +87,10 @@ export class ClientGrantsManager extends BaseAPI { key: 'client_id', config: {}, }, + { + key: 'allow_any_organization', + config: {}, + }, ]); const response = await this.request( @@ -97,6 +105,63 @@ export class ClientGrantsManager extends BaseAPI { return runtime.JSONApiResponse.fromResponse(response); } + /** + * Get the organizations associated to a client grant + * + * @throws {RequiredError} + */ + async getOrganizations( + requestParameters: GetClientGrantsOrganizationsRequest & { include_totals: true }, + initOverrides?: InitOverride + ): Promise>; + async getOrganizations( + requestParameters?: GetClientGrantsOrganizationsRequest, + initOverrides?: InitOverride + ): Promise>>; + async getOrganizations( + requestParameters: GetClientGrantsOrganizationsRequest, + initOverrides?: InitOverride + ): Promise> { + runtime.validateRequiredRequestParams(requestParameters, ['id']); + + const queryParameters = runtime.applyQueryParams(requestParameters, [ + { + key: 'page', + config: {}, + }, + { + key: 'per_page', + config: {}, + }, + { + key: 'include_totals', + config: {}, + }, + { + key: 'from', + config: {}, + }, + { + key: 'take', + config: {}, + }, + ]); + + const response = await this.request( + { + path: `/client-grants/{id}/organizations`.replace( + '{id}', + encodeURIComponent(String(requestParameters.id)) + ), + method: 'GET', + query: queryParameters, + }, + initOverrides + ); + + return runtime.JSONApiResponse.fromResponse(response); + } + /** * Update a client grant. * Update client grant diff --git a/src/management/__generated/managers/organizations-manager.ts b/src/management/__generated/managers/organizations-manager.ts index a2940a518..21035c79e 100644 --- a/src/management/__generated/managers/organizations-manager.ts +++ b/src/management/__generated/managers/organizations-manager.ts @@ -3,20 +3,23 @@ import type { InitOverride, ApiResponse } from '../../../lib/runtime.js'; import type { DeleteMembersRequest, DeleteOrganizationMemberRolesRequest, + GetClientGrantsOrganizations200Response, + GetClientGrantsOrganizations200ResponseOneOfInner, GetEnabledConnections200Response, GetEnabledConnections200ResponseOneOfInner, GetInvitations200Response, GetInvitations200ResponseOneOfInner, GetMembers200Response, GetOrganizationMemberRoles200Response, - GetOrganizations200Response, - GetOrganizations200ResponseOneOfInner, + GetOrganizationsClientGrants200Response, + GetOrganizationsClientGrants200ResponseOneOfInner, PatchEnabledConnectionsByConnectionIdRequest, PatchOrganizationsByIdRequest, PostEnabledConnectionsRequest, PostInvitationsRequest, PostMembersRequest, PostOrganizationMemberRolesRequest, + PostOrganizationsClientGrantsRequest, PostOrganizationsRequest, GetEnabledConnections200ResponseOneOf, GetInvitations200ResponseOneOf, @@ -24,7 +27,9 @@ import type { GetMembers200ResponseOneOfInner, GetOrganizationMemberRoles200ResponseOneOf, GetOrganizationMemberRoles200ResponseOneOfInner, - GetOrganizations200ResponseOneOf, + GetClientGrantsOrganizations200ResponseOneOf, + GetOrganizationsClientGrants200ResponseOneOf, + DeleteClientGrantsByGrantIdRequest, DeleteEnabledConnectionsByConnectionIdRequest, DeleteInvitationsByInvitationIdRequest, DeleteMembersOperationRequest, @@ -39,12 +44,14 @@ import type { GetOrganizationMemberRolesRequest, GetOrganizationsRequest, GetOrganizationsByIdRequest, + GetOrganizationsClientGrantsRequest, PatchEnabledConnectionsByConnectionIdOperationRequest, PatchOrganizationsByIdOperationRequest, PostEnabledConnectionsOperationRequest, PostInvitationsOperationRequest, PostMembersOperationRequest, PostOrganizationMemberRolesOperationRequest, + PostOrganizationsClientGrantsOperationRequest, } from '../models/index.js'; const { BaseAPI } = runtime; @@ -53,6 +60,30 @@ const { BaseAPI } = runtime; * */ export class OrganizationsManager extends BaseAPI { + /** + * Remove a client grant from an organization + * + * @throws {RequiredError} + */ + async deleteClientGrant( + requestParameters: DeleteClientGrantsByGrantIdRequest, + initOverrides?: InitOverride + ): Promise> { + runtime.validateRequiredRequestParams(requestParameters, ['id', 'grant_id']); + + const response = await this.request( + { + path: `/organizations/{id}/client-grants/{grant_id}` + .replace('{id}', encodeURIComponent(String(requestParameters.id))) + .replace('{grant_id}', encodeURIComponent(String(requestParameters.grant_id))), + method: 'DELETE', + }, + initOverrides + ); + + return runtime.VoidApiResponse.fromResponse(response); + } + /** * Delete connections from an organization * @@ -465,7 +496,7 @@ export class OrganizationsManager extends BaseAPI { async getByName( requestParameters: GetNameByNameRequest, initOverrides?: InitOverride - ): Promise> { + ): Promise> { runtime.validateRequiredRequestParams(requestParameters, ['name']); const response = await this.request( @@ -552,15 +583,15 @@ export class OrganizationsManager extends BaseAPI { async getAll( requestParameters: GetOrganizationsRequest & { include_totals: true }, initOverrides?: InitOverride - ): Promise>; + ): Promise>; async getAll( requestParameters?: GetOrganizationsRequest, initOverrides?: InitOverride - ): Promise>>; + ): Promise>>; async getAll( requestParameters: GetOrganizationsRequest = {}, initOverrides?: InitOverride - ): Promise> { + ): Promise> { const queryParameters = runtime.applyQueryParams(requestParameters, [ { key: 'page', @@ -610,7 +641,7 @@ export class OrganizationsManager extends BaseAPI { async get( requestParameters: GetOrganizationsByIdRequest, initOverrides?: InitOverride - ): Promise> { + ): Promise> { runtime.validateRequiredRequestParams(requestParameters, ['id']); const response = await this.request( @@ -627,6 +658,63 @@ export class OrganizationsManager extends BaseAPI { return runtime.JSONApiResponse.fromResponse(response); } + /** + * Get client grants associated to an organization + * + * @throws {RequiredError} + */ + async getClientGrants( + requestParameters: GetOrganizationsClientGrantsRequest & { include_totals: true }, + initOverrides?: InitOverride + ): Promise>; + async getClientGrants( + requestParameters?: GetOrganizationsClientGrantsRequest, + initOverrides?: InitOverride + ): Promise>>; + async getClientGrants( + requestParameters: GetOrganizationsClientGrantsRequest, + initOverrides?: InitOverride + ): Promise> { + runtime.validateRequiredRequestParams(requestParameters, ['id']); + + const queryParameters = runtime.applyQueryParams(requestParameters, [ + { + key: 'audience', + config: {}, + }, + { + key: 'client_id', + config: {}, + }, + { + key: 'page', + config: {}, + }, + { + key: 'per_page', + config: {}, + }, + { + key: 'include_totals', + config: {}, + }, + ]); + + const response = await this.request( + { + path: `/organizations/{id}/client-grants`.replace( + '{id}', + encodeURIComponent(String(requestParameters.id)) + ), + method: 'GET', + query: queryParameters, + }, + initOverrides + ); + + return runtime.JSONApiResponse.fromResponse(response); + } + /** * Modify an enabled_connection belonging to an Organization. * @@ -671,7 +759,7 @@ export class OrganizationsManager extends BaseAPI { requestParameters: PatchOrganizationsByIdOperationRequest, bodyParameters: PatchOrganizationsByIdRequest, initOverrides?: InitOverride - ): Promise> { + ): Promise> { runtime.validateRequiredRequestParams(requestParameters, ['id']); const headerParameters: runtime.HTTPHeaders = {}; @@ -831,7 +919,7 @@ export class OrganizationsManager extends BaseAPI { async create( bodyParameters: PostOrganizationsRequest, initOverrides?: InitOverride - ): Promise> { + ): Promise> { const headerParameters: runtime.HTTPHeaders = {}; headerParameters['Content-Type'] = 'application/json'; @@ -848,4 +936,36 @@ export class OrganizationsManager extends BaseAPI { return runtime.JSONApiResponse.fromResponse(response); } + + /** + * Associate a client grant with an organization + * + * @throws {RequiredError} + */ + async addClientGrant( + requestParameters: PostOrganizationsClientGrantsOperationRequest, + bodyParameters: PostOrganizationsClientGrantsRequest, + initOverrides?: InitOverride + ): Promise> { + runtime.validateRequiredRequestParams(requestParameters, ['id']); + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + const response = await this.request( + { + path: `/organizations/{id}/client-grants`.replace( + '{id}', + encodeURIComponent(String(requestParameters.id)) + ), + method: 'POST', + headers: headerParameters, + body: bodyParameters, + }, + initOverrides + ); + + return runtime.JSONApiResponse.fromResponse(response); + } } diff --git a/src/management/__generated/managers/users-manager.ts b/src/management/__generated/managers/users-manager.ts index 85b82fff9..3d5b2c7a9 100644 --- a/src/management/__generated/managers/users-manager.ts +++ b/src/management/__generated/managers/users-manager.ts @@ -30,8 +30,8 @@ import type { Log, GetPermissions200ResponseOneOf, GetPermissions200ResponseOneOfInner, - GetOrganizations200ResponseOneOf, - GetOrganizations200ResponseOneOfInner, + GetClientGrantsOrganizations200ResponseOneOf, + GetClientGrantsOrganizations200ResponseOneOfInner, GetOrganizationMemberRoles200ResponseOneOf, GetOrganizationMemberRoles200ResponseOneOfInner, GetUsers200ResponseOneOf, @@ -503,11 +503,11 @@ export class UsersManager extends BaseAPI { async getUserOrganizations( requestParameters: GetUserOrganizationsRequest & { include_totals: true }, initOverrides?: InitOverride - ): Promise>; + ): Promise>; async getUserOrganizations( requestParameters?: GetUserOrganizationsRequest, initOverrides?: InitOverride - ): Promise>>; + ): Promise>>; async getUserOrganizations( requestParameters: GetUserOrganizationsRequest, initOverrides?: InitOverride diff --git a/src/management/__generated/models/index.ts b/src/management/__generated/models/index.ts index e7d2d79fa..f9937d1d9 100644 --- a/src/management/__generated/models/index.ts +++ b/src/management/__generated/models/index.ts @@ -1877,7 +1877,26 @@ export interface ClientGrant { * */ scope: Array; + /** + * Defines whether organizations can be used with client credentials exchanges for this grant. + * + */ + organization_usage: ClientGrantOrganizationUsageEnum; + /** + * If enabled, any organization can be used with this grant. If disabled (default), the grant must be explicitly assigned to the desired organizations. + * + */ + allow_any_organization: boolean; } + +export const ClientGrantOrganizationUsageEnum = { + deny: 'deny', + allow: 'allow', + require: 'require', +} as const; +export type ClientGrantOrganizationUsageEnum = + (typeof ClientGrantOrganizationUsageEnum)[keyof typeof ClientGrantOrganizationUsageEnum]; + /** * */ @@ -1892,12 +1911,31 @@ export interface ClientGrantCreate { * */ audience: string; + /** + * Defines whether organizations can be used with client credentials exchanges for this grant. + * + */ + organization_usage?: ClientGrantCreateOrganizationUsageEnum; + /** + * If enabled, any organization can be used with this grant. If disabled (default), the grant must be explicitly assigned to the desired organizations. + * + */ + allow_any_organization?: boolean; /** * Scopes allowed for this client grant. * */ scope: Array; } + +export const ClientGrantCreateOrganizationUsageEnum = { + deny: 'deny', + allow: 'allow', + require: 'require', +} as const; +export type ClientGrantCreateOrganizationUsageEnum = + (typeof ClientGrantCreateOrganizationUsageEnum)[keyof typeof ClientGrantCreateOrganizationUsageEnum]; + /** * Configuration related to JWTs for the client. */ @@ -4664,6 +4702,98 @@ export interface GetClientGrants200ResponseOneOf { */ client_grants: Array; } +/** + * + */ +export type GetClientGrantsOrganizations200Response = + | Array + | GetClientGrantsOrganizations200ResponseOneOf + | GetClientGrantsOrganizations200ResponseOneOf1; +/** + * + */ +export interface GetClientGrantsOrganizations200ResponseOneOf { + /** + */ + start: number; + /** + */ + limit: number; + /** + */ + total: number; + /** + */ + organizations: Array; +} +/** + * + */ +export interface GetClientGrantsOrganizations200ResponseOneOf1 { + /** + */ + next: string; + /** + */ + organizations: Array; +} +/** + * + */ +export interface GetClientGrantsOrganizations200ResponseOneOfInner { + [key: string]: any | any; + /** + * Organization identifier + * + */ + id: string; + /** + * The name of this organization. + * + */ + name: string; + /** + * Friendly name of this organization. + * + */ + display_name: string; + /** + */ + branding: GetClientGrantsOrganizations200ResponseOneOfInnerBranding; + /** + * Metadata associated with the organization, in the form of an object with string values (max 255 chars). Maximum of 10 metadata properties allowed. + * + */ + metadata: { [key: string]: any }; +} +/** + * Theme defines how to style the login pages + */ +export interface GetClientGrantsOrganizations200ResponseOneOfInnerBranding { + /** + * URL of logo to display on login page + * + */ + logo_url: string; + /** + */ + colors: GetClientGrantsOrganizations200ResponseOneOfInnerBrandingColors; +} +/** + * Color scheme used to customize the login pages + */ +export interface GetClientGrantsOrganizations200ResponseOneOfInnerBrandingColors { + /** + * HEX Color for primary elements + * + */ + primary: string; + /** + * HEX Color for background + * + */ + page_background: string; +} /** * */ @@ -6088,14 +6218,13 @@ export interface GetOrganizationMemberRoles200ResponseOneOfInner { /** * */ -export type GetOrganizations200Response = - | Array - | GetOrganizations200ResponseOneOf - | GetOrganizations200ResponseOneOf1; +export type GetOrganizationsClientGrants200Response = + | Array + | GetOrganizationsClientGrants200ResponseOneOf; /** * */ -export interface GetOrganizations200ResponseOneOf { +export interface GetOrganizationsClientGrants200ResponseOneOf { /** */ start: number; @@ -6107,75 +6236,32 @@ export interface GetOrganizations200ResponseOneOf { total: number; /** */ - organizations: Array; + grants: Array; } /** * */ -export interface GetOrganizations200ResponseOneOf1 { +export interface GetOrganizationsClientGrants200ResponseOneOfInner { /** - */ - next: string; - /** - */ - organizations: Array; -} -/** - * - */ -export interface GetOrganizations200ResponseOneOfInner { - [key: string]: any | any; - /** - * Organization identifier + * ID of the client grant. * */ id: string; /** - * The name of this organization. - * - */ - name: string; - /** - * Friendly name of this organization. - * - */ - display_name: string; - /** - */ - branding: GetOrganizations200ResponseOneOfInnerBranding; - /** - * Metadata associated with the organization, in the form of an object with string values (max 255 chars). Maximum of 10 metadata properties allowed. - * - */ - metadata: { [key: string]: any }; -} -/** - * Theme defines how to style the login pages - */ -export interface GetOrganizations200ResponseOneOfInnerBranding { - /** - * URL of logo to display on login page + * ID of the client. * */ - logo_url: string; - /** - */ - colors: GetOrganizations200ResponseOneOfInnerBrandingColors; -} -/** - * Color scheme used to customize the login pages - */ -export interface GetOrganizations200ResponseOneOfInnerBrandingColors { + client_id: string; /** - * HEX Color for primary elements + * The audience (API identifier) of this client grant * */ - primary: string; + audience: string; /** - * HEX Color for background + * Scopes allowed for this client grant. * */ - page_background: string; + scope: Array; } /** * @@ -6569,8 +6655,8 @@ export interface GetUniversalLogin200ResponseOneOf { * */ export type GetUserOrganizations200Response = - | Array - | GetOrganizations200ResponseOneOf; + | Array + | GetClientGrantsOrganizations200ResponseOneOf; /** * */ @@ -7420,7 +7506,27 @@ export interface PatchClientGrantsByIdRequest { * */ scope?: Array; + /** + * Controls how organizations may be used with this grant + * + */ + organization_usage?: PatchClientGrantsByIdRequestOrganizationUsageEnum; + /** + * Controls allowing any organization to be used with this grant + * + */ + allow_any_organization?: boolean | null; } + +export const PatchClientGrantsByIdRequestOrganizationUsageEnum = { + deny: 'deny', + allow: 'allow', + require: 'require', + null: 'null', +} as const; +export type PatchClientGrantsByIdRequestOrganizationUsageEnum = + (typeof PatchClientGrantsByIdRequestOrganizationUsageEnum)[keyof typeof PatchClientGrantsByIdRequestOrganizationUsageEnum]; + /** * */ @@ -7710,7 +7816,7 @@ export interface PatchOrganizationsByIdRequestBranding { logo_url?: string; /** */ - colors?: GetOrganizations200ResponseOneOfInnerBrandingColors; + colors?: GetClientGrantsOrganizations200ResponseOneOfInnerBrandingColors; } /** * @@ -9431,6 +9537,16 @@ export interface PostOrganizationMemberRolesRequest { */ roles: Array; } +/** + * + */ +export interface PostOrganizationsClientGrantsRequest { + /** + * A Client Grant ID to add to the organization. + * + */ + grant_id: string; +} /** * */ @@ -9470,7 +9586,7 @@ export interface PostOrganizationsRequestBranding { logo_url?: string; /** */ - colors?: GetOrganizations200ResponseOneOfInnerBrandingColors; + colors?: GetClientGrantsOrganizations200ResponseOneOfInnerBrandingColors; } /** * Connection to be added to the organization. @@ -12211,6 +12327,16 @@ export interface DeleteClientGrantsByIdRequest { */ id: string; } + +/** + * + */ +export const GetClientGrantsAllowAnyOrganizationEnum = { + true: true, +} as const; +export type GetClientGrantsAllowAnyOrganizationEnum = + (typeof GetClientGrantsAllowAnyOrganizationEnum)[keyof typeof GetClientGrantsAllowAnyOrganizationEnum]; + /** * */ @@ -12240,6 +12366,46 @@ export interface GetClientGrantsRequest { * */ client_id?: string; + /** + * Optional filter on allow_any_organization. + * + */ + allow_any_organization?: GetClientGrantsAllowAnyOrganizationEnum; +} +/** + * + */ +export interface GetClientGrantsOrganizationsRequest { + /** + * ID of the client grant + * + */ + id: string; + /** + * Page index of the results to return. First page is 0. + * + */ + page?: number; + /** + * Number of results per page. Defaults to 50. + * + */ + per_page?: number; + /** + * Return results inside an object that contains the total result count (true) or as a direct array of results (false, default). + * + */ + include_totals?: boolean; + /** + * Optional Id from which to start selection. + * + */ + from?: string; + /** + * Number of results per page. Defaults to 50. + * + */ + take?: number; } /** * @@ -13193,6 +13359,21 @@ export interface GetLogsByIdRequest { */ id: string; } +/** + * + */ +export interface DeleteClientGrantsByGrantIdRequest { + /** + * Organization identifier + * + */ + id: string; + /** + * The Client Grant ID to remove from the organization + * + */ + grant_id: string; +} /** * */ @@ -13493,6 +13674,41 @@ export interface GetOrganizationsByIdRequest { */ id: string; } +/** + * + */ +export interface GetOrganizationsClientGrantsRequest { + /** + * Organization identifier + * + */ + id: string; + /** + * Optional filter on audience of the client grant. + * + */ + audience?: string; + /** + * Optional filter on client_id of the client grant. + * + */ + client_id?: string; + /** + * Page index of the results to return. First page is 0. + * + */ + page?: number; + /** + * Number of results per page. Defaults to 50. + * + */ + per_page?: number; + /** + * Return results inside an object that contains the total result count (true) or as a direct array of results (false, default). + * + */ + include_totals?: boolean; +} /** * */ @@ -13563,6 +13779,16 @@ export interface PostOrganizationMemberRolesOperationRequest { */ user_id: string; } +/** + * + */ +export interface PostOrganizationsClientGrantsOperationRequest { + /** + * Organization identifier + * + */ + id: string; +} /** * diff --git a/test/management/client-grants.test.ts b/test/management/client-grants.test.ts index adafbcb20..989e15521 100644 --- a/test/management/client-grants.test.ts +++ b/test/management/client-grants.test.ts @@ -1,237 +1,75 @@ import nock from 'nock'; +import { afterAll, beforeAll } from '@jest/globals'; +import { ClientGrantsManager, ManagementClient } from '../../src/index.js'; -const API_URL = 'https://tenant.auth0.com/api/v2'; - -import { ClientGrant, ClientGrantsManager, ManagementClient } from '../../src/index.js'; +const { back: nockBack } = nock; describe('ClientGrantsManager', () => { - let grants: ClientGrantsManager; - const token = 'TOKEN'; - beforeAll(() => { - const client = new ManagementClient({ - domain: 'tenant.auth0.com', - token: token, - }); - grants = client.clientGrants; - }); + let clientGrantsManager: ClientGrantsManager; - afterEach(() => { - nock.cleanAll(); - }); + let nockDone: () => void; - describe('instance', () => { - const methods = ['getAll', 'create', 'update', 'delete']; + beforeAll(async () => { + ({ nockDone } = await nockBack('management/fixtures/client-grants.json')); - methods.forEach((method) => { - it(`should have a ${method} method`, () => { - expect((grants as any)[method]).toBeInstanceOf(Function); - }); + const client = new ManagementClient({ + domain: 'test-domain.auth0.com', + token: 'TOKEN', }); + clientGrantsManager = client.clientGrants; }); - describe('#constructor', () => { - it('should throw an error when no base URL is provided', () => { - expect(() => { - new ClientGrantsManager({} as any); - }).toThrowError(Error); - }); - - it('should throw an error when the base URL is invalid', () => { - expect(() => { - new ClientGrantsManager({ - baseUrl: '', - } as any); - }).toThrowError(Error); - }); + afterAll(() => { + nockDone(); }); - describe('#getAll', () => { - const data = [{ id: '1', client_id: '123', audience: 'abc', scope: ['openid'] }]; - let request: nock.Scope; - - beforeEach(() => { - request = nock(API_URL).get('/client-grants').reply(200, data); - }); - - it('should return a promise if no callback is given', (done) => { - grants.getAll().then(done.bind(null, null)).catch(done.bind(null, null)); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL).get('/client-grants').reply(500, {}); - - grants.getAll().catch((err) => { - expect(err).toBeDefined(); - done(); - }); - }); - - it('should pass the body of the response to the "then" handler', (done) => { - nock.cleanAll(); - - nock(API_URL).get('/client-grants').reply(200, data); - - grants.getAll().then((grants) => { - expect(grants.data).toBeInstanceOf(Array); - - expect((grants.data as Array).length).toBe(data.length); - expect((grants.data as Array)[0].id).toBe(data[0].id); - expect((grants.data as Array)[0].client_id).toBe(data[0].client_id); - expect((grants.data as Array)[0].audience).toBe(data[0].audience); - expect((grants.data as Array)[0].scope?.[0]).toBe(data[0].scope[0]); - - done(); - }); - }); - - it('should perform a GET request to /api/v2/client-grants', (done) => { - grants.getAll().then(() => { - expect(request.isDone()).toBe(true); - done(); - }); - }); - - it('should include the token in the Authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .get('/client-grants') - .matchHeader('Authorization', `Bearer ${token}`) - .reply(200, data); - - grants.getAll().then(() => { - expect(request.isDone()).toBe(true); - done(); - }); - }); - - it('should pass the parameters in the query-string', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .get('/client-grants') - .query({ - page: 1, - per_page: 2, - }) - .reply(200, data); - - grants.getAll({ page: 1, per_page: 2 }).then(() => { - expect(request.isDone()).toBe(true); - done(); - }); + it('should create a client grant', async () => { + await expect( + clientGrantsManager.create({ + client_id: 'test-client-id', + audience: 'test-aud', + scope: ['read:foo', 'write:foo'], + }) + ).resolves.toMatchObject({ + status: 201, }); }); - describe('#create', () => { - const data = { - client_id: 'CLIENT_ID', - audience: 'AUDIENCE', - scope: ['user'], - }; - let request: nock.Scope; - - beforeEach(() => { - request = nock(API_URL).post('/client-grants').reply(201, data); - }); - - it('should return a promise if no callback is given', (done) => { - grants.create(data).then(done.bind(null, null)).catch(done.bind(null, null)); - }); - - it('should perform a POST request to /api/v2/client-grants', (done) => { - grants.create(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should include the token in the Authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .post('/client-grants') - .matchHeader('Authorization', `Bearer ${token}`) - .reply(201, data); - - grants.create(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should include the new client grant data in the request body', (done) => { - nock.cleanAll(); - - const request = nock(API_URL).post('/client-grants', data).reply(201, data); - - grants.create(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it('should get client grants by client id', async () => { + await expect( + clientGrantsManager.getAll({ client_id: 'test-client-id' }) + ).resolves.toMatchObject({ + status: 200, }); }); - describe('#update', () => { - const data = { - client_id: 'CLIENT_ID', - audience: 'AUDIENCE', - scope: ['user'], - }; - let request: nock.Scope; - - beforeEach(() => { - request = nock(API_URL).patch(`/client-grants/5`).reply(200, data); - }); - - it('should return a promise if no callback is given', (done) => { - grants.update({ id: '5' }, {}).then(done.bind(null, null)).catch(done.bind(null, null)); - }); - - it('should perform a PATCH request to /api/v2/client-grants/5', (done) => { - grants.update({ id: '5' }, {}).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should include the new data in the body of the request', (done) => { - nock.cleanAll(); - - const request = nock(API_URL).patch(`/client-grants/5`, data).reply(200, data); - - grants.update({ id: '5' }, data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it('should get client grants by client id and allow_any_organization', async () => { + await expect( + clientGrantsManager.getAll({ client_id: 'test-client-id', allow_any_organization: true }) + ).resolves.toMatchObject({ + status: 200, }); }); - describe('#delete', () => { - const id = '5'; - let request: nock.Scope; - - beforeEach(() => { - request = nock(API_URL).delete(`/client-grants/${id}`).reply(200, {}); + it('should update a client grant', async () => { + await expect( + clientGrantsManager.update({ id: 'test-client-grant' }, { scope: ['read:foo', 'read:bar'] }) + ).resolves.toMatchObject({ + status: 200, }); + }); - it('should return a promise when no callback is given', (done) => { - grants.delete({ id }).then(done.bind(null, null)); + it('should delete a client grant', async () => { + await expect(clientGrantsManager.delete({ id: 'test-client-grant' })).resolves.toMatchObject({ + status: 204, }); + }); - it(`should perform a DELETE request to /client-grants/${id}`, (done) => { - grants.delete({ id }).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it('should get an organization by client grant', async () => { + await expect( + clientGrantsManager.getOrganizations({ id: 'test-client-grant' }) + ).resolves.toMatchObject({ + status: 200, }); }); }); diff --git a/test/management/fixtures/client-grants.json b/test/management/fixtures/client-grants.json new file mode 100644 index 000000000..c284b07e2 --- /dev/null +++ b/test/management/fixtures/client-grants.json @@ -0,0 +1,53 @@ +[ + { + "scope": "https://test-domain.auth0.com", + "method": "POST", + "path": "/api/v2/client-grants", + "body": { + "client_id": "test-client-id", + "audience": "test-aud", + "scope": ["read:foo", "write:foo"] + }, + "response": {}, + "status": 201 + }, + { + "scope": "https://test-domain.auth0.com", + "method": "GET", + "path": "/api/v2/client-grants?client_id=test-client-id", + "response": {}, + "status": 200 + }, + { + "scope": "https://test-domain.auth0.com", + "method": "GET", + "path": "/api/v2/client-grants?client_id=test-client-id&allow_any_organization=true", + "response": {}, + "status": 200 + }, + { + "scope": "https://test-domain.auth0.com", + "method": "PATCH", + "path": "/api/v2/client-grants/test-client-grant", + "body": { + "scope": ["read:foo", "read:bar"] + }, + "response": {}, + "status": 200 + }, + { + "scope": "https://test-domain.auth0.com", + "method": "DELETE", + "path": "/api/v2/client-grants/test-client-grant", + "body": "", + "status": 204, + "response": "" + }, + { + "scope": "https://test-domain.auth0.com", + "method": "GET", + "path": "/api/v2/client-grants/test-client-grant/organizations", + "status": 200, + "response": {} + } +] diff --git a/test/management/fixtures/organizations.json b/test/management/fixtures/organizations.json new file mode 100644 index 000000000..f005f7237 --- /dev/null +++ b/test/management/fixtures/organizations.json @@ -0,0 +1,156 @@ +[ + { + "scope": "https://test-domain.auth0.com", + "method": "POST", + "path": "/api/v2/organizations", + "body": { "name": "organization" }, + "status": 201, + "response": { + "name": "organization", + "id": "test-org", + "display_name": "organization" + } + }, + { + "scope": "https://test-domain.auth0.com", + "method": "PATCH", + "path": "/api/v2/organizations/test-org", + "body": { "name": "organization-2" }, + "status": 200, + "response": {} + }, + { + "scope": "https://test-domain.auth0.com", + "method": "GET", + "path": "/api/v2/organizations/test-org", + "body": "", + "status": 200, + "response": {} + }, + { + "scope": "https://test-domain.auth0.com", + "method": "POST", + "path": "/api/v2/organizations/test-org/enabled_connections", + "body": { + "connection_id": "test-conn", + "assign_membership_on_login": true + }, + "status": 201, + "response": { + "connection_id": "test-conn", + "assign_membership_on_login": true, + "connection": { "name": "OrganizationConnection", "strategy": "auth0" } + } + }, + { + "scope": "https://test-domain.auth0.com", + "method": "PATCH", + "path": "/api/v2/organizations/test-org/enabled_connections/test-conn", + "body": { "assign_membership_on_login": false }, + "status": 200, + "response": {} + }, + { + "scope": "https://test-domain.auth0.com", + "method": "GET", + "path": "/api/v2/organizations/test-org/enabled_connections", + "body": "", + "status": 200, + "response": {} + }, + { + "scope": "https://test-domain.auth0.com", + "method": "GET", + "path": "/api/v2/organizations/test-org/enabled_connections/test-conn", + "body": "", + "status": 200, + "response": {} + }, + { + "scope": "https://test-domain.auth0.com", + "method": "POST", + "path": "/api/v2/organizations/test-org/members", + "body": { "members": ["test-user"] }, + "status": 204, + "response": "" + }, + { + "scope": "https://test-domain.auth0.com", + "method": "GET", + "path": "/api/v2/organizations/test-org/members", + "body": "", + "status": 200, + "response": {} + }, + { + "scope": "https://test-domain.auth0.com", + "method": "POST", + "path": "/api/v2/organizations/test-org/members/test-user/roles", + "body": { "roles": ["test-role"] }, + "status": 204, + "response": "" + }, + { + "scope": "https://test-domain.auth0.com", + "method": "GET", + "path": "/api/v2/organizations/test-org/members/test-user/roles", + "body": "", + "status": 200, + "response": {} + }, + { + "scope": "https://test-domain.auth0.com", + "method": "DELETE", + "path": "/api/v2/organizations/test-org/members/test-user/roles", + "body": { "roles": ["test-role"] }, + "status": 204, + "response": "" + }, + { + "scope": "https://test-domain.auth0.com", + "method": "DELETE", + "path": "/api/v2/organizations/test-org/members", + "body": { "members": ["test-user"] }, + "status": 204, + "response": "" + }, + { + "scope": "https://test-domain.auth0.com", + "method": "DELETE", + "path": "/api/v2/organizations/test-org", + "body": "", + "status": 204, + "response": "" + }, + { + "scope": "https://test-domain.auth0.com", + "method": "POST", + "path": "/api/v2/organizations/test-org/client-grants", + "body": { + "grant_id": "test-grant" + }, + "status": 201, + "response": { + "grant_id": "test-grant", + "client_id": "test-client", + "audience": "ClientGrantTests", + "scope": ["openid", "profile"] + } + }, + { + "scope": "https://test-domain.auth0.com", + "method": "GET", + "path": "/api/v2/organizations/test-org/client-grants", + "body": "", + "status": 200, + "response": {} + }, + { + "scope": "https://test-domain.auth0.com", + "method": "DELETE", + "path": "/api/v2/organizations/test-org/client-grants/test-grant", + "body": "", + "status": 204, + "response": "" + } +] diff --git a/test/management/organizations.test.ts b/test/management/organizations.test.ts index 62e3f18c1..aebb8fa10 100644 --- a/test/management/organizations.test.ts +++ b/test/management/organizations.test.ts @@ -1,1380 +1,179 @@ import nock from 'nock'; -const API_URL = 'https://tenant.auth0.com/api/v2'; +const { back: nockBack } = nock; -import { OrganizationsManager, ManagementClient, RequiredError } from '../../src/index.js'; +import { OrganizationsManager, ManagementClient } from '../../src/index.js'; +import { afterAll, beforeAll } from '@jest/globals'; describe('OrganizationsManager', () => { - let organizations: OrganizationsManager; + let organizationsManager: OrganizationsManager; - let request: nock.Scope; - const token = 'TOKEN'; + let nockDone: () => void; + + beforeAll(async () => { + ({ nockDone } = await nockBack('management/fixtures/organizations.json')); - beforeAll(() => { const client = new ManagementClient({ - domain: 'tenant.auth0.com', - token: token, + domain: 'test-domain.auth0.com', + token: 'TOKEN', }); - organizations = client.organizations; + organizationsManager = client.organizations; }); - describe('#constructor', () => { - it('should throw an error when no base URL is provided', () => { - expect(() => { - new OrganizationsManager({} as any); - }).toThrowError(Error); - }); - - it('should throw an error when the base URL is invalid', () => { - expect(() => { - new OrganizationsManager({ baseUrl: '' } as any); - }).toThrowError(Error); - }); + afterAll(() => { + nockDone(); }); - describe('#getAll', () => { - beforeEach(() => { - request = nock(API_URL).get('/organizations').reply(200, []); - }); - - it('should return a promise if no callback is given', (done) => { - organizations.getAll().then(done.bind(null, null)).catch(done.bind(null, null)); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL).get('/organizations').reply(500, {}); - - organizations.getAll().catch((err) => { - expect(err).toBeDefined(); - done(); - }); - }); - - it('should pass the body of the response to the "then" handler', (done) => { - nock.cleanAll(); - - const data = [{ name: 'org 1' }]; - nock(API_URL).get('/organizations').reply(200, data); - - organizations.getAll().then((result) => { - expect(result.data).toBeInstanceOf(Array); - - expect(result.data.length).toBe(data.length); - - expect(result.data[0].name).toBe(data[0].name); - - done(); - }); - }); - - it('should perform a GET request to /api/v2/organizations', (done) => { - organizations.getAll().then(() => { - expect(request.isDone()).toBe(true); - done(); - }); - }); - - it('should include the token in the Authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .get('/organizations') - .matchHeader('Authorization', `Bearer ${token}`) - .reply(200, []); - - organizations.getAll().then(() => { - expect(request.isDone()).toBe(true); - done(); - }); - }); - - it('should pass the parameters in the query-string', (done) => { - nock.cleanAll(); - - const params = { - page: 0, - per_page: 5, - }; - const request = nock(API_URL).get('/organizations').query(params).reply(200, []); - - organizations.getAll(params).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it('should create an organization', async () => { + await expect(organizationsManager.create({ name: 'organization' })).resolves.toMatchObject({ + status: 201, + data: expect.objectContaining({ + name: 'organization', + id: 'test-org', + display_name: 'organization', + }), }); }); - describe('#getByID', () => { - const data = { - id: 'org_123456', - name: 'organizations', - display_name: 'My organization', - }; - - beforeEach(() => { - request = nock(API_URL).get(`/organizations/${data.id}`).reply(200, data); - }); - - it('should return a promise if no callback is given', (done) => { - organizations.get({ id: data.id }).then(done.bind(null, null)).catch(done.bind(null, null)); - }); - - it('should perform a GET request to /api/v2/organizations/:id', (done) => { - organizations.get({ id: data.id }).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL).get(`/organizations/${data.id}`).reply(500, {}); - - organizations.get({ id: data.id }).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should include the token in the Authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .get(`/organizations/${data.id}`) - .matchHeader('Authorization', `Bearer ${token}`) - .reply(200, {}); - - organizations.get({ id: data.id }).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it('should update an organization', async () => { + await expect( + organizationsManager.update({ id: 'test-org' }, { name: 'organization-2' }) + ).resolves.toMatchObject({ + status: 200, }); }); - describe('#getByName', () => { - const data = { - id: 'org_123456', - name: 'organizations', - display_name: 'My organization', - }; - - beforeEach(() => { - request = nock(API_URL).get(`/organizations/name/${data.name}`).reply(200, data); - }); - - it('should return a promise if no callback is given', (done) => { - organizations - .getByName({ name: data.name }) - .then(done.bind(null, null)) - .catch(done.bind(null, null)); - }); - - it('should perform a GET request to /api/v2/organizations/name/:name', (done) => { - organizations.getByName({ name: data.name }).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL).get(`/organizations/${data.name}`).reply(500, {}); - - organizations.getByName({ name: data.name }).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should include the token in the Authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .get(`/organizations/name/${data.name}`) - .matchHeader('Authorization', `Bearer ${token}`) - .reply(200, {}); - - organizations.getByName({ name: data.name }).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it('should get an organization', async () => { + await expect(organizationsManager.get({ id: 'test-org' })).resolves.toMatchObject({ + status: 200, }); }); - describe('#create', () => { - const data = { - id: 'org_123', - name: 'org_name', - display_name: 'My Organization', - }; - - beforeEach(() => { - request = nock(API_URL).post('/organizations').reply(200, data); - }); - - it('should return a promise if no callback is given', (done) => { - organizations.create(data).then(done.bind(null, null)).catch(done.bind(null, null)); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL).post('/organizations').reply(500, {}); - - organizations.create(data).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should perform a POST request to /api/v2/organizations', (done) => { - organizations.create(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should pass the data in the body of the request', (done) => { - nock.cleanAll(); - - const request = nock(API_URL).post('/organizations', data).reply(200, data); - - organizations.create(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should include the token in the Authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .post('/organizations') - .matchHeader('Authorization', `Bearer ${token}`) - .reply(200, {}); - - organizations.create(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it('should add a connection to an organization', async () => { + await expect( + organizationsManager.addEnabledConnection( + { id: 'test-org' }, + { connection_id: 'test-conn', assign_membership_on_login: true } + ) + ).resolves.toMatchObject({ + status: 201, + data: expect.objectContaining({ + connection_id: 'test-conn', + assign_membership_on_login: true, + }), }); }); - describe('#update', () => { - const data = { id: 'org_123' }; - - beforeEach(() => { - request = nock(API_URL).patch(`/organizations/${data.id}`).reply(200, data); - }); - - it('should accept a callback', (done) => { - organizations.update({ id: 'org_123' }, {}, done.bind(null, null)); - }); - - it('should return a promise if no callback is given', (done) => { - organizations - .update({ id: 'org_123' }, {}) - .then(done.bind(null, null)) - .catch(done.bind(null, null)); - }); - - it('should perform a PATCH request to /api/v2/organizations/org_123', (done) => { - organizations.update({ id: 'org_123' }, {}).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should include the new data in the body of the request', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .patch(`/organizations/${data.id}`, { name: 'test' }) - .reply(200, {}); - - organizations.update({ id: 'org_123' }, { name: 'test' }).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL).patch(`/organizations/${data.id}`).reply(500, {}); - - organizations.update({ id: data.id }, {}).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); + it('should update a connection on an organization', async () => { + await expect( + organizationsManager.updateEnabledConnection( + { id: 'test-org', connectionId: 'test-conn' }, + { assign_membership_on_login: false } + ) + ).resolves.toMatchObject({ + status: 200, }); }); - describe('#delete', () => { - const id = 'rol_ID'; - - beforeEach(() => { - request = nock(API_URL).delete(`/organizations/${id}`).reply(200, {}); - }); - - it('should return a promise when no callback is given', (done) => { - organizations.delete({ id }).then(done.bind(null, null)); - }); - - it(`should perform a delete request to /organizations/${id}`, (done) => { - organizations.delete({ id }).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL).delete(`/organizations/${id}`).reply(500, {}); - - organizations.delete({ id }).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should include the token in the authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .delete(`/organizations/${id}`) - .matchHeader('authorization', `Bearer ${token}`) - .reply(200, {}); - - organizations.delete({ id }).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - }); - - //// Connections - describe('#getEnabledConnections', () => { - const data = { - id: 'org_id', - }; - - beforeEach(() => { - request = nock(API_URL).get(`/organizations/${data.id}/enabled_connections`).reply(200, []); - }); - - it('should return a promise when no callback is given', (done) => { - organizations.getEnabledConnections(data).then(done.bind(null, null)); - }); - - it('should perform a GET request to /api/v2/organizations/org_id/enabled_connections', (done) => { - organizations.getEnabledConnections(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL).get(`/organizations/${data.id}/enabled_connections`).reply(500, {}); - - organizations.getEnabledConnections(data).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should include the token in the authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .get(`/organizations/${data.id}/enabled_connections`) - .matchHeader('authorization', `Bearer ${token}`) - .reply(200, []); - - organizations.getEnabledConnections(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - }); - - describe('#getEnabledConnection', () => { - const data = { - id: 'org_id', - connectionId: 'conn_id', - }; - - beforeEach(() => { - request = nock(API_URL) - .get(`/organizations/${data.id}/enabled_connections/${data.connectionId}`) - .reply(200, {}); - }); - - it('should return a promise when no callback is given', (done) => { - organizations.getEnabledConnection(data).then(done.bind(null, null)); - }); - - it('should perform a GET request to /api/v2/organizations/rol_ID/enabled_connections/con_id', (done) => { - organizations.getEnabledConnection(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL) - .get(`/organizations/${data.id}/enabled_connections/${data.connectionId}`) - .reply(500, {}); - - organizations.getEnabledConnection(data).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should include the token in the authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .get(`/organizations/${data.id}/enabled_connections/${data.connectionId}`) - .matchHeader('authorization', `Bearer ${token}`) - .reply(200, {}); - - organizations.getEnabledConnection(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - }); - - describe('#addEnabledConnection', () => { - const data = { - id: 'org_123', - }; - - const body = { connection_id: '123', assign_membership_on_login: false }; - - beforeEach(() => { - request = nock(API_URL).post(`/organizations/${data.id}/enabled_connections`).reply(200, {}); - }); - - it('should return a promise if no callback is given', (done) => { - organizations - .addEnabledConnection(data, { connection_id: '' }) - .then(done.bind(null, null)) - .catch(done.bind(null, null)); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL).post(`/organizations/${data.id}/enabled_connections`).reply(500, {}); - - organizations.addEnabledConnection(data, { connection_id: '' }).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should perform a POST request to /api/v2/organizations/org_id/enabled_connections', (done) => { - organizations.addEnabledConnection(data, body).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should pass the data in the body of the request', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .post(`/organizations/${data.id}/enabled_connections`, body) - .reply(200, {}); - - organizations.addEnabledConnection(data, body).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should include the token in the Authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .post(`/organizations/${data.id}/enabled_connections`) - .matchHeader('Authorization', `Bearer ${token}`) - .reply(200, {}); - - organizations.addEnabledConnection(data, { connection_id: '' }).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it(`should get an organization's connections`, async () => { + await expect( + organizationsManager.getEnabledConnections({ id: 'test-org' }) + ).resolves.toMatchObject({ + status: 200, }); }); - describe('#updateEnabledConnection', () => { - const data = { - id: 'org_123', - connectionId: '123', - }; - const body = { assign_membership_on_login: false }; - - beforeEach(() => { - request = nock(API_URL) - .patch(`/organizations/${data.id}/enabled_connections/${data.connectionId}`) - .reply(200, {}); - }); - - it('should return a promise if no callback is given', (done) => { - organizations - .updateEnabledConnection(data, body) - .then(done.bind(null, null)) - .catch(done.bind(null, null)); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL) - .patch(`/organizations/${data.id}/enabled_connections/${data.connectionId}`) - .reply(500, {}); - - organizations.updateEnabledConnection(data, body).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should perform a PATCH request to /api/v2/organizations/org_id/enabled_connections/conn_id', (done) => { - organizations.updateEnabledConnection(data, body).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should return error when id is not sent', async () => { - await expect( - organizations.updateEnabledConnection({} as any, {} as any) - ).rejects.toThrowError(RequiredError); - }); - - it('should return error when connectionId is not sent', () => { - expect( - organizations.updateEnabledConnection({ id: 'test' } as any, {} as any) - ).rejects.toThrowError(RequiredError); - }); - - it('should pass the data in the body of the request', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .patch(`/organizations/${data.id}/enabled_connections/${data.connectionId}`, body) - .reply(200, {}); - - organizations.updateEnabledConnection(data, body).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should include the token in the Authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .patch(`/organizations/${data.id}/enabled_connections/${data.connectionId}`) - .matchHeader('Authorization', `Bearer ${token}`) - .reply(200, {}); - - organizations.updateEnabledConnection(data, body).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - }); - - describe('#deleteEnabledConnection', () => { - const data = { - id: 'org_123', - connectionId: '123', - }; - - beforeEach(() => { - request = nock(API_URL) - .delete(`/organizations/${data.id}/enabled_connections/${data.connectionId}`) - .reply(200, {}); - }); - - it('should validate empty organizationId', async () => { - await expect( - organizations.deleteEnabledConnection({} as any, {} as any) - ).rejects.toThrowError(RequiredError); - }); - - it('should validate empty connectionId', async () => { - await expect( - organizations.deleteEnabledConnection({ id: '123' } as any, {} as any) - ).rejects.toThrowError(RequiredError); - }); - - it('should return a promise if no callback is given', (done) => { - organizations - .deleteEnabledConnection(data) - .then(done.bind(null, null)) - .catch(done.bind(null, null)); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL) - .delete(`/organizations/${data.id}/enabled_connections/${data.connectionId}`) - .reply(500, {}); - - organizations.deleteEnabledConnection(data, {}).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should perform a DELETE request to /api/v2/organizations/organization_id/enabled_connections/connection_id', (done) => { - organizations.deleteEnabledConnection(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should include the token in the Authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .delete(`/organizations/${data.id}/enabled_connections/${data.connectionId}`) - .matchHeader('Authorization', `Bearer ${token}`) - .reply(200, {}); - - organizations.deleteEnabledConnection(data, {}).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it(`should get an organization's connection by id`, async () => { + await expect( + organizationsManager.getEnabledConnection({ id: 'test-org', connectionId: 'test-conn' }) + ).resolves.toMatchObject({ + status: 200, }); }); - //// Members - describe('#getMembers', () => { - const data = { - id: 'org_id', - }; - - beforeEach(() => { - request = nock(API_URL).get(`/organizations/${data.id}/members`).reply(200, []); - }); - - it('should return a promise when no callback is given', (done) => { - organizations.getMembers(data).then(done.bind(null, null)); - }); - - it('should perform a GET request to /api/v2/organizations/org_ID/members', (done) => { - organizations.getMembers(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL).get(`/organizations/${data.id}/members`).reply(500, {}); - - organizations.getMembers(data).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should include the token in the authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .get(`/organizations/${data.id}/members`) - .matchHeader('authorization', `Bearer ${token}`) - .reply(200, []); - - organizations.getMembers(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it(`should add a member to an organization`, async () => { + await expect( + organizationsManager.addMembers({ id: 'test-org' }, { members: ['test-user'] }) + ).resolves.toMatchObject({ + status: 204, }); }); - describe('#addMembers', () => { - const data = { - id: 'org_123', - }; - const body = { members: [] }; - - beforeEach(() => { - request = nock(API_URL).post(`/organizations/${data.id}/members`).reply(200, {}); - }); - - it('should return a promise if no callback is given', (done) => { - organizations - .addMembers(data, { members: [] }) - .then(done.bind(null, null)) - .catch(done.bind(null, null)); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL).post(`/organizations/${data.id}/members`).reply(500, {}); - - organizations.addMembers(data, { members: [] }).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should perform a POST request to /api/v2/organizations/org_id/members', (done) => { - organizations.addMembers(data, { members: [] }).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should return error when id is not sent', async () => { - await expect(organizations.addMembers({} as any, {} as any)).rejects.toThrowError( - RequiredError - ); - }); - - it('should pass the data in the body of the request', (done) => { - nock.cleanAll(); - - const request = nock(API_URL).post(`/organizations/${data.id}/members`, body).reply(200, {}); - - organizations.addMembers(data, body).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should include the token in the Authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .post(`/organizations/${data.id}/members`) - .matchHeader('Authorization', `Bearer ${token}`) - .reply(200, {}); - - organizations.addMembers(data, { members: [] }).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it(`should get an organization's members`, async () => { + await expect(organizationsManager.getMembers({ id: 'test-org' })).resolves.toMatchObject({ + status: 200, }); }); - describe('#removeMembers', () => { - const data = { id: 'org_123' }; - const body = { members: ['user_id'] }; - - beforeEach(() => { - request = nock(API_URL).delete(`/organizations/${data.id}/members`, {}).reply(200, {}); - }); - - it('should validate empty organizationId', async () => { - await expect(organizations.deleteMembers({} as any, {} as any)).rejects.toThrowError( - RequiredError - ); - }); - - it('should return a promise if no callback is given', (done) => { - organizations - .deleteMembers(data, body) - .then(done.bind(null, null)) - .catch(done.bind(null, null)); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL).delete(`/organizations/${data.id}/members`).reply(500, {}); - - organizations.deleteMembers(data, body).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should perform a DELETE request to /api/v2/organizations/organization_id/members', (done) => { - const request = nock(API_URL) - .delete(`/organizations/${data.id}/members`, body) - .reply(200, {}); - - organizations.deleteMembers(data, body).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should include the token in the Authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .delete(`/organizations/${data.id}/members`, body) - .matchHeader('Authorization', `Bearer ${token}`) - .reply(200, {}); - - organizations.deleteMembers(data, body).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it(`should add roles to a member`, async () => { + await expect( + organizationsManager.addMemberRoles( + { id: 'test-org', user_id: 'test-user' }, + { roles: ['test-role'] } + ) + ).resolves.toMatchObject({ + status: 204, }); }); - //// Roles - describe('#getMemberRoles', () => { - const data = { - id: 'org_id', - user_id: 'user_123', - }; - - beforeEach(() => { - request = nock(API_URL) - .get(`/organizations/${data.id}/members/${data.user_id}/roles`) - .reply(200, []); - }); - - it('should return a promise when no callback is given', (done) => { - organizations.getMemberRoles(data).then(done.bind(null, null)); - }); - - it('should perform a GET request to /api/v2/organizations/org_ID/members/user_id/roles', (done) => { - organizations.getMemberRoles(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL).get(`/organizations/${data.id}/members/${data.user_id}/roles`).reply(500, {}); - - organizations.getMemberRoles(data).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should include the token in the authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .get(`/organizations/${data.id}/members/${data.user_id}/roles`) - .matchHeader('authorization', `Bearer ${token}`) - .reply(200, []); - - organizations.getMemberRoles(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it(`should get a member's roles`, async () => { + await expect( + organizationsManager.getMemberRoles({ id: 'test-org', user_id: 'test-user' }) + ).resolves.toMatchObject({ + status: 200, }); }); - describe('#addMemberRoles', () => { - const data = { - id: 'org_123', - user_id: 'user_id', - }; - const body = { roles: ['user_id'] }; - - beforeEach(() => { - request = nock(API_URL) - .post(`/organizations/${data.id}/members/${data.user_id}/roles`, body) - .reply(200, {}); - }); - - it('should return a promise if no callback is given', (done) => { - organizations - .addMemberRoles(data, body) - .then(done.bind(null, null)) - .catch(done.bind(null, null)); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL).post(`/organizations/${data.id}/members/${data.user_id}/roles`).reply(500, {}); - - organizations.addMemberRoles(data, { roles: [] }).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should perform a POST request to /api/v2/organizations/org_id/members/user_id/roles', (done) => { - organizations.addMemberRoles(data, body).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should return error when id is not sent', async () => { - await expect(organizations.addMemberRoles({} as any, {} as any)).rejects.toThrowError( - RequiredError - ); - }); - - it('should pass the data in the body of the request', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .post(`/organizations/${data.id}/members/${data.user_id}/roles`, body) - .reply(200, {}); - - organizations.addMemberRoles(data, body).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should include the token in the Authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .post(`/organizations/${data.id}/members/${data.user_id}/roles`) - .matchHeader('Authorization', `Bearer ${token}`) - .reply(200, {}); - - organizations.addMemberRoles(data, { roles: [] }).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it(`should delete roles from a member`, async () => { + await expect( + organizationsManager.deleteMemberRoles( + { id: 'test-org', user_id: 'test-user' }, + { roles: ['test-role'] } + ) + ).resolves.toMatchObject({ + status: 204, }); }); - describe('#deleteMemberRoles', () => { - const data = { - id: 'org_123', - user_id: 'user_123', - }; - - const body = { roles: ['user_id'] }; - - beforeEach(() => { - request = nock(API_URL) - .delete(`/organizations/${data.id}/members/${data.user_id}/roles`, {}) - .reply(200, {}); - }); - - it('should validate empty id', async () => { - await expect(organizations.deleteMemberRoles({} as any, {} as any)).rejects.toThrowError( - RequiredError - ); - }); - - it('should return a promise if no callback is given', (done) => { - organizations - .deleteMemberRoles(data, body) - .then(done.bind(null, null)) - .catch(done.bind(null, null)); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL) - .delete(`/organizations/${data.id}/members/${data.user_id}/roles`) - .reply(500, {}); - - organizations.deleteMemberRoles(data, body).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should return error when user_id is not sent', () => { - expect( - organizations.deleteMemberRoles({ id: 'org_1' } as any, {} as any) - ).rejects.toThrowError(RequiredError); - }); - - it('should perform a DELETE request to /api/v2/organizations/organization_id/members/user_id/roles', (done) => { - const request = nock(API_URL) - .delete(`/organizations/${data.id}/members/${data.user_id}/roles`, body) - .reply(200, {}); - - organizations.deleteMemberRoles(data, body).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should include the token in the Authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .delete(`/organizations/${data.id}/members/${data.user_id}/roles`, body) - .matchHeader('Authorization', `Bearer ${token}`) - .reply(200, {}); - - organizations.deleteMemberRoles(data, body).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it('should associate a client grant with an organization', async () => { + await expect( + organizationsManager.addClientGrant({ id: 'test-org' }, { grant_id: 'test-grant' }) + ).resolves.toMatchObject({ + status: 201, + data: expect.objectContaining({ + grant_id: 'test-grant', + client_id: 'test-client', + audience: 'ClientGrantTests', + scope: ['openid', 'profile'], + }), }); }); - //// Invites - describe('#getInvitations', () => { - const data = { - id: 'org_id', - }; - - beforeEach(() => { - request = nock(API_URL).get(`/organizations/${data.id}/invitations`).reply(200, []); - }); - - it('should return a promise when no callback is given', (done) => { - organizations.getInvitations(data).then(done.bind(null, null)); - }); - - it('should perform a GET request to /api/v2/organizations/org_ID/invitations', (done) => { - organizations.getInvitations(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL).get(`/organizations/${data.id}/invitations`).reply(500, {}); - - organizations.getInvitations(data).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should include the token in the authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .get(`/organizations/${data.id}/invitations`) - .matchHeader('authorization', `Bearer ${token}`) - .reply(200, []); - - organizations.getInvitations(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it(`should get client grants for an organization`, async () => { + await expect(organizationsManager.getClientGrants({ id: 'test-org' })).resolves.toMatchObject({ + status: 200, }); }); - describe('#getInvitation', () => { - const data = { - id: 'org_id', - invitation_id: 'inv_123', - }; - - beforeEach(() => { - request = nock(API_URL) - .get(`/organizations/${data.id}/invitations/${data.invitation_id}`) - .reply(200, {}); - }); - - it('should return a promise when no callback is given', (done) => { - organizations.getInvitation(data).then(done.bind(null, null)); - }); - - it('should perform a GET request to /api/v2/organizations/rol_ID/invitations/inv_id', (done) => { - organizations.getInvitation(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL) - .get(`/organizations/${data.id}/invitations/${data.invitation_id}`) - .reply(500, {}); - - organizations.getInvitation(data).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should return error when id is not sent', async () => { - await expect(organizations.getInvitation({} as any, {} as any)).rejects.toThrowError( - RequiredError - ); - }); - - it('should return error when invitation_id is not sent', async () => { - await expect( - organizations.getInvitation({ id: '123' } as any, {} as any) - ).rejects.toThrowError(RequiredError); - }); - - it('should include the token in the authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .get(`/organizations/${data.id}/invitations/${data.invitation_id}`) - .matchHeader('authorization', `Bearer ${token}`) - .reply(200, {}); - - organizations.getInvitation(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it(`should delete client grants for an organization`, async () => { + await expect( + organizationsManager.deleteClientGrant({ id: 'test-org', grant_id: 'test-grant' }) + ).resolves.toMatchObject({ + status: 204, }); }); - describe('#createInvitation', () => { - const data = { - id: 'org_123', - }; - - beforeEach(() => { - request = nock(API_URL).post(`/organizations/${data.id}/invitations`).reply(200, {}); - }); - - it('should return a promise if no callback is given', (done) => { - organizations - .createInvitation(data, { - client_id: '123', - invitee: { email: '12' }, - inviter: { name: '12' }, - }) - .then(done.bind(null, null)) - .catch(done.bind(null, null)); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL).post(`/organizations/${data.id}/invitations`).reply(500, {}); - - organizations - .createInvitation(data, { - client_id: '123', - invitee: { email: '12' }, - inviter: { name: '12' }, - }) - .catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should perform a POST request to /api/v2/organizations/org_id/invitations', (done) => { - organizations - .createInvitation(data, { - client_id: '123', - invitee: { email: '12' }, - inviter: { name: '12' }, - }) - .then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should return error when id is not sent', async () => { - await expect(organizations.createInvitation({} as any, {} as any)).rejects.toThrowError( - RequiredError - ); - }); - - it('should pass the data in the body of the request', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .post(`/organizations/${data.id}/invitations`, { - client_id: '123', - invitee: { email: '12' }, - inviter: { name: '12' }, - }) - .reply(200, {}); - - organizations - .createInvitation(data, { - client_id: '123', - invitee: { email: '12' }, - inviter: { name: '12' }, - }) - .then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should include the token in the Authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .post(`/organizations/${data.id}/invitations`) - .matchHeader('Authorization', `Bearer ${token}`) - .reply(200, {}); - - organizations - .createInvitation(data, { - client_id: '123', - invitee: { email: '12' }, - inviter: { name: '12' }, - }) - .then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it(`should delete a member`, async () => { + await expect( + organizationsManager.deleteMembers({ id: 'test-org' }, { members: ['test-user'] }) + ).resolves.toMatchObject({ + status: 204, }); }); - describe('#deleteInvitation', () => { - const data = { - id: 'org_123', - invitation_id: 'inv_123', - }; - - beforeEach(() => { - request = nock(API_URL) - .delete(`/organizations/${data.id}/invitations/${data.invitation_id}`) - .reply(200, {}); - }); - - it('should validate empty id', async () => { - await expect(organizations.deleteInvitation({} as any, {} as any)).rejects.toThrowError( - RequiredError - ); - }); - - it('should return a promise if no callback is given', (done) => { - organizations.deleteInvitation(data).then(done.bind(null, null)).catch(done.bind(null, null)); - }); - - it('should pass any errors to the promise catch handler', (done) => { - nock.cleanAll(); - - nock(API_URL) - .delete(`/organizations/${data.id}/invitations/${data.invitation_id}`, {}) - .reply(500, {}); - - organizations.deleteInvitation(data).catch((err) => { - expect(err).toBeDefined(); - - done(); - }); - }); - - it('should perform a DELETE request to /api/v2/organizations/organization_id/invitations/inv_id', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .delete(`/organizations/${data.id}/invitations/${data.invitation_id}`) - .reply(200, {}); - - organizations.deleteInvitation(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); - }); - - it('should return error when invitation_id is not sent', () => { - expect( - organizations.deleteInvitation({ id: 'org_123' } as any, {} as any) - ).rejects.toThrowError(RequiredError); - }); - - it('should include the token in the Authorization header', (done) => { - nock.cleanAll(); - - const request = nock(API_URL) - .delete(`/organizations/${data.id}/invitations/${data.invitation_id}`) - .matchHeader('Authorization', `Bearer ${token}`) - .reply(200, {}); - - organizations.deleteInvitation(data).then(() => { - expect(request.isDone()).toBe(true); - - done(); - }); + it(`should delete an organization`, async () => { + await expect(organizationsManager.delete({ id: 'test-org' })).resolves.toMatchObject({ + status: 204, }); }); });