Files
klz-cables.com/.pnpm-store/v10/files/7d/1b30048f7abcfbd4f9e403a062d681818b077a61a57b5a44e8ea96ce5c8e6ce20167d10fcbf99c4a7dc8f88202b499074f0d01075dbc8fdd542b589432b727
Marc Mintel 5397309103
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
fix(products): fix breadcrumbs and product filtering (backport from main)
2026-02-24 16:04:21 +01:00

1 line
8.0 KiB
Plaintext

{"version":3,"sources":["../../../../src/auth/strategies/local/incrementLoginAttempts.ts"],"sourcesContent":["import type { SanitizedCollectionConfig } from '../../../collections/config/types.js'\n\nimport { type JsonObject, type Payload, type TypedUser } from '../../../index.js'\nimport { isUserLocked } from '../../isUserLocked.js'\n\ntype Args = {\n collection: SanitizedCollectionConfig\n payload: Payload\n user: TypedUser\n}\n\n// Note: this function does not use req in its updates, as we want those to be visible in parallel requests that are on a different\n// transaction. At the same time, we want updates from parallel requests to be visible here.\nexport const incrementLoginAttempts = async ({\n collection,\n payload,\n user,\n}: Args): Promise<void> => {\n const {\n auth: { lockTime, maxLoginAttempts },\n } = collection\n\n const currentTime = Date.now()\n\n let updatedLockUntil: null | string = null\n let updatedLoginAttempts: null | number = null\n\n if (user.lockUntil && !isUserLocked(new Date(user.lockUntil))) {\n // Expired lock, restart count at 1\n const updatedUser = await payload.db.updateOne({\n id: user.id,\n collection: collection.slug,\n data: {\n lockUntil: null,\n loginAttempts: 1,\n },\n select: {\n lockUntil: true,\n loginAttempts: true,\n },\n })\n updatedLockUntil = updatedUser.lockUntil\n updatedLoginAttempts = updatedUser.loginAttempts\n user.lockUntil = updatedLockUntil\n } else {\n const data: JsonObject = {\n loginAttempts: {\n $inc: 1,\n },\n }\n\n const willReachMaxAttempts =\n typeof user.loginAttempts === 'number' && user.loginAttempts + 1 >= maxLoginAttempts\n // Lock the account if at max attempts and not already locked\n if (willReachMaxAttempts) {\n const lockUntil = new Date(currentTime + lockTime).toISOString()\n data.lockUntil = lockUntil\n }\n\n const updatedUser = await payload.db.updateOne({\n id: user.id,\n collection: collection.slug,\n data,\n select: {\n lockUntil: true,\n loginAttempts: true,\n },\n })\n\n updatedLockUntil = updatedUser.lockUntil\n updatedLoginAttempts = updatedUser.loginAttempts\n }\n\n if (updatedLoginAttempts === null) {\n throw new Error('Failed to update login attempts or lockUntil for user')\n }\n\n // Check updated latest lockUntil and loginAttempts in case there were parallel updates\n const reachedMaxAttemptsForCurrentUser =\n typeof updatedLoginAttempts === 'number' && updatedLoginAttempts - 1 >= maxLoginAttempts\n\n const reachedMaxAttemptsForNextUser =\n typeof updatedLoginAttempts === 'number' && updatedLoginAttempts >= maxLoginAttempts\n\n if (reachedMaxAttemptsForCurrentUser) {\n user.lockUntil = updatedLockUntil\n }\n user.loginAttempts = updatedLoginAttempts - 1 // -1, as the updated increment is applied for the *next* login attempt, not the current one\n\n if (\n reachedMaxAttemptsForNextUser &&\n (!updatedLockUntil || !isUserLocked(new Date(updatedLockUntil)))\n ) {\n // If lockUntil reached max login attempts due to multiple parallel attempts but user was not locked yet,\n const newLockUntil = new Date(currentTime + lockTime).toISOString()\n\n await payload.db.updateOne({\n id: user.id,\n collection: collection.slug,\n data: {\n lockUntil: newLockUntil,\n },\n returning: false,\n })\n\n if (reachedMaxAttemptsForCurrentUser) {\n user.lockUntil = newLockUntil\n }\n\n if (collection.auth.useSessions) {\n // Remove all active sessions that have been created in a 20 second window. This protects\n // against brute force attacks - example: 99 incorrect, 1 correct parallel login attempts.\n // The correct login attempt will be finished first, as it's faster due to not having to perform\n // an additional db update here.\n // However, this request (the incorrect login attempt request) can kill the successful login attempt here.\n\n // Fetch user sessions separately (do not do this in the updateOne select in order to preserve the returning: true db call optimization)\n const currentUser = await payload.db.findOne<TypedUser>({\n collection: collection.slug,\n select: {\n sessions: true,\n },\n where: {\n id: {\n equals: user.id,\n },\n },\n })\n if (currentUser?.sessions?.length) {\n // Does not hurt also removing expired sessions\n currentUser.sessions = currentUser.sessions.filter((session) => {\n const sessionCreatedAt = new Date(session.createdAt)\n const twentySecondsAgo = new Date(currentTime - 20000)\n\n // Remove sessions created within the last 20 seconds\n return sessionCreatedAt <= twentySecondsAgo\n })\n\n user.sessions = currentUser.sessions\n\n // Ensure updatedAt date is always updated\n user.updatedAt = new Date().toISOString()\n\n await payload.db.updateOne({\n id: user.id,\n collection: collection.slug,\n data: user,\n returning: false,\n })\n }\n }\n }\n}\n"],"names":["isUserLocked","incrementLoginAttempts","collection","payload","user","auth","lockTime","maxLoginAttempts","currentTime","Date","now","updatedLockUntil","updatedLoginAttempts","lockUntil","updatedUser","db","updateOne","id","slug","data","loginAttempts","select","$inc","willReachMaxAttempts","toISOString","Error","reachedMaxAttemptsForCurrentUser","reachedMaxAttemptsForNextUser","newLockUntil","returning","useSessions","currentUser","findOne","sessions","where","equals","length","filter","session","sessionCreatedAt","createdAt","twentySecondsAgo","updatedAt"],"mappings":"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"}