fix: enforce session auth and polish login page

This commit is contained in:
Sean McElwain 2026-04-26 21:35:15 -05:00
parent 7e347ad5c6
commit aecc7c5679
4 changed files with 283 additions and 9 deletions

View File

@ -2,6 +2,7 @@ from pathlib import Path
from decimal import Decimal
from fastapi import FastAPI, Request
from fastapi.responses import RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from sqlalchemy import create_engine, func
@ -199,6 +200,29 @@ from starlette.middleware.sessions import SessionMiddleware
from app.routes.auth import router as auth_router
@app.middleware("http")
async def auth_session_guard(request, call_next):
session = request.scope.get("session", {}) or {}
current_user = session.get("current_user")
request.state.current_user = current_user
path = request.url.path
allowed_prefixes = (
"/login",
"/logout",
"/static",
"/health",
)
if path == "/favicon.ico" or any(path.startswith(prefix) for prefix in allowed_prefixes):
return await call_next(request)
if not current_user:
login_url = f"/login?next={path}"
return RedirectResponse(url=login_url, status_code=303)
return await call_next(request)
app.add_middleware(
SessionMiddleware,
secret_key="document-processor-change-this-secret",
@ -208,10 +232,4 @@ app.add_middleware(
)
@app.middleware("http")
async def load_current_user(request, call_next):
session = request.scope.get("session", {}) or {}
request.state.current_user = session.get("current_user")
return await call_next(request)
app.include_router(auth_router)

View File

@ -948,3 +948,24 @@ body { background: var(--shell-bg); }
}
}
/* ===== end mobile spacing pass ===== */
/* ===== desktop app width fill ===== */
@media (min-width: 901px) {
.main {
padding-right: 0.6rem !important;
}
.main-content {
max-width: none !important;
width: calc(100vw - 4.8rem) !important;
margin-right: 0 !important;
padding-right: 0.6rem !important;
}
.app-shell.nav-open .main-content {
width: calc(100vw - 14.6rem) !important;
}
}
/* ===== end desktop app width fill ===== */

View File

@ -5460,3 +5460,238 @@ table {
}
}
/* ===== end dashboard mobile polish ===== */
/* ===== desktop detail top card layout v2 ===== */
@media (min-width: 901px) {
.detail-doc-actions-row {
display: block !important;
margin-bottom: 0.3rem !important;
}
.detail-doc-actions-grid {
display: grid !important;
grid-template-columns: minmax(20rem, 24rem) auto auto !important;
align-items: end !important;
column-gap: 0.45rem !important;
row-gap: 0.18rem !important;
width: 100% !important;
}
.detail-doc-type-form {
display: grid !important;
grid-template-columns: minmax(16rem, 1fr) auto !important;
align-items: end !important;
gap: 0.45rem !important;
margin: 0 !important;
min-width: 0 !important;
}
.detail-type-input-wrap {
min-width: 0 !important;
}
.detail-type-input-wrap input {
width: 100% !important;
max-width: none !important;
}
.detail-update-button {
margin: 0 !important;
align-self: end !important;
justify-self: start !important;
}
.detail-flags-stack {
display: flex !important;
flex-direction: column !important;
justify-content: center !important;
gap: 0.12rem !important;
margin: 0 !important;
align-self: center !important;
}
.detail-check-inline {
display: inline-flex !important;
align-items: center !important;
gap: 0.25rem !important;
white-space: nowrap !important;
line-height: 1.05 !important;
margin: 0 !important;
}
.detail-review-flags-form {
margin: 0 !important;
align-self: center !important;
}
.detail-saveflags-button {
margin: 0 !important;
}
.detail-save-pdf-form {
display: block !important;
margin: 0 !important;
}
.detail-path-row {
display: grid !important;
grid-template-columns: minmax(0, 1fr) auto !important;
align-items: end !important;
gap: 0.45rem !important;
width: 100% !important;
}
.detail-path-row > div:first-child {
min-width: 0 !important;
}
.detail-save-pdf-form input[name="output_path"] {
width: 100% !important;
min-width: 0 !important;
}
.queue-nav-row {
display: flex !important;
flex-wrap: wrap !important;
align-items: center !important;
gap: 0.35rem !important;
margin-top: 0.35rem !important;
}
.queue-nav-row > * {
margin: 0 !important;
}
.detail-trash-inline,
.detail-trash-form {
order: 3 !important;
}
.detail-save-document-button {
order: 4 !important;
margin-left: auto !important;
}
/* right pane title rows should match mobile polish on desktop too */
.ocr-review-header-row,
.extracted-fields-header-row,
.line-items-header-row {
display: grid !important;
grid-template-columns: minmax(0, 1fr) auto !important;
align-items: center !important;
column-gap: 0.45rem !important;
}
}
/* ===== end desktop detail top card layout v2 ===== */
/* ===== polished login page ===== */
.login-page-shell {
max-width: 34rem;
margin: 3.5rem auto;
padding: 1.25rem 1rem;
}
.login-card {
padding: 1.1rem !important;
border-radius: 1.1rem !important;
}
.login-card .page-title {
margin: 0 0 0.18rem 0 !important;
}
.login-card .page-subtitle {
margin: 0 0 0.75rem 0 !important;
color: #6b7280 !important;
}
.login-card .form-grid {
gap: 0.72rem !important;
}
.login-card .form-field label {
font-size: 0.82rem !important;
margin-bottom: 0.2rem !important;
color: #6b7280 !important;
}
.login-card input[type="text"],
.login-card input[type="password"] {
min-height: 2.5rem !important;
height: 2.5rem !important;
padding: 0 0.8rem !important;
border-radius: 0.85rem !important;
font-size: 0.98rem !important;
}
.login-button-row {
margin-top: 0.85rem !important;
}
.login-button-row button,
.login-button-row .button-link {
min-height: 2.35rem !important;
height: 2.35rem !important;
padding: 0 0.95rem !important;
border-radius: 999px !important;
}
@media (max-width: 900px) {
.login-page-shell {
max-width: none;
margin: 2.25rem auto;
padding: 0.8rem 0.7rem;
}
.login-card {
padding: 0.85rem !important;
border-radius: 1rem !important;
}
.login-card .page-title {
font-size: 1rem !important;
line-height: 1.08 !important;
margin-bottom: 0.12rem !important;
}
.login-card .page-subtitle {
font-size: 0.72rem !important;
line-height: 1.15 !important;
margin-bottom: 0.55rem !important;
}
.login-card .form-grid {
gap: 0.5rem !important;
}
.login-card .form-field label {
font-size: 0.72rem !important;
line-height: 1.1 !important;
margin-bottom: 0.14rem !important;
}
.login-card input[type="text"],
.login-card input[type="password"] {
min-height: 2.1rem !important;
height: 2.1rem !important;
padding: 0 0.65rem !important;
border-radius: 0.8rem !important;
font-size: 0.88rem !important;
}
.login-button-row {
margin-top: 0.6rem !important;
}
.login-button-row button,
.login-button-row .button-link {
min-height: 1.95rem !important;
height: 1.95rem !important;
padding: 0 0.75rem !important;
font-size: 0.8rem !important;
}
}
/* ===== end polished login page ===== */

View File

@ -7,8 +7,8 @@
<link rel="stylesheet" href="/static/app-shell.css?v=21">
</head>
<body>
<main class="main" style="max-width:520px; margin:3rem auto; padding:2rem 1rem;">
<div class="card">
<main class="main login-page-shell">
<div class="card login-card">
<h1 class="page-title">Login</h1>
<p class="page-subtitle">Sign in to Document Processor.</p>
@ -28,7 +28,7 @@
</div>
</div>
<div class="button-row" style="margin-top:1rem;">
<div class="button-row login-button-row">
<button class="primary" type="submit">Login</button>
</div>
</form>