Просмотр исходного кода

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.
Marian 1 месяц назад
Родитель
Сommit
ac2f4d058e

+ 40 - 0
frontend/src/__tests__/components/OIDCProviderSettings.test.tsx

@@ -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);
+  });
 });

+ 27 - 26
frontend/src/components/OIDCProviderSettings.tsx

@@ -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)}