From 97ec6893418d8d506cebe48974ed53323fe94431 Mon Sep 17 00:00:00 2001 From: Oliver Hofmann Date: Mon, 27 Apr 2026 18:45:30 +0200 Subject: [PATCH] feat: trigger LDAP background sync on successful login --- app/modules/auth/router.py | 15 ++++++++++++++- tests/test_auth_router.py | 26 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/app/modules/auth/router.py b/app/modules/auth/router.py index c91f99b..f9dff21 100644 --- a/app/modules/auth/router.py +++ b/app/modules/auth/router.py @@ -1,4 +1,4 @@ -from fastapi import APIRouter, Depends, Form, Request +from fastapi import APIRouter, BackgroundTasks, Depends, Form, Request from fastapi.responses import HTMLResponse, RedirectResponse from fastapi.templating import Jinja2Templates from sqlalchemy.orm import Session @@ -7,6 +7,7 @@ from app.core.auth import clear_auth_cookie, create_access_token, set_auth_cooki from app.core.config import get_settings from app.core.database import get_db from app.modules.auth.dependencies import get_current_user +from app.modules.auth.ldap import sync_all_users from app.modules.auth.schemas import UserOut from app.modules.auth.service import authenticate_user @@ -27,6 +28,7 @@ async def login_page(request: Request): @router.post("/login", response_class=HTMLResponse) async def login( request: Request, + background_tasks: BackgroundTasks, username: str = Form(...), password: str = Form(...), db: Session = Depends(get_db), @@ -39,6 +41,17 @@ async def login( {"nav_items": _NAV, "app_version": "0.1.0", "error": "Ungültige Zugangsdaten."}, status_code=200, ) + if settings.LDAP_ENABLED: + background_tasks.add_task( + sync_all_users, + username, + password, + settings.LDAP_SERVER, + settings.LDAP_DOMAIN, + settings.LDAP_SEARCH_BASE, + settings.LDAP_SYNC_MIN_INTERVAL_HOURS, + settings.LDAP_SYNC_LETTER_DELAY_SECONDS, + ) token = create_access_token(username=user.username, is_admin=user.is_admin) response = RedirectResponse(url="/", status_code=303) set_auth_cookie(response, token) diff --git a/tests/test_auth_router.py b/tests/test_auth_router.py index 4080665..8855de7 100644 --- a/tests/test_auth_router.py +++ b/tests/test_auth_router.py @@ -71,3 +71,29 @@ def test_logout_clears_cookie_and_redirects_to_landing(client, alice): assert response.status_code in (302, 303, 307) assert response.headers["location"] == "/" assert response.cookies.get("access_token", "") == "" + + +from unittest.mock import patch as mock_patch + + +def test_ldap_login_sets_cookie_and_redirects(client, override_db): + """LDAP login via mocked ldap_authenticate: cookie is set, redirects to /.""" + ldap_attrs = { + "username": "ldapuser", + "full_name": "LDAP User", + "department": "EFI", + "role": "ST", + "account_expires": None, + } + with mock_patch("app.modules.auth.ldap.ldap_authenticate", return_value=ldap_attrs), \ + mock_patch("app.modules.auth.ldap.sync_all_users"), \ + mock_patch("app.modules.auth.router.settings") as mock_settings: + mock_settings.LDAP_ENABLED = True + mock_settings.LDAP_SERVER = "test" + mock_settings.LDAP_DOMAIN = "ADS1" + mock_settings.LDAP_SEARCH_BASE = "OU=test" + mock_settings.LDAP_SYNC_MIN_INTERVAL_HOURS = 12 + mock_settings.LDAP_SYNC_LETTER_DELAY_SECONDS = 0.0 + response = client.post("/auth/login", data={"username": "ldapuser", "password": "any"}) + assert response.status_code in (302, 303, 307) + assert "access_token" in response.cookies