""" Auth-flow integration tests for genenetwork2 protected endpoints. Part 1 — Unauthenticated redirect checks: GN2's @login_required decorator redirects unauthenticated requests to the home page ("/"). These tests verify that all protected endpoints in the metadata-edit blueprint enforce that guard. No credentials are required. Part 2 — gn-auth contract tests (auth_flow, credentials required): GN2 calls back to gn-auth's POST /auth/data/authorisation and GET /auth/resource/system/roles per-request. These tests verify the contracts that gn2 depends on. Blueprint prefix: /datasets/ (registered in wqflask/__init__.py) Run all: pytest -m "gn2 and auth_flow" Run unauthenticated only (no credentials needed): pytest -m "gn2 and auth_flow" -k "unauthenticated" """ import pytest pytestmark = [pytest.mark.gn2, pytest.mark.auth_flow] # Known-good values reused from the smoke test suite. _DATASET_ID = "HC_M2_0606_P" _TRAIT_NAME = "1435395_s_at" _RESOURCE_ID = "00000000-0000-0000-0000-000000000000" # arbitrary; rejected before DB lookup _DIFF_NAME = "some-diff-name" # --------------------------------------------------------------------------- # Part 1: unauthenticated redirect — @login_required enforcement # --------------------------------------------------------------------------- def test_unauthenticated_display_phenotype_redirects(gn2_url, http): """GET /datasets//traits/ redirects to / without a session.""" resp = http.get( f"{gn2_url}/datasets/{_DATASET_ID}/traits/{_TRAIT_NAME}", timeout=30, allow_redirects=False, ) assert resp.status_code in (301, 302), ( f"Expected redirect for unauthenticated phenotype-display, " f"got {resp.status_code}: {resp.text[:200]}" ) def test_unauthenticated_update_phenotype_redirects(gn2_url, http): """POST /datasets//traits/ redirects to / without a session.""" resp = http.post( f"{gn2_url}/datasets/{_DATASET_ID}/traits/{_TRAIT_NAME}", data={}, timeout=30, allow_redirects=False, ) assert resp.status_code in (301, 302), ( f"Expected redirect for unauthenticated phenotype-update, " f"got {resp.status_code}: {resp.text[:200]}" ) def test_unauthenticated_list_diffs_redirects(gn2_url, http): """GET /datasets/diffs redirects to / without a session.""" resp = http.get( f"{gn2_url}/datasets/diffs", timeout=30, allow_redirects=False, ) assert resp.status_code in (301, 302), ( f"Expected redirect for unauthenticated diffs listing, " f"got {resp.status_code}: {resp.text[:200]}" ) def test_unauthenticated_show_diff_redirects(gn2_url, http): """GET /datasets/diffs/ redirects to / without a session.""" resp = http.get( f"{gn2_url}/datasets/diffs/{_DIFF_NAME}", timeout=30, allow_redirects=False, ) assert resp.status_code in (301, 302), ( f"Expected redirect for unauthenticated diff display, " f"got {resp.status_code}: {resp.text[:200]}" ) def test_unauthenticated_approve_diff_redirects(gn2_url, http): """POST /datasets//diffs//approve redirects to / without a session.""" resp = http.post( f"{gn2_url}/datasets/{_RESOURCE_ID}/diffs/{_DIFF_NAME}/approve", data={}, timeout=30, allow_redirects=False, ) assert resp.status_code in (301, 302), ( f"Expected redirect for unauthenticated diff approval, " f"got {resp.status_code}: {resp.text[:200]}" ) def test_unauthenticated_reject_diff_redirects(gn2_url, http): """POST /datasets//diffs//reject redirects to / without a session.""" resp = http.post( f"{gn2_url}/datasets/{_RESOURCE_ID}/diffs/{_DIFF_NAME}/reject", data={}, timeout=30, allow_redirects=False, ) assert resp.status_code in (301, 302), ( f"Expected redirect for unauthenticated diff rejection, " f"got {resp.status_code}: {resp.text[:200]}" )