Download mathly2/tests/test_auth.py from wzender/mathly: direct link, hf CLI and curl.
- Browser
- Download file 4.7 kB
-
https://huggingface.co/spaces/wzender/mathly/resolve/main/mathly2/tests/test_auth.py
- Command line
-
hf download hf://spaces/wzender/mathly/mathly2/tests/test_auth.py
-
curl -L -o test_auth.py https://huggingface.co/spaces/wzender/mathly/resolve/main/mathly2/tests/test_auth.py
4.7 kB
| import io | |
| import json | |
| import urllib.error | |
| import pytest | |
| from fastapi.testclient import TestClient | |
| from mathly2 import auth | |
| from mathly2.auth import AuthUnavailable, DevAuthenticator, SupabaseAuthenticator | |
| from mathly2.config import Settings | |
| from mathly2.main import create_app | |
| TEACHER = "teacher@school.test" | |
| def client(): | |
| return TestClient(create_app(Settings(teachers=frozenset({TEACHER})))) | |
| def sign(email): | |
| return {"Authorization": f"Bearer dev:{email}"} | |
| def test_no_token_is_refused(client): | |
| assert client.get("/api/me").status_code == 401 | |
| assert client.get("/api/me", headers={"Authorization": "Bearer nonsense"}).status_code == 401 | |
| assert client.get("/api/me", headers={"Authorization": "Bearer dev:not-an-email"}).status_code == 401 | |
| def me(client, email): | |
| return client.get("/api/me", headers=sign(email)).json() | |
| def test_a_listed_teacher_is_a_teacher(client): | |
| body = me(client, TEACHER) | |
| assert body["email"] == TEACHER and body["roles"] == ["teacher"] and body["classes"] == [] and body["teaching"] == [] | |
| assert "class.teach" in body["permissions"] and "classes.manage" not in body["permissions"] | |
| assert me(client, "Teacher@School.test")["roles"] == ["teacher"] # case does not matter | |
| def test_everyone_else_is_a_student(client): | |
| body = me(client, "kid@school.test") | |
| assert body["roles"] == ["student"] and body["permissions"] == ["path.use"] and body["classes"] == [] | |
| def test_developers_and_first_admins_come_from_the_settings(): | |
| app = create_app(Settings(developers=frozenset({"dev@school.test"}), admins=frozenset({"head@school.test"}))) | |
| client = TestClient(app) | |
| assert me(client, "dev@school.test")["roles"] == ["developer"] and me(client, "dev@school.test")["permissions"] == ["*"] | |
| assert me(client, "head@school.test")["roles"] == ["admin"] and me(client, "head@school.test")["permissions"] == ["roles.manage"] | |
| def test_page_carries_only_public_settings(): | |
| page = TestClient(create_app(Settings())).get("/").text | |
| assert '"devSignIn": true' in page and "__CONFIG__" not in page | |
| page = TestClient(create_app(Settings(supabase_url="https://p.test", supabase_key="pub", supabase_secret="SECRET-VALUE"))).get("/").text | |
| assert '"supabaseKey": "pub"' in page and '"devSignIn": false' in page and "SECRET-VALUE" not in page | |
| def test_half_configured_supabase_does_not_fall_back_to_dev_sign_in(): | |
| with pytest.raises(ValueError, match="all of SUPABASE_URL"): | |
| create_app(Settings(supabase_url="https://p.test")) | |
| def test_dev_sign_in_is_off_when_supabase_is_on(): | |
| app = create_app(Settings(supabase_url="https://p.test", supabase_key="pub", supabase_secret="sec")) | |
| assert isinstance(app.state.authenticator, SupabaseAuthenticator) | |
| assert TestClient(app).get("/api/me", headers=sign("kid@school.test")).status_code in (401, 503) | |
| def supabase_returns(monkeypatch, payload=None, error=None): | |
| """Stand in for the HTTP call to Supabase's /auth/v1/user: the calls made are returned as (url, headers).""" | |
| calls = [] | |
| def fake(method, url, headers=None, body=None, timeout=0): | |
| calls.append((url, headers or {})) | |
| if error: | |
| raise error | |
| return 200, json.dumps(payload).encode() | |
| monkeypatch.setattr(auth.pooled, "request", fake) | |
| return calls | |
| def test_supabase_user_is_checked_with_the_token_and_cached(monkeypatch): | |
| calls = supabase_returns(monkeypatch, {"id": "u1", "email": "Kid@School.test", "email_confirmed_at": "2026-01-01"}) | |
| a = SupabaseAuthenticator("https://p.test", "pub") | |
| assert a.user("tok") == {"id": "u1", "email": "kid@school.test"} | |
| assert a.user("tok")["id"] == "u1" | |
| assert len(calls) == 1 and calls[0][1]["Authorization"] == "Bearer tok" and calls[0][0].endswith("/auth/v1/user") | |
| def test_an_unconfirmed_email_is_not_trusted(monkeypatch): | |
| supabase_returns(monkeypatch, {"id": "u1", "email": TEACHER}) | |
| assert SupabaseAuthenticator("https://p.test", "pub").user("tok") is None | |
| def test_rejected_token_and_outage(monkeypatch): | |
| supabase_returns(monkeypatch, error=urllib.error.HTTPError("u", 401, "no", {}, None)) | |
| assert SupabaseAuthenticator("https://p.test", "pub").user("bad") is None | |
| supabase_returns(monkeypatch, error=urllib.error.URLError("down")) | |
| with pytest.raises(AuthUnavailable): | |
| SupabaseAuthenticator("https://p.test", "pub").user("tok") | |
| def test_outage_gives_503(monkeypatch): | |
| class Down: | |
| def user(self, token): raise AuthUnavailable("down") | |
| app = create_app(Settings(), authenticator=Down()) | |
| assert TestClient(app).get("/api/me", headers={"Authorization": "Bearer x"}).status_code == 503 | |