# retoor import time import pytest from devplacepy.database import get_table, set_consent, set_setting from devplacepy.database.nodes import save_node_settings from devplacepy.services.nodes.consent import REASONS, ConsentGate from devplacepy.utils import register_account GATE = ConsentGate() _counter = [0] def fresh(age_band="adult"): _counter[0] += 1 name = f"gate{int(time.time() * 1000)}{_counter[0]}" uid, _, _ = register_account( name, f"{name}@t.dev", "secret123", age_band=age_band, accepted_terms=True ) return uid @pytest.fixture def switched_on(local_db): set_setting("nodes_enabled", "1") yield set_setting("nodes_enabled", "0") def ready(): uid = fresh() set_consent("user", uid, "bandwidth_sharing", True) save_node_settings(uid, {"enabled": True}) return uid def test_a_fully_qualified_member_is_allowed(switched_on): verdict = GATE.allows(ready()) assert verdict.allowed and verdict.reason == "" and verdict.message == "" def test_the_kill_switch_beats_everything(local_db): set_setting("nodes_enabled", "1") uid = ready() set_setting("nodes_enabled", "0") assert GATE.allows(uid).reason == "kill_switch" def test_default_is_off_without_the_setting(local_db): get_table("site_settings").delete(key="nodes_enabled") assert GATE.allows(ready()).reason == "kill_switch" def test_unknown_account(switched_on): assert GATE.allows("nobody").reason == "no_account" assert GATE.allows("").reason == "no_account" def test_each_missing_requirement_has_its_own_reason(switched_on): no_consent = fresh() save_node_settings(no_consent, {"enabled": True}) assert GATE.allows(no_consent).reason == "no_consent" not_enabled = fresh() set_consent("user", not_enabled, "bandwidth_sharing", True) assert GATE.allows(not_enabled).reason == "not_enabled" withdrawn = ready() set_consent("user", withdrawn, "bandwidth_sharing", False) assert GATE.allows(withdrawn).reason == "no_consent" @pytest.mark.parametrize("band", ["", "under_min", "13_15", "16_17", "adult"]) def test_age_band_is_not_checked(switched_on, band): uid = fresh(age_band=band) set_consent("user", uid, "bandwidth_sharing", True) save_node_settings(uid, {"enabled": True}) assert GATE.allows(uid).allowed def test_account_states_block(switched_on): uid = ready() users = get_table("users") users.update({"uid": uid, "suspended_until": "2999-01-01T00:00:00+00:00"}, ["uid"]) assert GATE.allows(uid).reason == "suspended" users.update({"uid": uid, "suspended_until": ""}, ["uid"]) users.update({"uid": uid, "is_active": False}, ["uid"]) assert GATE.allows(uid).reason == "account_inactive" users.update({"uid": uid, "is_active": True}, ["uid"]) users.update({"uid": uid, "deletion_requested_at": "2026-01-01T00:00:00+00:00"}, ["uid"]) assert GATE.allows(uid).reason == "deletion_pending" def test_every_reason_is_described(): for reason in ( "kill_switch", "no_account", "account_inactive", "deletion_pending", "suspended", "no_consent", "not_enabled", ): assert REASONS[reason] def test_batch_decisions_equal_single_decisions(switched_on): qualified = ready() no_consent = fresh() save_node_settings(no_consent, {"enabled": True}) minor = fresh(age_band="16_17") set_consent("user", minor, "bandwidth_sharing", True) save_node_settings(minor, {"enabled": True}) withdrawn = ready() set_consent("user", withdrawn, "bandwidth_sharing", False) uids = [qualified, no_consent, minor, withdrawn, "nobody"] many = GATE.allows_many(uids) assert list(many) == uids for uid in uids: assert many[uid] == GATE.allows(uid) assert [many[uid].reason for uid in uids] == [ "", "no_consent", "", "no_consent", "no_account", ] def test_batch_with_the_kill_switch_off_refuses_everyone(local_db): set_setting("nodes_enabled", "0") many = GATE.allows_many([ready(), ready()]) assert {verdict.reason for verdict in many.values()} == {"kill_switch"} def test_batches_larger_than_the_chunk_size_are_all_decided(switched_on, monkeypatch): monkeypatch.setattr("devplacepy.services.nodes.consent.BATCH_SIZE", 2) uids = [ready() for _ in range(5)] many = GATE.allows_many(uids) assert len(many) == 5 and all(item.allowed for item in many.values()) def test_the_latest_consent_row_wins_in_a_batch(switched_on): uid = ready() set_consent("user", uid, "bandwidth_sharing", False) set_consent("user", uid, "bandwidth_sharing", True) assert GATE.allows_many([uid])[uid].allowed