simplify code and test cases. clean up rendering.

Signed-off-by: headphonejames <generalfuzz@gmail.com>
This commit is contained in:
headphonejames
2023-02-28 17:05:11 -08:00
parent 63a6a3d44b
commit d7e856ad55
18 changed files with 63 additions and 88 deletions
+1 -3
View File
@@ -265,7 +265,7 @@ export type AuthApiCreateOptions = {
discoveryApi: DiscoveryApi;
environment?: string;
provider?: AuthProviderInfo;
configApi: ConfigApi;
configApi?: ConfigApi;
};
// @public
@@ -564,9 +564,7 @@ export class SamlAuth
// @public
export type SignInPageProps = {
onSignInStarted(): void;
onSignInSuccess(identityApi: IdentityApi): void;
onSignInFailure(): void;
};
// @public
@@ -17,8 +17,7 @@
import MockOAuthApi from '../../OAuthRequestApi/MockOAuthApi';
import { UrlPatternDiscovery } from '../../DiscoveryApi';
import BitbucketAuth from './BitbucketAuth';
import { ConfigReader } from '@backstage/config';
import { ConfigApi } from '@backstage/core-plugin-api';
import { MockConfigApi } from '@backstage/test-utils';
const getSession = jest.fn();
@@ -34,9 +33,7 @@ describe('BitbucketAuth', () => {
jest.resetAllMocks();
});
const configApi: ConfigApi = new ConfigReader({
enableExperimentalRedirectFlow: false,
});
const configApi = new MockConfigApi({});
it.each([
['team api write_repository', ['team', 'api', 'write_repository']],
@@ -17,8 +17,7 @@
import MockOAuthApi from '../../OAuthRequestApi/MockOAuthApi';
import { UrlPatternDiscovery } from '../../DiscoveryApi';
import BitbucketServerAuth from './BitbucketServerAuth';
import { ConfigReader } from '@backstage/config';
import { ConfigApi } from '@backstage/core-plugin-api';
import { MockConfigApi } from '@backstage/test-utils';
const getSession = jest.fn();
@@ -42,9 +41,7 @@ describe('BitbucketServerAuth', () => {
['PROJECT_ADMIN', 'REPO_READ', 'ACCOUNT_WRITE'],
],
])(`should normalize scopes correctly - %p`, (scope, scopes) => {
const configApi: ConfigApi = new ConfigReader({
enableExperimentalRedirectFlow: false,
});
const configApi = new MockConfigApi({});
const bitbucketServerAuth = BitbucketServerAuth.create({
configApi: configApi,
@@ -17,8 +17,7 @@
import { UrlPatternDiscovery } from '../../DiscoveryApi';
import MockOAuthApi from '../../OAuthRequestApi/MockOAuthApi';
import GithubAuth from './GithubAuth';
import { ConfigReader } from '@backstage/config';
import { ConfigApi } from '@backstage/core-plugin-api';
import { MockConfigApi } from '@backstage/test-utils';
const getSession = jest.fn();
@@ -34,9 +33,7 @@ describe('GithubAuth', () => {
jest.resetAllMocks();
});
const configApi: ConfigApi = new ConfigReader({
enableExperimentalRedirectFlow: false,
});
const configApi = new MockConfigApi({});
it('should forward access token request to session manager', async () => {
const githubAuth = GithubAuth.create({
@@ -17,8 +17,7 @@
import MockOAuthApi from '../../OAuthRequestApi/MockOAuthApi';
import { UrlPatternDiscovery } from '../../DiscoveryApi';
import GitlabAuth from './GitlabAuth';
import { ConfigReader } from '@backstage/config';
import { ConfigApi } from '@backstage/core-plugin-api';
import { MockConfigApi } from '@backstage/test-utils';
const getSession = jest.fn();
@@ -41,9 +40,7 @@ describe('GitlabAuth', () => {
],
['read_repository sudo', ['read_repository', 'sudo']],
])(`should normalize scopes correctly - %p`, (scope, scopes) => {
const configApi: ConfigApi = new ConfigReader({
enableExperimentalRedirectFlow: false,
});
const configApi = new MockConfigApi({});
const gitlabAuth = GitlabAuth.create({
configApi: configApi,
@@ -17,8 +17,7 @@
import GoogleAuth from './GoogleAuth';
import MockOAuthApi from '../../OAuthRequestApi/MockOAuthApi';
import { UrlPatternDiscovery } from '../../DiscoveryApi';
import { ConfigReader } from '@backstage/config';
import { ConfigApi } from '@backstage/core-plugin-api';
import { MockConfigApi } from '@backstage/test-utils';
const PREFIX = 'https://www.googleapis.com/auth/';
@@ -60,9 +59,7 @@ describe('GoogleAuth', () => {
[`${PREFIX}profile`, [`${PREFIX}profile`]],
[`${PREFIX}openid`, [`${PREFIX}openid`]],
])(`should normalize scopes correctly - %p`, (scope, scopes) => {
const configApi: ConfigApi = new ConfigReader({
enableExperimentalRedirectFlow: false,
});
const configApi = new MockConfigApi({});
const googleAuth = GoogleAuth.create({
configApi: configApi,
@@ -17,8 +17,7 @@
import OAuth2 from './OAuth2';
import MockOAuthApi from '../../OAuthRequestApi/MockOAuthApi';
import { UrlPatternDiscovery } from '../../DiscoveryApi';
import { ConfigReader } from '@backstage/config';
import { ConfigApi } from '@backstage/core-plugin-api';
import { MockConfigApi } from '@backstage/test-utils';
const theFuture = new Date(Date.now() + 3600000);
const thePast = new Date(Date.now() - 10);
@@ -36,9 +35,7 @@ jest.mock('../../../../lib/AuthSessionManager', () => ({
},
}));
const configApi: ConfigApi = new ConfigReader({
enableExperimentalRedirectFlow: false,
});
const configApi = new MockConfigApi({});
describe('OAuth2', () => {
it('should get refreshed access token', async () => {
@@ -17,8 +17,7 @@
import OktaAuth from './OktaAuth';
import MockOAuthApi from '../../OAuthRequestApi/MockOAuthApi';
import { UrlPatternDiscovery } from '../../DiscoveryApi';
import { ConfigReader } from '@backstage/config';
import { ConfigApi } from '@backstage/core-plugin-api';
import { MockConfigApi } from '@backstage/test-utils';
const PREFIX = 'okta.';
@@ -52,9 +51,7 @@ describe('OktaAuth', () => {
[`${PREFIX}profile`, [`${PREFIX}profile`]],
[`${PREFIX}openid`, [`${PREFIX}openid`]],
])(`should normalize scopes correctly - %p`, (scope, scopes) => {
const configApi: ConfigApi = new ConfigReader({
enableExperimentalRedirectFlow: false,
});
const configApi = new MockConfigApi({});
const auth = OktaAuth.create({
configApi: configApi,
oauthRequestApi: new MockOAuthApi(),
@@ -37,5 +37,5 @@ export type AuthApiCreateOptions = {
discoveryApi: DiscoveryApi;
environment?: string;
provider?: AuthProviderInfo;
configApi: ConfigApi;
configApi?: ConfigApi;
};
+1 -15
View File
@@ -72,22 +72,8 @@ function SignInPageWrapper({
const configApi = useApi(configApiRef);
const basePath = getBasePath(configApi);
const handleSignInStarted = () => {
// no-op
};
const handleSignInFailure = () => {
// no-op
};
if (!identityApi) {
return (
<Component
onSignInSuccess={setIdentityApi}
onSignInStarted={handleSignInStarted}
onSignInFailure={handleSignInFailure}
/>
);
return <Component onSignInSuccess={setIdentityApi} />;
}
appIdentityProxy.setTarget(identityApi, {
-8
View File
@@ -44,18 +44,10 @@ export type BootErrorPageProps = {
* @public
*/
export type SignInPageProps = {
/**
* Invoked when the sign-in process has started.
*/
onSignInStarted(): void;
/**
* Set the IdentityApi on successful sign-in. This should only be called once.
*/
onSignInSuccess(identityApi: IdentityApi): void;
/**
* Invoked when the sign-in process has failed.
*/
onSignInFailure(): void;
};
/**
@@ -23,6 +23,8 @@ import {
import { showLoginPopup } from '../loginPopup';
import { AuthConnector, CreateSessionOptions } from './types';
let warned = false;
type Options<AuthSession> = {
/**
* DiscoveryApi instance used to locate the auth backend endpoint.
@@ -52,7 +54,7 @@ type Options<AuthSession> = {
/**
* ConfigApi instance used to configure authentication flow of pop-up or redirect.
*/
configApi: ConfigApi;
configApi?: ConfigApi;
};
function defaultJoinScopes(scopes: Set<string>) {
@@ -68,12 +70,12 @@ export class DefaultAuthConnector<AuthSession>
implements AuthConnector<AuthSession>
{
private readonly discoveryApi: DiscoveryApi;
private readonly configApi: ConfigApi;
private readonly environment: string;
private readonly provider: AuthProviderInfo;
private readonly joinScopesFunc: (scopes: Set<string>) => string;
private readonly authRequester: OAuthRequester<AuthSession>;
private readonly sessionTransform: (response: any) => Promise<AuthSession>;
private readonly enableExperimentalRedirectFlow: boolean;
constructor(options: Options<AuthSession>) {
const {
configApi,
@@ -85,20 +87,28 @@ export class DefaultAuthConnector<AuthSession>
sessionTransform = id => id,
} = options;
if (!warned && !configApi) {
// eslint-disable-next-line no-console
console.warn(
'DEPRECATION WARNING: Authentication providers require a configApi instance to configure the authentication flow. Please provide one to the authentication provider constructor.',
);
warned = true;
}
this.enableExperimentalRedirectFlow = configApi
? configApi.getOptionalBoolean('enableExperimentalRedirectFlow') ?? false
: false;
this.authRequester = oauthRequestApi.createAuthRequester({
provider,
onAuthRequest: async scopes => {
const enableExperimentalRedirectFlow =
this.configApi.getOptionalBoolean('enableExperimentalRedirectFlow') ??
false;
if (!enableExperimentalRedirectFlow) {
if (!this.enableExperimentalRedirectFlow) {
return this.showPopup(scopes);
}
return this.executeRedirect(scopes);
},
});
this.configApi = configApi;
this.discoveryApi = discoveryApi;
this.environment = environment;
this.provider = provider;
@@ -107,11 +117,10 @@ export class DefaultAuthConnector<AuthSession>
}
async createSession(options: CreateSessionOptions): Promise<AuthSession> {
const enableExperimentalRedirectFlow =
this.configApi.getOptionalBoolean('enableExperimentalRedirectFlow') ??
false;
if (options.instantPopup && !enableExperimentalRedirectFlow) {
if (options.instantPopup) {
if (this.enableExperimentalRedirectFlow) {
return this.executeRedirect(options.scopes);
}
return this.showPopup(options.scopes);
}
return this.authRequester(options.scopes);
@@ -65,9 +65,6 @@ export function OAuthRequestDialog(_props: {}) {
const authRedirect =
configApi.getOptionalBoolean('enableExperimentalRedirectFlow') ?? false;
const redirectMessage = authRedirect
? 'This will trigger a http redirect to OAuth Login.'
: '';
const requests = useObservable(
useMemo(() => oauthRequestApi.authRequest$(), [oauthRequestApi]),
@@ -94,7 +91,11 @@ export function OAuthRequestDialog(_props: {}) {
<Typography className={classes.titleHeading} variant="h1">
Login Required
</Typography>
<Typography>{redirectMessage}</Typography>
{authRedirect ? (
<Typography>
This will trigger a http redirect to OAuth Login.
</Typography>
) : null}
</DialogTitle>
<DialogContent dividers classes={{ root: classes.contentList }}>
@@ -35,8 +35,19 @@ export type SignInProviderConfig = {
/** @public */
export type IdentityProviders = ('guest' | 'custom' | SignInProviderConfig)[];
/**
* Invoked when the sign-in process has failed.
*/
export type onSignInFailure = () => void;
/**
* Invoked when the sign-in process has started.
*/
export type onSignInStarted = () => void;
export type ProviderComponent = ComponentType<
SignInPageProps & { config: SignInProviderConfig }
{ onSignInStarted: onSignInStarted } & {
onSignInFailure: onSignInFailure;
} & SignInPageProps & { config: SignInProviderConfig }
>;
export type ProviderLoader = (
-2
View File
@@ -687,9 +687,7 @@ export enum SessionState {
// @public
export type SignInPageProps = {
onSignInStarted(): void;
onSignInSuccess(identityApi: IdentityApi_2): void;
onSignInFailure(): void;
};
// @public
@@ -285,6 +285,7 @@ export type SessionApi = {
* Sign out from the current session. This will reload the page.
*/
signOut(): Promise<void>;
/**
* Observe the current state of the auth session. Emits the current state on subscription.
*/
@@ -114,7 +114,7 @@ export class OAuthAdapter implements AuthProviderRouteHandlers {
// set a nonce cookie before redirecting to oauth provider
this.setNonceCookie(res, nonce, cookieConfig);
const state: OAuthState = { nonce, env, origin, redirectUrl, flow: flow };
const state: OAuthState = { nonce, env, origin, redirectUrl, flow };
// If scopes are persisted then we pass them through the state so that we
// can set the cookie on successful auth
@@ -14,12 +14,14 @@
* limitations under the License.
*/
import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils';
import {
MockConfigApi,
renderInTestApp,
TestApiRegistry,
} from '@backstage/test-utils';
import React from 'react';
import { gitOpsApiRef, GitOpsRestApi } from '../../api';
import ProfileCatalog from './ProfileCatalog';
import { ConfigReader } from '@backstage/config';
import { ConfigApi } from '@backstage/core-plugin-api';
import {
ApiProvider,
@@ -33,9 +35,7 @@ import { githubAuthApiRef } from '@backstage/core-plugin-api';
describe('ProfileCatalog', () => {
it('should render', async () => {
const oauthRequestApi = new OAuthRequestManager();
const configApi: ConfigApi = new ConfigReader({
enableExperimentalRedirectFlow: false,
});
const configApi = new MockConfigApi({});
const apis = TestApiRegistry.from(
[gitOpsApiRef, new GitOpsRestApi('http://localhost:3008')],
[