fix(teamsbot): unblock WS loop for MFA so mfaResolved can close the modal

Made-with: Cursor
This commit is contained in:
patrick-motsch 2026-03-01 11:15:39 +01:00
parent 13e39ccc74
commit d1e081cf98
2 changed files with 36 additions and 22 deletions

View file

@ -786,6 +786,7 @@ async def deleteUserAccount(
# =========================================================================
_mfaCodeQueues: dict = {}
_mfaWaitTasks: dict = {}
@router.post("/{instanceId}/sessions/{sessionId}/mfa")
@limiter.limit("10/minute")

View file

@ -396,35 +396,48 @@ class TeamsbotService:
"timestamp": getIsoTimestamp(),
})
from .routeFeatureTeamsbot import _mfaCodeQueues
from .routeFeatureTeamsbot import _mfaCodeQueues, _mfaWaitTasks
mfaQueue = asyncio.Queue()
_mfaCodeQueues[sessionId] = mfaQueue
try:
mfaResponse = await asyncio.wait_for(mfaQueue.get(), timeout=120.0)
logger.info(f"[WS] MFA response received for session {sessionId}: action={mfaResponse.get('action')}")
await websocket.send_text(json.dumps({
"type": "mfaResponse",
"sessionId": sessionId,
"mfa": mfaResponse,
}))
except asyncio.TimeoutError:
logger.warning(f"[WS] MFA response timeout for session {sessionId}")
await websocket.send_text(json.dumps({
"type": "mfaResponse",
"sessionId": sessionId,
"mfa": {"action": "timeout"},
}))
await _emitSessionEvent(sessionId, "mfaChallenge", {
"mfaType": "timeout",
"prompt": "MFA-Zeitlimit ueberschritten. Bitte erneut versuchen.",
})
finally:
_mfaCodeQueues.pop(sessionId, None)
async def _waitAndForwardMfa(sid, queue, ws):
try:
mfaResponse = await asyncio.wait_for(queue.get(), timeout=120.0)
logger.info(f"[WS] MFA response received for session {sid}: action={mfaResponse.get('action')}")
await ws.send_text(json.dumps({
"type": "mfaResponse",
"sessionId": sid,
"mfa": mfaResponse,
}))
except asyncio.TimeoutError:
logger.warning(f"[WS] MFA response timeout for session {sid}")
await ws.send_text(json.dumps({
"type": "mfaResponse",
"sessionId": sid,
"mfa": {"action": "timeout"},
}))
await _emitSessionEvent(sid, "mfaChallenge", {
"mfaType": "timeout",
"prompt": "MFA-Zeitlimit ueberschritten. Bitte erneut versuchen.",
})
except asyncio.CancelledError:
logger.info(f"[WS] MFA wait cancelled for session {sid} (resolved via page)")
finally:
_mfaCodeQueues.pop(sid, None)
_mfaWaitTasks.pop(sid, None)
_mfaWaitTasks[sessionId] = asyncio.create_task(
_waitAndForwardMfa(sessionId, mfaQueue, websocket)
)
elif msgType == "mfaResolved":
success = message.get("success", False)
logger.info(f"[WS] MFA resolved: success={success}")
from .routeFeatureTeamsbot import _mfaCodeQueues, _mfaWaitTasks
task = _mfaWaitTasks.pop(sessionId, None)
if task and not task.done():
task.cancel()
_mfaCodeQueues.pop(sessionId, None)
await _emitSessionEvent(sessionId, "mfaResolved", {
"success": success,
"timestamp": getIsoTimestamp(),