feat(internal-admin): user lifecycle — suspend / reactivate / ban
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Süper Panel Phase 7 — Phase B. Founder can suspend, reactivate, or ban a
Sase user from the panel. Status enforced in the AuthGuard so blocked
users can no longer make authenticated requests.
Schema (migration 0006)
- users.status varchar(20) default 'active' — active|suspended|banned
- users.status_reason text — free-text reason set on transition
- users.status_changed_at, status_changed_by uuid — audit metadata
- users_status_idx
Auth
- AuthGuard rejects 'suspended' / 'banned' with TR-localized message.
- auth.ts: declared `status` as a Better Auth additionalField so the
session.user object exposes it (matches how `role` is wired).
Endpoints (InternalTokenGuard)
- POST /internal/admin/users/:id/suspend { reason, founderId }
- POST /internal/admin/users/:id/reactivate { founderId }
- POST /internal/admin/users/:id/ban { reason, founderId }
Service
- LifecycleService.setStatus():
- refuses to touch admin-role users
- refuses no-op transitions (already in target state)
- refuses suspended→banned→suspended downgrade path (must reactivate first)
- on suspend/ban: deletes all sessions for the user (immediate sign-out)
- returns { from, to, sessionsKilled, changedAt }
Wiring
- LifecycleService + LifecycleController added to InternalAdminModule.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -36,6 +36,17 @@ export class AuthGuard implements CanActivate {
|
||||
throw new UnauthorizedException("Kimlik doğrulama gerekli");
|
||||
}
|
||||
|
||||
// Süper Panel admin lifecycle controls: block non-active users.
|
||||
// The status column is added by migration 0006; tolerate older rows by
|
||||
// treating missing/empty as "active".
|
||||
const status = (session.user as { status?: string }).status ?? "active";
|
||||
if (status === "suspended") {
|
||||
throw new UnauthorizedException("Hesabınız askıya alınmıştır. Destek ile iletişime geçin.");
|
||||
}
|
||||
if (status === "banned") {
|
||||
throw new UnauthorizedException("Hesabınız kapatılmıştır.");
|
||||
}
|
||||
|
||||
request.user = session.user;
|
||||
request.session = session.session;
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user