Fix ban screen
This commit is contained in:
@@ -59,9 +59,15 @@ async def login(request: Request, data: UserLogin, db: DbSession):
|
||||
|
||||
# Check if user is banned
|
||||
if user.is_banned:
|
||||
# Return full ban info like in deps.py
|
||||
ban_info = {
|
||||
"banned_at": user.banned_at.isoformat() if user.banned_at else None,
|
||||
"banned_until": user.banned_until.isoformat() if user.banned_until else None,
|
||||
"reason": user.ban_reason,
|
||||
}
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Your account has been banned",
|
||||
detail=ban_info,
|
||||
)
|
||||
|
||||
# If admin with Telegram linked, require 2FA
|
||||
|
||||
@@ -61,7 +61,6 @@ function PublicRoute({ children }: { children: React.ReactNode }) {
|
||||
|
||||
function App() {
|
||||
const banInfo = useAuthStore((state) => state.banInfo)
|
||||
const isAuthenticated = useAuthStore((state) => state.isAuthenticated)
|
||||
const syncUser = useAuthStore((state) => state.syncUser)
|
||||
|
||||
// Sync user data with server on app load
|
||||
@@ -69,8 +68,8 @@ function App() {
|
||||
syncUser()
|
||||
}, [syncUser])
|
||||
|
||||
// Show banned screen if user is authenticated and banned
|
||||
if (isAuthenticated && banInfo) {
|
||||
// Show banned screen if user is banned (either authenticated or during login attempt)
|
||||
if (banInfo) {
|
||||
return (
|
||||
<>
|
||||
<ToastContainer />
|
||||
|
||||
@@ -10,6 +10,7 @@ interface BanInfo {
|
||||
|
||||
interface BannedScreenProps {
|
||||
banInfo: BanInfo
|
||||
onLogout?: () => void
|
||||
}
|
||||
|
||||
function formatDate(dateStr: string | null) {
|
||||
@@ -24,8 +25,9 @@ function formatDate(dateStr: string | null) {
|
||||
}) + ' (МСК)'
|
||||
}
|
||||
|
||||
export function BannedScreen({ banInfo }: BannedScreenProps) {
|
||||
const logout = useAuthStore((state) => state.logout)
|
||||
export function BannedScreen({ banInfo, onLogout }: BannedScreenProps) {
|
||||
const storeLogout = useAuthStore((state) => state.logout)
|
||||
const handleLogout = onLogout || storeLogout
|
||||
|
||||
const bannedAtFormatted = formatDate(banInfo.banned_at)
|
||||
const bannedUntilFormatted = formatDate(banInfo.banned_until)
|
||||
@@ -112,7 +114,7 @@ export function BannedScreen({ banInfo }: BannedScreenProps) {
|
||||
<NeonButton
|
||||
variant="secondary"
|
||||
size="lg"
|
||||
onClick={logout}
|
||||
onClick={handleLogout}
|
||||
icon={<LogOut className="w-5 h-5" />}
|
||||
>
|
||||
Выйти из аккаунта
|
||||
|
||||
@@ -54,7 +54,8 @@ export function LoginPage() {
|
||||
|
||||
navigate('/marathons')
|
||||
} catch {
|
||||
setSubmitError(error || 'Ошибка входа')
|
||||
// Error is already set in store by login function
|
||||
// Ban case is handled separately via banInfo state
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ export const useAuthStore = create<AuthState>()(
|
||||
banInfo: null,
|
||||
|
||||
login: async (data) => {
|
||||
set({ isLoading: true, error: null, pending2FA: null })
|
||||
set({ isLoading: true, error: null, pending2FA: null, banInfo: null })
|
||||
try {
|
||||
const response = await authApi.login(data)
|
||||
|
||||
@@ -85,9 +85,34 @@ export const useAuthStore = create<AuthState>()(
|
||||
}
|
||||
return { requires2FA: false }
|
||||
} catch (err: unknown) {
|
||||
const error = err as { response?: { data?: { detail?: string } } }
|
||||
const error = err as { response?: { status?: number; data?: { detail?: string | BanInfo } } }
|
||||
|
||||
// Check if user is banned (403 with ban info)
|
||||
if (error.response?.status === 403) {
|
||||
const detail = error.response?.data?.detail
|
||||
if (typeof detail === 'object' && detail !== null && 'banned_at' in detail) {
|
||||
set({
|
||||
banInfo: detail as BanInfo,
|
||||
isLoading: false,
|
||||
error: null,
|
||||
})
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
// Regular error - translate common messages
|
||||
let errorMessage = 'Ошибка входа'
|
||||
const detail = error.response?.data?.detail
|
||||
if (typeof detail === 'string') {
|
||||
if (detail === 'Incorrect login or password') {
|
||||
errorMessage = 'Неверный логин или пароль'
|
||||
} else {
|
||||
errorMessage = detail
|
||||
}
|
||||
}
|
||||
|
||||
set({
|
||||
error: error.response?.data?.detail || 'Login failed',
|
||||
error: errorMessage,
|
||||
isLoading: false,
|
||||
})
|
||||
throw err
|
||||
|
||||
Reference in New Issue
Block a user