chahinebrini 29c5d9c8e5 feat(admin): Phase 2 Backend — Users + Moderation endpoints + 2 schema migrations
Two parallel agent-batches consolidated:

USERS-MGMT (rebreak-backend agent):
- Schema: Profile gets banned, bannedAt, bannedReason, deletedAt + indexes
- Migration: 20260509_profile_admin_management (additive, idempotent)
- DB-layer backend/server/db/adminUsers.ts:
  listAdminUsers (cursor-pagination, search, plan-filter)
  updateAdminUser (plan-validation, ban-stamping)
  softDeleteAdminUser (DSGVO PII-scrub: nickname=null, email=deleted-{shortid}@deleted.local)
- 3 endpoints under /api/admin/users:
  GET (list with ?cursor&limit&q&plan&includeDeleted)
  PATCH /:id (plan/banned/bannedReason/lyraVoiceId)
  DELETE /:id (soft-delete idempotent)
- 12 tests passing

MODERATION (rebreak-backend agent):
- Schema: CommunityPost+CommunityReply get isModerated, isDeleted, deletedAt,
  reportedAt + index (is_moderated, reported_at)
- New ModerationAction model → audit-log table
- Migration: 20260509_moderation_queue (additive, idempotent)
- DB-layer backend/server/db/moderation.ts:
  listModerationQueue (merge posts+comments, sort by reportedAt, cursor)
  dismissModerationItem
  deleteModerationItem (content scrub + audit snapshot)
  banUserFromModerationItem (reuses banned/bannedAt/bannedReason fields)
- 4 endpoints under /api/admin/moderation:
  GET /queue, POST /:id/dismiss, POST /:id/delete, POST /:id/ban-user
- 11 tests passing

Backend total: 78 tests passing | 4 skipped (pre-existing requireAdmin tests)

Auth: x-admin-secret header (consistent with existing /admin/* endpoints).

DSGVO:
- Soft-delete scrubt PII statt hard-delete
- Email NICHT in admin user-list (lebt nur in auth.users)
- Audit-log für moderation-actions (90-day cleanup-cron pending hans-mueller-DSB-review)

⚠️ MIGRATIONS — auto-deploy via pipeline (commit b38bf17 detection):
- 20260509_profile_admin_management
- 20260509_moderation_queue

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 15:46:44 +02:00

26 lines
1.3 KiB
SQL

-- Profile Admin Management — Phase E
-- Felder für Admin-User-Management:
-- * banned → BOOLEAN, default false
-- * banned_at → TIMESTAMP, gesetzt wenn banned=true
-- * banned_reason → TEXT, optional Note vom Admin
-- * deleted_at → TIMESTAMP, soft-delete (DSGVO Art. 17, scrubbed PII)
--
-- Soft-Delete-Strategie:
-- nickname → NULL, username → 'deleted-{shortid}', avatar → NULL,
-- demographics → cleared. auth.users-Eintrag bleibt zunächst (manueller
-- Hard-Delete via Supabase-Admin-API in separater Operation).
--
-- Drift-Hinweis: Diese Migration wird via `pnpm prisma migrate deploy` auf
-- staging-/prod-DB gefahren. Lokal NICHT ausführen. Falls Drift erkannt wird:
-- pnpm prisma migrate resolve --applied 20260509_profile_admin_management
ALTER TABLE "rebreak"."profiles"
ADD COLUMN IF NOT EXISTS "banned" BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN IF NOT EXISTS "banned_at" TIMESTAMP(3),
ADD COLUMN IF NOT EXISTS "banned_reason" TEXT,
ADD COLUMN IF NOT EXISTS "deleted_at" TIMESTAMP(3);
-- Performance: Admin-User-Liste filtert oft auf nicht-gelöschte / nicht-gebannte
CREATE INDEX IF NOT EXISTS "profiles_deleted_at_idx" ON "rebreak"."profiles" ("deleted_at");
CREATE INDEX IF NOT EXISTS "profiles_plan_idx" ON "rebreak"."profiles" ("plan");