diff --git a/backend/app/api/v1/auth.py b/backend/app/api/v1/auth.py
index e34ee71..e5784a1 100644
--- a/backend/app/api/v1/auth.py
+++ b/backend/app/api/v1/auth.py
@@ -16,7 +16,8 @@ router = APIRouter(prefix="/auth", tags=["auth"])
@router.post("/login", response_model=TokenPair)
def login(payload: LoginRequest, db: Session = Depends(get_db)) -> TokenPair:
- user = db.scalar(select(User).where(User.email == payload.email))
+ email = payload.email.strip().lower()
+ user = db.scalar(select(User).where(User.email == email))
if not user or not verify_password(payload.password, user.password_hash):
if user:
user.failed_login_attempts += 1
@@ -41,4 +42,3 @@ def me(user: CurrentUser) -> User:
def logout(user: CurrentUser, db: Session = Depends(get_db)) -> dict[str, str]:
write_audit(db, action="logout", object_type="user", object_id=user.id, user_id=user.id)
return {"status": "ok", "at": datetime.utcnow().isoformat()}
-
diff --git a/backend/app/schemas/domain.py b/backend/app/schemas/domain.py
index e5762a1..f47ac2e 100644
--- a/backend/app/schemas/domain.py
+++ b/backend/app/schemas/domain.py
@@ -1,7 +1,7 @@
from datetime import datetime
from typing import Any
-from pydantic import BaseModel, ConfigDict, EmailStr, Field
+from pydantic import BaseModel, ConfigDict, Field
class OrmModel(BaseModel):
@@ -15,13 +15,13 @@ class TokenPair(BaseModel):
class LoginRequest(BaseModel):
- email: EmailStr
+ email: str
password: str
class UserRead(OrmModel):
id: str
- email: EmailStr
+ email: str
display_name: str
is_active: bool
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 6cb5464..c883352 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -1,4 +1,5 @@
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { useEffect } from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import { Layout } from "./components/Layout";
@@ -7,10 +8,17 @@ import { FirewallPreview } from "./pages/FirewallPreview";
import { ListPage } from "./pages/ListPage";
import { Login } from "./pages/Login";
import { PolicyDesigner } from "./pages/PolicyDesigner";
+import { useTheme } from "./stores/theme";
const queryClient = new QueryClient();
export function App() {
+ const dark = useTheme((state) => state.dark);
+
+ useEffect(() => {
+ document.documentElement.classList.toggle("dark", dark);
+ }, [dark]);
+
return (