From 8796b099a96adb79c1cc32fd8604e5cc68e1a1c5 Mon Sep 17 00:00:00 2001 From: Rosalie Liu <52677246+rosalie-liu@users.noreply.github.com> Date: Thu, 17 Oct 2019 12:23:56 -0400 Subject: [PATCH] feat(apikeys): implement the base paths for the api keys resource (#22) feat(apikeys): implement the base paths for the api keys resource --- src/resources/ApiKeys/ApiKeys.ts | 34 ++++++++ src/resources/ApiKeys/ApiKeysInterfaces.ts | 22 +++++ src/resources/ApiKeys/index.ts | 2 + src/resources/ApiKeys/test/ApiKeys.spec.ts | 97 ++++++++++++++++++++++ src/resources/BaseInterfaces.ts | 21 +++++ src/resources/Groups/GroupsInterfaces.ts | 23 +---- src/resources/PlatformResources.ts | 3 + 7 files changed, 181 insertions(+), 21 deletions(-) create mode 100644 src/resources/ApiKeys/ApiKeys.ts create mode 100644 src/resources/ApiKeys/ApiKeysInterfaces.ts create mode 100644 src/resources/ApiKeys/index.ts create mode 100644 src/resources/ApiKeys/test/ApiKeys.spec.ts diff --git a/src/resources/ApiKeys/ApiKeys.ts b/src/resources/ApiKeys/ApiKeys.ts new file mode 100644 index 000000000..53d75853d --- /dev/null +++ b/src/resources/ApiKeys/ApiKeys.ts @@ -0,0 +1,34 @@ +import API from '../../APICore'; +import {New} from '../BaseInterfaces'; +import Resource from '../Resource'; +import {ApiKeyModel, CreateApiKeyOptions} from './ApiKeysInterfaces'; + +export default class ApiKey extends Resource { + static baseUrl = `/rest/organizations/${API.orgPlaceholder}/apikeys`; + + list() { + return this.api.get(ApiKey.baseUrl); + } + + create(apiKey: New, options?: CreateApiKeyOptions) { + return this.api.post(this.buildPath(ApiKey.baseUrl, options), apiKey); + } + + get(apiKeyId: string) { + return this.api.get(`${ApiKey.baseUrl}/${apiKeyId}`); + } + + update(apiKey: ApiKeyModel) { + return this.api.put(`${ApiKey.baseUrl}/${apiKey.id}`, apiKey); + } + + toggle(apiKey: ApiKeyModel) { + const path = `${ApiKey.baseUrl}/${apiKey.id}/${apiKey.enabled ? 'disable' : 'activate'}`; + + return this.api.put(path, apiKey); + } + + delete(apiKeyId: string) { + return this.api.delete(`${ApiKey.baseUrl}/${apiKeyId}`); + } +} diff --git a/src/resources/ApiKeys/ApiKeysInterfaces.ts b/src/resources/ApiKeys/ApiKeysInterfaces.ts new file mode 100644 index 000000000..ede64b8a8 --- /dev/null +++ b/src/resources/ApiKeys/ApiKeysInterfaces.ts @@ -0,0 +1,22 @@ +import {IdAndDisplayNameModel, PrivilegeModel} from '../BaseInterfaces'; + +export interface ApiKeyModel { + organizationId?: string; + id?: string; + enabled?: boolean; + value?: string; + displayName?: string; + description?: string; + createdBy?: {}; + createdDate?: number; + allowedIps?: string[]; + apiKeysThatCanEdit?: IdAndDisplayNameModel[]; + deniedIps?: string[]; + groupsThatCanEdit?: IdAndDisplayNameModel[]; + privileges?: PrivilegeModel[]; + resourceId?: string; +} + +export interface CreateApiKeyOptions { + apiKeyTemplateId?: string; +} diff --git a/src/resources/ApiKeys/index.ts b/src/resources/ApiKeys/index.ts new file mode 100644 index 000000000..fc80b6c64 --- /dev/null +++ b/src/resources/ApiKeys/index.ts @@ -0,0 +1,2 @@ +export * from './ApiKeys'; +export * from './ApiKeysInterfaces'; diff --git a/src/resources/ApiKeys/test/ApiKeys.spec.ts b/src/resources/ApiKeys/test/ApiKeys.spec.ts new file mode 100644 index 000000000..6b7be3b47 --- /dev/null +++ b/src/resources/ApiKeys/test/ApiKeys.spec.ts @@ -0,0 +1,97 @@ +import API from '../../../APICore'; +import {New} from '../../BaseInterfaces'; +import ApiKey from '../ApiKeys'; +import {ApiKeyModel} from '../ApiKeysInterfaces'; + +jest.mock('../../../APICore'); + +const APIMock: jest.Mock = API as any; + +describe('ApiKey', () => { + let apiKey: ApiKey; + const api = new APIMock() as jest.Mocked; + + beforeEach(() => { + jest.clearAllMocks(); + apiKey = new ApiKey(api); + }); + + describe('list', () => { + it('should make a GET call to the ApiKeys base url', () => { + apiKey.list(); + expect(api.get).toHaveBeenCalledTimes(1); + expect(api.get).toHaveBeenCalledWith(ApiKey.baseUrl); + }); + }); + + describe('create', () => { + it('should make a POST call to the ApiKeys base url', () => { + const apiKeyModel: New = { + organizationId: 'a-smol-org', + value: '', + }; + + apiKey.create(apiKeyModel); + expect(api.post).toHaveBeenCalledTimes(1); + expect(api.post).toHaveBeenCalledWith(ApiKey.baseUrl, apiKeyModel); + }); + }); + + describe('get', () => { + it('should make a GET call to the specific ApiKey url', () => { + const apiKeyToGetId = 'ApiKey-to-be-fetched'; + + apiKey.get(apiKeyToGetId); + expect(api.get).toHaveBeenCalledTimes(1); + expect(api.get).toHaveBeenCalledWith(`${ApiKey.baseUrl}/${apiKeyToGetId}`); + }); + }); + + describe('update', () => { + it('should make a PUT call to the specific ApiKey url', () => { + const apiKeyModel: ApiKeyModel = { + organizationId: 'a-smol-org', + id: 'a-specific-id', + value: '', + }; + + apiKey.update(apiKeyModel); + expect(api.put).toHaveBeenCalledTimes(1); + expect(api.put).toHaveBeenCalledWith(`${ApiKey.baseUrl}/${apiKeyModel.id}`, apiKeyModel); + }); + }); + + describe('delete', () => { + it('should make a DELETE call to the specific ApiKey url', () => { + const apiKeyToDeleteId = 'ApiKey-to-be-deleted'; + + apiKey.delete(apiKeyToDeleteId); + expect(api.delete).toHaveBeenCalledTimes(1); + expect(api.delete).toHaveBeenCalledWith(`${ApiKey.baseUrl}/${apiKeyToDeleteId}`); + }); + }); + + describe('toggle', () => { + const apiKeyModel: ApiKeyModel = { + id: 'ApiKey-to-be-toggled', + organizationId: 'a-smol-org', + enabled: null, + }; + + it('should make a PUT call to disable the specific apiKey', () => { + apiKeyModel.enabled = true; + + apiKey.toggle(apiKeyModel); + expect(api.put).toHaveBeenCalledTimes(1); + expect(api.put).toHaveBeenCalledWith(`${ApiKey.baseUrl}/${apiKeyModel.id}/disable`, apiKeyModel); + }); + + it('should make a PUT call to activate the specific apiKey', () => { + apiKeyModel.enabled = false; + + apiKey.toggle(apiKeyModel); + expect(api.put).toHaveBeenCalledTimes(1); + expect(api.put).toHaveBeenCalledWith(`${ApiKey.baseUrl}/${apiKeyModel.id}/activate`, apiKeyModel); + }); + }); +}); diff --git a/src/resources/BaseInterfaces.ts b/src/resources/BaseInterfaces.ts index 0a9ee6b18..ca608b75b 100644 --- a/src/resources/BaseInterfaces.ts +++ b/src/resources/BaseInterfaces.ts @@ -5,3 +5,24 @@ export interface PageModel { } export type New = Omit; + +export enum AuthProvider { + SALESFORCE = 'SALESFORCE', + SALESFORCE_SANDBOX = 'SALESFORCE_SANDBOX', + GOOGLE = 'GOOGLE', + OFFICE365 = 'OFFICE365', + SAML = 'SAML', + EMAIL = 'EMAIL', +} + +export interface IdAndDisplayNameModel { + id: string; + displayName?: string; +} + +export interface PrivilegeModel { + owner: string; + targetDomain: string; + targetId: string; + type?: string; +} diff --git a/src/resources/Groups/GroupsInterfaces.ts b/src/resources/Groups/GroupsInterfaces.ts index 4fac48ef9..20dc758da 100644 --- a/src/resources/Groups/GroupsInterfaces.ts +++ b/src/resources/Groups/GroupsInterfaces.ts @@ -1,3 +1,5 @@ +import {AuthProvider, IdAndDisplayNameModel, PrivilegeModel} from '../BaseInterfaces'; + export interface GroupModel { id: string; displayName: string; @@ -11,11 +13,6 @@ export interface GroupModel { apiKeysThatCanEdit?: IdAndDisplayNameModel[]; } -export interface IdAndDisplayNameModel { - id: string; - displayName?: string; -} - export interface InviteByEmail { id: string; email: string; @@ -60,13 +57,6 @@ export interface MemberModel { providerUsername?: string; } -export interface PrivilegeModel { - owner: string; - targetDomain: string; - targetId?: string; - type?: string; -} - export interface RealmModel { id: string; provider: AuthProvider; @@ -74,15 +64,6 @@ export interface RealmModel { samlIdentityProviderId?: string; } -export enum AuthProvider { - SALESFORCE = 'SALESFORCE', - SALESFORCE_SANDBOX = 'SALESFORCE_SANDBOX', - GOOGLE = 'GOOGLE', - OFFICE365 = 'OFFICE365', - SAML = 'SAML', - EMAIL = 'EMAIL', -} - export interface CreateGroupOptions { canEditItself?: boolean; sendEmailToInviteUsers?: boolean; diff --git a/src/resources/PlatformResources.ts b/src/resources/PlatformResources.ts index 7a1f659f5..e93529fa4 100644 --- a/src/resources/PlatformResources.ts +++ b/src/resources/PlatformResources.ts @@ -1,4 +1,5 @@ import API from '../APICore'; +import ApiKey from './ApiKeys/ApiKeys'; import Catalog from './Catalogs/Catalog'; import Group from './Groups/Groups'; import Organization from './Organizations/Organization'; @@ -8,6 +9,7 @@ const resourcesMap: Array<{key: string; resource: typeof Resource}> = [ {key: 'catalog', resource: Catalog}, {key: 'group', resource: Group}, {key: 'organization', resource: Organization}, + {key: 'apiKey', resource: ApiKey}, ]; class PlatformResources { @@ -16,6 +18,7 @@ class PlatformResources { catalog: Catalog; group: Group; organization: Organization; + apiKey: ApiKey; registerAll() { resourcesMap.forEach(({key, resource}) => {