from tests.conftest import make_project from backend import portal_auth as pa from backend.auth_passwords import hash_password def _enabled_project(db_session, token="tok-1", password="secretpw"): return make_project(db_session, portal_enabled=True, portal_link_token=token, portal_password_hash=hash_password(password)) def test_get_prompt_renders_for_valid_token(client, db_session): _enabled_project(db_session) r = client.get("/portal/p/tok-1") assert r.status_code == 200 assert "password" in r.text.lower() def test_get_unknown_token_shows_generic_page(client, db_session): r = client.get("/portal/p/does-not-exist") assert r.status_code in (403, 404) assert "password" not in r.text.lower() or "isn't valid" in r.text.lower() def test_wrong_password_is_rejected(client, db_session): _enabled_project(db_session, password="rightpw") r = client.post("/portal/p/tok-1", data={"password": "wrongpw"}, follow_redirects=False) assert r.status_code == 200 # re-renders the form, no cookie assert "portal_session" not in r.headers.get("set-cookie", "") def test_correct_password_sets_cookie_and_redirects(client, db_session): _enabled_project(db_session, password="rightpw") r = client.post("/portal/p/tok-1", data={"password": "rightpw"}, follow_redirects=False) assert r.status_code == 303 assert r.headers["location"] == "/portal" assert "portal_session=" in r.headers.get("set-cookie", "") def test_lockout_after_five_wrong(client, db_session): _enabled_project(db_session, token="tok-lock", password="rightpw") for _ in range(5): client.post("/portal/p/tok-lock", data={"password": "x"}, follow_redirects=False) # 6th attempt — even the CORRECT password is refused while locked r = client.post("/portal/p/tok-lock", data={"password": "rightpw"}, follow_redirects=False) assert r.status_code == 200 assert "portal_session=" not in r.headers.get("set-cookie", "") assert "too many" in r.text.lower() def test_enabled_without_password_is_not_accessible(client, db_session): # enabled portal but no password set yet (operator enabled before generating one) # must NOT show a usable form — looks like an invalid link, no self-lockout. make_project(db_session, portal_enabled=True, portal_link_token="tok-nopw") r = client.get("/portal/p/tok-nopw") assert r.status_code == 404 assert "isn't valid" in r.text.lower() # and a POST can't succeed or set a cookie either r2 = client.post("/portal/p/tok-nopw", data={"password": "anything"}, follow_redirects=False) assert r2.status_code == 404 assert "portal_session=" not in r2.headers.get("set-cookie", "")