From 0b9a42c7f34b670066c97bbcbe255b7124bf6906 Mon Sep 17 00:00:00 2001 From: JamesFlare1212 Date: Mon, 6 Apr 2026 18:25:52 -0400 Subject: [PATCH] fix(auth): add login lock to prevent concurrent Playwright login attempts --- engage-api/get-activity.ts | 7 ++++--- services/playwright-auth.ts | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/engage-api/get-activity.ts b/engage-api/get-activity.ts index dede196..5d333b2 100644 --- a/engage-api/get-activity.ts +++ b/engage-api/get-activity.ts @@ -3,6 +3,7 @@ import axios from 'axios'; import { logger } from '../utils/logger'; import { loginWithPlaywright, + ensureSingleLogin, loadCachedCookies, saveCookiesToCache, clearCookieCache, @@ -90,18 +91,18 @@ async function testCookieValidityWithApi(cookieString: string): Promise } /** - * Get complete cookies using Playwright + * Get complete cookies using Playwright with single login lock */ async function getCompleteCookies(userName: string, userPwd: string): Promise { logger.info('Attempting to get complete cookie string using Playwright login...'); - const cookies = await loginWithPlaywright(userName, userPwd); + const cookies = await ensureSingleLogin(userName, userPwd); if (!cookies || cookies.length === 0) { throw new Error("Login failed: Could not obtain cookies."); } - const cookieString = cookies.map(c => `${c.name}=${c.value}`).join('; '); + const cookieString = cookies.map((c: any) => `${c.name}=${c.value}`).join('; '); return cookieString; } diff --git a/services/playwright-auth.ts b/services/playwright-auth.ts index 5f57bb5..6045b4b 100644 --- a/services/playwright-auth.ts +++ b/services/playwright-auth.ts @@ -8,10 +8,35 @@ const COOKIE_FILE_PATH = resolve(import.meta.dir, 'cookies.json'); let _inMemoryCookies: Cookie[] | null = null; +// Login lock to prevent concurrent login attempts +let _loginLock: Promise | null = null; + // Proxy configuration const USE_PROXY = process.env.USE_PROXY === 'true'; const PROXY_SERVER = process.env.ALL_PROXY || process.env.HTTP_PROXY || `http://host.docker.internal:9091`; +/** + * Ensure only one login process runs at a time + */ +export async function ensureSingleLogin(username: string, password: string): Promise { + // Wait for any existing login to complete + if (_loginLock) { + logger.info('Login in progress, waiting for existing login to complete...'); + await _loginLock; + } + + // Create new lock promise for this login attempt + _loginLock = (async () => { + try { + return await loginWithPlaywright(username, password); + } finally { + _loginLock = null; + } + })(); + + return await _loginLock; +} + /** * Login using Playwright and extract cookies */