open-swe/tests/dashboard/test_dashboard_org_login_gate.py
Adam Moussa ae1f883b4c
refactor: move tests into tests/<domain>/ layout
Applies the plan's C5 step: git mv every test per the domain-reorg
move-map (movemap-m50.txt) into tests/{agent,analyzer,auth,dashboard,
github,middleware,models,reviewer,sandbox,slack,tools,webhooks}/, plus
the 13 fork-only placements from the scoping report §2c (Atlassian
webhook tests -> tests/webhooks/, test_atlassian_connect.py and
test_auth_error_leak.py -> tests/auth/, jira/confluence util tests ->
tests/tools/, test_repo_binding_isolation.py -> tests/sandbox/,
bot-identity/autofix tests -> tests/github/).

Path-only move: the only content edits are parents[1] -> parents[2]
fixes in test_e2b_integration.py and test_daytona_integration.py,
required because their __file__-relative ROOT path gained one more
directory level in the move.

Monkeypatch retargets for these files were already completed in C4;
none remained outstanding here.
2026-07-17 14:42:45 -04:00

79 lines
2.6 KiB
Python

"""Tests for the dashboard GitHub-org login gate (ALLOWED_GITHUB_ORGS)."""
from __future__ import annotations
import pytest
from fastapi import HTTPException
from agent.dashboard import oauth
def _stub_membership(monkeypatch, members: dict[str, set[str]]) -> dict[str, list[tuple[str, str]]]:
"""Stub is_user_active_org_member; ``members`` maps org -> set of logins."""
seen: dict[str, list[tuple[str, str]]] = {"calls": []}
async def fake_is_user_active_org_member(username: str, org: str) -> bool:
seen["calls"].append((username, org))
return username in members.get(org, set())
monkeypatch.setattr(oauth, "is_user_active_org_member", fake_is_user_active_org_member)
return seen
@pytest.mark.asyncio
async def test_gate_noop_when_unset(monkeypatch) -> None:
monkeypatch.delenv("ALLOWED_GITHUB_ORGS", raising=False)
seen = _stub_membership(monkeypatch, {})
await oauth.enforce_org_login_gate("anyone")
assert seen["calls"] == []
@pytest.mark.asyncio
async def test_gate_noop_when_blank(monkeypatch) -> None:
monkeypatch.setenv("ALLOWED_GITHUB_ORGS", " , ")
seen = _stub_membership(monkeypatch, {})
await oauth.enforce_org_login_gate("anyone")
assert seen["calls"] == []
@pytest.mark.asyncio
async def test_gate_allows_member(monkeypatch) -> None:
monkeypatch.setenv("ALLOWED_GITHUB_ORGS", "langchain-ai")
_stub_membership(monkeypatch, {"langchain-ai": {"insider"}})
await oauth.enforce_org_login_gate("insider")
@pytest.mark.asyncio
async def test_gate_rejects_non_member(monkeypatch) -> None:
monkeypatch.setenv("ALLOWED_GITHUB_ORGS", "langchain-ai")
_stub_membership(monkeypatch, {"langchain-ai": {"insider"}})
with pytest.raises(HTTPException) as exc:
await oauth.enforce_org_login_gate("stranger")
assert exc.value.status_code == 403
@pytest.mark.asyncio
async def test_gate_allows_member_of_any_configured_org(monkeypatch) -> None:
monkeypatch.setenv("ALLOWED_GITHUB_ORGS", "langchain-ai, anthropics")
_stub_membership(monkeypatch, {"anthropics": {"insider"}})
await oauth.enforce_org_login_gate("insider")
@pytest.mark.asyncio
async def test_gate_rejects_when_member_of_no_configured_org(monkeypatch) -> None:
monkeypatch.setenv("ALLOWED_GITHUB_ORGS", "langchain-ai,anthropics")
seen = _stub_membership(monkeypatch, {"other-org": {"stranger"}})
with pytest.raises(HTTPException) as exc:
await oauth.enforce_org_login_gate("stranger")
assert exc.value.status_code == 403
assert {org for _, org in seen["calls"]} == {"langchain-ai", "anthropics"}