From ff27933a1748f13c5d7f0f06dcd6f10dcf0b5102 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 9 Oct 2024 16:11:32 +0200 Subject: [PATCH 1/6] chore: added some more default api implementations, and default sign in page Signed-off-by: blam --- plugins/app/package.json | 1 + plugins/app/src/defaultApis.ts | 21 ++++++++++++++++ .../app/src/extensions/DefaultSignInPage.tsx | 25 +++++++++++++++++++ plugins/app/src/extensions/index.ts | 1 + plugins/app/src/plugin.ts | 2 ++ 5 files changed, 50 insertions(+) create mode 100644 plugins/app/src/extensions/DefaultSignInPage.tsx diff --git a/plugins/app/package.json b/plugins/app/package.json index d45f08b5df..a14e1eab43 100644 --- a/plugins/app/package.json +++ b/plugins/app/package.json @@ -40,6 +40,7 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/frontend-plugin-api": "workspace:^", + "@backstage/integration-react": "workspace:^", "@backstage/plugin-permission-react": "workspace:^", "@backstage/theme": "workspace:^", "@material-ui/core": "^4.9.13", diff --git a/plugins/app/src/defaultApis.ts b/plugins/app/src/defaultApis.ts index 85c89a6278..b4f6fa0b48 100644 --- a/plugins/app/src/defaultApis.ts +++ b/plugins/app/src/defaultApis.ts @@ -61,6 +61,11 @@ import { vmwareCloudAuthApiRef, } from '@backstage/core-plugin-api'; import { ApiBlueprint } from '@backstage/frontend-plugin-api'; +import { + ScmAuth, + ScmIntegrationsApi, + scmIntegrationsApiRef, +} from '@backstage/integration-react'; import { permissionApiRef, IdentityPermissionApi, @@ -380,4 +385,20 @@ export const apis = [ }), }, }), + ApiBlueprint.make({ + name: 'scm-auth', + params: { + factory: ScmAuth.createDefaultApiFactory(), + }, + }), + ApiBlueprint.make({ + name: 'scm-integrations', + params: { + factory: createApiFactory({ + api: scmIntegrationsApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => ScmIntegrationsApi.fromConfig(configApi), + }), + }, + }), ] as const; diff --git a/plugins/app/src/extensions/DefaultSignInPage.tsx b/plugins/app/src/extensions/DefaultSignInPage.tsx new file mode 100644 index 0000000000..29b384c7a2 --- /dev/null +++ b/plugins/app/src/extensions/DefaultSignInPage.tsx @@ -0,0 +1,25 @@ +/* + * 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 { SignInPageBlueprint } from '@backstage/frontend-plugin-api'; +import { SignInPage } from '@backstage/core-components'; + +export const DefaultSignInPage = SignInPageBlueprint.make({ + params: { + loader: async () => props => + , + }, +}); diff --git a/plugins/app/src/extensions/index.ts b/plugins/app/src/extensions/index.ts index 157f7ddb62..22b020a441 100644 --- a/plugins/app/src/extensions/index.ts +++ b/plugins/app/src/extensions/index.ts @@ -24,6 +24,7 @@ export { ComponentsApi } from './ComponentsApi'; export { IconsApi } from './IconsApi'; export { FeatureFlagsApi } from './FeatureFlagsApi'; export { TranslationsApi } from './TranslationsApi'; +export { DefaultSignInPage } from './DefaultSignInPage'; export { DefaultProgressComponent, DefaultErrorBoundaryComponent, diff --git a/plugins/app/src/plugin.ts b/plugins/app/src/plugin.ts index ff0c69faec..18c412bf77 100644 --- a/plugins/app/src/plugin.ts +++ b/plugins/app/src/plugin.ts @@ -34,6 +34,7 @@ import { DefaultErrorBoundaryComponent, oauthRequestDialogAppRootElement, alertDisplayAppRootElement, + DefaultSignInPage, } from './extensions'; import { apis } from './defaultApis'; @@ -58,6 +59,7 @@ export const appPlugin = createFrontendPlugin({ DefaultProgressComponent, DefaultNotFoundErrorPageComponent, DefaultErrorBoundaryComponent, + DefaultSignInPage, oauthRequestDialogAppRootElement, alertDisplayAppRootElement, ], From 65d7b507b49a2165bc56ac7e80176710c1035a7f Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 9 Oct 2024 16:14:39 +0200 Subject: [PATCH 2/6] chore: updating api-reports Signed-off-by: blam --- plugins/app/report.api.md | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/plugins/app/report.api.md b/plugins/app/report.api.md index 1ff398a346..208f9dcfb0 100644 --- a/plugins/app/report.api.md +++ b/plugins/app/report.api.md @@ -383,6 +383,21 @@ const appPlugin: FrontendPlugin< factory: AnyApiFactory; }; }>; + 'sign-in-page:app': ExtensionDefinition<{ + kind: 'sign-in-page'; + name: undefined; + config: {}; + configInput: {}; + output: ConfigurableExtensionDataRef< + ComponentType, + 'core.sign-in-page.component', + {} + >; + inputs: {}; + params: { + loader: () => Promise>; + }; + }>; 'app-root-element:app/oauth-request-dialog': ExtensionDefinition<{ kind: 'app-root-element'; name: 'oauth-request-dialog'; @@ -705,6 +720,36 @@ const appPlugin: FrontendPlugin< factory: AnyApiFactory; }; }>; + 'api:app/scm-auth': ExtensionDefinition<{ + kind: 'api'; + name: 'scm-auth'; + config: {}; + configInput: {}; + output: ConfigurableExtensionDataRef< + AnyApiFactory, + 'core.api.factory', + {} + >; + inputs: {}; + params: { + factory: AnyApiFactory; + }; + }>; + 'api:app/scm-integrations': ExtensionDefinition<{ + kind: 'api'; + name: 'scm-integrations'; + config: {}; + configInput: {}; + output: ConfigurableExtensionDataRef< + AnyApiFactory, + 'core.api.factory', + {} + >; + inputs: {}; + params: { + factory: AnyApiFactory; + }; + }>; } >; export default appPlugin; From b36be7a3ed9d073a86bf2403f198d1a78f2ca9c3 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 9 Oct 2024 16:28:34 +0200 Subject: [PATCH 3/6] chore: changeset Signed-off-by: blam --- .changeset/pretty-pans-exist.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/pretty-pans-exist.md diff --git a/.changeset/pretty-pans-exist.md b/.changeset/pretty-pans-exist.md new file mode 100644 index 0000000000..e9ccdda0e0 --- /dev/null +++ b/.changeset/pretty-pans-exist.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-app': patch +--- + +Added missing default `SignInPageExtension` which by default uses guest auth, missing `ApiExtensions` for `scmAuth` From 374d3f70406f114234a6e3eddbf4daeda380f247 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 9 Oct 2024 16:33:06 +0200 Subject: [PATCH 4/6] chore: need a yarn.lock Signed-off-by: blam --- .../frontend-defaults/src/createApp.test.tsx | 17 ++++++++++++++++- .../src/app/renderInTestApp.tsx | 3 +++ yarn.lock | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/frontend-defaults/src/createApp.test.tsx b/packages/frontend-defaults/src/createApp.test.tsx index 06872a5691..899d5d1640 100644 --- a/packages/frontend-defaults/src/createApp.test.tsx +++ b/packages/frontend-defaults/src/createApp.test.tsx @@ -29,9 +29,17 @@ import { CreateAppFeatureLoader, createApp } from './createApp'; import { mockApis, renderWithEffects } from '@backstage/test-utils'; import React from 'react'; import { featureFlagsApiRef, useApi } from '@backstage/core-plugin-api'; -import appPlugin from '@backstage/plugin-app'; +import { default as appPluginOriginal } from '@backstage/plugin-app'; describe('createApp', () => { + const appPlugin = appPluginOriginal.withOverrides({ + extensions: [ + appPluginOriginal + .getExtension('sign-in-page:app') + .override({ disabled: true }), + ], + }); + it('should allow themes to be installed', async () => { const app = createApp({ configLoader: async () => ({ @@ -98,6 +106,7 @@ describe('createApp', () => { }), ], }), + appPlugin, ], }); @@ -231,6 +240,7 @@ describe('createApp', () => { const app = createApp({ configLoader: async () => ({ config: mockApis.config() }), features: [ + appPlugin, createFrontendPlugin({ id: 'my-plugin', extensions: [ @@ -277,6 +287,8 @@ describe('createApp', () => { + + themes [ @@ -317,6 +329,9 @@ describe('createApp', () => { ] + signInPage [ + + ] ] diff --git a/packages/frontend-test-utils/src/app/renderInTestApp.tsx b/packages/frontend-test-utils/src/app/renderInTestApp.tsx index e53566a118..7f03921077 100644 --- a/packages/frontend-test-utils/src/app/renderInTestApp.tsx +++ b/packages/frontend-test-utils/src/app/renderInTestApp.tsx @@ -96,6 +96,9 @@ const NavItem = (props: { const appPluginOverride = appPlugin.withOverrides({ extensions: [ + appPlugin.getExtension('sign-in-page:app').override({ + disabled: true, + }), appPlugin.getExtension('app/nav').override({ output: [coreExtensionData.reactElement], factory(_originalFactory, { inputs }) { diff --git a/yarn.lock b/yarn.lock index f8618cba94..f50c38ad17 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4978,6 +4978,7 @@ __metadata: "@backstage/dev-utils": "workspace:^" "@backstage/frontend-plugin-api": "workspace:^" "@backstage/frontend-test-utils": "workspace:^" + "@backstage/integration-react": "workspace:^" "@backstage/plugin-permission-react": "workspace:^" "@backstage/theme": "workspace:^" "@material-ui/core": ^4.9.13 From 47aea432092261f65b68e9a14471f275002f9b82 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 14 Oct 2024 11:17:22 +0200 Subject: [PATCH 5/6] chore: cleanup app-next a little bit Signed-off-by: blam --- packages/app-next/src/App.tsx | 32 ----------------- .../app-next/src/overrides/SignInPage.tsx | 35 ------------------- 2 files changed, 67 deletions(-) delete mode 100644 packages/app-next/src/overrides/SignInPage.tsx diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx index 79adc13daf..1992d5b35f 100644 --- a/packages/app-next/src/App.tsx +++ b/packages/app-next/src/App.tsx @@ -26,7 +26,6 @@ import homePlugin, { import { coreExtensionData, createExtension, - ApiBlueprint, createFrontendModule, } from '@backstage/frontend-plugin-api'; import { @@ -41,14 +40,7 @@ import { convertLegacyApp } from '@backstage/core-compat-api'; import { FlatRoutes } from '@backstage/core-app-api'; import { Route } from 'react-router'; import { CatalogImportPage } from '@backstage/plugin-catalog-import'; -import { createApiFactory, configApiRef } from '@backstage/core-plugin-api'; -import { - ScmAuth, - ScmIntegrationsApi, - scmIntegrationsApiRef, -} from '@backstage/integration-react'; import kubernetesPlugin from '@backstage/plugin-kubernetes/alpha'; -import { signInPageModule } from './overrides/SignInPage'; import { convertLegacyPlugin } from '@backstage/core-compat-api'; import { convertLegacyPageExtension } from '@backstage/core-compat-api'; import { convertLegacyEntityContentExtension } from '@backstage/plugin-catalog-react/alpha'; @@ -118,28 +110,6 @@ const customHomePageModule = createFrontendModule({ ], }); -const scmModule = createFrontendModule({ - pluginId: 'app', - extensions: [ - ApiBlueprint.make({ - name: 'scm-auth', - params: { - factory: ScmAuth.createDefaultApiFactory(), - }, - }), - ApiBlueprint.make({ - name: 'scm-integrations', - params: { - factory: createApiFactory({ - api: scmIntegrationsApiRef, - deps: { configApi: configApiRef }, - factory: ({ configApi }) => ScmIntegrationsApi.fromConfig(configApi), - }), - }, - }), - ], -}); - const notFoundErrorPageModule = createFrontendModule({ pluginId: 'app', extensions: [notFoundErrorPage], @@ -159,8 +129,6 @@ const app = createApp({ homePlugin, appVisualizerPlugin, kubernetesPlugin, - signInPageModule, - scmModule, notFoundErrorPageModule, customHomePageModule, ...collectedLegacyPlugins, diff --git a/packages/app-next/src/overrides/SignInPage.tsx b/packages/app-next/src/overrides/SignInPage.tsx deleted file mode 100644 index f1e37a241b..0000000000 --- a/packages/app-next/src/overrides/SignInPage.tsx +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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 { SignInPage } from '@backstage/core-components'; -import { - SignInPageBlueprint, - createFrontendModule, -} from '@backstage/frontend-plugin-api'; - -const signInPage = SignInPageBlueprint.make({ - name: 'guest', - params: { - loader: async () => props => - , - }, -}); - -export const signInPageModule = createFrontendModule({ - pluginId: 'app', - extensions: [signInPage], -}); From 666d5b14314abb0cf2c3d294128acbd7c898af69 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 14 Oct 2024 11:18:14 +0200 Subject: [PATCH 6/6] chore: new changeset Signed-off-by: blam --- .changeset/chilly-meals-sniff.md | 5 +++++ packages/app-next/src/index-public-experimental.tsx | 5 +---- 2 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 .changeset/chilly-meals-sniff.md diff --git a/.changeset/chilly-meals-sniff.md b/.changeset/chilly-meals-sniff.md new file mode 100644 index 0000000000..6776f93154 --- /dev/null +++ b/.changeset/chilly-meals-sniff.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-test-utils': patch +--- + +Disable the built-in `SignInPage` in `createExtensionTester` in order to not mess with existing tests diff --git a/packages/app-next/src/index-public-experimental.tsx b/packages/app-next/src/index-public-experimental.tsx index f258a660e3..16535dae98 100644 --- a/packages/app-next/src/index-public-experimental.tsx +++ b/packages/app-next/src/index-public-experimental.tsx @@ -15,11 +15,8 @@ */ import ReactDOM from 'react-dom/client'; -import { signInPageModule } from './overrides/SignInPage'; import { createPublicSignInApp } from '@backstage/frontend-defaults'; -const app = createPublicSignInApp({ - features: [signInPageModule], -}); +const app = createPublicSignInApp(); ReactDOM.createRoot(document.getElementById('root')!).render(app.createRoot());