ConsentOS — a privacy-first cookie consent management platform. Self-hosted, source-available alternative to OneTrust, Cookiebot, and CookieYes. Full standards coverage (IAB TCF v2.2, GPP v1, Google Consent Mode v2, GPC, Shopify Customer Privacy API), multi-tenant architecture with role-based access, configuration cascade (system → org → group → site → region), dark-pattern detection in the scanner, and a tamper-evident consent record audit trail. This is the initial public release. Prior development history is retained internally. See README.md for the feature list, architecture overview, and quick-start instructions. Licensed under the Elastic Licence 2.0 — self-host freely; do not resell as a managed service.
49 lines
2.0 KiB
Python
49 lines
2.0 KiB
Python
import uuid
|
|
|
|
from sqlalchemy import ForeignKey, String, UniqueConstraint
|
|
from sqlalchemy.dialects.postgresql import ARRAY, UUID
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from src.models.base import Base, SoftDeleteMixin, TimestampMixin, UUIDPrimaryKeyMixin
|
|
|
|
|
|
class Site(UUIDPrimaryKeyMixin, TimestampMixin, SoftDeleteMixin, Base):
|
|
"""A domain being managed for cookie consent, belongs to an organisation."""
|
|
|
|
__tablename__ = "sites"
|
|
__table_args__ = (UniqueConstraint("organisation_id", "domain", name="uq_sites_org_domain"),)
|
|
|
|
organisation_id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True),
|
|
ForeignKey("organisations.id", ondelete="CASCADE"),
|
|
nullable=False,
|
|
index=True,
|
|
)
|
|
domain: Mapped[str] = mapped_column(String(255), nullable=False, index=True)
|
|
display_name: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
is_active: Mapped[bool] = mapped_column(default=True, nullable=False)
|
|
additional_domains: Mapped[list[str] | None] = mapped_column(
|
|
ARRAY(String(255)), nullable=True, server_default=None
|
|
)
|
|
site_group_id: Mapped[uuid.UUID | None] = mapped_column(
|
|
UUID(as_uuid=True),
|
|
ForeignKey("site_groups.id", ondelete="SET NULL"),
|
|
nullable=True,
|
|
index=True,
|
|
)
|
|
|
|
# Relationships
|
|
organisation: Mapped["Organisation"] = relationship(back_populates="sites") # noqa: F821
|
|
site_group: Mapped["SiteGroup | None"] = relationship(back_populates="sites") # noqa: F821
|
|
config: Mapped["SiteConfig | None"] = relationship( # noqa: F821
|
|
back_populates="site", uselist=False
|
|
)
|
|
cookies: Mapped[list["Cookie"]] = relationship(back_populates="site") # noqa: F821
|
|
cookie_allow_list: Mapped[list["CookieAllowListEntry"]] = relationship( # noqa: F821
|
|
back_populates="site"
|
|
)
|
|
scan_jobs: Mapped[list["ScanJob"]] = relationship(back_populates="site") # noqa: F821
|
|
translations: Mapped[list["Translation"]] = relationship( # noqa: F821
|
|
back_populates="site"
|
|
)
|