From 6708dbfffe6e1c3b2a9035839af73ef97d29e37e Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 25 Jan 2022 19:10:08 +0100 Subject: [PATCH] feat: added grabbing the token from the form with a debounce to not happen on every key press Signed-off-by: blam --- packages/integration-react/src/api/ScmAuth.ts | 1 + .../RepoUrlPicker/RepoUrlPicker.test.tsx | 53 +++++++++++++++++++ .../fields/RepoUrlPicker/RepoUrlPicker.tsx | 45 +++++++++++++++- .../RepoUrlPicker/RepoUrlPickerHost.tsx | 2 +- .../src/components/secrets/SecretsContext.tsx | 4 +- 5 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx diff --git a/packages/integration-react/src/api/ScmAuth.ts b/packages/integration-react/src/api/ScmAuth.ts index f450d63cec..071374e6cb 100644 --- a/packages/integration-react/src/api/ScmAuth.ts +++ b/packages/integration-react/src/api/ScmAuth.ts @@ -15,6 +15,7 @@ */ import { + bitbucketAuthApiRef, createApiFactory, githubAuthApiRef, gitlabAuthApiRef, diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx new file mode 100644 index 0000000000..f31b152882 --- /dev/null +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx @@ -0,0 +1,53 @@ +/* + * 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 React from 'react'; +import { render } from '@testing-library/react'; +import { RepoUrlPicker } from './RepoUrlPicker'; +import Form from '@rjsf/core'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { + scmIntegrationsApiRef, + scmAuthApiRef, +} from '@backstage/integration-react'; +import { scaffolderApiRef } from '../../../api'; +import { SecretsContextProvider } from '../../secrets/SecretsContext'; + +describe('RepoUrlPicker', () => { + describe('happy path rendering', () => { + it('should render the repo url picker', async () => { + const { getByRole } = await renderInTestApp( + + +
+ + , + , + ); + + console.log(getByRole('form')); + }); + }); +}); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx index 998fa41588..b4a1eedc8e 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx @@ -14,7 +14,10 @@ * limitations under the License. */ import { useApi } from '@backstage/core-plugin-api'; -import { scmIntegrationsApiRef } from '@backstage/integration-react'; +import { + scmIntegrationsApiRef, + scmAuthApiRef, +} from '@backstage/integration-react'; import React, { useEffect, useState, useMemo, useCallback } from 'react'; import { GithubRepoPicker } from './GithubRepoPicker'; import { GitlabRepoPicker } from './GitlabRepoPicker'; @@ -24,10 +27,21 @@ import { FieldExtensionComponentProps } from '../../../extensions'; import { RepoUrlPickerHost } from './RepoUrlPickerHost'; import { parseRepoPickerUrl, serializeRepoPickerUrl } from './utils'; import { RepoUrlPickerState } from './types'; +import useDebounce from 'react-use/lib/useDebounce'; +import { useSecretsContext } from '../../secrets'; export interface RepoUrlPickerUiOptions { allowedHosts?: string[]; allowedOwners?: string[]; + requestUserCredentials?: { + resultSecretsKey: string; + additionalScopes?: { + github?: string[]; + gitlab?: string[]; + bitbucket?: string[]; + azure?: string[]; + }; + }; } export const RepoUrlPicker = ( @@ -38,7 +52,8 @@ export const RepoUrlPicker = ( parseRepoPickerUrl(formData), ); const integrationApi = useApi(scmIntegrationsApiRef); - + const scmAuthApi = useApi(scmAuthApiRef); + const { setSecret } = useSecretsContext(); const allowedHosts = useMemo( () => uiSchema?.['ui:options']?.allowedHosts ?? [], [uiSchema], @@ -66,6 +81,32 @@ export const RepoUrlPicker = ( [setState], ); + useDebounce( + async () => { + const { requestUserCredentials } = uiSchema?.['ui:options'] ?? {}; + + if ( + !requestUserCredentials || + !(state.host && state.owner && !state.repoName) + ) { + return; + } + + // user has requested that we use the users credentials + const { token } = await scmAuthApi.getCredentials({ + url: `https://${state.host}/${state.owner}/${state.repoName}`, + additionalScope: { + repoWrite: true, + customScopes: requestUserCredentials.additionalScopes, + }, + }); + + setSecret({ [requestUserCredentials.resultSecretsKey]: token }); + }, + 1000, + [state], + ); + const hostType = (state.host && integrationApi.byHost(state.host)?.type) ?? null; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx index 261429c757..652e214714 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx @@ -37,7 +37,7 @@ export const RepoUrlPickerHost = (props: { }); useEffect(() => { - if (hosts && !host) { + if (hosts && hosts.length && !host) { // This is only hear to set the default as the first one in the hosts array // if the host is not set yet and there is a list of hosts. onChange(hosts[0]); diff --git a/plugins/scaffolder/src/components/secrets/SecretsContext.tsx b/plugins/scaffolder/src/components/secrets/SecretsContext.tsx index 771a53fda1..4f8295bb27 100644 --- a/plugins/scaffolder/src/components/secrets/SecretsContext.tsx +++ b/plugins/scaffolder/src/components/secrets/SecretsContext.tsx @@ -64,9 +64,9 @@ export const useSecretsContext = () => { const setSecret = useCallback( (input: Record) => { - setSecrets({ ...secrets, ...input }); + setSecrets(currentSecrets => ({ ...currentSecrets, ...input })); }, - [secrets, setSecrets], + [setSecrets], ); return { setSecret };