WIP checkpoint: Trust & Safety: Moderation data model + Alembic migration

This commit is contained in:
2026-08-18 18:48:01 +00:00
parent 10764a3546
commit 1dacc2a684
+29 -6
View File
@@ -18,16 +18,40 @@ branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None
def _create_enum_if_not_exists(enum_name: str, values: list[str]) -> None:
"""Create a PostgreSQL ENUM type if it does not already exist."""
bind = op.get_bind()
# Check if the type already exists in pg_type
result = bind.execute(
sa.text(
"SELECT 1 FROM pg_type WHERE typname = :name"
).bindparams(name=enum_name)
).fetchone()
if result is None:
values_str = ", ".join(f"'{v}'" for v in values)
op.execute(f"CREATE TYPE {enum_name} AS ENUM ({values_str})")
def upgrade() -> None: def upgrade() -> None:
"""Add role, banned_until, suspended_until to users table """Add role, banned_until, suspended_until to users table
and create reports, moderation_actions, appeals tables.""" and create reports, moderation_actions, appeals tables."""
# --- Create ENUM types if they don't exist ---
_create_enum_if_not_exists("user_role", ["user", "moderator", "admin"])
_create_enum_if_not_exists("report_target_type", ["user", "world", "asset", "chat_message"])
_create_enum_if_not_exists("report_reason_category", [
"harassment", "hate_speech", "sexual_content",
"violence", "spam", "self_harm", "other"
])
_create_enum_if_not_exists("report_status", ["open", "in_review", "resolved", "dismissed"])
_create_enum_if_not_exists("report_resolution", ["warn", "suspend", "ban", "restrict", "remove"])
_create_enum_if_not_exists("moderation_target_type", ["user", "world", "asset", "chat_message"])
_create_enum_if_not_exists("moderation_action_type", ["warn", "suspend", "ban", "restrict", "remove", "restore"])
_create_enum_if_not_exists("appeal_status", ["pending", "approved", "rejected"])
# --- Extend users table --- # --- Extend users table ---
# Add role column as ENUM # Add role column
op.execute(
"CREATE TYPE user_role AS ENUM ('user', 'moderator', 'admin')"
)
op.add_column( op.add_column(
"users", "users",
sa.Column( sa.Column(
@@ -176,9 +200,8 @@ def downgrade() -> None:
op.drop_column("users", "banned_until") op.drop_column("users", "banned_until")
op.drop_column("users", "role") op.drop_column("users", "role")
# Drop the user_role enum type # Drop the enum types
op.execute("DROP TYPE IF EXISTS user_role") op.execute("DROP TYPE IF EXISTS user_role")
# Drop other enum types created
op.execute("DROP TYPE IF EXISTS report_target_type") op.execute("DROP TYPE IF EXISTS report_target_type")
op.execute("DROP TYPE IF EXISTS report_reason_category") op.execute("DROP TYPE IF EXISTS report_reason_category")
op.execute("DROP TYPE IF EXISTS report_status") op.execute("DROP TYPE IF EXISTS report_status")