feat: add web login handler — form POST sets cookie and redirects to dashboard

This commit is contained in:
ZdenekSrotyr 2026-04-09 19:33:25 +02:00
parent d49844c1fe
commit 5ae13b199c
2 changed files with 32 additions and 2 deletions

View file

@ -3,7 +3,8 @@
import logging import logging
import os import os
from fastapi import APIRouter, Depends, HTTPException from fastapi import APIRouter, Depends, Form, HTTPException
from fastapi.responses import RedirectResponse
from pydantic import BaseModel from pydantic import BaseModel
import duckdb import duckdb
from argon2 import PasswordHasher from argon2 import PasswordHasher
@ -57,6 +58,35 @@ async def password_login(
return {"access_token": token, "token_type": "bearer", "email": user["email"], "role": user["role"]} return {"access_token": token, "token_type": "bearer", "email": user["email"], "role": user["role"]}
@router.post("/login/web")
async def password_login_web(
email: str = Form(...),
password: str = Form(""),
conn: duckdb.DuckDBPyConnection = Depends(_get_db),
):
"""Web form login — sets cookie and redirects to dashboard."""
repo = UserRepository(conn)
user = repo.get_by_email(email)
if not user or not user.get("password_hash"):
return RedirectResponse(url="/login/password?error=invalid", status_code=302)
try:
ph = PasswordHasher()
ph.verify(user["password_hash"], password)
except (VerifyMismatchError, Exception):
return RedirectResponse(url="/login/password?error=invalid", status_code=302)
token = create_access_token(user["id"], user["email"], user["role"])
is_production = os.environ.get("TESTING", "").lower() not in ("1", "true")
response = RedirectResponse(url="/dashboard", status_code=302)
response.set_cookie(
key="access_token", value=token,
httponly=True, max_age=86400, samesite="lax",
secure=is_production,
)
return response
@router.post("/setup") @router.post("/setup")
async def password_setup( async def password_setup(
request: PasswordSetupRequest, request: PasswordSetupRequest,

View file

@ -18,7 +18,7 @@
<!-- Sign In Tab --> <!-- Sign In Tab -->
<div id="signin-tab" class="auth-tab-content active"> <div id="signin-tab" class="auth-tab-content active">
<form method="POST" action="/auth/password/login" class="login-form"> <form method="POST" action="/auth/password/login/web" class="login-form">
<div class="form-group"> <div class="form-group">
<label for="email-signin">Email Address</label> <label for="email-signin">Email Address</label>
<input type="email" <input type="email"