Files
NexaFabric/backend/app/api/v1/auth.py
T
nessi dea27b5459
CI / backend (push) Failing after 2s
CI / frontend (push) Failing after 27s
feat: normalize email login and improve theme handling
Normalize email input by stripping whitespace and converting to lowercase in login endpoint, remove EmailStr validation in favor of plain string type, move dark mode class toggle from Layout to App component for better initialization, add theme toggle button to login page, and set dark mode as default theme when no preference is stored
2026-07-09 12:23:28 +02:00

45 lines
1.7 KiB
Python

from datetime import datetime
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy import select
from sqlalchemy.orm import Session
from app.api.deps import CurrentUser
from app.core.security import create_access_token, create_refresh_token, verify_password
from app.db.session import get_db
from app.models.domain import User
from app.schemas.domain import LoginRequest, TokenPair, UserRead
from app.services.audit import write_audit
router = APIRouter(prefix="/auth", tags=["auth"])
@router.post("/login", response_model=TokenPair)
def login(payload: LoginRequest, db: Session = Depends(get_db)) -> TokenPair:
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
db.commit()
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials")
permissions = sorted({permission for role in user.roles for permission in role.permissions})
user.failed_login_attempts = 0
db.commit()
write_audit(db, action="login", object_type="user", object_id=user.id, user_id=user.id)
return TokenPair(
access_token=create_access_token(user.id, permissions),
refresh_token=create_refresh_token(user.id),
)
@router.get("/me", response_model=UserRead)
def me(user: CurrentUser) -> User:
return user
@router.post("/logout")
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()}