from datetime import datetime, timezone from fastapi import APIRouter, Request, Form, HTTPException from fastapi.responses import HTMLResponse, RedirectResponse from fastapi.templating import Jinja2Templates from sqlalchemy import select from app.models.base import async_session from app.models.user import User from app.auth import hash_password, verify_password, create_session router = APIRouter() templates = Jinja2Templates(directory="app/templates") @router.get("/login", response_class=HTMLResponse) async def login_page(request: Request): return templates.TemplateResponse("login.html", {"request": request}) @router.post("/login") async def login(request: Request, username: str = Form(), password: str = Form()): async with async_session() as session: result = await session.execute(select(User).where(User.username == username)) user = result.scalar_one_or_none() if not user or not verify_password(password, user.password_hash): return templates.TemplateResponse( "login.html", {"request": request, "error": "Invalid username or password"}, ) token = await create_session(user.id) resp = RedirectResponse(url="/dashboard", status_code=303) resp.set_cookie(key="session_token", value=token, httponly=True, max_age=86400 * 30) return resp @router.get("/register", response_class=HTMLResponse) async def register_page(request: Request): return templates.TemplateResponse("register.html", {"request": request}) @router.post("/register") async def register( request: Request, username: str = Form(), password: str = Form(), display_name: str = Form(default=""), ): async with async_session() as session: result = await session.execute(select(User).where(User.username == username)) if result.scalar_one_or_none(): return templates.TemplateResponse( "register.html", {"request": request, "error": "Username already taken"}, ) user = User( username=username, password_hash=hash_password(password), display_name=display_name or username, created_at=datetime.now(timezone.utc).isoformat(), ) session.add(user) await session.commit() await session.refresh(user) token = await create_session(user.id) resp = RedirectResponse(url="/dashboard", status_code=303) resp.set_cookie(key="session_token", value=token, httponly=True, max_age=86400 * 30) return resp @router.get("/logout") async def logout(): resp = RedirectResponse(url="/login", status_code=303) resp.delete_cookie("session_token") return resp