Allow passing identity providers as a union type

This commit is contained in:
Kinga Sieminiak
2020-08-06 09:41:20 +02:00
parent 25a869f579
commit 5d24ef4c68
7 changed files with 74 additions and 55 deletions
+4 -2
View File
@@ -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 <SignInPage {...props} providers={providers} />;
return (
<SignInPage {...props} providers={['guest', 'custom', ...providers]} />
);
},
},
});
@@ -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,
},
];
@@ -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<Props> = ({ onResult, providers }) => {
export const SignInPage: FC<Props> = ({ 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 <Progress />;
@@ -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);
@@ -15,6 +15,3 @@
*/
export { SignInPage } from './SignInPage';
export { commonProvider } from './commonProvider';
export { guestProvider } from './guestProvider';
export { customProvider } from './customProvider';
@@ -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 (
<Component
key={config.id}
provider={config}
key={provider.id}
config={provider.config!}
onResult={handleResult}
/>
);
+3 -12
View File
@@ -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 = (