mirror of
https://github.com/supabase/supabase.git
synced 2026-05-10 10:50:18 -04:00
31794b83f2
## Summary by CodeRabbit * **New Features** * Added Passkeys configuration page to manage WebAuthn relying-party settings and enable/disable passkey auth. * Added a Beta "Passkeys" item to the Auth settings menu. * Enabled saving passkey-related authentication parameters. * **Tests** * Added test coverage to ensure the Passkeys menu appears or is omitted based on feature flags. * **Chores** * Removed an unused import to tidy the code. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: fadymak <dev@fadymak.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
157 lines
5.1 KiB
TypeScript
157 lines
5.1 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
|
|
import { generateAuthMenu, GenerateAuthMenuOptions } from './AuthLayout.utils'
|
|
|
|
const allFeaturesEnabled: GenerateAuthMenuOptions = {
|
|
ref: 'test-ref',
|
|
isPlatform: true,
|
|
showOverview: true,
|
|
features: {
|
|
signInProviders: true,
|
|
rateLimits: true,
|
|
emails: true,
|
|
multiFactor: true,
|
|
attackProtection: true,
|
|
performance: true,
|
|
passkeys: true,
|
|
},
|
|
}
|
|
|
|
const allFeaturesDisabled: GenerateAuthMenuOptions = {
|
|
ref: 'test-ref',
|
|
isPlatform: true,
|
|
showOverview: false,
|
|
features: {
|
|
signInProviders: false,
|
|
rateLimits: false,
|
|
emails: false,
|
|
multiFactor: false,
|
|
attackProtection: false,
|
|
performance: false,
|
|
passkeys: true,
|
|
},
|
|
}
|
|
|
|
function flatItemNames(menu: ReturnType<typeof generateAuthMenu>): string[] {
|
|
return menu.flatMap((group) => group.items.map((item) => item.name))
|
|
}
|
|
|
|
function findItem(menu: ReturnType<typeof generateAuthMenu>, name: string) {
|
|
for (const group of menu) {
|
|
const item = group.items.find((i) => i.name === name)
|
|
if (item) return item
|
|
}
|
|
return undefined
|
|
}
|
|
|
|
describe('generateAuthMenu', () => {
|
|
it('platform with all features enabled includes all menu items', () => {
|
|
const menu = generateAuthMenu(allFeaturesEnabled)
|
|
const names = flatItemNames(menu)
|
|
|
|
expect(names).toContain('Overview')
|
|
expect(names).toContain('Users')
|
|
expect(names).toContain('OAuth Apps')
|
|
expect(names).toContain('Email')
|
|
expect(names).toContain('Sign In / Providers')
|
|
expect(names).toContain('OAuth Server')
|
|
expect(names).toContain('Passkeys')
|
|
expect(names).toContain('Sessions')
|
|
expect(names).toContain('Rate Limits')
|
|
expect(names).toContain('Multi-Factor')
|
|
expect(names).toContain('URL Configuration')
|
|
expect(names).toContain('Attack Protection')
|
|
expect(names).toContain('Auth Hooks')
|
|
expect(names).toContain('Audit Logs')
|
|
expect(names).toContain('Performance')
|
|
})
|
|
|
|
it('platform with all features disabled shows only core items', () => {
|
|
const menu = generateAuthMenu(allFeaturesDisabled)
|
|
const names = flatItemNames(menu)
|
|
|
|
expect(names).toContain('Users')
|
|
expect(names).toContain('OAuth Apps')
|
|
expect(names).toContain('Policies')
|
|
expect(names).toContain('OAuth Server')
|
|
expect(names).toContain('Passkeys')
|
|
expect(names).toContain('Sessions')
|
|
expect(names).toContain('URL Configuration')
|
|
expect(names).toContain('Auth Hooks')
|
|
expect(names).toContain('Audit Logs')
|
|
|
|
expect(names).not.toContain('Overview')
|
|
expect(names).not.toContain('Email')
|
|
expect(names).not.toContain('Sign In / Providers')
|
|
expect(names).not.toContain('Rate Limits')
|
|
expect(names).not.toContain('Multi-Factor')
|
|
expect(names).not.toContain('Attack Protection')
|
|
expect(names).not.toContain('Performance')
|
|
})
|
|
|
|
it('self-hosted hides OAuth Apps, Notifications, and platform-only Configuration items', () => {
|
|
const menu = generateAuthMenu({
|
|
...allFeaturesEnabled,
|
|
isPlatform: false,
|
|
})
|
|
const names = flatItemNames(menu)
|
|
const groupTitles = menu.map((g) => g.title)
|
|
|
|
expect(names).not.toContain('OAuth Apps')
|
|
expect(groupTitles).not.toContain('Notifications')
|
|
|
|
// Configuration should only have Policies
|
|
const configGroup = menu.find((g) => g.title === 'Configuration')!
|
|
expect(configGroup.items).toHaveLength(1)
|
|
expect(configGroup.items[0].name).toBe('Policies')
|
|
})
|
|
|
|
it('shows Overview when showOverview is true', () => {
|
|
const menu = generateAuthMenu({ ...allFeaturesDisabled, showOverview: true })
|
|
expect(flatItemNames(menu)).toContain('Overview')
|
|
})
|
|
|
|
it('hides Overview when showOverview is false', () => {
|
|
const menu = generateAuthMenu({ ...allFeaturesEnabled, showOverview: false })
|
|
expect(flatItemNames(menu)).not.toContain('Overview')
|
|
})
|
|
|
|
it.each([
|
|
['signInProviders', 'Sign In / Providers'],
|
|
['rateLimits', 'Rate Limits'],
|
|
['emails', 'Email'],
|
|
['multiFactor', 'Multi-Factor'],
|
|
['attackProtection', 'Attack Protection'],
|
|
['performance', 'Performance'],
|
|
] as const)('feature flag %s toggles %s', (flag, itemName) => {
|
|
const withEnabled = generateAuthMenu({
|
|
...allFeaturesDisabled,
|
|
features: { ...allFeaturesDisabled.features, [flag]: true },
|
|
})
|
|
const withDisabled = generateAuthMenu({
|
|
...allFeaturesEnabled,
|
|
features: { ...allFeaturesEnabled.features, [flag]: false },
|
|
})
|
|
|
|
expect(flatItemNames(withEnabled)).toContain(itemName)
|
|
expect(flatItemNames(withDisabled)).not.toContain(itemName)
|
|
})
|
|
|
|
it('generates correct URLs using the ref parameter', () => {
|
|
const menu = generateAuthMenu({ ...allFeaturesEnabled, ref: 'my-project' })
|
|
const users = findItem(menu, 'Users')
|
|
const oauthApps = findItem(menu, 'OAuth Apps')
|
|
|
|
expect(users?.url).toBe('/project/my-project/auth/users')
|
|
expect(oauthApps?.url).toBe('/project/my-project/auth/oauth-apps')
|
|
})
|
|
|
|
it('hides Passkeys when passkeys feature is false', () => {
|
|
const menu = generateAuthMenu({
|
|
...allFeaturesEnabled,
|
|
features: { ...allFeaturesEnabled.features, passkeys: false },
|
|
})
|
|
expect(flatItemNames(menu)).not.toContain('Passkeys')
|
|
})
|
|
})
|