84 lines
2.4 KiB
Python
84 lines
2.4 KiB
Python
import html
|
|
|
|
from fastapi import APIRouter, Form, Request
|
|
from fastapi.responses import HTMLResponse, RedirectResponse
|
|
|
|
from app.auth import authenticate_user, current_user
|
|
from app.db.audit import log_audit_event
|
|
from app.templates.layout import page
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/login", response_class=HTMLResponse)
|
|
def login_form(request: Request):
|
|
if current_user(request):
|
|
return RedirectResponse(url="/portal/operations", status_code=303)
|
|
|
|
return _render_login()
|
|
|
|
|
|
@router.post("/login", response_class=HTMLResponse)
|
|
def login(request: Request, username: str = Form(...), password: str = Form(...)):
|
|
user = authenticate_user(username, password)
|
|
|
|
if not user:
|
|
return _render_login("Neplatné přihlašovací údaje.")
|
|
|
|
request.session.clear()
|
|
request.session["user_id"] = user["id"]
|
|
log_audit_event(
|
|
user,
|
|
action="login_success",
|
|
target_type="user",
|
|
target_id=user.get("id"),
|
|
metadata={"username": user.get("username")},
|
|
)
|
|
|
|
return RedirectResponse(url="/portal/operations", status_code=303)
|
|
|
|
|
|
@router.post("/logout")
|
|
def logout(request: Request):
|
|
user = current_user(request)
|
|
log_audit_event(
|
|
user,
|
|
action="logout",
|
|
target_type="user",
|
|
target_id=user.get("id") if user else None,
|
|
metadata={"username": user.get("username")} if user else {},
|
|
)
|
|
request.session.clear()
|
|
return RedirectResponse(url="/portal/login", status_code=303)
|
|
|
|
|
|
def _render_login(error: str | None = None) -> str:
|
|
error_html = ""
|
|
if error:
|
|
error_html = f'<p class="alert alert-danger">{html.escape(error)}</p>'
|
|
|
|
return page(
|
|
"Přihlášení",
|
|
f"""
|
|
<div class="auth-card card">
|
|
<h2>CSBot Services Portal</h2>
|
|
<p class="muted">Přihlaste se interním účtem.</p>
|
|
{error_html}
|
|
|
|
<form method="post" action="/portal/login">
|
|
<p>
|
|
<label>Uživatelské jméno</label><br>
|
|
<input name="username" autocomplete="username" required autofocus>
|
|
</p>
|
|
|
|
<p>
|
|
<label>Heslo</label><br>
|
|
<input type="password" name="password" autocomplete="current-password" required>
|
|
</p>
|
|
|
|
<button type="submit">Přihlásit</button>
|
|
</form>
|
|
</div>
|
|
""",
|
|
)
|