diff options
| -rw-r--r-- | pyproject.toml | 1 | ||||
| -rw-r--r-- | tests/test_gn3_case_attr_access.py | 50 |
2 files changed, 51 insertions, 0 deletions
diff --git a/pyproject.toml b/pyproject.toml index 773b57a..0a1d58d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,7 @@ markers = [ "gn_auth: Tests exercising the gn-auth service", "auth_flow: Tests requiring valid user credentials (set GN_TEST_EMAIL and GN_TEST_PASSWORD)", "transient: Tests known to fail intermittently due to timing or load; candidates for retry logic", + "case_attr_access: Tests for case-attribute endpoint access-control levels", ] [build-system] diff --git a/tests/test_gn3_case_attr_access.py b/tests/test_gn3_case_attr_access.py new file mode 100644 index 0000000..e2399c8 --- /dev/null +++ b/tests/test_gn3_case_attr_access.py @@ -0,0 +1,50 @@ +"""Access-control tests for case-attribute endpoints (old flat + v1 hierarchy). + +Case-attribute names are publicly accessible (no token required). +All write endpoints require a valid token, and a token with appropriate +edit privileges. +""" +import pytest + +pytestmark = pytest.mark.gn3 + +_SPECIES_ID = 1 # Mouse +_INBREDSET_ID = 1 # BXD + + +@pytest.mark.case_attr_access +@pytest.mark.parametrize("path", [ + f"/case-attribute/{_INBREDSET_ID}/edit", + f"/v1/species/{_SPECIES_ID}/populations/{_INBREDSET_ID}/case-attributes/edit", +]) +def test_no_token_edit_returns_400(gn3_url, http, path): + """POST to any edit endpoint with no token must be rejected with 400.""" + resp = http.post( + f"{gn3_url}{path}", + json={"edit-data": []}, + timeout=30, + ) + assert resp.status_code == 400, ( + f"Expected 400 for unauthenticated POST {path!r}, " + f"got {resp.status_code}. Body: {resp.text[:200]}" + ) + + +@pytest.mark.case_attr_access +@pytest.mark.auth_flow +@pytest.mark.parametrize("path", [ + f"/case-attribute/{_INBREDSET_ID}/edit", + f"/v1/species/{_SPECIES_ID}/populations/{_INBREDSET_ID}/case-attributes/edit", +]) +def test_no_privilege_edit_returns_401(gn3_url, http, basic_access_token, path): + """A token with no case-attribute edit privileges must be refused with 401.""" + resp = http.post( + f"{gn3_url}{path}", + json={"edit-data": []}, + headers={"Authorization": f"Bearer {basic_access_token}"}, + timeout=30, + ) + assert resp.status_code == 401, ( + f"Expected 401 for unprivileged POST {path!r}, " + f"got {resp.status_code}. Body: {resp.text[:200]}" + ) |
