feat: support login for the development app
this fixes the local development issue with new backend system where the user is not logged in thus resulting 401 errors from all api endpoints. adds possibility to also add other login providers for testing plugins independently. Signed-off-by: Heikki Hellgren <heikki.hellgren@op.fi>
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2024 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 { SidebarItem } from '@backstage/core-components';
|
||||
import LockIcon from '@material-ui/icons/Lock';
|
||||
import {
|
||||
IconComponent,
|
||||
identityApiRef,
|
||||
useApi,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
/**
|
||||
* Button for sidebar that signs out user
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const SidebarSignOutButton = (props: {
|
||||
icon?: IconComponent;
|
||||
text?: string;
|
||||
}) => {
|
||||
const identityApi = useApi(identityApiRef);
|
||||
|
||||
return (
|
||||
<SidebarItem
|
||||
onClick={() => identityApi.signOut()}
|
||||
icon={props.icon ?? LockIcon}
|
||||
text={props.text ?? 'Sign Out'}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2024 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.
|
||||
*/
|
||||
export * from './SidebarSignOutButton';
|
||||
@@ -15,3 +15,4 @@
|
||||
*/
|
||||
|
||||
export * from './EntityGridItem';
|
||||
export * from './SidebarSignOutButton';
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { createDevApp } from './render';
|
||||
import { useApi, configApiRef } from '@backstage/core-plugin-api';
|
||||
import { configApiRef, useApi } from '@backstage/core-plugin-api';
|
||||
|
||||
const anyEnv = (process.env = { ...process.env }) as any;
|
||||
|
||||
@@ -28,6 +28,7 @@ describe('DevAppBuilder', () => {
|
||||
context: 'test',
|
||||
data: {
|
||||
app: { title: 'Test App' },
|
||||
backend: { baseUrl: 'http://localhost' },
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -25,6 +25,8 @@ import {
|
||||
SidebarPage,
|
||||
SidebarSpace,
|
||||
SidebarSpacer,
|
||||
SignInPage,
|
||||
SignInProviderConfig,
|
||||
} from '@backstage/core-components';
|
||||
import {
|
||||
AnyApiFactory,
|
||||
@@ -48,6 +50,7 @@ import React, { ComponentType, PropsWithChildren, ReactNode } from 'react';
|
||||
import { createRoutesFromChildren, Route } from 'react-router-dom';
|
||||
import { SidebarThemeSwitcher } from './SidebarThemeSwitcher';
|
||||
import 'react-dom';
|
||||
import { SidebarSignOutButton } from '../components';
|
||||
|
||||
let ReactDOMPromise: Promise<
|
||||
typeof import('react-dom') | typeof import('react-dom/client')
|
||||
@@ -80,7 +83,6 @@ export type DevAppPageOptions = {
|
||||
children?: JSX.Element;
|
||||
title?: string;
|
||||
icon?: IconComponent;
|
||||
sidebarItem?: JSX.Element;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -95,6 +97,7 @@ export class DevAppBuilder {
|
||||
private readonly rootChildren = new Array<ReactNode>();
|
||||
private readonly routes = new Array<JSX.Element>();
|
||||
private readonly sidebarItems = new Array<JSX.Element>();
|
||||
private readonly signInProviders = new Array<SignInProviderConfig>();
|
||||
|
||||
private defaultPage?: string;
|
||||
private themes?: Array<AppTheme>;
|
||||
@@ -129,6 +132,16 @@ export class DevAppBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new sidebar item to the dev app.
|
||||
*
|
||||
* Useful for adding only sidebar items without a corresponding page.
|
||||
*/
|
||||
addSidebarItem(sidebarItem: JSX.Element): DevAppBuilder {
|
||||
this.sidebarItems.push(sidebarItem);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a page component along with accompanying sidebar item.
|
||||
*
|
||||
@@ -142,9 +155,7 @@ export class DevAppBuilder {
|
||||
this.defaultPage = path;
|
||||
}
|
||||
|
||||
if (opts.sidebarItem) {
|
||||
this.sidebarItems.push(opts.sidebarItem);
|
||||
} else if (opts.title) {
|
||||
if (opts.title) {
|
||||
this.sidebarItems.push(
|
||||
<SidebarItem
|
||||
key={path}
|
||||
@@ -174,6 +185,14 @@ export class DevAppBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new sign in provider for the dev app
|
||||
*/
|
||||
addSignInProvider(provider: SignInProviderConfig) {
|
||||
this.signInProviders.push(provider);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a DevApp component using the resources registered so far
|
||||
*/
|
||||
@@ -197,6 +216,18 @@ export class DevAppBuilder {
|
||||
apis,
|
||||
plugins: this.plugins,
|
||||
themes: this.themes,
|
||||
components: {
|
||||
SignInPage: props => {
|
||||
return (
|
||||
<SignInPage
|
||||
{...props}
|
||||
providers={['guest', ...this.signInProviders]}
|
||||
title="Select a sign-in method"
|
||||
align="center"
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
bindRoutes: ({ bind }) => {
|
||||
for (const plugin of this.plugins ?? []) {
|
||||
const targets: Record<string, RouteRef<any>> = {};
|
||||
@@ -221,6 +252,7 @@ export class DevAppBuilder {
|
||||
<SidebarSpace />
|
||||
<SidebarDivider />
|
||||
<SidebarThemeSwitcher />
|
||||
<SidebarSignOutButton />
|
||||
</Sidebar>
|
||||
<FlatRoutes>
|
||||
{this.routes}
|
||||
|
||||
Reference in New Issue
Block a user