# retoor import pytest from devplacepy.database import CONSENTS_TABLE, get_setting, get_table, set_setting from devplacepy.services.acceptance.agreements import agreement_for from devplacepy.services.acceptance.pending import ( LIVE_ACCOUNT_CLAUSES, current_version, live_account_clauses, pending, ) from devplacepy.utils import generate_uid TERMS = agreement_for("terms") PRIVACY = agreement_for("privacy") AI = agreement_for("ai_third_party") @pytest.fixture def account(local_db): uid = generate_uid() get_table("users").insert( { "uid": uid, "username": f"pendingprobe_{uid[:8]}", "email": f"pendingprobe_{uid[:8]}@example.com", "password_hash": "x", "role": "Member", "terms_version": "", "terms_accepted_at": "", "deletion_requested_at": "", "created_at": "2020-01-01T00:00:00", } ) yield uid get_table("users").delete(uid=uid) get_table(CONSENTS_TABLE).delete(owner_id=uid) @pytest.fixture def versions(): before = { "terms_version": get_setting("terms_version", "1"), "privacy_version": get_setting("privacy_version", "1"), } yield for key, value in before.items(): set_setting(key, value) def write_consent(uid, kind, state, version): get_table(CONSENTS_TABLE).insert( { "uid": generate_uid(), "owner_kind": "user", "owner_id": uid, "kind": kind, "version": version, "state": state, "granted_at": "2021-01-01T00:00:00" if state == "granted" else "", "withdrawn_at": "" if state == "granted" else "2021-01-01T00:00:00", "created_at": "2021-01-01T00:00:00", "deleted_at": None, "deleted_by": None, } ) def is_pending(agreement, uid): return uid in {row["uid"] for row in pending(agreement, 5000)} def test_an_account_that_never_accepted_is_pending(account): assert is_pending(TERMS, account) assert is_pending(AI, account) def test_a_null_gate_column_is_pending_not_invisible(account, versions): set_setting("terms_version", "1") get_table("users").update({"uid": account, "terms_version": None}, ["uid"]) assert is_pending(TERMS, account) def test_a_satisfied_gate_column_is_not_pending(account, versions): set_setting("terms_version", "7") get_table("users").update({"uid": account, "terms_version": "7"}, ["uid"]) assert not is_pending(TERMS, account) def test_a_stale_gate_column_is_pending_again(account, versions): set_setting("terms_version", "7") get_table("users").update({"uid": account, "terms_version": "7"}, ["uid"]) set_setting("terms_version", "8") assert is_pending(TERMS, account) def test_a_withdrawal_removes_the_account_permanently(account, versions): set_setting("terms_version", "1") write_consent(account, "terms", "withdrawn", "1") assert not is_pending(TERMS, account) set_setting("terms_version", "2") assert not is_pending(TERMS, account) get_table("users").update({"uid": account, "terms_version": None}, ["uid"]) assert not is_pending(TERMS, account) def test_an_unversioned_agreement_is_satisfied_by_a_granted_row(account): write_consent(account, "ai_third_party", "granted", "1") assert not is_pending(AI, account) def test_a_versioned_ledger_agreement_tracks_the_policy_version(account, versions): set_setting("privacy_version", "3") write_consent(account, "privacy", "granted", "3") assert not is_pending(PRIVACY, account) set_setting("privacy_version", "4") assert is_pending(PRIVACY, account) def test_a_legacy_consent_row_without_a_version_is_stale(account, versions): set_setting("privacy_version", "1") write_consent(account, "privacy", "granted", None) assert is_pending(PRIVACY, account) def test_a_deleted_account_is_never_pending(account): get_table("users").update( {"uid": account, "deletion_requested_at": "2024-01-01T00:00:00"}, ["uid"] ) assert not is_pending(TERMS, account) def test_a_deactivated_account_is_never_pending(account): get_table("users").update({"uid": account, "is_active": False}, ["uid"]) assert not is_pending(TERMS, account) def test_the_batch_size_bounds_the_sweep_and_the_order_is_stable(account): first = [row["uid"] for row in pending(TERMS, 1)] second = [row["uid"] for row in pending(TERMS, 1)] assert len(first) <= 1 assert first == second def test_a_zero_batch_size_still_returns_at_most_one_row(account): assert len(pending(TERMS, 0)) <= 1 def test_the_live_account_clauses_only_name_existing_columns(local_db): users = get_table("users") expected = [ clause for column, clause in LIVE_ACCOUNT_CLAUSES if users.has_column(column) ] assert live_account_clauses() == expected def test_an_empty_version_setting_falls_back_to_one(versions): set_setting("terms_version", "") assert current_version(TERMS) == "1" def test_an_unversioned_agreement_reports_version_one(): assert current_version(AI) == "1"