diff --git a/assets/admin/App.tsx b/assets/admin/App.tsx index 27b0d597..abc84792 100644 --- a/assets/admin/App.tsx +++ b/assets/admin/App.tsx @@ -43,9 +43,12 @@ import PwaInstallBanner from './components/ui/PwaInstallBanner'; // ── Guards ────────────────────────────────────────────────────────────────── +const ALLOWED_ROLES = ['admin', 'doctor', 'clinic', 'secretary'] as const; + function PrivateRoute({ children }: { children: React.ReactNode }) { - const { isAuthenticated, primaryRole, availableContexts, dbUuid, fetchMe } = useAuthStore(); + const { isAuthenticated, primaryRole, availableContexts, dbUuid, fetchMe, logout } = useAuthStore(); const location = useLocation(); + const [accessDenied, setAccessDenied] = React.useState(false); useEffect(() => { if (isAuthenticated && !primaryRole) { @@ -53,10 +56,21 @@ function PrivateRoute({ children }: { children: React.ReactNode }) { } }, [isAuthenticated, primaryRole, fetchMe]); + useEffect(() => { + if (isAuthenticated && primaryRole && !ALLOWED_ROLES.includes(primaryRole as any)) { + setAccessDenied(true); + logout(); + } + }, [isAuthenticated, primaryRole, logout]); + + if (accessDenied) { + return ; + } + if (!isAuthenticated) return ; // اگر context هنوز لود نشده — صبر کن - if (isAuthenticated && !primaryRole) { + if (!primaryRole) { return
در حال بارگذاری...
; } diff --git a/assets/admin/pages/LoginPage.tsx b/assets/admin/pages/LoginPage.tsx index 7f912183..f33c0e38 100644 --- a/assets/admin/pages/LoginPage.tsx +++ b/assets/admin/pages/LoginPage.tsx @@ -1,4 +1,5 @@ import React, { useEffect, useRef, useState } from 'react'; +import { useSearchParams } from 'react-router-dom'; import { toast } from 'sonner'; import { EyeIcon, EyeSlashIcon } from '@heroicons/react/24/outline'; import { useAuthStore } from '../stores/authStore'; @@ -10,6 +11,7 @@ type ForgotStep = 1 | 2 | 3; export default function LoginPage() { const login = useAuthStore((s) => s.login); + const [searchParams] = useSearchParams(); const [mode, setMode] = useState('password'); const [pwMobile, setPwMobile] = useState(''); @@ -186,6 +188,17 @@ export default function LoginPage() {

+ {searchParams.get('error') === 'access_denied' && ( +
+ حساب شما دسترسی به پنل مدیریت را ندارد +
+ )} + {mode !== 'forgot' && (
{(['password', 'sms'] as const).map((m) => (