fix: authorize flow management, gate runs, token-gate callbacks, strict tenants

This commit is contained in:
Jonas Miederer 2026-09-14 20:12:17 +02:00
parent cfcf0e8bd6
commit 94e5e53092
21 changed files with 662 additions and 160 deletions

View file

@ -17,6 +17,8 @@ TEST_AREA = Path(tempfile.mkdtemp(prefix="kirche-tests-"))
# Must precede all `app.*` imports: Settings is instantiated at import time.
os.environ["DATABASE_URL"] = f"sqlite:///{TEST_AREA / 'test.db'}"
os.environ["FLOWS_DIR"] = str(TEST_AREA / "flows")
# Flow callbacks (POST /api/approvals) authenticate with this token.
os.environ["CALLBACK_TOKEN"] = "test-callback-token"
# The embedded watcher + startup sync stay off in tests; sync is exercised
# directly (sync_from_directory) with per-test tmp dirs instead.
os.environ["FLOWS_WATCH_ENABLED"] = "false"
@ -81,6 +83,48 @@ async def client():
yield c
@pytest.fixture()
def login(client, session):
"""Log the test client in as a fresh user: ``await login()`` (admin)
or ``await login(role="member", tenant_id="pfarramt-a")``."""
async def _login(
email: str = "admin@example.com",
role: str = "admin",
tenant_id: str = "default",
):
from datetime import UTC, datetime, timedelta
from uuid import uuid4
from sqlmodel import select
from app.auth.deps import SESSION_COOKIE
from app.models import User, UserSession
# Idempotent: re-login updates the existing row (tests switch
# identity mid-test by calling login() again).
user = session.exec(select(User).where(User.email == email)).first()
if user is None:
user = User(name="Test", email=email, role=role, tenant_id=tenant_id)
session.add(user)
else:
user.role = role
user.tenant_id = tenant_id
session.add(user)
session.flush()
user_session = UserSession(
id=f"test-session-{uuid4().hex}",
user_id=user.id,
expires_at=datetime.now(UTC) + timedelta(days=1),
)
session.add(user_session)
session.commit()
client.cookies.set(SESSION_COOKIE, user_session.id)
return user
return _login
@pytest.fixture(scope="session")
def lfx_server(tmp_path_factory):
"""Real `lfx serve` subprocess on a free port; points settings at it.