from fastapi import APIRouter, Depends, HTTPException, status from fastapi.security import OAuth2PasswordRequestForm from sqlalchemy.orm import Session from ..database import get_db from ..deps import get_current_user, nutzer_aus_payload, oauth2_scheme from ..models import User from ..schemas import Token, UserOut from ..security import create_access_token, decode_access_token, verify_password from .settings import get_session_minutes router = APIRouter(prefix="/auth", tags=["auth"]) @router.post("/login", response_model=Token) def login( form: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db) ) -> Token: user = db.query(User).filter(User.username == form.username).first() if user is None or not verify_password(form.password, user.password_hash): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Benutzername oder Passwort falsch", ) token = create_access_token( user_id=user.id, role=user.role.value, gueltig_minuten=get_session_minutes(db) ) return Token(access_token=token, role=user.role, username=user.username) @router.post("/refresh", response_model=Token) def refresh( token: str = Depends(oauth2_scheme), db: Session = Depends(get_db) ) -> Token: """Stellt der laufenden Sitzung ein frisches Token aus. Ohne das laeuft die Frist ab dem *Anmelden*, nicht ab der letzten Nutzung: Wer die App taeglich benutzt, fliegt trotzdem punktgenau nach Ablauf hinaus. Weboberflaeche und App rufen das beim Start auf; damit zaehlt die eingestellte Dauer ab dem letzten Besuch. Bewusst NICHT ueber ``get_current_user``: das nimmt auch langlebige API-Token an (Home Assistant). Aus so einem Token hier ein JWT zu machen, haette aus einem jederzeit widerrufbaren Zugang einen unwiderruflichen gemacht. """ payload = decode_access_token(token) user = nutzer_aus_payload(db, payload) if payload is not None else None if user is None: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Ungültige oder abgelaufene Anmeldung", headers={"WWW-Authenticate": "Bearer"}, ) neu = create_access_token( user_id=user.id, role=user.role.value, gueltig_minuten=get_session_minutes(db) ) return Token(access_token=neu, role=user.role, username=user.username) @router.get("/me", response_model=UserOut) def me(current_user: User = Depends(get_current_user)) -> User: return current_user