mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
Compare commits
2
Commits
2.0.1-alpha.1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b1f6cae8c | ||
|
|
e57d1e41e0 |
@@ -103,6 +103,8 @@ export interface User {
|
||||
account_permissions: Record<number, string[]>
|
||||
created_at: number;
|
||||
updated_at: number;
|
||||
sso_id?: string | null;
|
||||
sso_provider?: string | null;
|
||||
}
|
||||
|
||||
type Theme = 'dark' | 'light'
|
||||
|
||||
@@ -21,6 +21,9 @@ import { useNavigate, useLocation } from '@tanstack/react-router'
|
||||
import { ConfirmDialog } from '@/components/confirm-dialog'
|
||||
import { resetToken } from '@/stores/authStore'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useCurrentUser } from '@/hooks/use-current-user'
|
||||
import { useEdition } from '@/hooks/use-edition'
|
||||
import { useState } from 'react'
|
||||
|
||||
interface SignOutDialogProps {
|
||||
open: boolean
|
||||
@@ -31,9 +34,17 @@ export function SignOutDialog({ open, onOpenChange }: SignOutDialogProps) {
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation()
|
||||
const { t } = useTranslation()
|
||||
const handleSignOut = () => {
|
||||
resetToken()
|
||||
const currentPath = location.href
|
||||
const { user } = useCurrentUser()
|
||||
const { isPro, features } = useEdition()
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
||||
const isSsoUser =
|
||||
isPro &&
|
||||
features.includes('sso') &&
|
||||
!!user?.sso_provider &&
|
||||
user.sso_provider !== ''
|
||||
|
||||
const goToSignIn = (currentPath: string) => {
|
||||
navigate({
|
||||
to: '/sign-in',
|
||||
search: { redirect: currentPath },
|
||||
@@ -41,19 +52,73 @@ export function SignOutDialog({ open, onOpenChange }: SignOutDialogProps) {
|
||||
})
|
||||
}
|
||||
|
||||
const localSignOut = () => {
|
||||
resetToken()
|
||||
goToSignIn(location.href)
|
||||
}
|
||||
|
||||
const handleConfirm = () => {
|
||||
if (!isSsoUser) {
|
||||
localSignOut()
|
||||
return
|
||||
}
|
||||
setIsLoading(true)
|
||||
// Only sign out of bichon; keep the SSO session for one-click sign-in.
|
||||
fetch('/api/auth/oidc/local-logout', { redirect: 'follow' })
|
||||
.catch(() => {})
|
||||
.finally(() => {
|
||||
setIsLoading(false)
|
||||
localSignOut()
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<ConfirmDialog
|
||||
open={open}
|
||||
onOpenChange={onOpenChange}
|
||||
title={t('sign_out.title', 'Sign out')}
|
||||
desc={t(
|
||||
'sign_out.desc',
|
||||
'Are you sure you want to sign out? You will need to sign in again to access your account.'
|
||||
)}
|
||||
confirmText={t('sign_out.confirm', 'Sign out')}
|
||||
desc={
|
||||
isSsoUser
|
||||
? t(
|
||||
'sign_out.sso_desc',
|
||||
'Signing out of Bichon only keeps your SSO session (e.g. Keycloak) active. For full security, choose "Sign out and end SSO session".'
|
||||
)
|
||||
: t(
|
||||
'sign_out.desc',
|
||||
'Are you sure you want to sign out? You will need to sign in again to access your account.'
|
||||
)
|
||||
}
|
||||
confirmText={
|
||||
isSsoUser
|
||||
? t('sign_out.confirm_sso', 'Sign out of Bichon only')
|
||||
: t('sign_out.confirm', 'Sign out')
|
||||
}
|
||||
destructive
|
||||
handleConfirm={handleSignOut}
|
||||
isLoading={isLoading}
|
||||
handleConfirm={handleConfirm}
|
||||
className="sm:max-w-sm"
|
||||
/>
|
||||
>
|
||||
{isSsoUser && (
|
||||
<div className='grid gap-2'>
|
||||
<button
|
||||
type='button'
|
||||
className='inline-flex h-10 items-center justify-center gap-2 rounded-md border border-destructive/50 bg-background px-4 text-sm font-medium text-destructive transition-colors hover:bg-destructive/10'
|
||||
disabled={isLoading}
|
||||
onClick={() => {
|
||||
resetToken()
|
||||
window.location.href = '/api/auth/oidc/logout'
|
||||
}}
|
||||
>
|
||||
{t('sign_out.full_sign_out', 'Sign out and end SSO session')}
|
||||
</button>
|
||||
<p className='text-muted-foreground px-2 text-xs'>
|
||||
{t(
|
||||
'sign_out.sso_warning',
|
||||
'This will end your SSO session (e.g. Keycloak) and sign you out of all applications using it.'
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</ConfirmDialog>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -53,11 +53,12 @@ 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') || '/';
|
||||
|
||||
const { isPro, features } = useEdition()
|
||||
const ssoEnabled = isPro && features.includes('sso')
|
||||
|
||||
const formSchema = getFormSchema(t)
|
||||
const form = useForm<LoginFormValues>({
|
||||
resolver: zodResolver(formSchema),
|
||||
@@ -159,7 +160,7 @@ export function UserAuthForm({ className, ...props }: UserAuthFormProps) {
|
||||
{t('auth.login')}
|
||||
</Button>
|
||||
|
||||
{isPro && (
|
||||
{ssoEnabled && (
|
||||
<Button
|
||||
variant='outline'
|
||||
className='mt-2'
|
||||
|
||||
@@ -1446,7 +1446,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "تسجيل الخروج",
|
||||
"confirm_sso": "تسجيل الخروج من Bichon فقط",
|
||||
"desc": "هل أنت متأكد أنك تريد تسجيل الخروج؟ ستحتاج إلى تسجيل الدخول مرة أخرى للوصول إلى حسابك.",
|
||||
"full_sign_out": "تسجيل الخروج وإنهاء جلسة SSO",
|
||||
"sso_desc": "الخروج من Bichon يُبقي جلسة SSO نشطة. للأمان الكامل، اختر \"الخروج وإنهاء جلسة SSO\".",
|
||||
"sso_warning": "سيؤدي هذا إلى إنهاء جلسة SSO والخروج من جميع التطبيقات المرتبطة بها.",
|
||||
"title": "تسجيل الخروج"
|
||||
},
|
||||
"system": {
|
||||
|
||||
@@ -1446,7 +1446,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "Log ud",
|
||||
"confirm_sso": "Log kun ud af Bichon",
|
||||
"desc": "Er du sikker på, at du vil logge ud? Du skal logge ind igen for at få adgang til din konto.",
|
||||
"full_sign_out": "Log ud og afslut SSO-session",
|
||||
"sso_desc": "Udlogning fra Bichon beholder SSO-sessionen aktiv. For fuld sikkerhed, vælg \"Log ud og afslut SSO-session\".",
|
||||
"sso_warning": "Dette vil afslutte din SSO-session og logge dig ud af alle tilknyttede apps.",
|
||||
"title": "Log ud"
|
||||
},
|
||||
"system": {
|
||||
|
||||
@@ -1446,7 +1446,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "Abmelden",
|
||||
"confirm_sso": "Nur bei Bichon abmelden",
|
||||
"desc": "Möchten Sie sich wirklich abmelden? Sie müssen sich erneut anmelden, um auf Ihr Konto zuzugreifen.",
|
||||
"full_sign_out": "Abmelden und SSO-Sitzung beenden",
|
||||
"sso_desc": "Abmelden bei Bichon lässt die SSO-Sitzung aktiv. Für volle Sicherheit \"Abmelden und SSO-Sitzung beenden\" wählen.",
|
||||
"sso_warning": "Dies beendet Ihre SSO-Sitzung und meldet Sie von allen verknüpften Apps ab.",
|
||||
"title": "Abmelden"
|
||||
},
|
||||
"system": {
|
||||
|
||||
@@ -1462,7 +1462,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "Sign out",
|
||||
"confirm_sso": "Sign out of Bichon only",
|
||||
"desc": "Are you sure you want to sign out? You will need to sign in again to access your account.",
|
||||
"full_sign_out": "Sign out and end SSO session",
|
||||
"sso_desc": "Signing out of Bichon leaves your SSO session active. For full security, select \"Sign out and end SSO session\".",
|
||||
"sso_warning": "This will end your SSO session and sign you out of all connected apps.",
|
||||
"title": "Sign out"
|
||||
},
|
||||
"system": {
|
||||
|
||||
@@ -1446,7 +1446,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "Cerrar sesión",
|
||||
"confirm_sso": "Solo cerrar sesión en Bichon",
|
||||
"desc": "¿Está seguro de que desea cerrar sesión? Necesitará iniciar sesión nuevamente para acceder a su cuenta.",
|
||||
"full_sign_out": "Cerrar sesión y finalizar sesión SSO",
|
||||
"sso_desc": "Cerrar sesión en Bichon mantiene activa la sesión SSO. Para mayor seguridad, elija \"Cerrar sesión y finalizar sesión SSO\".",
|
||||
"sso_warning": "Esto finalizará su sesión SSO y cerrará la sesión en todas las aplicaciones vinculadas.",
|
||||
"title": "Cerrar sesión"
|
||||
},
|
||||
"system": {
|
||||
|
||||
@@ -1446,7 +1446,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "Kirjaudu ulos",
|
||||
"confirm_sso": "Kirjaudu ulos vain Bichonista",
|
||||
"desc": "Haluatko varmasti kirjautua ulos? Sinun täytyy kirjautua uudelleen päästäksesi tilillesi.",
|
||||
"full_sign_out": "Kirjaudu ulos ja lopeta SSO-istunto",
|
||||
"sso_desc": "Uloskirjautuminen Bichonista jättää SSO-istunnon aktiiviseksi. Täyden turvallisuuden saamiseksi valitse \"Kirjaudu ulos ja lopeta SSO-istunto\".",
|
||||
"sso_warning": "Tämä lopettaa SSO-istunnon ja kirjautuu ulos kaikista liitetyistä sovelluksista.",
|
||||
"title": "Kirjaudu ulos"
|
||||
},
|
||||
"system": {
|
||||
|
||||
@@ -1446,7 +1446,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "Déconnexion",
|
||||
"confirm_sso": "Se déconnecter de Bichon uniquement",
|
||||
"desc": "Êtes-vous sûr de vouloir vous déconnecter ? Vous devrez vous reconnecter pour accéder à votre compte.",
|
||||
"full_sign_out": "Se déconnecter et mettre fin à la session SSO",
|
||||
"sso_desc": "Mettre fin à Bichon laisse la session SSO active. Pour une sécurité totale, choisissez « Se déconnecter et mettre fin à la session SSO ».",
|
||||
"sso_warning": "Ceci mettra fin à votre session SSO et vous déconnectera de toutes les applications associées.",
|
||||
"title": "Déconnexion"
|
||||
},
|
||||
"system": {
|
||||
|
||||
@@ -1446,7 +1446,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "Disconnetti",
|
||||
"confirm_sso": "Disconnettiti solo da Bichon",
|
||||
"desc": "Sei sicuro di voler disconnetterti? Dovrai accedere di nuovo per usare il tuo account.",
|
||||
"full_sign_out": "Disconnettiti e termina sessione SSO",
|
||||
"sso_desc": "La disconnessione da Bichon lascia attiva la sessione SSO. Per la massima sicurezza, scegli \"Disconnettiti e termina sessione SSO\".",
|
||||
"sso_warning": "Questo terminerà la sessione SSO e ti disconnetterà da tutte le app collegate.",
|
||||
"title": "Disconnetti"
|
||||
},
|
||||
"system": {
|
||||
|
||||
@@ -1446,7 +1446,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "サインアウト",
|
||||
"confirm_sso": "Bichon のみログアウト",
|
||||
"desc": "本当にサインアウトしますか? アカウントにアクセスするには再度サインインが必要です。",
|
||||
"full_sign_out": "ログアウトして SSO セッションを終了",
|
||||
"sso_desc": "Bichon からログアウトしても SSO は有効なままです。完全に終了するには「ログアウトして SSO セッションを終了」を選択してください。",
|
||||
"sso_warning": "SSO セッションが終了し、連携しているすべてのアプリからログアウトします。",
|
||||
"title": "サインアウト"
|
||||
},
|
||||
"system": {
|
||||
|
||||
@@ -1446,7 +1446,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "로그아웃",
|
||||
"confirm_sso": "Bichon만 로그아웃",
|
||||
"desc": "로그아웃하시겠습니까? 계정에 접근하려면 다시 로그인해야 합니다.",
|
||||
"full_sign_out": "로그아웃 및 SSO 세션 종료",
|
||||
"sso_desc": "Bichon 로그아웃 후에도 SSO 세션은 유지됩니다. 완전한 보안을 위해 \"로그아웃 및 SSO 세션 종료\"를 선택하세요.",
|
||||
"sso_warning": "SSO 세션이 종료되며 연결된 모든 앱에서 로그아웃됩니다.",
|
||||
"title": "로그아웃"
|
||||
},
|
||||
"system": {
|
||||
|
||||
@@ -1446,7 +1446,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "Uitloggen",
|
||||
"confirm_sso": "Alleen uitloggen bij Bichon",
|
||||
"desc": "Weet je zeker dat je wilt uitloggen? Je moet opnieuw inloggen om toegang te krijgen tot je account.",
|
||||
"full_sign_out": "Uitloggen en SSO-sessie beëindigen",
|
||||
"sso_desc": "Uitloggen bij Bichon laat de SSO-sessie actief. Kies voor volledige beveiliging \"Uitloggen en SSO-sessie beëindigen\".",
|
||||
"sso_warning": "Dit beëindigt uw SSO-sessie en logt u uit bij alle gekoppelde apps.",
|
||||
"title": "Uitloggen"
|
||||
},
|
||||
"system": {
|
||||
|
||||
@@ -1446,7 +1446,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "Logg ut",
|
||||
"confirm_sso": "Logg kun ut av Bichon",
|
||||
"desc": "Er du sikker på at du vil logge ut? Du må logge inn igjen for å få tilgang til kontoen din.",
|
||||
"full_sign_out": "Logg ut og avslutt SSO-sesjon",
|
||||
"sso_desc": "Utlogging fra Bichon beholder SSO-sesjonen aktiv. For full sikkerhet, velg \"Logg ut og avslutt SSO-sesjon\".",
|
||||
"sso_warning": "Dette vil avslutte SSO-sesjonen og logge deg ut av alle tilknyttede apper.",
|
||||
"title": "Logg ut"
|
||||
},
|
||||
"system": {
|
||||
|
||||
@@ -1446,7 +1446,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "Wyloguj się",
|
||||
"confirm_sso": "Wyloguj tylko z Bichon",
|
||||
"desc": "Czy na pewno chcesz się wylogować? Aby uzyskać dostęp do konta, będziesz musiał zalogować się ponownie.",
|
||||
"full_sign_out": "Wyloguj i zakończ sesję SSO",
|
||||
"sso_desc": "Wylogowanie z Bichon pozostawia sesję SSO aktywną. Dla pełnego bezpieczeństwa wybierz \"Wyloguj i zakończ sesję SSO\".",
|
||||
"sso_warning": "To zakończy sesję SSO i wyloguje Cię ze wszystkich połączonych aplikacji.",
|
||||
"title": "Wyloguj się"
|
||||
},
|
||||
"system": {
|
||||
|
||||
@@ -1446,7 +1446,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "Sair",
|
||||
"confirm_sso": "Sair apenas do Bichon",
|
||||
"desc": "Tem certeza de que deseja sair? Você precisará entrar novamente para acessar sua conta.",
|
||||
"full_sign_out": "Sair e encerrar sessão SSO",
|
||||
"sso_desc": "Sair do Bichon mantém a sessão SSO ativa. Para segurança total, escolha \"Sair e encerrar sessão SSO\".",
|
||||
"sso_warning": "Isso encerrará sua sessão SSO e fará o logoff de todos os apps conectados.",
|
||||
"title": "Sair"
|
||||
},
|
||||
"system": {
|
||||
|
||||
@@ -1446,7 +1446,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "Выйти",
|
||||
"confirm_sso": "Выйти только из Bichon",
|
||||
"desc": "Вы уверены, что хотите выйти? Вам нужно будет снова войти, чтобы получить доступ к аккаунту.",
|
||||
"full_sign_out": "Выйти и завершить сессию SSO",
|
||||
"sso_desc": "Выход из Bichon оставляет сессию SSO активной. Для полной безопасности выберите \"Выйти и завершить сессию SSO\".",
|
||||
"sso_warning": "Это завершит сессию SSO и выведет вас из всех связанных приложений.",
|
||||
"title": "Выйти"
|
||||
},
|
||||
"system": {
|
||||
|
||||
@@ -1446,7 +1446,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "Logga ut",
|
||||
"confirm_sso": "Logga endast ut från Bichon",
|
||||
"desc": "Är du säker på att du vill logga ut? Du måste logga in igen för att få åtkomst till ditt konto.",
|
||||
"full_sign_out": "Logga ut och avsluta SSO-session",
|
||||
"sso_desc": "Utloggning från Bichon behåller SSO-sessionen aktiv. För full säkerhet, välj \"Logga ut och avsluta SSO-session\".",
|
||||
"sso_warning": "Detta avslutar din SSO-session och loggar ut dig från alla anslutna appar.",
|
||||
"title": "Logga ut"
|
||||
},
|
||||
"system": {
|
||||
|
||||
@@ -1446,7 +1446,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "登出",
|
||||
"confirm_sso": "僅登出 Bichon",
|
||||
"desc": "您確定要登出嗎?您需要重新登入才能存取帳戶。",
|
||||
"full_sign_out": "登出並結束 SSO 工作階段",
|
||||
"sso_desc": "僅登出 Bichon 仍會保持 SSO 工作階段。如需完全安全,請選擇「登出並結束 SSO 工作階段」。",
|
||||
"sso_warning": "這將結束 SSO 工作階段並從所有關聯應用程式中登出。",
|
||||
"title": "登出"
|
||||
},
|
||||
"system": {
|
||||
|
||||
@@ -1456,7 +1456,11 @@
|
||||
},
|
||||
"sign_out": {
|
||||
"confirm": "退出登录",
|
||||
"confirm_sso": "仅退出 Bichon",
|
||||
"desc": "您确定要退出登录吗?您需要重新登录才能访问账户。",
|
||||
"full_sign_out": "退出登录并结束 SSO 会话",
|
||||
"sso_desc": "仅退出 Bichon 仍会保持 SSO 会话。如需完全安全,请选择“退出登录并结束 SSO 会话”。",
|
||||
"sso_warning": "这将结束 SSO 会话并从所有关联应用中退出。",
|
||||
"title": "退出登录"
|
||||
},
|
||||
"system": {
|
||||
|
||||
+11
-1
@@ -26,7 +26,7 @@ import {
|
||||
QueryClientProvider,
|
||||
} from '@tanstack/react-query'
|
||||
import { RouterProvider, createRouter } from '@tanstack/react-router'
|
||||
import { resetToken } from '@/stores/authStore'
|
||||
import { resetToken, setToken } from '@/stores/authStore'
|
||||
import { toast } from '@/hooks/use-toast'
|
||||
import { ThemeProvider } from './context/theme-context'
|
||||
import './index.css'
|
||||
@@ -117,6 +117,16 @@ const queryClient = new QueryClient({
|
||||
|
||||
const basepath = (window as any).__BICHON_BASE__ || '/';
|
||||
console.log('Current Basepath:', basepath);
|
||||
|
||||
// OIDC SSO callback: the Pro server redirects back with ?access_token=.
|
||||
// Store it and strip it from the URL before the router/auth flow runs.
|
||||
const ssoToken = new URLSearchParams(window.location.search).get('access_token');
|
||||
if (ssoToken) {
|
||||
setToken({ success: true, access_token: ssoToken });
|
||||
const clean = `${window.location.pathname}${window.location.hash}`;
|
||||
window.history.replaceState(null, '', clean);
|
||||
}
|
||||
|
||||
// Create a new router instance
|
||||
const router = createRouter({
|
||||
routeTree,
|
||||
|
||||
Reference in New Issue
Block a user