Files
Joshua Ryder 0126b7e835 fix: Clear IP rate limits when admin unlocks account
When an admin manually unlocks an account, both the account-level
lockout and all IP-based rate limits for the login endpoint are now
cleared. This ensures legitimate users can immediately attempt to
login after being unlocked, without being blocked by stale rate
limit cache entries.

Changes:
- Added clearAllRateLimitsForEndpoint() function to database utils
- Modified unlock endpoint to clear login rate limits after unlocking
- Updated success message to reflect rate limit clearing
- Enhanced logging to track rate limit clearing operations

Fixes issue where users would see "Too many login attempts" message
even with correct credentials after admin unlock, due to persistent
IP rate limit cache from previous failed attempts.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 07:53:36 -05:00

63 lines
1.8 KiB
TypeScript

import { unlockAccount, getUserByUsername, getDatabase, clearAllRateLimitsForEndpoint } from '~/server/utils/database'
import { getSessionUsername } from '~/server/utils/auth'
export default defineEventHandler(async (event) => {
const username = await getSessionUsername(event)
if (!username) {
throw createError({
statusCode: 401,
message: 'Unauthorized'
})
}
const user = getUserByUsername(username)
if (!user || user.is_admin !== 1) {
throw createError({
statusCode: 403,
message: 'Forbidden - Admin access required'
})
}
const id = parseInt(event.context.params?.id || '')
if (isNaN(id)) {
throw createError({
statusCode: 400,
message: 'Invalid user ID'
})
}
// Get target user info
const db = getDatabase()
const targetUser = db.prepare('SELECT username, failed_login_attempts, locked_until FROM users WHERE id = ?')
.get(id) as { username: string, failed_login_attempts: number, locked_until: string | null } | undefined
if (!targetUser) {
throw createError({
statusCode: 404,
message: 'User not found'
})
}
// Unlock the account (resets account-level lockout)
unlockAccount(id)
// Clear ALL IP-based rate limits for the login endpoint
// This ensures the user can immediately attempt to login without being blocked by stale rate limits
clearAllRateLimitsForEndpoint('login')
console.log(`[ACCOUNT UNLOCKED] Admin ${username} unlocked account: ${targetUser.username} and cleared all login rate limits`)
return {
success: true,
message: `Account unlocked successfully. Failed attempts and rate limits have been reset.`,
user: {
username: targetUser.username,
previousAttempts: targetUser.failed_login_attempts,
wasLocked: !!targetUser.locked_until
}
}
})