Files
DumiFlex-ComfyUI-Wildcard-P…/engine/db/migrations_sql/015_content_rating.py
T
DumiFlex 395af63b1a feat(engine): content_rating column on library rows (migration 015)
Adds `content_rating TEXT NOT NULL DEFAULT 'safe'` to modules + bundles.
Defaults all pre-015 rows to 'safe'. Repository create/update accept a
new content_rating kwarg with validation against {'safe', 'nsfw'}.
Importer _insert_module / _insert_bundle pass entity.content_rating
through; _update_module / _update_bundle use COALESCE(?, content_rating)
so an install path that omits the key preserves the existing flag.

Why: user wants two NSFW behaviors:
1. Edit page toggle to mark a module/bundle as NSFW locally.
2. Community posts with content_rating='nsfw' auto-stamp NSFW on
   the local row at install time.

This is the engine half of that work -- the schema, the data
plumbing, and validation. The SPA half (IdentityCard toggle + pill
render on ModuleListView + install.ts plumbing) lands next.

Tests cover: migration head bump to 15, column existence on both
tables, safe default backfill, accepts nsfw, rejects invalid, update
toggle round-trip, update without content_rating preserves prior.
2026-06-06 05:22:02 +03:00

45 lines
1.7 KiB
Python

"""Migration 015 -- content_rating column on library rows.
Adds ``content_rating`` (TEXT, default 'safe') to both ``modules`` and
``bundles``. Stamped by:
- The IdentityCard's NSFW toggle in every editor (user-controlled
flag the author sets on their own row).
- The community install bridge when ``opts.origin.content_rating`` is
supplied -- NSFW community posts auto-stamp the row at install
time, so the SPA can render the ``18+`` pill without an extra
fetch.
Default 'safe' means rows that pre-date this migration (every
locally-authored row prior to v2.3) end up marked safe. Toggle to
'nsfw' if needed. No CHECK constraint at the DB level (SQLite ALTER
TABLE does not support adding CHECK); validation happens at the
application layer (``set_content_rating``).
Idempotent: each ALTER is gated on ``PRAGMA table_info``. The
migration runner's version table is the primary re-run guard; the
column check exists for test fixtures that rewind ``migrations``.
"""
from __future__ import annotations
import sqlite3
def _has_column(conn: sqlite3.Connection, table: str, column: str) -> bool:
cur = conn.execute(f"PRAGMA table_info({table});")
return any(row[1] == column for row in cur.fetchall())
def up(conn: sqlite3.Connection) -> None:
with conn:
if not _has_column(conn, "modules", "content_rating"):
conn.execute(
"ALTER TABLE modules ADD COLUMN content_rating TEXT "
"NOT NULL DEFAULT 'safe';"
)
if not _has_column(conn, "bundles", "content_rating"):
conn.execute(
"ALTER TABLE bundles ADD COLUMN content_rating TEXT "
"NOT NULL DEFAULT 'safe';"
)