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.
60 lines
1.6 KiB
Python
60 lines
1.6 KiB
Python
import uuid
|
|
from datetime import UTC, datetime, timedelta
|
|
|
|
import bcrypt
|
|
from jose import jwt
|
|
|
|
from src.config.settings import get_settings
|
|
|
|
|
|
def hash_password(password: str) -> str:
|
|
return bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode()
|
|
|
|
|
|
def verify_password(plain_password: str, hashed_password: str) -> bool:
|
|
return bcrypt.checkpw(plain_password.encode(), hashed_password.encode())
|
|
|
|
|
|
def create_access_token(
|
|
user_id: uuid.UUID,
|
|
organisation_id: uuid.UUID,
|
|
role: str,
|
|
email: str,
|
|
) -> str:
|
|
settings = get_settings()
|
|
now = datetime.now(UTC)
|
|
expire = now + timedelta(minutes=settings.jwt_access_token_expire_minutes)
|
|
payload = {
|
|
"sub": str(user_id),
|
|
"org_id": str(organisation_id),
|
|
"role": role,
|
|
"email": email,
|
|
"exp": expire,
|
|
"iat": now,
|
|
"type": "access",
|
|
}
|
|
return jwt.encode(payload, settings.jwt_secret_key, algorithm=settings.jwt_algorithm)
|
|
|
|
|
|
def create_refresh_token(
|
|
user_id: uuid.UUID,
|
|
organisation_id: uuid.UUID,
|
|
) -> str:
|
|
settings = get_settings()
|
|
now = datetime.now(UTC)
|
|
expire = now + timedelta(days=settings.jwt_refresh_token_expire_days)
|
|
payload = {
|
|
"sub": str(user_id),
|
|
"org_id": str(organisation_id),
|
|
"exp": expire,
|
|
"iat": now,
|
|
"type": "refresh",
|
|
}
|
|
return jwt.encode(payload, settings.jwt_secret_key, algorithm=settings.jwt_algorithm)
|
|
|
|
|
|
def decode_token(token: str) -> dict:
|
|
"""Decode and validate a JWT token. Raises JWTError on failure."""
|
|
settings = get_settings()
|
|
return jwt.decode(token, settings.jwt_secret_key, algorithms=[settings.jwt_algorithm])
|