Add user disable and permanent delete for system admins

- Added disabledAt column to users table
- Disabled users are blocked at login and session validation (immediate logout)
- Admin users page shows Active/Disabled status badges
- Disable/Enable toggle button per user (kills all sessions on disable)
- Permanent delete with confirmation modal (removes user, sessions, memberships)
- Self-protection: admins cannot disable or delete themselves

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-06 13:14:03 +07:00
parent d58443ed73
commit 1c7166adc5
5 changed files with 152 additions and 14 deletions
+8 -1
View File
@@ -60,7 +60,8 @@ export async function validateSession(
email: users.email,
username: users.username,
displayName: users.displayName,
isSystemAdmin: users.isSystemAdmin
isSystemAdmin: users.isSystemAdmin,
disabledAt: users.disabledAt
}
})
.from(sessions)
@@ -74,6 +75,12 @@ export async function validateSession(
const { session, user } = result[0];
// Disabled user — kill session
if (user.disabledAt) {
await db.delete(sessions).where(eq(sessions.id, sessionId));
return { session: null, user: null };
}
// Session expired
if (Date.now() >= session.expiresAt.getTime()) {
await db.delete(sessions).where(eq(sessions.id, sessionId));
+1
View File
@@ -31,6 +31,7 @@ export const users = pgTable(
oidcProvider: text('oidc_provider'),
oidcSubject: text('oidc_subject'),
isSystemAdmin: boolean('is_system_admin').notNull().default(false),
disabledAt: timestamp('disabled_at', { withTimezone: true }),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow()
},