# retoor <retoor@molodetz.nl>
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"