fix(auth): preserve backward-compatible oauth defaults

This commit is contained in:
IanShaw027
2026-04-22 11:17:32 +08:00
parent dd314c41e3
commit 84628108fc
18 changed files with 661 additions and 142 deletions

View File

@@ -362,6 +362,16 @@ function getBindingDetails(provider: UserAuthProvider): UserAuthBindingStatus |
return binding
}
function isProviderEnabledForBinding(provider: BindableProvider): boolean {
if (provider === 'linuxdo') {
return props.linuxdoEnabled
}
if (provider === 'oidc') {
return props.oidcEnabled
}
return resolvedWeChatBinding.value.mode !== null
}
const providerItems = computed(() => [
{
provider: 'email' as const,
@@ -375,7 +385,10 @@ const providerItems = computed(() => [
provider: 'linuxdo' as const,
label: t('profile.authBindings.providers.linuxdo'),
bound: getBindingStatus('linuxdo'),
canBind: getBindingDetails('linuxdo')?.can_bind ?? (props.linuxdoEnabled && !getBindingStatus('linuxdo')),
canBind:
!getBindingStatus('linuxdo') &&
isProviderEnabledForBinding('linuxdo') &&
(getBindingDetails('linuxdo')?.can_bind ?? true),
canUnbind: Boolean(getBindingStatus('linuxdo') && getBindingDetails('linuxdo')?.can_unbind),
details: getBindingDetails('linuxdo'),
},
@@ -383,7 +396,10 @@ const providerItems = computed(() => [
provider: 'oidc' as const,
label: t('profile.authBindings.providers.oidc', { providerName: props.oidcProviderName }),
bound: getBindingStatus('oidc'),
canBind: getBindingDetails('oidc')?.can_bind ?? (props.oidcEnabled && !getBindingStatus('oidc')),
canBind:
!getBindingStatus('oidc') &&
isProviderEnabledForBinding('oidc') &&
(getBindingDetails('oidc')?.can_bind ?? true),
canUnbind: Boolean(getBindingStatus('oidc') && getBindingDetails('oidc')?.can_unbind),
details: getBindingDetails('oidc'),
},
@@ -391,7 +407,10 @@ const providerItems = computed(() => [
provider: 'wechat' as const,
label: t('profile.authBindings.providers.wechat'),
bound: getBindingStatus('wechat'),
canBind: getBindingDetails('wechat')?.can_bind ?? (resolvedWeChatBinding.value.mode !== null && !getBindingStatus('wechat')),
canBind:
!getBindingStatus('wechat') &&
isProviderEnabledForBinding('wechat') &&
(getBindingDetails('wechat')?.can_bind ?? true),
canUnbind: Boolean(getBindingStatus('wechat') && getBindingDetails('wechat')?.can_unbind),
details: getBindingDetails('wechat'),
},

View File

@@ -474,4 +474,26 @@ describe('ProfileIdentityBindingsSection', () => {
expect(userApiMocks.unbindAuthIdentity).toHaveBeenCalledWith('linuxdo')
expect(wrapper.get('[data-testid="profile-binding-linuxdo-status"]').text()).toBe('Not bound')
})
it('hides bind actions when provider details say bindable but the provider is disabled', () => {
const wrapper = mount(ProfileIdentityBindingsSection, {
global: {
plugins: [pinia],
},
props: {
user: createUser({
auth_bindings: {
linuxdo: { bound: false, can_bind: true },
oidc: { bound: false, can_bind: true },
},
}),
linuxdoEnabled: false,
oidcEnabled: false,
wechatEnabled: false,
},
})
expect(wrapper.find('[data-testid="profile-binding-linuxdo-action"]').exists()).toBe(false)
expect(wrapper.find('[data-testid="profile-binding-oidc-action"]').exists()).toBe(false)
})
})

View File

@@ -2032,7 +2032,7 @@
</div>
<Toggle
v-model="form.oidc_connect_use_pkce"
:disabled="true"
data-testid="oidc-connect-use-pkce"
/>
</div>
@@ -2046,7 +2046,7 @@
</div>
<Toggle
v-model="form.oidc_connect_validate_id_token"
:disabled="true"
data-testid="oidc-connect-validate-id-token"
/>
</div>
@@ -4961,8 +4961,8 @@ const form = reactive<SettingsForm>({
oidc_connect_redirect_url: "",
oidc_connect_frontend_redirect_url: "/auth/oidc/callback",
oidc_connect_token_auth_method: "client_secret_post",
oidc_connect_use_pkce: true,
oidc_connect_validate_id_token: true,
oidc_connect_use_pkce: false,
oidc_connect_validate_id_token: false,
oidc_connect_allowed_signing_algs: "RS256,ES256,PS256",
oidc_connect_clock_skew_seconds: 120,
oidc_connect_require_email_verified: false,
@@ -5846,8 +5846,8 @@ async function saveSettings() {
oidc_connect_frontend_redirect_url:
form.oidc_connect_frontend_redirect_url,
oidc_connect_token_auth_method: form.oidc_connect_token_auth_method,
oidc_connect_use_pkce: true,
oidc_connect_validate_id_token: true,
oidc_connect_use_pkce: form.oidc_connect_use_pkce,
oidc_connect_validate_id_token: form.oidc_connect_validate_id_token,
oidc_connect_allowed_signing_algs: form.oidc_connect_allowed_signing_algs,
oidc_connect_clock_skew_seconds: form.oidc_connect_clock_skew_seconds,
oidc_connect_require_email_verified:

View File

@@ -776,4 +776,28 @@ describe("admin SettingsView wechat connect controls", () => {
).toBe(true);
expect(wrapper.text()).toContain("首次绑定时授权");
});
it("preserves optional OIDC compatibility flags instead of forcing them on save", async () => {
getSettings.mockResolvedValueOnce({
...baseSettingsResponse,
oidc_connect_enabled: true,
oidc_connect_use_pkce: false,
oidc_connect_validate_id_token: false,
});
const wrapper = mountView();
await flushPromises();
await openSecurityTab(wrapper);
await wrapper.find("form").trigger("submit.prevent");
await flushPromises();
expect(updateSettings).toHaveBeenCalledTimes(1);
expect(updateSettings).toHaveBeenCalledWith(
expect.objectContaining({
oidc_connect_use_pkce: false,
oidc_connect_validate_id_token: false,
}),
);
});
});