Skip to content

Commit 847b500

Browse files
Siddhantclaude
authored andcommitted
chore(sso-ui): integrate Test Login + align fields with proposal
- Wire SSO Test Login to PR #27336's backend: TestLoginButton (OIDC/SAML hidden-form-POST popup + LDAP credential modal) and a ClaimSelector modal that auto-populates adminPrincipal (email local-part) and principalDomain from the chosen email claim. Drop the old broken call to /security/config/test. - Make oidcConfiguration.secret optional with a recommended hint; auto-derive clientType from secret presence; hide the manual radio. - Drop adminPrincipals + principalDomain from authorizerConfiguration required[] so initial save isn't blocked. Hide them during the new-config flow; keep main tier so they surface once Test Login fills. - Strip oidcConfiguration from the schema for SAML/LDAP to stop RJSF materializing defaults inside a hidden subtree. - Hide root-level OIDC mirrors and tenant per the field-layout proposal; surface preferredJwsAlgorithm in advanced; remove in-form callbackUrl (the read-only display beside the form is the source). - Fix TestLoginButton formData prop shape so SAML/LDAP click paths route correctly; vertically center action-bar buttons. - Sync 19 new i18n keys across the 17 locales. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 9cebb7b commit 847b500

11 files changed

Lines changed: 985 additions & 215 deletions

File tree

openmetadata-spec/src/main/resources/json/schema/configuration/authorizerConfiguration.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,6 @@
8989
"type": "string"
9090
}
9191
},
92-
"required": ["className", "containerRequestFilter", "adminPrincipals", "principalDomain", "enforcePrincipalDomain", "enableSecureSocketConnection"],
92+
"required": ["className", "containerRequestFilter", "enforcePrincipalDomain", "enableSecureSocketConnection"],
9393
"additionalProperties": false
9494
}

openmetadata-spec/src/main/resources/json/schema/security/client/oidcClientConfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,6 @@
9898
"default": "604800"
9999
}
100100
},
101-
"required": ["id", "secret", "discoveryUri", "tenant"],
101+
"required": ["id", "discoveryUri", "tenant"],
102102
"additionalProperties": false
103103
}

openmetadata-ui/src/main/resources/ui/src/components/SettingsSso/SSOConfigurationForm/SSOConfigurationForm.test.tsx

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import {
3434
patchSecurityConfiguration,
3535
SecurityConfiguration,
3636
SecurityValidationResponse,
37-
testSecurityConfiguration,
3837
validateSecurityConfiguration,
3938
} from '../../../rest/securityConfigAPI';
4039
import { getAuthConfig } from '../../../utils/AuthProvider.util';
@@ -107,6 +106,52 @@ jest.mock('@openmetadata/ui-core-components', () => ({
107106
</button>
108107
),
109108
FileTrigger: ({ children }: { children: React.ReactNode }) => <>{children}</>,
109+
Input: ({
110+
label,
111+
value,
112+
onChange,
113+
...rest
114+
}: {
115+
label?: string;
116+
value?: string;
117+
onChange?: (value: string) => void;
118+
} & Record<string, unknown>) => (
119+
<label>
120+
{label}
121+
<input
122+
value={value ?? ''}
123+
{...rest}
124+
onChange={(event) => onChange?.(event.target.value)}
125+
/>
126+
</label>
127+
),
128+
ModalOverlay: ({
129+
children,
130+
isOpen,
131+
}: {
132+
children: React.ReactNode;
133+
isOpen?: boolean;
134+
}) => (isOpen ? <div data-testid="modal-overlay">{children}</div> : null),
135+
Modal: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
136+
Dialog: Object.assign(
137+
({
138+
children,
139+
title,
140+
...rest
141+
}: React.PropsWithChildren<Record<string, unknown>> & {
142+
title?: string;
143+
}) => (
144+
<div role="dialog" {...rest}>
145+
{title && <h3>{title}</h3>}
146+
{children}
147+
</div>
148+
),
149+
{
150+
Header: ({ children }: { children: React.ReactNode }) => <>{children}</>,
151+
Content: ({ children }: { children: React.ReactNode }) => <>{children}</>,
152+
Footer: ({ children }: { children: React.ReactNode }) => <>{children}</>,
153+
}
154+
),
110155
}));
111156

112157
// Mock SSOUtils - use actual implementations where needed
@@ -266,11 +311,6 @@ const mockGetSecurityConfiguration =
266311
getSecurityConfiguration as jest.MockedFunction<
267312
typeof getSecurityConfiguration
268313
>;
269-
const mockTestSecurityConfiguration =
270-
testSecurityConfiguration as jest.MockedFunction<
271-
typeof testSecurityConfiguration
272-
>;
273-
274314
const mockFetchAuthenticationConfig =
275315
fetchAuthenticationConfig as jest.MockedFunction<
276316
typeof fetchAuthenticationConfig
@@ -2158,33 +2198,7 @@ describe('SSOConfigurationForm', () => {
21582198
});
21592199
});
21602200

2161-
it('should auto-fill adminPrincipals and principalDomain on success', async () => {
2162-
mockTestSecurityConfiguration.mockResolvedValue(
2163-
createAxiosResponse({
2164-
component: 'authentication',
2165-
status: VALIDATION_STATUS.SUCCESS,
2166-
})
2167-
);
2168-
2169-
renderComponent({ selectedProvider: AuthProvider.Google });
2170-
2171-
await waitFor(() => {
2172-
expect(screen.getByTestId('test-login-button')).toBeInTheDocument();
2173-
});
2174-
2175-
fireEvent.click(screen.getByTestId('test-login-button'));
2176-
2177-
await waitFor(() => {
2178-
expect(mockTestSecurityConfiguration).toHaveBeenCalled();
2179-
});
2180-
});
2181-
2182-
it('should show error toast when test login fails', async () => {
2183-
const axiosError = {
2184-
response: { data: { errors: [] } },
2185-
} as unknown as AxiosError;
2186-
mockTestSecurityConfiguration.mockRejectedValue(axiosError);
2187-
2201+
it('should show error toast when required OIDC fields are missing', async () => {
21882202
renderComponent({ selectedProvider: AuthProvider.Google });
21892203

21902204
await waitFor(() => {
@@ -2194,7 +2208,6 @@ describe('SSOConfigurationForm', () => {
21942208
fireEvent.click(screen.getByTestId('test-login-button'));
21952209

21962210
await waitFor(() => {
2197-
expect(mockTestSecurityConfiguration).toHaveBeenCalled();
21982211
expect(mockShowErrorToast).toHaveBeenCalled();
21992212
});
22002213
});

0 commit comments

Comments
 (0)