70 lines
2.1 KiB
Python
70 lines
2.1 KiB
Python
from fastapi import APIRouter, Depends, Form, Request, status
|
|
from fastapi.responses import HTMLResponse, RedirectResponse, Response
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.core.config import settings
|
|
from app.core.database import get_db
|
|
from app.crud import user as user_crud
|
|
from app.deps import get_current_web_user
|
|
from app.models.user import User
|
|
from app.services.auth import issue_token_pair
|
|
from app.web.templates import templates
|
|
|
|
router = APIRouter(include_in_schema=False)
|
|
|
|
|
|
def _set_auth_cookie(response: Response, access_token: str) -> None:
|
|
response.set_cookie(
|
|
key=settings.cookie_name,
|
|
value=access_token,
|
|
httponly=True,
|
|
secure=settings.cookie_secure,
|
|
samesite="lax",
|
|
max_age=settings.access_token_expire_minutes * 60,
|
|
path="/",
|
|
)
|
|
|
|
|
|
@router.get("/", response_class=HTMLResponse)
|
|
async def dashboard(
|
|
request: Request,
|
|
user: User = Depends(get_current_web_user),
|
|
):
|
|
return templates.TemplateResponse(
|
|
request, "dashboard.html", {"user": user}
|
|
)
|
|
|
|
|
|
@router.get("/login", response_class=HTMLResponse)
|
|
async def login_page(request: Request):
|
|
return templates.TemplateResponse(request, "login.html", {})
|
|
|
|
|
|
@router.post("/login")
|
|
async def login_submit(
|
|
request: Request,
|
|
email: str = Form(...),
|
|
password: str = Form(...),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
user = await user_crud.authenticate(db, email, password)
|
|
if user is None:
|
|
# Re-render the form with an error (HTMX swaps the form partial).
|
|
return templates.TemplateResponse(
|
|
request,
|
|
"login.html",
|
|
{"error": "Incorrect email or password", "email": email},
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
)
|
|
access, _ = await issue_token_pair(db, user)
|
|
response = RedirectResponse(url="/", status_code=status.HTTP_303_SEE_OTHER)
|
|
_set_auth_cookie(response, access)
|
|
return response
|
|
|
|
|
|
@router.post("/logout")
|
|
async def logout(request: Request):
|
|
response = RedirectResponse(url="/login", status_code=status.HTTP_303_SEE_OTHER)
|
|
response.delete_cookie(settings.cookie_name, path="/")
|
|
return response
|