diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index d4d0cc0490..9a9fdfe5c4 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -25,14 +25,16 @@ import Root from './components/Root'; import * as plugins from './plugins'; import { apis } from './apis'; import { hot } from 'react-hot-loader/root'; -import { providers } from './authProviders'; +import { providers } from './identityProviders'; const app = createApp({ apis, plugins: Object.values(plugins), components: { SignInPage: props => { - return ; + return ( + + ); }, }, }); diff --git a/packages/app/src/authProviders.ts b/packages/app/src/identityProviders.ts similarity index 80% rename from packages/app/src/authProviders.ts rename to packages/app/src/identityProviders.ts index d95848e014..e80b1d6fea 100644 --- a/packages/app/src/authProviders.ts +++ b/packages/app/src/identityProviders.ts @@ -19,9 +19,6 @@ import { gitlabAuthApiRef, oktaAuthApiRef, githubAuthApiRef, - commonProvider, - customProvider, - guestProvider, } from '@backstage/core'; export const providers = [ @@ -30,35 +27,23 @@ export const providers = [ title: 'Google', message: 'Sign In using Google', apiRef: googleAuthApiRef, - provider: commonProvider, }, { id: 'gitlab-auth-provider', title: 'Gitlab', message: 'Sign In using Gitlab', apiRef: gitlabAuthApiRef, - provider: commonProvider, }, { id: 'github-auth-provider', title: 'Github', message: 'Sign In using Github', apiRef: githubAuthApiRef, - provider: commonProvider, }, { id: 'okta-auth-provider', title: 'Okta', message: 'Sign In using Okta', apiRef: oktaAuthApiRef, - provider: commonProvider, - }, - { - id: 'guest-provider', - provider: guestProvider, - }, - { - id: 'custom-provider', - provider: customProvider, }, ]; diff --git a/packages/core/src/layout/SignInPage/SignInPage.tsx b/packages/core/src/layout/SignInPage/SignInPage.tsx index e07e6490ae..52a27f190e 100644 --- a/packages/core/src/layout/SignInPage/SignInPage.tsx +++ b/packages/core/src/layout/SignInPage/SignInPage.tsx @@ -21,18 +21,22 @@ import { Content } from '../Content/Content'; import { ContentHeader } from '../ContentHeader/ContentHeader'; import { Grid } from '@material-ui/core'; import { SignInPageProps, useApi, configApiRef } from '@backstage/core-api'; -import { useSignInProviders } from './providers'; -import { SignInProviderConfig } from './types'; +import { useSignInProviders, getSignInProviders } from './providers'; +import { IdentityProviders } from './types'; import { Progress } from '../../components/Progress'; export type Props = SignInPageProps & { - providers: SignInProviderConfig[]; + providers: IdentityProviders; }; -export const SignInPage: FC = ({ onResult, providers }) => { +export const SignInPage: FC = ({ onResult, providers = [] }) => { const configApi = useApi(configApiRef); - const [loading, providerElements] = useSignInProviders(providers, onResult); + const signInProviders = getSignInProviders(providers); + const [loading, providerElements] = useSignInProviders( + signInProviders, + onResult, + ); if (loading) { return ; diff --git a/packages/core/src/layout/SignInPage/commonProvider.tsx b/packages/core/src/layout/SignInPage/commonProvider.tsx index da0247fd6f..f9611342a2 100644 --- a/packages/core/src/layout/SignInPage/commonProvider.tsx +++ b/packages/core/src/layout/SignInPage/commonProvider.tsx @@ -21,12 +21,12 @@ import { ProviderComponent, ProviderLoader, SignInProvider, - CommonSignInConfig, + SignInConfig, } from './types'; import { useApi, errorApiRef } from '@backstage/core-api'; -const Component: ProviderComponent = ({ provider, onResult }) => { - const { apiRef, title, message } = provider as CommonSignInConfig; +const Component: ProviderComponent = ({ config, onResult }) => { + const { apiRef, title, message } = config as SignInConfig; const authApi = useApi(apiRef); const errorApi = useApi(errorApiRef); diff --git a/packages/core/src/layout/SignInPage/index.ts b/packages/core/src/layout/SignInPage/index.ts index e58d6a85df..49f55aefc5 100644 --- a/packages/core/src/layout/SignInPage/index.ts +++ b/packages/core/src/layout/SignInPage/index.ts @@ -15,6 +15,3 @@ */ export { SignInPage } from './SignInPage'; -export { commonProvider } from './commonProvider'; -export { guestProvider } from './guestProvider'; -export { customProvider } from './customProvider'; diff --git a/packages/core/src/layout/SignInPage/providers.tsx b/packages/core/src/layout/SignInPage/providers.tsx index 9ab742b516..a0e1941d90 100644 --- a/packages/core/src/layout/SignInPage/providers.tsx +++ b/packages/core/src/layout/SignInPage/providers.tsx @@ -22,12 +22,53 @@ import { useApiHolder, errorApiRef, } from '@backstage/core-api'; -import { SignInProviderConfig, CommonSignInConfig } from './types'; +import { SignInConfig, IdentityProviders, SignInProvider } from './types'; +import { commonProvider } from './commonProvider'; +import { guestProvider } from './guestProvider'; +import { customProvider } from './customProvider'; const PROVIDER_STORAGE_KEY = '@backstage/core:SignInPage:provider'; +export type SignInProviderId = 'guest' | 'custom' | string; + +export type SignInProviderType = { + [id in SignInProviderId]: { + components: SignInProvider; + id: SignInProviderId; + config?: SignInConfig; + }; +}; + +const signInProviders: { [id in SignInProviderId]: SignInProvider } = { + guest: guestProvider, + custom: customProvider, + common: commonProvider, +}; + +export function getSignInProviders( + identityProviders: IdentityProviders, +): SignInProviderType { + const providers = identityProviders.reduce( + (acc: SignInProviderType, config) => { + if (typeof config === 'string') { + acc[config] = { components: signInProviders[config], id: config }; + + return acc; + } + + const { id } = config as SignInConfig; + acc[id] = { components: signInProviders.common, id, config }; + + return acc; + }, + {}, + ); + + return providers; +} + export const useSignInProviders = ( - providers: SignInProviderConfig[], + providers: SignInProviderType, onResult: SignInPageProps['onResult'], ) => { const errorApi = useApi(errorApiRef); @@ -58,7 +99,7 @@ export const useSignInProviders = ( // We can't use storageApi here, as it might have a dependency on the IdentityApi const selectedProviderId = localStorage.getItem( PROVIDER_STORAGE_KEY, - ) as string; + ) as SignInProviderId; // No provider selected, let the user pick one if (selectedProviderId === null) { @@ -66,19 +107,16 @@ export const useSignInProviders = ( return undefined; } - const config = providers.find( - provider => provider.id === selectedProviderId, - ); - if (!config) { + const provider = providers[selectedProviderId]; + if (!provider) { setLoading(false); return undefined; } let didCancel = false; - const { apiRef } = config as CommonSignInConfig; - config.provider - .loader(apiHolder, apiRef) + provider.components + .loader(apiHolder, provider.config?.apiRef!) .then(result => { if (didCancel) { return; @@ -105,19 +143,21 @@ export const useSignInProviders = ( // This renders all available sign-in providers const elements = useMemo( () => - providers.map(config => { - const { Component } = config.provider; + Object.keys(providers).map(key => { + const provider = providers[key]; + + const { Component } = provider.components; const handleResult = (result: SignInResult) => { - localStorage.setItem(PROVIDER_STORAGE_KEY, config.id); + localStorage.setItem(PROVIDER_STORAGE_KEY, provider.id); handleWrappedResult(result); }; return ( ); diff --git a/packages/core/src/layout/SignInPage/types.ts b/packages/core/src/layout/SignInPage/types.ts index 089ebac823..9c501e8095 100644 --- a/packages/core/src/layout/SignInPage/types.ts +++ b/packages/core/src/layout/SignInPage/types.ts @@ -24,30 +24,21 @@ import { ProfileInfoApi, BackstageIdentityApi, SessionStateApi, - OpenIdConnectApi, } from '@backstage/core-api'; export type SignInConfig = { id: string; - provider: SignInProvider; -}; - -export type CommonSignInConfig = SignInConfig & { title: string; message: string; apiRef: ApiRef< - OAuthApi & - ProfileInfoApi & - BackstageIdentityApi & - SessionStateApi & - OpenIdConnectApi + OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionStateApi >; }; -export type SignInProviderConfig = SignInConfig | CommonSignInConfig; +export type IdentityProviders = ('guest' | 'custom' | SignInConfig)[]; export type ProviderComponent = ComponentType< - SignInPageProps & { provider: SignInProviderConfig } + SignInPageProps & { config: SignInConfig } >; export type ProviderLoader = (