feat(auth): sync Keycloak users for authorization
Generic Container CI/CD / test-build-publish (push) Failing after 33s
Server CI/CD v2 / build-test-publish-and-deploy (push) Failing after 34s

This commit is contained in:
2026-11-04 13:35:29 +08:00
parent bd8c619bfb
commit 9a9add1531
11 changed files with 716 additions and 8 deletions
@@ -20,6 +20,7 @@ from app.domain.schemas.admin_metadata import (
ProjectMemberUpdateRequest,
)
from app.infra.db.metadb.repositories.metadata_repository import ProjectDbRouting
from app.services.keycloak_user_sync import KeycloakUserSnapshot
@pytest.fixture
@@ -176,6 +177,66 @@ async def test_batch_sync_metadata_users_returns_per_user_results(monkeypatch):
assert admin_metadata.log_audit_event.await_count == 2
@pytest.mark.anyio
async def test_sync_keycloak_user_directory_preserves_authorization(monkeypatch):
new_id = uuid4()
existing_id = uuid4()
repo = SimpleNamespace(
session=SimpleNamespace(rollback=AsyncMock()),
sync_user_snapshot_from_keycloak=AsyncMock(
side_effect=[
(_user(keycloak_id=new_id, is_active=False), True),
(_user(keycloak_id=existing_id, role="admin"), False),
]
),
)
monkeypatch.setattr(
admin_metadata,
"fetch_keycloak_users",
AsyncMock(
return_value=[
KeycloakUserSnapshot(new_id, "new-user", "new@example.com"),
KeycloakUserSnapshot(existing_id, "admin-user", "admin@example.com"),
KeycloakUserSnapshot(uuid4(), "no-email", None),
KeycloakUserSnapshot(
uuid4(),
"service-account-client",
"service@example.com",
service_account_client_id="client",
),
]
),
)
monkeypatch.setattr(admin_metadata, "log_audit_event", AsyncMock())
response = await admin_metadata.sync_keycloak_user_directory(
current_user=_user(role="admin", is_superuser=True),
keycloak_payload={"iss": "https://keycloak.example.com/realms/tjwater"},
keycloak_access_token="admin-token",
metadata_repo=repo,
)
assert response.scanned == 4
assert response.created == 1
assert response.updated == 1
assert response.skipped == 2
assert [issue.reason for issue in response.issues] == [
"missing_email",
"service_account",
]
assert repo.sync_user_snapshot_from_keycloak.await_count == 2
admin_metadata.fetch_keycloak_users.assert_awaited_once_with(
issuer="https://keycloak.example.com/realms/tjwater",
bearer_token="admin-token",
)
assert repo.sync_user_snapshot_from_keycloak.await_args_list[1].kwargs == {
"keycloak_id": existing_id,
"username": "admin-user",
"email": "admin@example.com",
}
admin_metadata.log_audit_event.assert_awaited_once()
@pytest.mark.anyio
async def test_update_metadata_user_updates_role_and_active_status(monkeypatch):
user_id = uuid4()