about summary refs log tree commit diff
path: root/tests/test_gn_auth_auth_flow.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_gn_auth_auth_flow.py')
-rw-r--r--tests/test_gn_auth_auth_flow.py108
1 files changed, 108 insertions, 0 deletions
diff --git a/tests/test_gn_auth_auth_flow.py b/tests/test_gn_auth_auth_flow.py
index cb164cd..98d792a 100644
--- a/tests/test_gn_auth_auth_flow.py
+++ b/tests/test_gn_auth_auth_flow.py
@@ -191,3 +191,111 @@ class TestUserProfileWithoutToken:
             f"Expected 401 from /auth/user/ with garbage token, "
             f"got {resp.status_code}: {resp.text}"
         )
+
+
+# ---------------------------------------------------------------------------
+# POST /auth/user/masquerade/ — role-based privilege check
+#
+# The masquerade endpoint requires the "system:user:masquerade" privilege
+# which only system-administrators hold.  Both admin and basic users can
+# obtain a token with "masquerade" scope (the test client supports it), but
+# gn-auth's can_masquerade decorator checks the user's roles and raises
+# ForbiddenAccess (→ 403) for users without the privilege.
+# ---------------------------------------------------------------------------
+
+@pytest.fixture(scope="session")
+def admin_masquerade_token(gn_auth_url, http, oauth2_credentials):
+    """Admin Bearer token with masquerade scope."""
+    email, password, client_id, client_secret = oauth2_credentials
+    resp = http.post(
+        f"{gn_auth_url}/auth/token",
+        json={
+            "grant_type": "password",
+            "username": email,
+            "password": password,
+            "scope": "profile group resource user masquerade",
+            "client_id": client_id,
+            "client_secret": client_secret,
+        },
+        timeout=30,
+    )
+    assert resp.status_code == 200, f"Admin masquerade token request failed: {resp.text}"
+    return resp.json()["access_token"]
+
+
+@pytest.fixture(scope="session")
+def basic_masquerade_token(gn_auth_url, http, basic_oauth2_credentials):
+    """Unprivileged user Bearer token with masquerade scope."""
+    email, password, client_id, client_secret = basic_oauth2_credentials
+    resp = http.post(
+        f"{gn_auth_url}/auth/token",
+        json={
+            "grant_type": "password",
+            "username": email,
+            "password": password,
+            "scope": "profile group resource user masquerade",
+            "client_id": client_id,
+            "client_secret": client_secret,
+        },
+        timeout=30,
+    )
+    assert resp.status_code == 200, f"Basic masquerade token request failed: {resp.text}"
+    return resp.json()["access_token"]
+
+
+@pytest.fixture(scope="session")
+def basic_user_id(gn_auth_url, http, basic_access_token):
+    """User ID of the unprivileged test user, fetched via GET /auth/user/."""
+    resp = http.get(
+        f"{gn_auth_url}/auth/user/",
+        headers={"Authorization": f"Bearer {basic_access_token}"},
+        timeout=30,
+    )
+    assert resp.status_code == 200, f"Could not fetch basic user profile: {resp.text}"
+    return resp.json()["user_id"]
+
+
+class TestMasqueradePrivilege:
+    """POST /auth/user/masquerade/ enforces the system:user:masquerade privilege."""
+
+    def test_basic_user_cannot_masquerade_returns_403(
+            self, gn_auth_url, http, basic_masquerade_token, basic_user_id,
+            access_token):
+        # Basic user tries to masquerade as the admin; the admin's user_id is
+        # obtained via the profile endpoint.
+        admin_profile = http.get(
+            f"{gn_auth_url}/auth/user/",
+            headers={"Authorization": f"Bearer {access_token}"},
+            timeout=30,
+        )
+        assert admin_profile.status_code == 200
+        admin_id = admin_profile.json()["user_id"]
+
+        resp = http.post(
+            f"{gn_auth_url}/auth/user/masquerade/",
+            json={"masquerade_as": admin_id},
+            headers={"Authorization": f"Bearer {basic_masquerade_token}"},
+            timeout=30,
+        )
+        assert resp.status_code == 403, (
+            f"Expected 403 when unprivileged user attempts masquerade, "
+            f"got {resp.status_code}: {resp.text}"
+        )
+
+    def test_admin_can_masquerade_as_basic_user(
+            self, gn_auth_url, http, admin_masquerade_token, basic_user_id):
+        resp = http.post(
+            f"{gn_auth_url}/auth/user/masquerade/",
+            json={"masquerade_as": basic_user_id},
+            headers={"Authorization": f"Bearer {admin_masquerade_token}"},
+            timeout=30,
+        )
+        assert resp.status_code == 200, (
+            f"Expected 200 when admin masquerades as basic user, "
+            f"got {resp.status_code}: {resp.text}"
+        )
+        data = resp.json()
+        assert "masquerade_as" in data, f"Missing 'masquerade_as' in response: {data}"
+        assert data["masquerade_as"]["user"]["user_id"] == basic_user_id, (
+            "Masquerade response user_id does not match target user"
+        )