feat: add SSO/OIDC support to user model and settings

This commit is contained in:
rustmailer
2026-06-24 17:32:14 +08:00
parent b0f229618c
commit 9e55026f12
10 changed files with 109 additions and 8 deletions
+17 -1
View File
@@ -41,9 +41,10 @@ import { useLocation, useNavigate } from '@tanstack/react-router'
import { Button } from '@/components/button'
import { useTranslation } from 'react-i18next'
import i18n from '@/i18n'
import { Loader2, LogIn } from 'lucide-react'
import { Loader2, LogIn, Shield } from 'lucide-react'
import { login } from '@/api/users/api'
import { useTheme } from '@/context/theme-context'
import { useEdition } from '@/hooks/use-edition'
type UserAuthFormProps = HTMLAttributes<HTMLDivElement>
@@ -52,6 +53,7 @@ export function UserAuthForm({ className, ...props }: UserAuthFormProps) {
const { setTheme } = useTheme();
const navigate = useNavigate()
const { t } = useTranslation()
const { isPro } = useEdition()
const { search } = useLocation();
const redirect = toSearchParams(search).get('redirect') || '/';
@@ -156,6 +158,20 @@ export function UserAuthForm({ className, ...props }: UserAuthFormProps) {
{isLoading ? <Loader2 className='animate-spin' /> : <LogIn size={16} className='mr-2' />}
{t('auth.login')}
</Button>
{isPro && (
<Button
variant='outline'
className='mt-2'
type='button'
onClick={() => {
window.location.href = '/api/auth/oidc/login'
}}
>
<Shield size={16} className='mr-2' />
{t('auth.ssoLogin')}
</Button>
)}
</div>
</form>
</Form>
+28
View File
@@ -0,0 +1,28 @@
import axiosInstance from '@/api/axiosInstance'
import { useQuery } from '@tanstack/react-query'
export interface EditionInfo {
features: string[]
edition: 'community' | 'pro' | 'enterprise'
version: string
}
async function fetchEdition(): Promise<EditionInfo> {
const { data } = await axiosInstance.get<EditionInfo>('api/v1/features')
return data
}
export function useEdition() {
const { data } = useQuery({
queryKey: ['edition'],
queryFn: fetchEdition,
staleTime: Infinity,
retry: 1,
})
return {
isPro: data?.edition === 'pro' || data?.edition === 'enterprise',
edition: data?.edition ?? 'community',
features: data?.features ?? [],
} as const
}
+1
View File
@@ -423,6 +423,7 @@
"sessionExpired": "Session expired!",
"sessionExpiredDesc": "Your session has ended due to inactivity. Please log in again to continue.",
"somethingWentWrong": "Something went wrong",
"ssoLogin": "Sign in with SSO",
"username": "Username",
"welcome": "Welcome to Bichon",
"youWillNeedToLogInAgain": "You will need to log in again to access your account."