refactor: tighten backend, flows, frontend, tests; push flows to Langflow
This commit is contained in:
parent
6688fb08c6
commit
06ab25fb47
31 changed files with 783 additions and 358 deletions
|
|
@ -6,16 +6,11 @@ from uuid import UUID
|
|||
from fastapi import APIRouter, Depends, HTTPException, Query, Request, Response
|
||||
from sqlmodel import Session
|
||||
|
||||
from app.db import get_db
|
||||
from app.models import User
|
||||
|
||||
from . import mail, service
|
||||
from .deps import (
|
||||
SESSION_COOKIE,
|
||||
SESSION_MAX_AGE,
|
||||
get_current_user,
|
||||
get_db,
|
||||
require_admin,
|
||||
)
|
||||
from .deps import SESSION_COOKIE, SESSION_MAX_AGE, get_current_user, require_admin
|
||||
from .schemas import (
|
||||
AccessDecisionRead,
|
||||
AccessRequestCreate,
|
||||
|
|
@ -33,26 +28,11 @@ auth_router = APIRouter(prefix="/api/auth", tags=["auth"])
|
|||
|
||||
|
||||
def _read_request(r) -> AccessRequestRead:
|
||||
return AccessRequestRead(
|
||||
id=r.id,
|
||||
name=r.name,
|
||||
email=r.email,
|
||||
reason=r.reason,
|
||||
status=r.status,
|
||||
created_at=r.created_at,
|
||||
decided_at=r.decided_at,
|
||||
decided_by=r.decided_by,
|
||||
)
|
||||
return AccessRequestRead.model_validate(r, from_attributes=True)
|
||||
|
||||
|
||||
def _read_me(user: User) -> MeRead:
|
||||
return MeRead(
|
||||
id=user.id,
|
||||
email=user.email,
|
||||
name=user.name,
|
||||
role=user.role,
|
||||
tenant_id=user.tenant_id,
|
||||
)
|
||||
return MeRead.model_validate(user, from_attributes=True)
|
||||
|
||||
|
||||
def _set_session_cookie(response: Response, session_id: str) -> None:
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
"""Session-cookie dependencies. Handlers stay thin; DB via get_session."""
|
||||
"""Session-cookie dependencies. Handlers stay thin; DB via app.db.get_db."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterator
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Depends, HTTPException, Request
|
||||
from sqlmodel import Session
|
||||
|
||||
from app.db import get_session
|
||||
from app.db import get_db
|
||||
from app.models import User
|
||||
|
||||
from . import service
|
||||
|
|
@ -17,10 +16,6 @@ SESSION_COOKIE = "kirche_session"
|
|||
SESSION_MAX_AGE = int(service.SESSION_TTL.total_seconds())
|
||||
|
||||
|
||||
def get_db() -> Iterator[Session]:
|
||||
yield from get_session()
|
||||
|
||||
|
||||
def get_optional_user(
|
||||
request: Request, session: Annotated[Session, Depends(get_db)]
|
||||
) -> User | None:
|
||||
|
|
|
|||
|
|
@ -22,11 +22,6 @@ BLUE_LIGHT = "#eef4fb"
|
|||
INK = "#162f4c"
|
||||
MUTED = "#5b6b7c"
|
||||
|
||||
BLUE = "#1d4a79"
|
||||
BLUE_LIGHT = "#eef4fb"
|
||||
INK = "#162f4c"
|
||||
MUTED = "#5b6b7c"
|
||||
|
||||
|
||||
def magic_link(token: str) -> str:
|
||||
return f"{settings.frontend_url.rstrip('/')}/login?token={token}"
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ from uuid import UUID
|
|||
from sqlmodel import Session, func, select
|
||||
|
||||
from app.models import AccessRequest, MagicLinkToken, User, UserSession
|
||||
from app.models.base import utcnow
|
||||
from app.settings import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -60,10 +61,6 @@ class RateLimitedError(AuthError):
|
|||
pass
|
||||
|
||||
|
||||
def utcnow() -> datetime:
|
||||
return datetime.now(UTC)
|
||||
|
||||
|
||||
def normalize_email(email: str) -> str:
|
||||
return email.strip().lower()
|
||||
|
||||
|
|
@ -92,18 +89,22 @@ def user_count(session: Session) -> int:
|
|||
return session.exec(select(func.count()).select_from(User)).one()
|
||||
|
||||
|
||||
def recent_request_count(session: Session, email: str, hours: int = 1) -> int:
|
||||
def _recent_count(session: Session, model, *filters, hours: int = 1) -> int:
|
||||
since = utcnow() - timedelta(hours=hours)
|
||||
return session.exec(
|
||||
select(func.count())
|
||||
.select_from(AccessRequest)
|
||||
.where(
|
||||
AccessRequest.email == normalize_email(email),
|
||||
AccessRequest.created_at >= since,
|
||||
)
|
||||
select(func.count()).select_from(model).where(*filters, model.created_at >= since)
|
||||
).one()
|
||||
|
||||
|
||||
def recent_request_count(session: Session, email: str, hours: int = 1) -> int:
|
||||
return _recent_count(
|
||||
session,
|
||||
AccessRequest,
|
||||
AccessRequest.email == normalize_email(email),
|
||||
hours=hours,
|
||||
)
|
||||
|
||||
|
||||
def create_access_request(
|
||||
session: Session, name: str, email: str, reason: str = ""
|
||||
) -> AccessRequest:
|
||||
|
|
@ -165,15 +166,7 @@ def issue_magic_token(session: Session, user: User) -> str:
|
|||
|
||||
|
||||
def recent_token_count(session: Session, user: User, hours: int = 1) -> int:
|
||||
since = utcnow() - timedelta(hours=hours)
|
||||
return session.exec(
|
||||
select(func.count())
|
||||
.select_from(MagicLinkToken)
|
||||
.where(
|
||||
MagicLinkToken.user_id == user.id,
|
||||
MagicLinkToken.created_at >= since,
|
||||
)
|
||||
).one()
|
||||
return _recent_count(session, MagicLinkToken, MagicLinkToken.user_id == user.id, hours=hours)
|
||||
|
||||
|
||||
def request_magic_link(session: Session, email: str) -> tuple[User, str]:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue