fix(profile): stabilize identity binding management
This commit is contained in:
@@ -444,7 +444,14 @@ function providerIconClass(provider: UserAuthProvider): string {
|
||||
|
||||
function providerSummary(provider: UserAuthProvider): string {
|
||||
if (provider === 'email') {
|
||||
return currentUser.value?.email || ''
|
||||
const email = currentUser.value?.email?.trim() || ''
|
||||
if (!email) {
|
||||
return ''
|
||||
}
|
||||
if (currentUser.value?.email_bound === false && email.endsWith('.invalid')) {
|
||||
return ''
|
||||
}
|
||||
return email
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
<div class="space-y-1">
|
||||
<p class="truncate text-sm text-gray-600 dark:text-gray-300">
|
||||
{{ user?.email }}
|
||||
{{ primaryEmailDisplay }}
|
||||
</p>
|
||||
<div
|
||||
v-if="sourceHints.length"
|
||||
@@ -208,6 +208,16 @@ const { t } = useI18n()
|
||||
|
||||
const avatarUrl = computed(() => props.user?.avatar_url?.trim() || '')
|
||||
const displayName = computed(() => props.user?.username?.trim() || props.user?.email?.trim() || t('profile.user'))
|
||||
const primaryEmailDisplay = computed(() => {
|
||||
const email = props.user?.email?.trim() || ''
|
||||
if (!email) {
|
||||
return ''
|
||||
}
|
||||
if (props.user?.email_bound === false && email.endsWith('.invalid')) {
|
||||
return ''
|
||||
}
|
||||
return email
|
||||
})
|
||||
const avatarInitial = computed(() => displayName.value.charAt(0).toUpperCase() || 'U')
|
||||
const memberSinceLabel = computed(() => {
|
||||
const raw = props.user?.created_at?.trim()
|
||||
@@ -229,7 +239,7 @@ const memberSinceLabel = computed(() => {
|
||||
const providerLabels = computed<Record<UserAuthProvider, string>>(() => ({
|
||||
email: t('profile.authBindings.providers.email'),
|
||||
linuxdo: t('profile.authBindings.providers.linuxdo'),
|
||||
oidc: t('profile.authBindings.providers.oidc', { providerName: 'OIDC' }),
|
||||
oidc: t('profile.authBindings.providers.oidc', { providerName: props.oidcProviderName }),
|
||||
wechat: t('profile.authBindings.providers.wechat')
|
||||
}))
|
||||
|
||||
|
||||
@@ -335,6 +335,29 @@ describe('ProfileIdentityBindingsSection', () => {
|
||||
expect(wrapper.get('[data-testid="profile-binding-email-input"]').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('does not show a synthetic oauth-only email as the bound email summary', () => {
|
||||
const wrapper = mount(ProfileIdentityBindingsSection, {
|
||||
global: {
|
||||
plugins: [pinia],
|
||||
},
|
||||
props: {
|
||||
user: createUser({
|
||||
email: 'legacy-user@linuxdo-connect.invalid',
|
||||
email_bound: false,
|
||||
auth_bindings: {
|
||||
email: { bound: false },
|
||||
},
|
||||
}),
|
||||
linuxdoEnabled: false,
|
||||
oidcEnabled: false,
|
||||
wechatEnabled: false,
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.text()).not.toContain('legacy-user@linuxdo-connect.invalid')
|
||||
expect(wrapper.get('[data-testid="profile-binding-email-status"]').text()).toBe('Not bound')
|
||||
})
|
||||
|
||||
it('keeps the email form available for replacing a bound primary email', async () => {
|
||||
userApiMocks.sendEmailBindingCode.mockResolvedValue(undefined)
|
||||
userApiMocks.bindEmailIdentity.mockResolvedValue(
|
||||
|
||||
@@ -111,6 +111,47 @@ describe('ProfileInfoCard', () => {
|
||||
expect(wrapper.text()).toContain('Username synced from LinuxDo')
|
||||
})
|
||||
|
||||
it('uses the configured OIDC provider name in source hints', () => {
|
||||
const wrapper = mount(ProfileInfoCard, {
|
||||
props: {
|
||||
user: createUser({
|
||||
profile_sources: {
|
||||
username: { provider: 'oidc', source: 'oidc' }
|
||||
}
|
||||
}),
|
||||
oidcProviderName: 'ExampleID'
|
||||
},
|
||||
global: {
|
||||
stubs: {
|
||||
Icon: true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expect(wrapper.text()).toContain('Username synced from ExampleID')
|
||||
})
|
||||
|
||||
it('does not display synthetic oauth-only emails as a real bound email', () => {
|
||||
const wrapper = mount(ProfileInfoCard, {
|
||||
props: {
|
||||
user: createUser({
|
||||
email: 'legacy-user@oidc-connect.invalid',
|
||||
email_bound: false,
|
||||
auth_bindings: {
|
||||
email: { bound: false }
|
||||
}
|
||||
})
|
||||
},
|
||||
global: {
|
||||
stubs: {
|
||||
Icon: true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expect(wrapper.text()).not.toContain('legacy-user@oidc-connect.invalid')
|
||||
})
|
||||
|
||||
it('renders the approved overview hero and two-column content shell', () => {
|
||||
const wrapper = mount(ProfileInfoCard, {
|
||||
props: {
|
||||
|
||||
Reference in New Issue
Block a user