From f28242025e29066478364b511ade883fedc31d5d Mon Sep 17 00:00:00 2001 From: Heikki Hellgren Date: Thu, 21 Mar 2024 07:41:02 +0100 Subject: [PATCH] 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 --- .changeset/light-eggs-switch.md | 2 +- packages/dev-utils/api-report.md | 11 ++++- .../SidebarSignOutButton.tsx | 44 +++++++++++++++++++ .../components/SidebarSignOutButton/index.ts | 16 +++++++ packages/dev-utils/src/components/index.ts | 1 + packages/dev-utils/src/devApp/render.test.tsx | 3 +- packages/dev-utils/src/devApp/render.tsx | 40 +++++++++++++++-- plugins/notifications/dev/index.tsx | 3 +- plugins/signals-backend/dev/index.ts | 2 + plugins/signals-backend/package.json | 2 + yarn.lock | 2 + 11 files changed, 117 insertions(+), 9 deletions(-) create mode 100644 packages/dev-utils/src/components/SidebarSignOutButton/SidebarSignOutButton.tsx create mode 100644 packages/dev-utils/src/components/SidebarSignOutButton/index.ts diff --git a/.changeset/light-eggs-switch.md b/.changeset/light-eggs-switch.md index 3fbb77b0d8..26934f155e 100644 --- a/.changeset/light-eggs-switch.md +++ b/.changeset/light-eggs-switch.md @@ -2,4 +2,4 @@ '@backstage/dev-utils': patch --- -Allow defining custom side bar item for page +Allow defining custom sidebar item for page and login for the development app diff --git a/packages/dev-utils/api-report.md b/packages/dev-utils/api-report.md index d30df29200..0a5b3d10e8 100644 --- a/packages/dev-utils/api-report.md +++ b/packages/dev-utils/api-report.md @@ -13,7 +13,9 @@ import { Entity } from '@backstage/catalog-model'; import { GridProps } from '@material-ui/core/Grid'; import { IconComponent } from '@backstage/core-plugin-api'; import { PropsWithChildren } from 'react'; +import { default as React_2 } from 'react'; import { ReactNode } from 'react'; +import { SignInProviderConfig } from '@backstage/core-components'; // @public export function createDevApp(): DevAppBuilder; @@ -22,6 +24,8 @@ export function createDevApp(): DevAppBuilder; export class DevAppBuilder { addPage(opts: DevAppPageOptions): DevAppBuilder; addRootChild(node: ReactNode): DevAppBuilder; + addSidebarItem(sidebarItem: JSX.Element): DevAppBuilder; + addSignInProvider(provider: SignInProviderConfig): this; addThemes(themes: AppTheme[]): this; build(): ComponentType>; registerApi< @@ -42,7 +46,6 @@ export type DevAppPageOptions = { children?: JSX.Element; title?: string; icon?: IconComponent; - sidebarItem?: JSX.Element; }; // @public (undocumented) @@ -51,4 +54,10 @@ export const EntityGridItem: ( entity: Entity; }, ) => JSX.Element; + +// @public +export const SidebarSignOutButton: (props: { + icon?: IconComponent; + text?: string; +}) => React_2.JSX.Element; ``` diff --git a/packages/dev-utils/src/components/SidebarSignOutButton/SidebarSignOutButton.tsx b/packages/dev-utils/src/components/SidebarSignOutButton/SidebarSignOutButton.tsx new file mode 100644 index 0000000000..9cfe888d4d --- /dev/null +++ b/packages/dev-utils/src/components/SidebarSignOutButton/SidebarSignOutButton.tsx @@ -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 ( + identityApi.signOut()} + icon={props.icon ?? LockIcon} + text={props.text ?? 'Sign Out'} + /> + ); +}; diff --git a/packages/dev-utils/src/components/SidebarSignOutButton/index.ts b/packages/dev-utils/src/components/SidebarSignOutButton/index.ts new file mode 100644 index 0000000000..6182e1fa12 --- /dev/null +++ b/packages/dev-utils/src/components/SidebarSignOutButton/index.ts @@ -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'; diff --git a/packages/dev-utils/src/components/index.ts b/packages/dev-utils/src/components/index.ts index d71b424a34..8959b6e7b1 100644 --- a/packages/dev-utils/src/components/index.ts +++ b/packages/dev-utils/src/components/index.ts @@ -15,3 +15,4 @@ */ export * from './EntityGridItem'; +export * from './SidebarSignOutButton'; diff --git a/packages/dev-utils/src/devApp/render.test.tsx b/packages/dev-utils/src/devApp/render.test.tsx index 2da6ef370a..7fc0024cc3 100644 --- a/packages/dev-utils/src/devApp/render.test.tsx +++ b/packages/dev-utils/src/devApp/render.test.tsx @@ -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' }, }, }, ]; diff --git a/packages/dev-utils/src/devApp/render.tsx b/packages/dev-utils/src/devApp/render.tsx index 26fd96052b..3b3c993a6b 100644 --- a/packages/dev-utils/src/devApp/render.tsx +++ b/packages/dev-utils/src/devApp/render.tsx @@ -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(); private readonly routes = new Array(); private readonly sidebarItems = new Array(); + private readonly signInProviders = new Array(); private defaultPage?: string; private themes?: Array; @@ -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( { + return ( + + ); + }, + }, bindRoutes: ({ bind }) => { for (const plugin of this.plugins ?? []) { const targets: Record> = {}; @@ -221,6 +252,7 @@ export class DevAppBuilder { + {this.routes} diff --git a/plugins/notifications/dev/index.tsx b/plugins/notifications/dev/index.tsx index 1406f55b59..f4d9176a70 100644 --- a/plugins/notifications/dev/index.tsx +++ b/plugins/notifications/dev/index.tsx @@ -18,12 +18,11 @@ import { createDevApp } from '@backstage/dev-utils'; import { NotificationsPage, notificationsPlugin } from '../src/plugin'; import { NotificationsSidebarItem } from '../src'; -// TODO: How to sign in here as guest user? createDevApp() .registerPlugin(notificationsPlugin) .addPage({ element: , path: '/notifications', - sidebarItem: , }) + .addSidebarItem() .render(); diff --git a/plugins/signals-backend/dev/index.ts b/plugins/signals-backend/dev/index.ts index ae98e54eed..39021a9fcd 100644 --- a/plugins/signals-backend/dev/index.ts +++ b/plugins/signals-backend/dev/index.ts @@ -53,6 +53,8 @@ const signalDebug = createBackendPlugin({ const backend = createBackend(); backend.add(import('@backstage/plugin-events-backend/alpha')); +backend.add(import('@backstage/plugin-auth-backend')); +backend.add(import('@backstage/plugin-auth-backend-module-guest-provider')); backend.add(import('../src')); backend.add(signalDebug); diff --git a/plugins/signals-backend/package.json b/plugins/signals-backend/package.json index 923b4bb150..a6ebb228e4 100644 --- a/plugins/signals-backend/package.json +++ b/plugins/signals-backend/package.json @@ -47,6 +47,8 @@ "devDependencies": { "@backstage/backend-defaults": "workspace:^", "@backstage/cli": "workspace:^", + "@backstage/plugin-auth-backend": "workspace:^", + "@backstage/plugin-auth-backend-module-guest-provider": "workspace:^", "@backstage/plugin-events-backend": "workspace:^", "@types/supertest": "^2.0.8", "msw": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index e392282e15..893930d505 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9285,6 +9285,8 @@ __metadata: "@backstage/backend-plugin-api": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" + "@backstage/plugin-auth-backend": "workspace:^" + "@backstage/plugin-auth-backend-module-guest-provider": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" "@backstage/plugin-events-backend": "workspace:^" "@backstage/plugin-events-node": "workspace:^"