""" auth.py — Register, verify, login, profil. """ from datetime import datetime, timezone from fastapi import APIRouter, Depends, HTTPException, BackgroundTasks from fastapi.security import OAuth2PasswordRequestForm from fastapi.responses import HTMLResponse from sqlalchemy.orm import Session from pydantic import BaseModel, EmailStr from app.core.database import get_db from app.core.security import hash_password, verify_password, create_access_token, get_current_user from app.core.mail import generate_verify_token, send_verification_email from app.models import User router = APIRouter(prefix="/auth", tags=["auth"]) # ── Schemas ─────────────────────────────────────────────────────────────────── class UserCreate(BaseModel): username: str email: EmailStr full_name: str = "" password: str class UserOut(BaseModel): id: str username: str email: str full_name: str is_verified: bool created_at: datetime class Config: from_attributes = True class Token(BaseModel): access_token: str token_type: str = "bearer" user: UserOut # ── Endpoints ───────────────────────────────────────────────────────────────── @router.post("/register", response_model=dict, status_code=201) async def register( data: UserCreate, background_tasks: BackgroundTasks, db: Session = Depends(get_db) ): # Tjek om brugernavn eller email allerede er i brug if db.query(User).filter(User.username == data.username).first(): raise HTTPException(400, "Brugernavnet er allerede i brug") if db.query(User).filter(User.email == data.email).first(): raise HTTPException(400, "E-mailadressen er allerede registreret") token = generate_verify_token() user = User( username=data.username, email=data.email, full_name=data.full_name, password_hash=hash_password(data.password), is_verified=False, verify_token=token, ) db.add(user) db.commit() # Send verificerings-mail i baggrunden background_tasks.add_task( send_verification_email, data.email, data.username, token ) return { "message": f"Konto oprettet. Tjek din e-mail ({data.email}) for at bekræfte.", "email": data.email, } @router.get("/verify/{token}", response_class=HTMLResponse) def verify_email(token: str, db: Session = Depends(get_db)): user = db.query(User).filter(User.verify_token == token).first() if not user: return HTMLResponse("""
Prøv at registrere dig igen.
""", status_code=400) user.is_verified = True user.verify_token = None db.commit() return HTMLResponse("""Din konto er nu aktiv. Du kan logge ind i LineDance Player.
Du kan lukke dette vindue.
""") @router.post("/login", response_model=Token) def login( form: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db) ): user = db.query(User).filter( (User.username == form.username) | (User.email == form.username) ).first() if not user or not verify_password(form.password, user.password_hash): raise HTTPException(401, "Forkert brugernavn eller kodeord") if not user.is_verified: raise HTTPException(403, "E-mailadressen er ikke bekræftet endnu. Tjek din indbakke.") token = create_access_token({"sub": user.id}) return Token( access_token=token, user=UserOut.model_validate(user) ) @router.get("/me", response_model=UserOut) def me(current_user: User = Depends(get_current_user)): return current_user @router.post("/resend-verification") async def resend_verification( email: str, background_tasks: BackgroundTasks, db: Session = Depends(get_db) ): user = db.query(User).filter(User.email == email).first() if not user or user.is_verified: # Svar altid OK — afslør ikke om email eksisterer return {"message": "Hvis e-mailen er registreret, sendes et nyt link."} token = generate_verify_token() user.verify_token = token db.commit() background_tasks.add_task( send_verification_email, user.email, user.username, token ) return {"message": "Nyt verificerings-link er sendt."}