import time from tests.conftest import make_project from backend import portal_auth as pa from backend.models import Client, ClientAccessToken def test_portal_client_for_project_is_1to1_and_idempotent(db_session): p = make_project(db_session) c1 = pa.portal_client_for_project(p, db_session) c2 = pa.portal_client_for_project(p, db_session) assert isinstance(c1, Client) and c1.id == c2.id assert c1.slug == f"portal-{p.id}" assert db_session.query(Client).filter_by(slug=f"portal-{p.id}").count() == 1 def test_mint_portal_session_returns_usable_token_id(db_session): p = make_project(db_session) tid = pa.mint_portal_session(p, db_session) tok = db_session.query(ClientAccessToken).filter_by(id=tid, revoked_at=None).first() assert tok is not None cookie = pa.make_session_cookie(tid) client = pa.client_from_cookie(cookie, db_session) assert client is not None and client.slug == f"portal-{p.id}" def test_resolve_project_by_link_token(db_session): p = make_project(db_session, portal_enabled=True, portal_link_token="tok-abc") assert pa.resolve_project_by_link_token("tok-abc", db_session).id == p.id assert pa.resolve_project_by_link_token("nope", db_session) is None def test_resolve_project_ignores_disabled_portal(db_session): make_project(db_session, portal_enabled=False, portal_link_token="tok-off") assert pa.resolve_project_by_link_token("tok-off", db_session) is None def test_lockout_after_max_attempts(): pa.clear_failures("k1") assert pa.is_locked("k1") is False for _ in range(pa.MAX_ATTEMPTS): pa.register_failure("k1") assert pa.is_locked("k1") is True pa.clear_failures("k1") assert pa.is_locked("k1") is False