diff --git a/packages/main/src/plugin/authentication-menu.spec.ts b/packages/main/src/plugin/authentication-menu.spec.ts deleted file mode 100644 index 2ebca15da854a..0000000000000 --- a/packages/main/src/plugin/authentication-menu.spec.ts +++ /dev/null @@ -1,132 +0,0 @@ -/********************************************************************** - * Copyright (C) 2023-2024 Red Hat, Inc. - * - * 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. - * - * SPDX-License-Identifier: Apache-2.0 - ***********************************************************************/ - -import type { BrowserWindow } from 'electron'; -import { Menu } from 'electron'; -import { afterEach, beforeEach, expect, test, vi } from 'vitest'; - -import type { ApiSenderType } from './api.js'; -import { AuthenticationImpl } from './authentication.js'; -import { AuthenticationProviderSingleAccount } from './authentication.spec.js'; -import { showAccountsMenu } from './authentication-menu.js'; -import type { MessageBox } from './message-box.js'; -import type { NavigationManager } from './navigation/navigation-manager.js'; - -const menu = { - popup: vi.fn(), -} as unknown as Menu; - -vi.mock('electron', () => ({ - Menu: { - buildFromTemplate: (): Menu => menu, - }, - BrowserWindow: { - getFocusedWindow: (): BrowserWindow => - ({ - webContents: { - getZoomFactor: (): number => 1.3, - }, - }) as unknown as BrowserWindow, - }, -})); - -const navigationManager = { - navigateToAuthentication: vi.fn(), -} as unknown as NavigationManager; - -let authModule: AuthenticationImpl; - -const apiSender: ApiSenderType = { - send: vi.fn(), - receive: vi.fn(), -}; - -const messageBox: MessageBox = { - showMessageBox: () => Promise.resolve({ response: 1 }), -} as unknown as MessageBox; - -beforeEach(function () { - authModule = new AuthenticationImpl(apiSender, messageBox); -}); - -afterEach(() => { - vi.resetAllMocks(); -}); - -test('showAccountsMenu creates menu with authentication requests and current sessions', async () => { - const authProvidrer1 = new AuthenticationProviderSingleAccount(); - const authProvidrer2 = new AuthenticationProviderSingleAccount(); - authModule.registerAuthenticationProvider('company.auth-provider1', 'Provider 1', authProvidrer1); - authModule.registerAuthenticationProvider('company.auth-provider2', 'Provider 2', authProvidrer2); - - const session1 = await authModule.getSession( - { id: 'ext1', label: 'Ext 1' }, - 'company.auth-provider2', - ['scope1', 'scope2'], - { createIfNone: true }, - ); - expect(session1).toBeDefined(); - - const session2 = await authModule.getSession( - { id: 'ext2', label: 'Ext 2' }, - 'company.auth-provider1', - ['scope1', 'scope2'], - { silent: false }, - ); - expect(session2).toBeUndefined(); - - const session3 = await authModule.getSession( - { id: 'ext3', label: 'Ext 3' }, - 'company.auth-provider1', - ['scope1', 'scope2'], - { silent: false }, - ); - expect(session3).toBeUndefined(); - - expect(authModule.getSessionRequests()).length(2); - - const buildFromTemplateSpy = vi.spyOn(Menu, 'buildFromTemplate'); - - await showAccountsMenu(10, 10, authModule, navigationManager); - - expect(menu.popup).toBeCalledWith({ x: 13, y: 13 }); - expect(buildFromTemplateSpy).toBeCalledWith( - expect.arrayContaining([ - expect.objectContaining({ - label: 'Manage authentication', - }), - expect.objectContaining({ - type: 'separator', - }), - expect.objectContaining({ - label: 'Sign in with Provider 1 to use Ext 2', - }), - expect.objectContaining({ - label: 'Sign in with Provider 1 to use Ext 3', - }), - expect.objectContaining({ - label: `${session1?.account.label} (Provider 2)`, - submenu: expect.arrayContaining([ - expect.objectContaining({ - label: 'Sign out', - }), - ]), - }), - ]), - ); -}); diff --git a/packages/main/src/plugin/authentication-menu.ts b/packages/main/src/plugin/authentication-menu.ts deleted file mode 100644 index c78fc0815c12f..0000000000000 --- a/packages/main/src/plugin/authentication-menu.ts +++ /dev/null @@ -1,72 +0,0 @@ -/********************************************************************** - * Copyright (C) 2023 Red Hat, Inc. - * - * 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. - * - * SPDX-License-Identifier: Apache-2.0 - ***********************************************************************/ - -import type { MenuItem, MenuItemConstructorOptions } from 'electron'; -import { BrowserWindow, Menu } from 'electron'; - -import type { AuthenticationImpl } from './authentication.js'; -import type { NavigationManager } from './navigation/navigation-manager.js'; - -export async function showAccountsMenu( - x: number, - y: number, - auth: AuthenticationImpl, - navigation: NavigationManager, -): Promise { - const template: (MenuItemConstructorOptions | MenuItem)[] = [ - { - label: 'Manage authentication', - click: (): void => { - navigation.navigateToAuthentication().catch(console.error); - }, - }, - { - type: 'separator', - } as MenuItem, - ]; - const menuInfo = await auth.getAccountsMenuInfo(); - menuInfo.forEach(item => { - if ('requestId' in item) { - template.push({ - label: item.label, - click: (): void => { - auth.executeSessionRequest(item.requestId).catch(console.error); - }, - }); - } else { - template.push({ - label: item.label, - submenu: [ - { - label: 'Sign out', - click: (): void => { - auth.signOut(item.providerId, item.sessionId).catch(console.error); - }, - }, - ], - }); - } - }); - const menu = Menu.buildFromTemplate(template); - const zf = BrowserWindow.getFocusedWindow()?.webContents.getZoomFactor(); - const zoomFactor = zf ? zf : 1; - menu.popup({ - x: Math.round(x * zoomFactor), - y: Math.round(y * zoomFactor), - }); -} diff --git a/packages/main/src/plugin/index.ts b/packages/main/src/plugin/index.ts index 6b19b5de2747d..03cb84567e73f 100644 --- a/packages/main/src/plugin/index.ts +++ b/packages/main/src/plugin/index.ts @@ -108,7 +108,6 @@ import type { PodInfo, PodInspectInfo } from './api/pod-info.js'; import { AppearanceInit } from './appearance-init.js'; import type { AuthenticationProviderInfo } from './authentication.js'; import { AuthenticationImpl } from './authentication.js'; -import { showAccountsMenu } from './authentication-menu.js'; import { AutostartEngine } from './autostart-engine.js'; import { CancellationTokenRegistry } from './cancellation-token-registry.js'; import { Certificates } from './certificates.js'; @@ -1557,10 +1556,6 @@ export class PluginSystem { }, ); - this.ipcHandle('authentication:showAccountsMenu', async (_listener, x: number, y: number): Promise => { - return showAccountsMenu(x, y, authentication, navigationManager); - }); - this.ipcHandle( 'configuration-registry:getConfigurationProperties', async (): Promise> => { diff --git a/packages/renderer/src/AppNavigation.svelte b/packages/renderer/src/AppNavigation.svelte index f925b99d57808..7ca4be1f1a52c 100644 --- a/packages/renderer/src/AppNavigation.svelte +++ b/packages/renderer/src/AppNavigation.svelte @@ -4,9 +4,9 @@ import { onMount } from 'svelte'; import type { TinroRouteMeta } from 'tinro'; +import AuthActions from './lib/authentication/AuthActions.svelte'; import { CommandRegistry } from './lib/CommandRegistry'; import NewContentOnDashboardBadge from './lib/dashboard/NewContentOnDashboardBadge.svelte'; -import AccountIcon from './lib/images/AccountIcon.svelte'; import DashboardIcon from './lib/images/DashboardIcon.svelte'; import SettingsIcon from './lib/images/SettingsIcon.svelte'; import NavItem from './lib/ui/NavItem.svelte'; @@ -14,7 +14,13 @@ import NavRegistryEntry from './lib/ui/NavRegistryEntry.svelte'; import NavSection from './lib/ui/NavSection.svelte'; import { navigationRegistry } from './stores/navigation/navigation-registry'; -let { exitSettingsCallback, meta = $bindable() }: { exitSettingsCallback: () => void; meta: TinroRouteMeta } = $props(); +let { + exitSettingsCallback, + meta = $bindable(), +}: { + exitSettingsCallback: () => void; + meta: TinroRouteMeta; +} = $props(); const iconSize = '22'; @@ -71,12 +77,8 @@ function clickSettings(b: boolean) {
- window.showAccountsMenu(event.x, event.y)}> - + {}}> + +import { faKey, faSignIn, faSignOut } from '@fortawesome/free-solid-svg-icons'; +import { DropdownMenu } from '@podman-desktop/ui-svelte'; + +import AccountIcon from '/@/lib/images/AccountIcon.svelte'; +import { handleNavigation } from '/@/navigation'; +import { authenticationProviders } from '/@/stores/authenticationProviders'; +import { NavigationPage } from '/@api/navigation-page'; + +export let iconSize: string; + + + + + + + + handleNavigation({ page: NavigationPage.AUTHENTICATION })} /> + + {#each $authenticationProviders as provider} + {@const sessionRequests = provider.sessionRequests ?? []} + {#if provider?.accounts?.length > 0} + {#each provider.accounts as account} + window.requestAuthenticationProviderSignOut(provider.id, account.id)} + icon={faSignOut} /> + {/each} + {/if} + + {#each sessionRequests as request} + window.requestAuthenticationProviderSignIn(request.id)} + icon={faSignIn} /> + {/each} + {/each} + diff --git a/packages/ui/src/lib/dropdownMenu/DropdownMenu.svelte b/packages/ui/src/lib/dropdownMenu/DropdownMenu.svelte index 62d9054cc2313..a69594f2ede70 100644 --- a/packages/ui/src/lib/dropdownMenu/DropdownMenu.svelte +++ b/packages/ui/src/lib/dropdownMenu/DropdownMenu.svelte @@ -1,5 +1,5 @@