"""First-run setup, login, and the basic frame-visibility permission gate (require_frame_view/can_view_frame) -- the things every other endpoint's own permission test implicitly depends on already working.""" from __future__ import annotations from app.models import Frame from .conftest import get_csrf_token, link_user, login, make_user def test_setup_creates_admin_and_claims_migrated_frame(client, db_session): resp = client.post("/setup", data={ "username": "alice", "password": "hunter22", "display_name": "Alice", }) assert resp.status_code == 303 assert resp.headers["location"] == "/" frame = db_session.get(Frame, 1) assert frame is not None assert frame.owner_user_id is not None assert frame.controlled_by_user_id is not None def test_setup_only_works_once(client): resp = client.post("/setup", data={"username": "alice", "password": "hunter22"}) assert resp.status_code == 303 resp = client.post("/setup", data={"username": "mallory", "password": "hunter22"}) assert resp.status_code == 403 def test_login_requires_correct_password(client): client.post("/setup", data={"username": "alice", "password": "hunter22"}) client.cookies.clear() resp = client.post("/login", data={"username": "alice", "password": "wrong"}) assert resp.status_code == 401 resp = client.post("/login", data={"username": "alice", "password": "hunter22"}) assert resp.status_code == 303 def test_root_redirects_to_setup_before_any_user_exists(client): resp = client.get("/") assert resp.status_code == 303 assert resp.headers["location"] == "/setup" def test_unauthenticated_request_redirects_to_login_once_a_user_exists(client): client.post("/setup", data={"username": "alice", "password": "hunter22"}) client.cookies.clear() resp = client.get("/") assert resp.status_code == 303 assert resp.headers["location"] == "/login" def test_user_not_linked_to_a_frame_cannot_view_it(client, db_session): client.post("/setup", data={"username": "alice", "password": "hunter22"}) bob = make_user(db_session, "bob") db_session.flush() client.cookies.clear() login(client, "bob") resp = client.get("/frames/1") assert resp.status_code == 404 def test_linked_user_can_view_but_not_configure_by_default(client, db_session): """Being linked grants view access; whether they can also *control* (change settings/take the wheel) is a separate, narrower gate -- require_frame_control, exercised via the permission-boundary tests for individual features rather than here.""" client.post("/setup", data={"username": "alice", "password": "hunter22"}) bob = make_user(db_session, "bob") frame = db_session.get(Frame, 1) link_user(db_session, bob, frame) client.cookies.clear() login(client, "bob") resp = client.get("/frames/1") assert resp.status_code == 200 def test_csrf_token_required_for_settings_save(client): client.post("/setup", data={"username": "alice", "password": "hunter22"}) resp = client.post("/settings", data={ "display_name": "Alice", "email": "alice@example.com", "csrf_token": "bogus", }) assert resp.status_code == 403 def test_settings_save_round_trips_with_real_csrf_token(client, db_session): client.post("/setup", data={"username": "alice", "password": "hunter22"}) csrf = get_csrf_token(client, "/settings") resp = client.post("/settings", data={ "display_name": "Alice Smith", "email": "alice@example.com", "csrf_token": csrf, }) assert resp.status_code in (200, 303), resp.text from app.models import User user = db_session.query(User).filter_by(username="alice").one() assert user.display_name == "Alice Smith"