MediaRouter / app /social /oauth /encryption.py
basyx's picture
Upload 236 files
e1104b3 verified
Raw
History Blame Contribute Delete
1.45 kB
from __future__ import annotations
import base64
import hashlib
import json
from typing import Any
from app.social.domain.errors import SocialProviderUnavailableError
class TokenCipher:
"""Narrow encryption boundary for non-Vault local development.
Imports cryptography lazily so provider discovery and existing media APIs
still start when social token storage is unused. Production should use
Supabase Vault references instead of this encrypted database fallback.
"""
def __init__(self, key: str | None) -> None:
self._key = key
def _fernet(self):
if not self._key:
raise SocialProviderUnavailableError(
"SOCIAL_OAUTH_ENCRYPTION_KEY is required when Supabase Vault is disabled."
)
try:
from cryptography.fernet import Fernet
except ImportError as exc:
raise SocialProviderUnavailableError("The cryptography package is required for token storage.") from exc
digest = hashlib.sha256(self._key.encode("utf-8")).digest()
return Fernet(base64.urlsafe_b64encode(digest))
def encrypt(self, value: dict[str, Any]) -> str:
return self._fernet().encrypt(json.dumps(value, separators=(",", ":")).encode()).decode()
def decrypt(self, value: str) -> dict[str, Any]:
result = json.loads(self._fernet().decrypt(value.encode()).decode())
return result if isinstance(result, dict) else {}