import hashlib
import re
import uuid
from datetime import datetime, timedelta, timezone
from pathlib import Path
from fastapi import APIRouter, Depends, File, HTTPException, Query, Request, UploadFile
from pydantic import BaseModel
from sqlalchemy import delete, func, select
from sqlalchemy.ext.asyncio import AsyncSession
from api.depends import get_session, verify_identity_admin
from api.v2.schemas import WebBlockResponse, WebPageResponse, WebPageUpdate, WebTheme
from api.v2.schemas.web import (
WebPageVariantCreate,
WebPageVariantSummary,
WebPageVariantUpdate,
WebPageVariantsResponse,
WebUploadResponse,
)
from database.models import (
WebBlock,
WebCustomElementBuild,
WebErrorReport,
WebFlow,
WebFlowEvent,
WebPage,
WebPageVariant,
WebPageVariantBlock,
WebTheme as WebThemeModel,
)
from logger import logger
UPLOAD_DIR = Path("static/web_uploads")
ALLOWED_EXTENSIONS = frozenset({".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg", ".mp4", ".webm"})
MAX_FILE_SIZE = 100 * 1024 * 1024
_SLUG_RE = re.compile(r"^[a-z0-9][a-z0-9\-]*$")
EXTENSION_CONTENT_TYPES: dict[str, frozenset[str]] = {
".png": frozenset({"image/png"}),
".jpg": frozenset({"image/jpeg"}),
".jpeg": frozenset({"image/jpeg"}),
".gif": frozenset({"image/gif"}),
".webp": frozenset({"image/webp"}),
".svg": frozenset({"image/svg+xml", "text/xml", "application/xml", "text/plain"}),
".mp4": frozenset({"video/mp4"}),
".webm": frozenset({"video/webm"}),
}
def _sanitize_svg(data: bytes) -> bytes:
import re as _re
text = data.decode("utf-8", errors="replace")
text = _re.sub(r"", "", text, flags=_re.DOTALL | _re.IGNORECASE)
text = _re.sub(r"", "", text, flags=_re.DOTALL | _re.IGNORECASE)
text = _re.sub(r"\bon\w+\s*=\s*[\"'][^\"']*[\"']", "", text, flags=_re.IGNORECASE)
text = _re.sub(r"\bon\w+\s*=\s*\S+", "", text, flags=_re.IGNORECASE)
text = _re.sub(r"(?:href|xlink:href)\s*=\s*[\"']\s*javascript:[^\"']*[\"']", "", text, flags=_re.IGNORECASE)
text = _re.sub(r"(?:href|xlink:href)\s*=\s*[\"']\s*data:\s*text/html[^\"']*[\"']", "", text, flags=_re.IGNORECASE)
text = _re.sub(r"(?:href|xlink:href)\s*=\s*[\"']\s*vbscript:[^\"']*[\"']", "", text, flags=_re.IGNORECASE)
text = _re.sub(r"]*>.*?", "", text, flags=_re.DOTALL | _re.IGNORECASE)
text = _re.sub(r"", "", text, flags=_re.DOTALL | _re.IGNORECASE)
text = _re.sub(r"