feat: user invite flow, deactivate/delete, favicon, dashboard loading fix, admin full-width
- Invite flow: admin can invite users by email with role selection; accept-invite page sets password and creates the account; 72-hour token expiry; E2E tests - User deactivate/reactivate/delete: new tRPC procedures + UI buttons; deactivation revokes all active sessions immediately; delete cascades vacation/broadcast records; isActive field added via migration 20260402000000_user_isactive - Auth: block login for inactive users with audit entry - Favicon: SVG favicon + ICO/PNG fallbacks (16, 32, 180, 192, 512px); manifest updated - Dashboard: GridLayout dynamic-import loading skeleton prevents blank dark area on first login before react-grid-layout chunk is cached - Admin users: remove max-w-5xl constraint so table uses full page width - Dev: docker container restart workflow documented in LEARNINGS.md; Prisma generate must run inside the container after schema changes (named node_modules volume) Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -68,7 +68,6 @@ const authConfig = {
|
||||
const user = await prisma.user.findUnique({ where: { email } });
|
||||
if (!user?.passwordHash) {
|
||||
logger.warn({ email, reason: "user_not_found" }, "Failed login attempt");
|
||||
// Audit failed login (unknown user)
|
||||
void createAuditEntry({
|
||||
db: prisma,
|
||||
entityType: "Auth",
|
||||
@@ -81,6 +80,21 @@ const authConfig = {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!user.isActive) {
|
||||
logger.warn({ email, userId: user.id, reason: "account_deactivated" }, "Login blocked — account deactivated");
|
||||
void createAuditEntry({
|
||||
db: prisma,
|
||||
entityType: "Auth",
|
||||
entityId: user.id,
|
||||
entityName: user.email,
|
||||
action: "CREATE",
|
||||
userId: user.id,
|
||||
summary: "Login blocked — account deactivated",
|
||||
source: "ui",
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
const isValid = await verify(user.passwordHash, password);
|
||||
if (!isValid) {
|
||||
logger.warn({ email, reason: "invalid_password" }, "Failed login attempt");
|
||||
|
||||
Reference in New Issue
Block a user