fix(oidc): hide the icon buttons on the env-managed provider too

refresh-icon and remove-icon rendered outside the !provider.is_env_managed
block, and both routes answer 409 for that provider -- so a click could only
ever produce an error toast, which is the reason the comment right below them
gives for hiding everything else. Its icon comes from BAMBUDDY_OIDC_ICON_URL
and is re-applied on every boot.

Reported by maziggy in review of #2625.
This commit is contained in:
Marian
2026-07-30 14:43:23 +00:00
parent d64f5d9651
commit ac2f4d058e
2 changed files with 67 additions and 26 deletions
@@ -361,6 +361,25 @@ describe('env-managed provider (#2593)', () => {
expect(screen.queryByTestId('delete-provider-2')).not.toBeInTheDocument();
});
it('offers no icon controls for it either', async () => {
server.use(
http.get('/api/v1/auth/oidc/providers/all', () =>
HttpResponse.json([
{ ...envManagedProvider, icon_url: 'https://idp.example.com/i.png', has_icon: true },
])
)
);
render(<OIDCProviderSettings />);
await waitFor(() => {
expect(screen.getByText('EnvIdP')).toBeInTheDocument();
});
// Both icon routes answer 409 for an env-managed provider, so a click could
// only ever produce an error toast — the same reason the rest are hidden.
expect(screen.queryByTestId('refresh-icon-2')).not.toBeInTheDocument();
expect(screen.queryByTestId('remove-icon-2')).not.toBeInTheDocument();
});
it('still offers them for a UI-created provider', async () => {
server.use(
http.get('/api/v1/auth/oidc/providers/all', () =>
@@ -375,4 +394,25 @@ describe('env-managed provider (#2593)', () => {
expect(screen.getByTestId('edit-provider-1')).toBeInTheDocument();
expect(screen.getByTestId('delete-provider-1')).toBeInTheDocument();
});
it('hides the enable/disable toggle for env-managed providers', async () => {
server.use(
http.get('/api/v1/auth/oidc/providers/all', () =>
HttpResponse.json([
{ ...mockProviders[0], id: 2, name: 'EnvIdP', is_enabled: true, is_env_managed: true },
{ ...mockProviders[0], id: 3, name: 'UiIdP', is_enabled: true, is_env_managed: false },
])
)
);
render(<OIDCProviderSettings />);
await waitFor(() => {
expect(screen.getByText('EnvIdP')).toBeInTheDocument();
expect(screen.getByText('UiIdP')).toBeInTheDocument();
});
// The toggle carries no testid, so it is counted: two cards are rendered and
// exactly one switch may exist — the UI provider's. Enabling the env-managed
// one would be reverted by the next boot, and the API answers 409.
expect(screen.getAllByRole('switch')).toHaveLength(1);
});
});
@@ -398,35 +398,36 @@ export function OIDCProviderSettings() {
</div>
</div>
<div className="flex items-center gap-2">
{provider.icon_url && (
<Button
variant="secondary"
size="sm"
onClick={() => refreshIconMutation.mutate(provider.id)}
disabled={refreshIconMutation.isPending}
title={t('settings.oidc.refreshIcon')}
data-testid={`refresh-icon-${provider.id}`}
>
<RefreshCw className={`w-4 h-4 ${refreshIconMutation.isPending ? 'animate-spin' : ''}`} />
</Button>
)}
{provider.has_icon && (
<Button
variant="secondary"
size="sm"
onClick={() => removeIconMutation.mutate(provider.id)}
disabled={removeIconMutation.isPending}
title={t('settings.oidc.removeIcon')}
data-testid={`remove-icon-${provider.id}`}
>
<ImageOff className="w-4 h-4" />
</Button>
)}
{/* #2593: startup rewrites the env-managed row from BAMBUDDY_OIDC_*
and the API answers 409, so offering these would promise a
change that cannot land. */}
and the API answers 409, so offering any of these would promise
a change that cannot land -- the icon routes included, where the
click only ever produced an error toast. */}
{!provider.is_env_managed && (
<>
{provider.icon_url && (
<Button
variant="secondary"
size="sm"
onClick={() => refreshIconMutation.mutate(provider.id)}
disabled={refreshIconMutation.isPending}
title={t('settings.oidc.refreshIcon')}
data-testid={`refresh-icon-${provider.id}`}
>
<RefreshCw className={`w-4 h-4 ${refreshIconMutation.isPending ? 'animate-spin' : ''}`} />
</Button>
)}
{provider.has_icon && (
<Button
variant="secondary"
size="sm"
onClick={() => removeIconMutation.mutate(provider.id)}
disabled={removeIconMutation.isPending}
title={t('settings.oidc.removeIcon')}
data-testid={`remove-icon-${provider.id}`}
>
<ImageOff className="w-4 h-4" />
</Button>
)}
<Toggle
checked={provider.is_enabled}
onChange={() => toggleEnabled(provider)}