diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts index 20cc35f423..d9bfb1eebd 100644 --- a/packages/catalog-client/src/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -72,7 +72,7 @@ describe('CatalogClient', () => { }); it('should entities from correct endpoint', async () => { - const response = await client.getEntities(token); + const response = await client.getEntities({}, { token }); expect(response).toEqual(defaultResponse); }); @@ -86,13 +86,16 @@ describe('CatalogClient', () => { }), ); - const response = await client.getEntities(token, { - filter: { - a: '1', - b: ['2', '3'], - ö: '=', + const response = await client.getEntities( + { + filter: { + a: '1', + b: ['2', '3'], + ö: '=', + }, }, - }); + { token }, + ); expect(response.items).toEqual([]); }); @@ -107,9 +110,12 @@ describe('CatalogClient', () => { }), ); - const response = await client.getEntities(token, { - fields: ['a.b', 'ö'], - }); + const response = await client.getEntities( + { + fields: ['a.b', 'ö'], + }, + { token }, + ); expect(response.items).toEqual([]); }); diff --git a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts index 0fad8122f4..9967a7be17 100644 --- a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts +++ b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts @@ -48,7 +48,10 @@ export class CatalogIdentityClient { filter[`metadata.annotations.${key}`] = value; } - const { items } = await this.catalogClient.getEntities(token, { filter }); + const { items } = await this.catalogClient.getEntities( + { filter }, + { token }, + ); if (items.length !== 1) { if (items.length > 1) { diff --git a/plugins/auth-backend/src/providers/aws-alb/provider.test.ts b/plugins/auth-backend/src/providers/aws-alb/provider.test.ts index d05b6bbfaf..536ba71f6b 100644 --- a/plugins/auth-backend/src/providers/aws-alb/provider.test.ts +++ b/plugins/auth-backend/src/providers/aws-alb/provider.test.ts @@ -14,6 +14,7 @@ * limitations under the License. */ import { getVoidLogger } from '@backstage/backend-common'; +import { CatalogClient } from '@backstage/catalog-client'; import express from 'express'; import { JWT } from 'jose'; @@ -43,6 +44,9 @@ jest.mock('cross-fetch', () => ({ }, })); +jest.mock('@backstage/catalog-client'); +const MockedCatalogClient = CatalogClient as jest.Mock; + const identityResolutionCallbackMock = async (): Promise> => { return { backstageIdentity: { @@ -67,15 +71,7 @@ beforeEach(() => { }); describe('AwsALBAuthProvider', () => { - const catalogApi = { - /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ - addLocation: jest.fn(), - getEntities: jest.fn(), - getLocationByEntity: jest.fn(), - getLocationById: jest.fn(), - removeEntityByUid: jest.fn(), - getEntityByName: jest.fn(), - }; + const catalogClient = new MockedCatalogClient(); const mockResponseSend = jest.fn(); const mockRequest = ({ @@ -95,7 +91,7 @@ describe('AwsALBAuthProvider', () => { describe('should transform to type OAuthResponse', () => { it('when JWT is valid and identity is resolved successfully', async () => { - const provider = new AwsAlbAuthProvider(getVoidLogger(), catalogApi, { + const provider = new AwsAlbAuthProvider(getVoidLogger(), catalogClient, { region: 'us-west-2', identityResolutionCallback: identityResolutionCallbackMock, issuer: 'foo', @@ -121,7 +117,7 @@ describe('AwsALBAuthProvider', () => { }); describe('should fail when', () => { it('JWT is missing', async () => { - const provider = new AwsAlbAuthProvider(getVoidLogger(), catalogApi, { + const provider = new AwsAlbAuthProvider(getVoidLogger(), catalogClient, { region: 'us-west-2', identityResolutionCallback: identityResolutionCallbackMock, issuer: 'foo', @@ -133,7 +129,7 @@ describe('AwsALBAuthProvider', () => { }); it('JWT is invalid', async () => { - const provider = new AwsAlbAuthProvider(getVoidLogger(), catalogApi, { + const provider = new AwsAlbAuthProvider(getVoidLogger(), catalogClient, { region: 'us-west-2', identityResolutionCallback: identityResolutionCallbackMock, issuer: 'foo', @@ -149,7 +145,7 @@ describe('AwsALBAuthProvider', () => { }); it('issuer is invalid', async () => { - const provider = new AwsAlbAuthProvider(getVoidLogger(), catalogApi, { + const provider = new AwsAlbAuthProvider(getVoidLogger(), catalogClient, { region: 'us-west-2', identityResolutionCallback: identityResolutionCallbackMock, issuer: 'foobar', @@ -163,7 +159,7 @@ describe('AwsALBAuthProvider', () => { }); it('identity resolution callback rejects', async () => { - const provider = new AwsAlbAuthProvider(getVoidLogger(), catalogApi, { + const provider = new AwsAlbAuthProvider(getVoidLogger(), catalogClient, { region: 'us-west-2', identityResolutionCallback: identityResolutionCallbackRejectedMock, issuer: 'foo', diff --git a/plugins/auth-backend/src/providers/aws-alb/provider.ts b/plugins/auth-backend/src/providers/aws-alb/provider.ts index 61ea10947e..f8b61c15fd 100644 --- a/plugins/auth-backend/src/providers/aws-alb/provider.ts +++ b/plugins/auth-backend/src/providers/aws-alb/provider.ts @@ -25,7 +25,7 @@ import { KeyObject } from 'crypto'; import { Logger } from 'winston'; import NodeCache from 'node-cache'; import { JWT } from 'jose'; -import { CatalogApi } from '@backstage/catalog-client'; +import { CatalogClient } from '@backstage/catalog-client'; const ALB_JWT_HEADER = 'x-amzn-oidc-data'; /** @@ -44,13 +44,13 @@ export const getJWTHeaders = (input: string) => { export class AwsAlbAuthProvider implements AuthProviderRouteHandlers { private logger: Logger; - private readonly catalogClient: CatalogApi; + private readonly catalogClient: CatalogClient; private options: AwsAlbAuthProviderOptions; private readonly keyCache: NodeCache; constructor( logger: Logger, - catalogClient: CatalogApi, + catalogClient: CatalogClient, options: AwsAlbAuthProviderOptions, ) { this.logger = logger; @@ -108,14 +108,14 @@ export class AwsAlbAuthProvider implements AuthProviderRouteHandlers { export const createAwsAlbProvider = ({ logger, - catalogApi, + catalogClient, config, identityResolver, }: AuthProviderFactoryOptions) => { const region = config.getString('region'); const issuer = config.getOptionalString('iss'); if (identityResolver !== undefined) { - return new AwsAlbAuthProvider(logger, catalogApi, { + return new AwsAlbAuthProvider(logger, catalogClient, { region, issuer, identityResolutionCallback: identityResolver, diff --git a/plugins/auth-backend/src/providers/types.ts b/plugins/auth-backend/src/providers/types.ts index 1ab90ac522..b2f488546b 100644 --- a/plugins/auth-backend/src/providers/types.ts +++ b/plugins/auth-backend/src/providers/types.ts @@ -122,7 +122,7 @@ export type ExperimentalIdentityResolver = ( * An object containing information specific to the auth provider. */ payload: object, - catalogApi: CatalogApi, + catalogClient: CatalogClient, ) => Promise>; export type AuthProviderFactoryOptions = { diff --git a/plugins/catalog-import/src/api/CatalogImportClient.test.ts b/plugins/catalog-import/src/api/CatalogImportClient.test.ts index 0e0cf4b323..321e4ba108 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.test.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.test.ts @@ -45,10 +45,25 @@ jest.mock('@octokit/rest', () => ({ })); describe('CatalogImportClient', () => { + const identityApi = { + getUserId: () => { + return 'user'; + }, + getProfile: () => { + return {}; + }, + getIdToken: () => { + return Promise.resolve('token'); + }, + signOut: () => { + return Promise.resolve(); + }, + }; describe('checkForExistingCatalogInfo', () => { const cic = new CatalogImportClient({ discoveryApi: { getBaseUrl: () => Promise.resolve('base') }, githubAuthApi: { getAccessToken: (_, __) => Promise.resolve('token') }, + identityApi, configApi: {} as any, }); it('should return the closest-to-root catalog-info from multiple responses', async () => { diff --git a/plugins/catalog-import/src/components/ImportComponentForm.test.tsx b/plugins/catalog-import/src/components/ImportComponentForm.test.tsx index 38b1065325..9aef548856 100644 --- a/plugins/catalog-import/src/components/ImportComponentForm.test.tsx +++ b/plugins/catalog-import/src/components/ImportComponentForm.test.tsx @@ -35,6 +35,21 @@ describe('', () => { error$: jest.fn(), }; + const identityApi = { + getUserId: () => { + return 'user'; + }, + getProfile: () => { + return {}; + }, + getIdToken: () => { + return Promise.resolve('token'); + }, + signOut: () => { + return Promise.resolve(); + }, + }; + beforeEach(() => { apis = ApiRegistry.from([ [catalogApiRef, new CatalogClient({ discoveryApi: {} as DiscoveryApi })], @@ -45,6 +60,7 @@ describe('', () => { githubAuthApi: { getAccessToken: (_, __) => Promise.resolve('token'), }, + identityApi, configApi: {} as any, }), ], diff --git a/plugins/catalog-import/src/components/ImportComponentPage.test.tsx b/plugins/catalog-import/src/components/ImportComponentPage.test.tsx index f6ef07e1b2..90974e671d 100644 --- a/plugins/catalog-import/src/components/ImportComponentPage.test.tsx +++ b/plugins/catalog-import/src/components/ImportComponentPage.test.tsx @@ -70,6 +70,21 @@ describe('', () => { const server = setupServer(); msw.setupDefaultHandlers(server); + const identityApi = { + getUserId: () => { + return 'user'; + }, + getProfile: () => { + return {}; + }, + getIdToken: () => { + return Promise.resolve('token'); + }, + signOut: () => { + return Promise.resolve(); + }, + }; + beforeEach(() => { server.use( rest.post('https://backend.localhost/locations', (_, res, ctx) => { @@ -112,6 +127,7 @@ describe('', () => { githubAuthApi: { getAccessToken: (_, __) => Promise.resolve('token'), }, + identityApi, configApi: {} as any, }), ], diff --git a/plugins/catalog/src/CatalogClientWrapper.ts b/plugins/catalog/src/CatalogClientWrapper.ts index fab551de48..1f06cd380b 100644 --- a/plugins/catalog/src/CatalogClientWrapper.ts +++ b/plugins/catalog/src/CatalogClientWrapper.ts @@ -36,33 +36,33 @@ export class CatalogClientWrapper implements CatalogApi { async getLocationById(id: String): Promise { const token = await this.identityApi.getIdToken(); - return await this.client.getLocationById(token, id); + return await this.client.getLocationById(id, { token }); } async getEntities( request?: CatalogEntitiesRequest, ): Promise> { const token = await this.identityApi.getIdToken(); - return await this.client.getEntities(token, request); + return await this.client.getEntities(request, { token }); } async getEntityByName(compoundName: EntityName): Promise { const token = await this.identityApi.getIdToken(); - return await this.client.getEntityByName(token, compoundName); + return await this.client.getEntityByName(compoundName, { token }); } async addLocation(request: AddLocationRequest): Promise { const token = await this.identityApi.getIdToken(); - return await this.client.addLocation(token, request); + return await this.client.addLocation(request, { token }); } async getLocationByEntity(entity: Entity): Promise { const token = await this.identityApi.getIdToken(); - return await this.client.getLocationByEntity(token, entity); + return await this.client.getLocationByEntity(entity, { token }); } async removeEntityByUid(uid: string): Promise { const token = await this.identityApi.getIdToken(); - return await this.client.removeEntityByUid(token, uid); + return await this.client.removeEntityByUid(uid, { token }); } } diff --git a/plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts b/plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts index 6c2909d360..0440a45f66 100644 --- a/plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts +++ b/plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts @@ -37,12 +37,15 @@ export class CatalogEntityClient { token: string | undefined, templateName: string, ): Promise { - const { items: templates } = (await this.catalogClient.getEntities(token, { - filter: { - kind: 'template', - 'metadata.name': templateName, + const { items: templates } = (await this.catalogClient.getEntities( + { + filter: { + kind: 'template', + 'metadata.name': templateName, + }, }, - })) as { items: TemplateEntityV1alpha1[] }; + { token }, + )) as { items: TemplateEntityV1alpha1[] }; if (templates.length !== 1) { if (templates.length > 1) { diff --git a/yarn.lock b/yarn.lock index aac0d3735b..1e17345f48 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2645,6 +2645,46 @@ remark-gfm "^1.0.0" zen-observable "^0.8.15" +"@backstage/core@^0.4.3": + version "0.4.4" + resolved "https://registry.npmjs.org/@backstage/core/-/core-0.4.4.tgz#83d5ce5c8dd8a9803badc1dde389b5bde963e959" + integrity sha512-UEZhPBC7DAZEOCRAYQ9XcXch5JDuPn+wYNp65Ik60SSz/RFjqhq8D3P7V074cMQqWLAddVDj5dUrNeN8N1gAUQ== + dependencies: + "@backstage/config" "^0.1.2" + "@backstage/core-api" "^0.2.8" + "@backstage/theme" "^0.2.2" + "@material-ui/core" "^4.11.0" + "@material-ui/icons" "^4.9.1" + "@material-ui/lab" "4.0.0-alpha.45" + "@types/dagre" "^0.7.44" + "@types/prop-types" "^15.7.3" + "@types/react" "^16.9" + "@types/react-sparklines" "^1.7.0" + classnames "^2.2.6" + clsx "^1.1.0" + d3-selection "^2.0.0" + d3-shape "^2.0.0" + d3-zoom "^2.0.0" + dagre "^0.8.5" + immer "^7.0.9" + lodash "^4.17.15" + material-table "^1.69.1" + prop-types "^15.7.2" + qs "^6.9.4" + rc-progress "^3.0.0" + react "^16.12.0" + react-dom "^16.12.0" + react-helmet "6.1.0" + react-hook-form "^6.6.0" + react-markdown "^5.0.2" + react-router "6.0.0-beta.0" + react-router-dom "6.0.0-beta.0" + react-sparklines "^1.7.0" + react-syntax-highlighter "^13.5.1" + react-use "^15.3.3" + remark-gfm "^1.0.0" + zen-observable "^0.8.15" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -15469,6 +15509,11 @@ immer@1.10.0: resolved "https://registry.npmjs.org/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d" integrity sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg== +immer@^7.0.9: + version "7.0.15" + resolved "https://registry.npmjs.org/immer/-/immer-7.0.15.tgz#dc3bc6db87401659d2e737c67a21b227c484a4ad" + integrity sha512-yM7jo9+hvYgvdCQdqvhCNRRio0SCXc8xDPzA25SvKWa7b1WVPjLwQs1VYU5JPXjcJPTqAa5NP5dqpORGYBQ2AA== + immer@^8.0.1: version "8.0.1" resolved "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz#9c73db683e2b3975c424fb0572af5889877ae656"