PIN a 4 cifre: migrazione 017, login-pin, pin-users, PUT pin, capoturno via PIN (#59)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 12:27:31 +02:00
parent 86290274e5
commit 07e23b957d
12 changed files with 441 additions and 11 deletions
+38 -1
View File
@@ -1,5 +1,6 @@
"""Authentication router - login, logout, profile."""
from fastapi import APIRouter, Depends, HTTPException, Request, status
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from src.backend.database import get_db
@@ -8,10 +9,17 @@ from src.backend.models.orm.user import User
from src.backend.models.api.user import (
LoginRequest,
LoginResponse,
PinLoginRequest,
PinUserItem,
UserProfileUpdate,
UserResponse,
)
from src.backend.services.auth_service import authenticate_user, login_user, logout_user
from src.backend.services.auth_service import (
authenticate_pin,
authenticate_user,
login_user,
logout_user,
)
router = APIRouter(prefix="/api/auth", tags=["auth"])
@@ -32,6 +40,35 @@ async def login(data: LoginRequest, db: AsyncSession = Depends(get_db)):
)
@router.get("/pin-users", response_model=list[PinUserItem])
async def pin_users(db: AsyncSession = Depends(get_db)):
"""Utenti che possono entrare con PIN (#59): attivi, non admin, con PIN.
Pubblico per costruzione (serve prima del login): espone solo id e nome.
"""
result = await db.execute(
select(User).where(
User.active == True, # noqa: E712
User.is_admin == False, # noqa: E712
User.pin_hash.is_not(None),
)
)
items = [
PinUserItem(id=u.id, display_name=u.display_name or u.username)
for u in result.scalars().all()
]
items.sort(key=lambda i: i.display_name.casefold())
return items
@router.post("/login-pin", response_model=LoginResponse)
async def login_pin(data: PinLoginRequest, db: AsyncSession = Depends(get_db)):
"""Login con user_id e PIN a 4 cifre (#59); stessa risposta del login."""
user = await authenticate_pin(db, data.user_id, data.pin)
api_key = await login_user(db, user)
return LoginResponse(user=UserResponse.model_validate(user), api_key=api_key)
@router.post("/logout", status_code=status.HTTP_204_NO_CONTENT)
async def logout(
request: Request,