diff --git a/server/api/users/unlock/[id].post.ts b/server/api/users/unlock/[id].post.ts index c5a6bcc..1d08f57 100644 --- a/server/api/users/unlock/[id].post.ts +++ b/server/api/users/unlock/[id].post.ts @@ -1,4 +1,4 @@ -import { unlockAccount, getUserByUsername, getDatabase } from '~/server/utils/database' +import { unlockAccount, getUserByUsername, getDatabase, clearAllRateLimitsForEndpoint } from '~/server/utils/database' import { getSessionUsername } from '~/server/utils/auth' export default defineEventHandler(async (event) => { @@ -41,14 +41,18 @@ export default defineEventHandler(async (event) => { }) } - // Unlock the account + // Unlock the account (resets account-level lockout) unlockAccount(id) - console.log(`[ACCOUNT UNLOCKED] Admin ${username} unlocked account: ${targetUser.username}`) + // 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 reset to 0.`, + message: `Account unlocked successfully. Failed attempts and rate limits have been reset.`, user: { username: targetUser.username, previousAttempts: targetUser.failed_login_attempts, diff --git a/server/utils/database.ts b/server/utils/database.ts index 392f6fb..988fad9 100644 --- a/server/utils/database.ts +++ b/server/utils/database.ts @@ -600,6 +600,17 @@ export function resetRateLimit(identifier: string, endpoint: string) { .run(identifier, endpoint) } +/** + * Clear all rate limits for a specific endpoint + * Used when admin performs actions that should clear all rate limiting (e.g., unlocking accounts) + */ +export function clearAllRateLimitsForEndpoint(endpoint: string) { + const db = getDatabase() + const result = db.prepare('DELETE FROM rate_limits WHERE endpoint = ?').run(endpoint) + console.log(`[RATE LIMIT CLEARED] Cleared ${result.changes} rate limit entries for endpoint: ${endpoint}`) + return result +} + // Settings management functions export function getSetting(key: string) { const db = getDatabase()