mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
feat: add SSO/OIDC support to user model and settings
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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."
|
||||
|
||||
Reference in New Issue
Block a user