feat(sase): user lifecycle controls — Phase B

Suspend / Reactivate / Ban buttons on the user detail page; wired to
spoke endpoints (sase.tr#27).

Admin SDK
- suspendUser/reactivateUser/banUser on SaseAdmin + LifecycleResult.
- SASE_ADMIN_ENDPOINTS updated.

Route
- POST /api/sase/users/[id]/lifecycle (action + reason). Auth + spoke
  wired + min reason length checks. Audit on both success and failure.

RO model
- Sase Prisma schema adds status/statusReason/statusChangedAt/
  statusChangedBy. getUser() returns lifecycleStatus + statusReason.

UI
- LifecycleStatusBadge in header next to email reveal.
- LifecycleButtons renders the right actions for the current state.
- Modals with reason textarea; ban requires a double-confirm checkbox.
- Impersonate hidden when user is suspended/banned (AuthGuard rejects).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Semih
2026-05-18 09:38:07 +03:00
parent 5b26d10485
commit b1ec7a5277
6 changed files with 345 additions and 11 deletions

View File

@@ -13,16 +13,20 @@ datasource db {
}
model User {
id String @id @default(uuid()) @db.Uuid
name String @db.VarChar(255)
email String @unique @db.VarChar(255)
emailVerified Boolean @default(false) @map("email_verified")
role String @default("user") @db.VarChar(20)
image String?
referralCode String? @map("referral_code") @db.VarChar(20)
referredBy String? @map("referred_by") @db.Uuid
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamptz(6)
id String @id @default(uuid()) @db.Uuid
name String @db.VarChar(255)
email String @unique @db.VarChar(255)
emailVerified Boolean @default(false) @map("email_verified")
role String @default("user") @db.VarChar(20)
status String @default("active") @db.VarChar(20)
statusReason String? @map("status_reason")
statusChangedAt DateTime? @map("status_changed_at") @db.Timestamptz(6)
statusChangedBy String? @map("status_changed_by") @db.Uuid
image String?
referralCode String? @map("referral_code") @db.VarChar(20)
referredBy String? @map("referred_by") @db.Uuid
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamptz(6)
subscriptions UserSubscription[]
payments Payment[]