From 831a8fee86c21777ca81c78e45c3a06c083fc8a7 Mon Sep 17 00:00:00 2001 From: Robert Cen Date: Thu, 11 Aug 2022 14:25:05 +1000 Subject: [PATCH] Send Authorization headers in fetch requests in Code Climate plugin to fix unauthorized requests to Backstage backends with authentication enabled as per https://github.com/backstage/backstage/blob/master/contrib/docs/tutorials/authenticate-api-requests.md Signed-off-by: Robert Cen --- .changeset/weak-drinks-report.md | 5 +++ .../code-climate/src/api/production-api.ts | 37 ++++++++++++++++--- plugins/code-climate/src/plugin.ts | 3 +- 3 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 .changeset/weak-drinks-report.md diff --git a/.changeset/weak-drinks-report.md b/.changeset/weak-drinks-report.md new file mode 100644 index 0000000000..d9ab3880f7 --- /dev/null +++ b/.changeset/weak-drinks-report.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-code-climate': patch +--- + +Send Authorization headers in fetch requests in Code Climate plugin to fix unauthorized requests to Backstage backends with authentication enabled as per https://github.com/backstage/backstage/blob/master/contrib/docs/tutorials/authenticate-api-requests.md. diff --git a/plugins/code-climate/src/api/production-api.ts b/plugins/code-climate/src/api/production-api.ts index 665d7e9f63..d37ec61458 100644 --- a/plugins/code-climate/src/api/production-api.ts +++ b/plugins/code-climate/src/api/production-api.ts @@ -22,7 +22,7 @@ import { CodeClimateIssuesData, } from './code-climate-data'; import { CodeClimateApi } from './code-climate-api'; -import { DiscoveryApi } from '@backstage/core-plugin-api'; +import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api'; import { Duration } from 'luxon'; import humanizeDuration from 'humanize-duration'; @@ -34,8 +34,19 @@ const codeSmellsQuery = `${basicIssuesOptions}&${categoriesFilter}=Complexity`; const duplicationQuery = `${basicIssuesOptions}&${categoriesFilter}=Duplication`; const otherIssuesQuery = `${basicIssuesOptions}&${categoriesFilter}=Bug%20Risk`; +type Options = { + discoveryApi: DiscoveryApi; + identityApi: IdentityApi; +}; + export class ProductionCodeClimateApi implements CodeClimateApi { - constructor(private readonly discoveryApi: DiscoveryApi) {} + private readonly discoveryApi: DiscoveryApi; + private readonly identityApi: IdentityApi; + + constructor(options: Options) { + this.discoveryApi = options.discoveryApi; + this.identityApi = options.identityApi; + } async fetchAllData(options: { apiUrl: string; @@ -45,6 +56,10 @@ export class ProductionCodeClimateApi implements CodeClimateApi { }): Promise { const { apiUrl, repoID, snapshotID, testReportID } = options; + const { token } = await this.identityApi.getCredentials(); + const headersWithAuth = { + headers: { Authorization: `Bearer ${token}` }, + }; const [ maintainabilityResponse, testCoverageResponse, @@ -52,16 +67,25 @@ export class ProductionCodeClimateApi implements CodeClimateApi { duplicationResponse, otherIssuesResponse, ] = await Promise.all([ - await fetch(`${apiUrl}/repos/${repoID}/snapshots/${snapshotID}`), - await fetch(`${apiUrl}/repos/${repoID}/test_reports/${testReportID}`), + await fetch( + `${apiUrl}/repos/${repoID}/snapshots/${snapshotID}`, + headersWithAuth, + ), + await fetch( + `${apiUrl}/repos/${repoID}/test_reports/${testReportID}`, + headersWithAuth, + ), await fetch( `${apiUrl}/repos/${repoID}/snapshots/${snapshotID}/issues?${codeSmellsQuery}`, + headersWithAuth, ), await fetch( `${apiUrl}/repos/${repoID}/snapshots/${snapshotID}/issues?${duplicationQuery}`, + headersWithAuth, ), await fetch( `${apiUrl}/repos/${repoID}/snapshots/${snapshotID}/issues?${otherIssuesQuery}`, + headersWithAuth, ), ]); @@ -108,8 +132,11 @@ export class ProductionCodeClimateApi implements CodeClimateApi { const apiUrl = `${await this.discoveryApi.getBaseUrl( 'proxy', )}/codeclimate/api`; + const { token } = await this.identityApi.getCredentials(); - const repoResponse = await fetch(`${apiUrl}/repos/${repoID}`); + const repoResponse = await fetch(`${apiUrl}/repos/${repoID}`, { + headers: { Authorization: `Bearer ${token}` }, + }); if (!repoResponse.ok) { throw new Error('Failed fetching Code Climate info'); diff --git a/plugins/code-climate/src/plugin.ts b/plugins/code-climate/src/plugin.ts index dcf86f1e19..d8f7ea5028 100644 --- a/plugins/code-climate/src/plugin.ts +++ b/plugins/code-climate/src/plugin.ts @@ -39,7 +39,8 @@ export const codeClimatePlugin = createPlugin({ discoveryApi: discoveryApiRef, identityApi: identityApiRef, }, - factory: ({ discoveryApi }) => new ProductionCodeClimateApi(discoveryApi), + factory: ({ discoveryApi, identityApi }) => + new ProductionCodeClimateApi({ discoveryApi, identityApi }), }), ], routes: {