60 lines
1.6 KiB
Python
60 lines
1.6 KiB
Python
from __future__ import annotations
|
|
|
|
import time
|
|
from dataclasses import dataclass
|
|
from urllib.parse import parse_qs, urlencode
|
|
|
|
from django.conf import settings
|
|
|
|
CONSENT_COOKIE_NAME = "nhAiConsent"
|
|
|
|
|
|
@dataclass
|
|
class ConsentState:
|
|
analytics: bool = False
|
|
advertising: bool = False
|
|
policy_version: int = 0
|
|
timestamp: int = 0
|
|
|
|
@property
|
|
def requires_prompt(self) -> bool:
|
|
return self.policy_version != settings.CONSENT_POLICY_VERSION
|
|
|
|
|
|
class ConsentService:
|
|
@staticmethod
|
|
def get_consent(request) -> ConsentState:
|
|
raw = request.COOKIES.get(CONSENT_COOKIE_NAME, "")
|
|
if not raw:
|
|
return ConsentState()
|
|
|
|
try:
|
|
data = {k: v[0] for k, v in parse_qs(raw).items()}
|
|
return ConsentState(
|
|
analytics=data.get("a", "0") == "1",
|
|
advertising=data.get("d", "0") == "1",
|
|
policy_version=int(data.get("v", "0")),
|
|
timestamp=int(data.get("ts", "0")),
|
|
)
|
|
except (ValueError, AttributeError):
|
|
return ConsentState()
|
|
|
|
@staticmethod
|
|
def set_consent(response, *, analytics: bool, advertising: bool) -> None:
|
|
payload = urlencode(
|
|
{
|
|
"a": int(analytics),
|
|
"d": int(advertising),
|
|
"v": settings.CONSENT_POLICY_VERSION,
|
|
"ts": int(time.time()),
|
|
}
|
|
)
|
|
response.set_cookie(
|
|
CONSENT_COOKIE_NAME,
|
|
payload,
|
|
max_age=60 * 60 * 24 * 365,
|
|
httponly=False,
|
|
samesite="Lax",
|
|
secure=not settings.DEBUG,
|
|
)
|