Files
fitguide/app/web/pages.py
T
2026-07-16 17:05:30 -03:00

102 lines
3.2 KiB
Python

from fastapi import APIRouter, Depends, Form, HTTPException, 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 import ldap as ldap_service
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", {"ldap_enabled": settings.ldap_enabled}
)
@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,
"ldap_enabled": settings.ldap_enabled,
},
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("/login/ldap")
async def login_ldap_submit(
request: Request,
username: str = Form(...),
password: str = Form(...),
db: AsyncSession = Depends(get_db),
):
if not settings.ldap_enabled:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
user = await ldap_service.login(db, username, password)
if user is None:
return templates.TemplateResponse(
request,
"login.html",
{
"error": "LDAP sign-in failed",
"username": username,
"ldap_enabled": True,
},
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