From f0e7231091cbe96ee4e719d0114d44aa829fb6a5 Mon Sep 17 00:00:00 2001 From: scott Date: Thu, 11 Jun 2026 16:34:58 -0700 Subject: [PATCH] Update user tests for the removed POST /api/users endpoint User creation moved to Keycloak-only, so the creation tests now just assert the endpoint returns 405, and the history test seeds its audit entry directly instead of creating a user through the API. Co-Authored-By: Claude Fable 5 --- backend/tests/test_users.py | 134 ++++++------------------------------ 1 file changed, 20 insertions(+), 114 deletions(-) diff --git a/backend/tests/test_users.py b/backend/tests/test_users.py index 438dd1e..e56a3ec 100644 --- a/backend/tests/test_users.py +++ b/backend/tests/test_users.py @@ -5,6 +5,8 @@ from unittest.mock import patch, MagicMock import pytest +from app.audit import AuditLog +from app.extensions import db from app.kc_queue_models import KcSyncQueue @@ -117,115 +119,16 @@ class TestListUsers: class TestCreateUser: - """POST /api/users -- admin-only user creation.""" - - def test_create_user_success(self, admin_client): - """Creates user with valid data.""" - with _mock_keycloak(): - resp = admin_client.post("/api/users", json={ - "first_name": "New", - "last_name": "User", - "email": "new@example.com", - }) - assert resp.status_code == 201 - data = resp.get_json() - assert data["name"] == "New User" - assert data["email"] == "new@example.com" - assert data["enabled"] is True - - def test_create_user_with_keycloak_id(self, admin_client): - """Creating with keycloak_id skips Keycloak sync.""" - with _mock_keycloak() as mock_kc: - resp = admin_client.post("/api/users", json={ - "first_name": "KC", - "last_name": "User", - "email": "kc@example.com", - "keycloak_id": "existing-kc-id", - }) - assert resp.status_code == 201 - # Should NOT have tried to create in Keycloak since keycloak_id was provided - mock_kc.create_user.assert_not_called() - - def test_create_user_missing_name(self, admin_client): - """Missing first_name returns 400.""" - resp = admin_client.post("/api/users", json={ - "email": "no-name@example.com", - }) - assert resp.status_code == 400 - assert "required" in resp.get_json()["error"].lower() - - def test_create_user_missing_email(self, admin_client): - """Missing email returns 400.""" - resp = admin_client.post("/api/users", json={ - "first_name": "No Email", - }) - assert resp.status_code == 400 - assert "required" in resp.get_json()["error"].lower() - - def test_create_user_empty_name(self, admin_client): - """Empty first_name string returns 400.""" - resp = admin_client.post("/api/users", json={ - "first_name": " ", - "email": "empty@example.com", - }) - assert resp.status_code == 400 - - def test_create_user_empty_email(self, admin_client): - """Empty email string returns 400.""" - resp = admin_client.post("/api/users", json={ - "first_name": "Empty Email", - "email": " ", - }) - assert resp.status_code == 400 - - def test_create_user_duplicate_email(self, admin_client, make_user): - """Duplicate email returns 400.""" - make_user(name="Existing", email="dupe@example.com") + """POST /api/users -- removed; users are created in Keycloak only.""" + def test_create_user_not_allowed(self, admin_client): + """User creation via the API returns 405 (users come from Keycloak/OIDC).""" resp = admin_client.post("/api/users", json={ "first_name": "New", - "email": "dupe@example.com", + "last_name": "User", + "email": "new@example.com", }) - assert resp.status_code == 400 - assert "already exists" in resp.get_json()["error"] - - def test_create_user_nonadmin_forbidden(self, authed_client): - """Non-admin user gets 403.""" - resp = authed_client.post("/api/users", json={ - "first_name": "Not", - "last_name": "Allowed", - "email": "nope@example.com", - }) - assert resp.status_code == 403 - - def test_create_user_missing_body(self, admin_client): - """No JSON body returns 400.""" - resp = admin_client.post("/api/users", content_type="application/json") - assert resp.status_code == 400 - - def test_create_user_enqueues_keycloak_sync(self, admin_client): - """User creation enqueues a KC create_user job (KC writes are async via - the sync queue; failures surface in kc_sync_errors, not the response).""" - resp = admin_client.post("/api/users", json={ - "first_name": "KC", - "last_name": "Sync", - "email": "kcsync@example.com", - }) - assert resp.status_code == 201 - assert _queue_count("create_user") == 1 - - def test_create_user_returns_projects_list(self, admin_client): - """Newly created user response includes empty projects list.""" - with _mock_keycloak(): - resp = admin_client.post("/api/users", json={ - "first_name": "Fresh", - "last_name": "User", - "email": "fresh@example.com", - }) - assert resp.status_code == 201 - data = resp.get_json() - assert "projects" in data - assert data["projects"] == [] + assert resp.status_code == 405 # =================================================================== @@ -566,16 +469,19 @@ class TestDeleteUser: class TestUserHistory: """GET /api/users//history -- audit log for user.""" - def test_user_history_after_create(self, admin_client): - """History includes the 'created' entry.""" - with _mock_keycloak(): - resp = admin_client.post("/api/users", json={ - "first_name": "Audited", - "email": "audited@example.com", - }) - user_id = resp.get_json()["id"] + def test_user_history_returns_audit_entries(self, admin_client, make_user, app): + """History returns audit entries recorded for the user.""" + user = make_user(name="Audited", email="audited@example.com") + with app.app_context(): + db.session.add(AuditLog( + entity_type="user", + entity_id=user.id, + action="created", + user="admin", + )) + db.session.commit() - resp = admin_client.get(f"/api/users/{user_id}/history") + resp = admin_client.get(f"/api/users/{user.id}/history") assert resp.status_code == 200 entries = resp.get_json()["entries"] actions = [e["action"] for e in entries]