From bbd9f627f53b874deacc42cddeaa0158c38a8880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Ign=C3=A1cio=20Fontoura=20Solla?= Date: Mon, 20 Jul 2026 18:23:23 -0300 Subject: [PATCH] Show a distinct message when campaign login is temporarily locked. Users hitting Payload maxLoginAttempts now see lockout guidance instead of the generic invalid-credentials copy. --- src/app/(campaign)/campanha/actions/auth.ts | 19 ++++++++++++++++--- src/lib/campaignAuthCopy.ts | 6 ++++++ tests/unit/campaignLoginAction.unit.spec.ts | 16 ++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/app/(campaign)/campanha/actions/auth.ts b/src/app/(campaign)/campanha/actions/auth.ts index ff06cbc4..8b6865d2 100644 --- a/src/app/(campaign)/campanha/actions/auth.ts +++ b/src/app/(campaign)/campanha/actions/auth.ts @@ -5,6 +5,10 @@ import { cookies } from 'next/headers' import { redirect } from 'next/navigation' import { getPayload } from 'payload' +import { + CAMPAIGN_ACCOUNT_LOCKED_MESSAGE, + CAMPAIGN_LOGIN_INVALID_CREDENTIALS_MESSAGE, +} from '@/lib/campaignAuthCopy' import { requiredFormSecret, requiredFormText } from '@/lib/formData' import { campaignLoginSchema, type CampaignLoginInput } from '@/lib/schemas/campaign-login' import { @@ -15,6 +19,12 @@ import { export type LoginResult = { error?: string } +const isLockedAuthError = (error: unknown): boolean => + typeof error === 'object' && + error !== null && + 'name' in error && + (error as { name: unknown }).name === 'LockedAuth' + export const loginCampaign = async (input: CampaignLoginInput): Promise => { const parsed = campaignLoginSchema.safeParse(input) @@ -38,12 +48,15 @@ export const loginCampaign = async (input: CampaignLoginInput): Promise { error: 'E-mail, celular ou senha inválidos.', }) }) + + it('returns a distinct message when Payload locks the account', async () => { + const locked = new Error('This user is locked due to having too many failed login attempts.') + locked.name = 'LockedAuth' + mocks.login.mockRejectedValueOnce(locked) + + await expect( + loginCampaign({ + identifier: 'staff@example.com', + password: 'any-password', + }), + ).resolves.toEqual({ + error: + 'Conta temporariamente bloqueada após várias tentativas. Aguarde alguns minutos e tente de novo.', + }) + }) })