# retoor from devplacepy.database import get_setting, set_setting from devplacepy.database.nodes import LIMITS, find_device_by_secret from tests.api.nodes.conftest import make_member def create(client, who, **body): payload = {"label": "Home laptop", "kind": "native", **body} return client.post("/nodes/devices", json=payload, headers=who["headers"]) def test_guests_get_401(client): assert client.get("/nodes/devices").status_code == 401 assert client.post("/nodes/devices", json={"label": "x"}).status_code == 401 assert client.post("/nodes/devices/x/rotate").status_code == 401 assert client.post("/nodes/devices/x/delete").status_code == 401 def test_registration_returns_the_secret_once_and_never_caches_it(client, member): response = create(client, member) assert response.status_code == 201 assert response.headers["cache-control"] == "no-store" body = response.json() assert body["secret"].startswith("dpn_") assert body["device"]["label"] == "Home laptop" assert "secret_hash" not in body["device"] and "ip_hash" not in body["device"] assert find_device_by_secret(body["secret"])["uid"] == body["device"]["uid"] listing = client.get("/nodes/devices", headers=member["headers"]).json() assert [item["uid"] for item in listing["devices"]] == [body["device"]["uid"]] assert listing["max_devices"] == LIMITS.max_devices_per_user assert "secret" not in str(listing) def test_registration_needs_consent_and_enablement(client): no_consent = make_member(consent=False) refused = create(client, no_consent) assert refused.status_code == 403 assert refused.json()["error"]["reason"] == "no_consent" not_enabled = make_member(enabled=False) assert create(client, not_enabled).json()["error"]["reason"] == "not_enabled" minor = make_member(age_band="16_17") assert create(client, minor).json()["error"]["reason"] == "not_adult" def test_kill_switch_blocks_registration(client, member): previous = get_setting("nodes_enabled", "0") set_setting("nodes_enabled", "0") try: response = create(client, member) assert response.status_code == 403 assert response.json()["error"]["reason"] == "kill_switch" finally: set_setting("nodes_enabled", previous) def test_device_cap_is_a_409(client, member): for _ in range(LIMITS.max_devices_per_user): assert create(client, member).status_code == 201 assert create(client, member).status_code == 409 def test_unknown_kind_is_a_validation_error(client, member): assert create(client, member, kind="browser").status_code == 422 def test_rotate_replaces_the_secret_and_is_owner_only(client, member): created = create(client, member).json() uid, old = created["device"]["uid"], created["secret"] other = make_member() assert ( client.post(f"/nodes/devices/{uid}/rotate", headers=other["headers"]).status_code == 404 ) rotated = client.post(f"/nodes/devices/{uid}/rotate", headers=member["headers"]) assert rotated.status_code == 200 new = rotated.json()["secret"] assert new != old assert find_device_by_secret(old) is None assert find_device_by_secret(new)["uid"] == uid def test_delete_is_owner_or_admin(client, member): uid = create(client, member).json()["device"]["uid"] other = make_member() assert ( client.post(f"/nodes/devices/{uid}/delete", headers=other["headers"]).status_code == 403 ) admin = make_member(role="Admin") assert ( client.post(f"/nodes/devices/{uid}/delete", headers=admin["headers"]).status_code == 200 ) assert client.get("/nodes/devices", headers=member["headers"]).json()["devices"] == [] assert ( client.post(f"/nodes/devices/{uid}/delete", headers=member["headers"]).status_code == 404 ) def test_owner_can_delete_their_own_device(client, member): uid = create(client, member).json()["device"]["uid"] response = client.post(f"/nodes/devices/{uid}/delete", headers=member["headers"]) assert response.status_code == 200 and response.json() == {"ok": True}