mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
feat(editor): Add tracking on oidc save setting (#16378)
This commit is contained in:
committed by
GitHub
parent
58a556430c
commit
62a33e8074
@@ -1,4 +1,4 @@
|
||||
import type { SamlPreferences } from '@n8n/api-types';
|
||||
import type { OidcConfigDto, SamlPreferences } from '@n8n/api-types';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { within, waitFor } from '@testing-library/vue';
|
||||
import { mockedStore, retry } from '@/__tests__/utils';
|
||||
@@ -23,6 +23,10 @@ const samlConfig = {
|
||||
returnUrl: 'https://n8n-tunnel.myhost.com/rest/sso/saml/acs',
|
||||
} as SamlPreferences & SamlPreferencesExtractedData;
|
||||
|
||||
const oidcConfig = {
|
||||
discoveryEndpoint: 'https://dev-qqkrykgkoo0p63d5.eu.auth0.com/.well-known/openid-configuration',
|
||||
} as OidcConfigDto;
|
||||
|
||||
const telemetryTrack = vi.fn();
|
||||
vi.mock('@/composables/useTelemetry', () => ({
|
||||
useTelemetry: () => ({
|
||||
@@ -152,7 +156,7 @@ describe('SettingsSso View', () => {
|
||||
|
||||
expect(telemetryTrack).toHaveBeenCalledWith(
|
||||
expect.any(String),
|
||||
expect.objectContaining({ identity_provider: 'metadata' }),
|
||||
expect.objectContaining({ identity_provider: 'metadata', authentication_method: 'saml' }),
|
||||
);
|
||||
|
||||
expect(ssoStore.getSamlConfig).toHaveBeenCalledTimes(2);
|
||||
@@ -282,6 +286,68 @@ describe('SettingsSso View', () => {
|
||||
expect(toggle.textContent).toContain('Deactivated');
|
||||
});
|
||||
});
|
||||
|
||||
it('allows user to save OIDC config', async () => {
|
||||
const pinia = createTestingPinia();
|
||||
|
||||
const ssoStore = mockedStore(useSSOStore);
|
||||
ssoStore.saveOidcConfig.mockResolvedValue(oidcConfig);
|
||||
ssoStore.isEnterpriseOidcEnabled = true;
|
||||
ssoStore.isEnterpriseSamlEnabled = false;
|
||||
ssoStore.isOidcLoginEnabled = true;
|
||||
ssoStore.isSamlLoginEnabled = false;
|
||||
|
||||
const { getByTestId, getByRole } = renderView({ pinia });
|
||||
|
||||
// Set authProtocol component ref to OIDC
|
||||
const protocolSelect = getByRole('combobox');
|
||||
expect(protocolSelect).toBeInTheDocument();
|
||||
await userEvent.click(protocolSelect);
|
||||
|
||||
const dropdown = await waitFor(() => getByRole('listbox'));
|
||||
expect(dropdown).toBeInTheDocument();
|
||||
const items = dropdown.querySelectorAll('.el-select-dropdown__item');
|
||||
const oidcItem = Array.from(items).find((item) => item.textContent?.includes('OIDC'));
|
||||
expect(oidcItem).toBeDefined();
|
||||
|
||||
await userEvent.click(oidcItem!);
|
||||
|
||||
const saveButton = await waitFor(() => getByTestId('sso-oidc-save'));
|
||||
expect(saveButton).toBeVisible();
|
||||
|
||||
const oidcDiscoveryUrlInput = getByTestId('oidc-discovery-endpoint');
|
||||
|
||||
expect(oidcDiscoveryUrlInput).toBeVisible();
|
||||
await userEvent.type(oidcDiscoveryUrlInput, oidcConfig.discoveryEndpoint);
|
||||
|
||||
const clientIdInput = getByTestId('oidc-client-id');
|
||||
expect(clientIdInput).toBeVisible();
|
||||
await userEvent.type(clientIdInput, 'test-client-id');
|
||||
const clientSecretInput = getByTestId('oidc-client-secret');
|
||||
expect(clientSecretInput).toBeVisible();
|
||||
await userEvent.type(clientSecretInput, 'test-client-secret');
|
||||
|
||||
expect(saveButton).not.toBeDisabled();
|
||||
await userEvent.click(saveButton);
|
||||
|
||||
expect(ssoStore.saveOidcConfig).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
discoveryEndpoint: oidcConfig.discoveryEndpoint,
|
||||
clientId: 'test-client-id',
|
||||
clientSecret: 'test-client-secret',
|
||||
loginEnabled: true,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(telemetryTrack).toHaveBeenCalledWith(
|
||||
expect.any(String),
|
||||
expect.objectContaining({
|
||||
authentication_method: 'oidc',
|
||||
discovery_endpoint: oidcConfig.discoveryEndpoint,
|
||||
is_active: true,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
let pinia: ReturnType<typeof createPinia>;
|
||||
|
||||
@@ -118,6 +118,28 @@ const getSamlConfig = async () => {
|
||||
ssoSettingsSaved.value = !!config?.metadata;
|
||||
};
|
||||
|
||||
const trackUpdateSettings = () => {
|
||||
const trackingMetadata: {
|
||||
instance_id: string;
|
||||
authentication_method: SupportedProtocolType;
|
||||
is_active?: boolean;
|
||||
discovery_endpoint?: string;
|
||||
identity_provider?: 'metadata' | 'xml';
|
||||
} = {
|
||||
instance_id: rootStore.instanceId,
|
||||
authentication_method: authProtocol.value,
|
||||
};
|
||||
|
||||
if (authProtocol.value === SupportedProtocols.SAML) {
|
||||
trackingMetadata.identity_provider = ipsType.value === 'url' ? 'metadata' : 'xml';
|
||||
trackingMetadata.is_active = ssoStore.isSamlLoginEnabled;
|
||||
} else if (authProtocol.value === SupportedProtocols.OIDC) {
|
||||
trackingMetadata.discovery_endpoint = discoveryEndpoint.value;
|
||||
trackingMetadata.is_active = ssoStore.isOidcLoginEnabled;
|
||||
}
|
||||
telemetry.track('User updated single sign on settings', trackingMetadata);
|
||||
};
|
||||
|
||||
const onSave = async () => {
|
||||
try {
|
||||
validateInput();
|
||||
@@ -142,11 +164,7 @@ const onSave = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
telemetry.track('User updated single sign on settings', {
|
||||
instance_id: rootStore.instanceId,
|
||||
identity_provider: ipsType.value === 'url' ? 'metadata' : 'xml',
|
||||
is_active: ssoStore.isSamlLoginEnabled,
|
||||
});
|
||||
trackUpdateSettings();
|
||||
} catch (error) {
|
||||
toast.showError(error, i18n.baseText('settings.sso.settings.save.error'));
|
||||
return;
|
||||
@@ -267,6 +285,7 @@ async function onOidcSettingsSave() {
|
||||
});
|
||||
|
||||
clientSecret.value = newConfig.clientSecret;
|
||||
trackUpdateSettings();
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -281,13 +300,17 @@ async function onOidcSettingsSave() {
|
||||
{{ i18n.baseText('settings.sso.info.link') }}
|
||||
</a>
|
||||
</n8n-info-tip>
|
||||
<div v-if="ssoStore.isEnterpriseSamlEnabled" data-test-id="sso-content-licensed">
|
||||
<div
|
||||
v-if="ssoStore.isEnterpriseSamlEnabled || ssoStore.isEnterpriseOidcEnabled"
|
||||
data-test-id="sso-content-licensed"
|
||||
>
|
||||
<div :class="$style.group">
|
||||
<label>Select Authentication Protocol</label>
|
||||
<div>
|
||||
<N8nSelect
|
||||
filterable
|
||||
:model-value="authProtocol"
|
||||
data-test-id="sso-auth-protocol-select"
|
||||
:placeholder="i18n.baseText('parameterInput.select')"
|
||||
@update:model-value="onAuthProtocolUpdated"
|
||||
@keydown.stop
|
||||
@@ -407,6 +430,7 @@ async function onOidcSettingsSave() {
|
||||
<N8nInput
|
||||
:model-value="discoveryEndpoint"
|
||||
type="text"
|
||||
data-test-id="oidc-discovery-endpoint"
|
||||
placeholder="https://accounts.google.com/.well-known/openid-configuration"
|
||||
@update:model-value="(v: string) => (discoveryEndpoint = v)"
|
||||
/>
|
||||
@@ -417,6 +441,7 @@ async function onOidcSettingsSave() {
|
||||
<N8nInput
|
||||
:model-value="clientId"
|
||||
type="text"
|
||||
data-test-id="oidc-client-id"
|
||||
@update:model-value="(v: string) => (clientId = v)"
|
||||
/>
|
||||
<small
|
||||
@@ -428,6 +453,7 @@ async function onOidcSettingsSave() {
|
||||
<N8nInput
|
||||
:model-value="clientSecret"
|
||||
type="password"
|
||||
data-test-id="oidc-client-secret"
|
||||
@update:model-value="(v: string) => (clientSecret = v)"
|
||||
/>
|
||||
<small
|
||||
@@ -445,7 +471,12 @@ async function onOidcSettingsSave() {
|
||||
</div>
|
||||
|
||||
<div :class="$style.buttons">
|
||||
<n8n-button size="large" :disabled="cannotSaveOidcSettings" @click="onOidcSettingsSave">
|
||||
<n8n-button
|
||||
data-test-id="sso-oidc-save"
|
||||
size="large"
|
||||
:disabled="cannotSaveOidcSettings"
|
||||
@click="onOidcSettingsSave"
|
||||
>
|
||||
{{ i18n.baseText('settings.sso.settings.save') }}
|
||||
</n8n-button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user