feat(cmp): Phase 2 — script blocking + cookie tracking
Migration 108: scripts_blocked, scripts_released, cookies_set JSONB columns. Backend models/schema/service/serializer/routes extended. Admin detail modal shows released scripts and set cookies with categories. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -223,6 +223,37 @@ export default function BannerConsentsTab() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Scripts & Cookies */}
|
||||
{(detail.scripts_released?.length > 0 || detail.cookies_set?.length > 0) && (
|
||||
<div className="border-t border-gray-100 pt-3">
|
||||
<p className="text-xs font-semibold text-gray-700 mb-2">Scripts & Cookies</p>
|
||||
{detail.scripts_released?.length > 0 && (
|
||||
<div className="mb-2">
|
||||
<span className="text-gray-500 text-xs">Freigegebene Scripts</span>
|
||||
{detail.scripts_released.map((s, i) => (
|
||||
<p key={i} className="text-xs text-gray-600 font-mono truncate">{s.src} <span className={`px-1 rounded ${categoryColors[s.category] || 'bg-gray-100'}`}>{s.category}</span></p>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{detail.scripts_blocked?.length > 0 && (
|
||||
<div className="mb-2">
|
||||
<span className="text-gray-500 text-xs">Blockierte Scripts</span>
|
||||
{detail.scripts_blocked.map((s, i) => (
|
||||
<p key={i} className="text-xs text-red-600 font-mono truncate">{s.src} <span className="px-1 rounded bg-red-100 text-red-700">{s.category}</span></p>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{detail.cookies_set?.length > 0 && (
|
||||
<div>
|
||||
<span className="text-gray-500 text-xs">Gesetzte Cookies</span>
|
||||
{detail.cookies_set.map((c, i) => (
|
||||
<p key={i} className="text-xs text-gray-600 font-mono">{c.name} <span className="text-gray-400">({c.domain})</span> <span className={`px-1 rounded ${categoryColors[c.category] || 'bg-gray-100'}`}>{c.category}</span></p>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Technische Details */}
|
||||
<div className="border-t border-gray-100 pt-3">
|
||||
<p className="text-xs font-semibold text-gray-700 mb-2">Technisch</p>
|
||||
|
||||
@@ -126,6 +126,10 @@ export interface BannerConsentRecord {
|
||||
os: string | null
|
||||
screen_resolution: string | null
|
||||
session_id: string | null
|
||||
// Script/Cookie-Tracking (Migration 108)
|
||||
scripts_blocked: { src: string; category: string }[]
|
||||
scripts_released: { src: string; category: string }[]
|
||||
cookies_set: { name: string; domain: string; expiry_days: number; category: string }[]
|
||||
expires_at: string | null
|
||||
created_at: string | null
|
||||
updated_at: string | null
|
||||
|
||||
@@ -87,6 +87,9 @@ async def record_consent(
|
||||
screen_resolution=body.screen_resolution,
|
||||
session_id=body.session_id,
|
||||
consent_scope=body.consent_scope,
|
||||
scripts_blocked=body.scripts_blocked,
|
||||
scripts_released=body.scripts_released,
|
||||
cookies_set=body.cookies_set,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -50,6 +50,10 @@ class BannerConsentDB(Base):
|
||||
os = Column(Text)
|
||||
screen_resolution = Column(Text)
|
||||
session_id = Column(Text)
|
||||
# Script/Cookie-Tracking (Migration 108)
|
||||
scripts_blocked = Column(JSON, default=list)
|
||||
scripts_released = Column(JSON, default=list)
|
||||
cookies_set = Column(JSON, default=list)
|
||||
expires_at = Column(DateTime)
|
||||
created_at = Column(DateTime, nullable=False, default=datetime.utcnow)
|
||||
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
@@ -30,6 +30,10 @@ class ConsentCreate(BaseModel):
|
||||
screen_resolution: Optional[str] = None
|
||||
session_id: Optional[str] = None
|
||||
consent_scope: Optional[str] = None
|
||||
# Script/Cookie-Tracking (Migration 108)
|
||||
scripts_blocked: List[dict[str, Any]] = []
|
||||
scripts_released: List[dict[str, Any]] = []
|
||||
cookies_set: List[dict[str, Any]] = []
|
||||
|
||||
|
||||
class SiteConfigCreate(BaseModel):
|
||||
|
||||
@@ -41,6 +41,9 @@ def consent_to_dict(c: BannerConsentDB) -> dict[str, Any]:
|
||||
"os": c.os,
|
||||
"screen_resolution": c.screen_resolution,
|
||||
"session_id": c.session_id,
|
||||
"scripts_blocked": c.scripts_blocked or [],
|
||||
"scripts_released": c.scripts_released or [],
|
||||
"cookies_set": c.cookies_set or [],
|
||||
"expires_at": c.expires_at.isoformat() if c.expires_at else None,
|
||||
"created_at": c.created_at.isoformat() if c.created_at else None,
|
||||
"updated_at": c.updated_at.isoformat() if c.updated_at else None,
|
||||
|
||||
@@ -181,6 +181,9 @@ class BannerConsentService:
|
||||
screen_resolution: Optional[str] = None,
|
||||
session_id: Optional[str] = None,
|
||||
consent_scope: Optional[str] = None,
|
||||
scripts_blocked: Optional[list[dict]] = None,
|
||||
scripts_released: Optional[list[dict]] = None,
|
||||
cookies_set: Optional[list[dict]] = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Upsert a device consent row for (tenant, site, device_fingerprint).
|
||||
|
||||
@@ -213,6 +216,9 @@ class BannerConsentService:
|
||||
"screen_resolution": screen_resolution,
|
||||
"session_id": session_id,
|
||||
"consent_scope": consent_scope or "domain",
|
||||
"scripts_blocked": scripts_blocked or [],
|
||||
"scripts_released": scripts_released or [],
|
||||
"cookies_set": cookies_set or [],
|
||||
}
|
||||
|
||||
existing = (
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
-- Migration 108: Script- und Cookie-Tracking fuer Banner-Consents
|
||||
-- Erfasst welche Scripts blockiert/freigegeben und welche Cookies gesetzt wurden.
|
||||
-- Alle Felder JSONB + nullable → backward-compatible.
|
||||
|
||||
-- Scripts die VOR Consent blockiert waren
|
||||
ALTER TABLE compliance_banner_consents
|
||||
ADD COLUMN IF NOT EXISTS scripts_blocked JSONB DEFAULT '[]'::jsonb;
|
||||
-- [{"src": "https://www.googletagmanager.com/gtag/js", "category": "analytics"}]
|
||||
|
||||
-- Scripts die NACH Consent freigegeben wurden
|
||||
ALTER TABLE compliance_banner_consents
|
||||
ADD COLUMN IF NOT EXISTS scripts_released JSONB DEFAULT '[]'::jsonb;
|
||||
-- [{"src": "https://www.googletagmanager.com/gtag/js", "category": "analytics"}]
|
||||
|
||||
-- Cookies die NACH Consent gesetzt wurden
|
||||
ALTER TABLE compliance_banner_consents
|
||||
ADD COLUMN IF NOT EXISTS cookies_set JSONB DEFAULT '[]'::jsonb;
|
||||
-- [{"name": "_ga", "domain": ".breakpilot.ai", "expiry_days": 730, "category": "analytics"}]
|
||||
Reference in New Issue
Block a user