From fb8ca7c1bfc89952e8af4e8e211d43ff02fc42ae Mon Sep 17 00:00:00 2001 From: Brian Fletcher Date: Wed, 5 Jan 2022 16:53:30 +0000 Subject: [PATCH] remove code accidently added in Signed-off-by: Brian Fletcher --- .../src/github/GithubAppCredentialsMux.ts | 214 ------------------ .../processors/UrlReaderProcessor.ts | 6 - 2 files changed, 220 deletions(-) delete mode 100644 packages/integration/src/github/GithubAppCredentialsMux.ts diff --git a/packages/integration/src/github/GithubAppCredentialsMux.ts b/packages/integration/src/github/GithubAppCredentialsMux.ts deleted file mode 100644 index c6d055a213..0000000000 --- a/packages/integration/src/github/GithubAppCredentialsMux.ts +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright 2022 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { GithubAppConfig, GitHubIntegrationConfig } from './config'; -import { Octokit, RestEndpointMethodTypes } from '@octokit/rest'; -import { createAppAuth } from '@octokit/auth-app'; -import { DateTime } from 'luxon'; - -/** - * This accept header is required when calling App APIs in GitHub Enterprise. - * It has no effect on calls to github.com and can probably be removed entirely - * once GitHub Apps is out of preview. - */ -const HEADERS = { - Accept: 'application/vnd.github.machine-man-preview+json', -}; - -type InstallationData = { - installationId: number; - suspended: boolean; -}; - -class Cache { - private readonly tokenCache = new Map< - string, - { token: string; expiresAt: DateTime } - >(); - - async getOrCreateToken( - key: string, - supplier: () => Promise<{ token: string; expiresAt: DateTime }>, - ): Promise<{ accessToken: string }> { - const item = this.tokenCache.get(key); - if (item && this.isNotExpired(item.expiresAt)) { - return { accessToken: item.token }; - } - - const result = await supplier(); - this.tokenCache.set(key, result); - return { accessToken: result.token }; - } - - // consider timestamps older than 50 minutes to be expired. - private isNotExpired = (date: DateTime) => - date.diff(DateTime.local(), 'minutes').minutes > 50; -} - -/** - * GithubAppManager issues and caches tokens for a specific GitHub App. - */ -class GithubAppManager { - private readonly appClient: Octokit; - private readonly baseUrl?: string; - private readonly baseAuthConfig: { appId: number; privateKey: string }; - private readonly cache = new Cache(); - private readonly allowedInstallationOwners: string[] | undefined; // undefined allows all installations - - constructor(config: GithubAppConfig, baseUrl?: string) { - this.allowedInstallationOwners = config.allowedInstallationOwners; - this.baseUrl = baseUrl; - this.baseAuthConfig = { - appId: config.appId, - privateKey: config.privateKey.replace(/\\n/gm, '\n'), - }; - this.appClient = new Octokit({ - baseUrl, - headers: HEADERS, - authStrategy: createAppAuth, - auth: this.baseAuthConfig, - }); - } - - async getInstallationCredentials( - owner: string, - repo?: string, - ): Promise<{ accessToken: string }> { - const { installationId, suspended } = await this.getInstallationData(owner); - if (this.allowedInstallationOwners) { - if (!this.allowedInstallationOwners?.includes(owner)) { - throw new Error( - `The GitHub application for ${owner} is not included in the allowed installation list (${installationId}).`, - ); - } - } - if (suspended) { - throw new Error(`The GitHub application for ${owner} is suspended`); - } - - const cacheKey = repo ? `${owner}/${repo}` : owner; - - // Go and grab an access token for the app scoped to a repository if provided, if not use the organisation installation. - return this.cache.getOrCreateToken(cacheKey, async () => { - const result = await this.appClient.apps.createInstallationAccessToken({ - installation_id: installationId, - headers: HEADERS, - }); - if (repo && result.data.repository_selection === 'selected') { - const installationClient = new Octokit({ - baseUrl: this.baseUrl, - auth: result.data.token, - }); - const repos = await installationClient.paginate( - installationClient.apps.listReposAccessibleToInstallation, - ); - const hasRepo = repos.some(repository => { - return repository.name === repo; - }); - if (!hasRepo) { - throw new Error( - `The Backstage GitHub application used in the ${owner} organization does not have access to a repository with the name ${repo}`, - ); - } - } - return { - token: result.data.token, - expiresAt: DateTime.fromISO(result.data.expires_at), - }; - }); - } - - getInstallations(): Promise< - RestEndpointMethodTypes['apps']['listInstallations']['response']['data'] - > { - return this.appClient.paginate(this.appClient.apps.listInstallations); - } - - private async getInstallationData(owner: string): Promise { - const allInstallations = await this.getInstallations(); - const installation = allInstallations.find( - inst => - inst.account?.login?.toLocaleLowerCase('en-US') === - owner.toLocaleLowerCase('en-US'), - ); - if (installation) { - return { - installationId: installation.id, - suspended: Boolean(installation.suspended_by), - }; - } - const notFoundError = new Error( - `No app installation found for ${owner} in ${this.baseAuthConfig.appId}`, - ); - notFoundError.name = 'NotFoundError'; - throw notFoundError; - } -} - -/** - * Corresponds to a Github installation which internally could hold several GitHub Apps. - * - * @public - */ -export class GithubAppCredentialsMux { - private readonly apps: GithubAppManager[]; - - constructor(config: GitHubIntegrationConfig) { - this.apps = - config.apps?.map(ac => new GithubAppManager(ac, config.apiBaseUrl)) ?? []; - } - - async getAllInstallations(): Promise< - RestEndpointMethodTypes['apps']['listInstallations']['response']['data'] - > { - if (!this.apps.length) { - return []; - } - - const installs = await Promise.all( - this.apps.map(app => app.getInstallations()), - ); - - return installs.flat(); - } - - async getAppToken(owner: string, repo?: string): Promise { - if (this.apps.length === 0) { - return undefined; - } - - const results = await Promise.all( - this.apps.map(app => - app.getInstallationCredentials(owner, repo).then( - credentials => ({ credentials, error: undefined }), - error => ({ credentials: undefined, error }), - ), - ), - ); - - const result = results.find(resultItem => resultItem.credentials); - if (result) { - return result.credentials!.accessToken; - } - - const errors = results.map(r => r.error); - const notNotFoundError = errors.find(err => err.name !== 'NotFoundError'); - if (notNotFoundError) { - throw notNotFoundError; - } - - return undefined; - } -} diff --git a/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.ts index 83f22249d7..6a85cc07c7 100644 --- a/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.ts @@ -140,9 +140,3 @@ export class UrlReaderProcessor implements CatalogProcessor { return { response: [{ url: location, data }] }; } } - -export class RoadieDemoDataReaderProcessor extends UrlReaderProcessor { - getProcessorName() { - return 'roadie-demo-data-reader'; - } -}