fix: load system bot credentials from DB and pass to browser bot for authenticated join

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
patrick-motsch 2026-02-17 19:58:01 +01:00
parent ad254aafb1
commit a3c92ae8d5
2 changed files with 41 additions and 17 deletions

View file

@ -195,20 +195,41 @@ async def startSession(
userId = str(context.user.id)
effectiveConfig = _getEffectiveConfig(instanceId, userId, interface)
# Determine effective join mode and bot name.
# NOTE: Authentication is currently disabled. The bot always joins as an anonymous
# guest with the system bot's display name. See Teamsbot-Auth-Join-Learnings.md.
# Credentials are NOT sent to the browser bot.
# Determine effective join mode, bot name, and credentials
joinMode = body.joinMode or TeamsbotJoinMode.ANONYMOUS
effectiveBotName = body.botName
botAccountEmail = None
botAccountPassword = None
# If a system bot exists, use its display name as the bot name (e.g. "Nyla Larsson")
# Load system bot from DB (try mandate-specific first, then any active bot)
systemBot = interface.getActiveSystemBot(mandateId)
if not systemBot:
from .datamodelTeamsbot import TeamsbotSystemBot
allBots = interface.db.getRecordset(TeamsbotSystemBot, recordFilter={"isActive": True})
if allBots:
systemBot = allBots[0]
logger.info(f"No mandate-specific system bot, using fallback: {systemBot.get('name')} ({systemBot.get('email')})")
if systemBot:
if not effectiveBotName:
effectiveBotName = systemBot.get("name") or effectiveConfig.botName
logger.info(f"System bot found: {systemBot.get('name')} ({systemBot.get('email')}), using name: {effectiveBotName}")
logger.info(f"System bot found: {systemBot.get('name')} ({systemBot.get('email')})")
# Load and decrypt credentials for authenticated join
botAccountEmail = systemBot.get("email")
encryptedPwd = systemBot.get("encryptedPassword")
if botAccountEmail and encryptedPwd:
try:
from modules.shared.configuration import decryptValue
botAccountPassword = decryptValue(encryptedPwd, userId=str(context.user.id), keyName="systemBotPassword")
logger.info(f"System bot credentials loaded and decrypted for: {botAccountEmail}")
except Exception as e:
logger.warning(f"Could not decrypt system bot password: {e} — falling back to anonymous join")
botAccountEmail = None
botAccountPassword = None
else:
logger.info("No system bot found in DB — using anonymous join")
if not effectiveBotName:
effectiveBotName = effectiveConfig.botName
@ -216,17 +237,15 @@ async def startSession(
if effectiveBotName != (body.botName or config.botName):
interface.updateSession(sessionId, {"botName": effectiveBotName})
# Build session config — no credentials sent (auth disabled)
# Build session config
sessionConfig = effectiveConfig.model_copy(update={
"botAccountEmail": None,
"botAccountPassword": None,
"botName": effectiveBotName,
})
# Start the bot in background (join meeting via bridge)
# Start the bot in background — pass credentials separately (not in config)
service = TeamsbotService(context.user, mandateId, instanceId, sessionConfig)
asyncio.create_task(
service.joinMeeting(sessionId, cleanMeetingUrl, body.connectionId, gatewayBaseUrl)
service.joinMeeting(sessionId, cleanMeetingUrl, body.connectionId, gatewayBaseUrl, botAccountEmail, botAccountPassword)
)
logger.info(f"Teamsbot session {sessionId} created for instance {instanceId}")

View file

@ -90,14 +90,16 @@ class TeamsbotService:
meetingLink: str,
connectionId: Optional[str] = None,
gatewayBaseUrl: str = "",
botAccountEmail: Optional[str] = None,
botAccountPassword: Optional[str] = None,
):
"""Send join command to the Browser Bot service.
The browser bot will:
1. Launch a headless browser
1. Launch browser (headful if credentials provided, headless otherwise)
2. Navigate to Teams web app
3. Join the meeting as anonymous guest
4. Enable captions and start scraping
3. Authenticate if credentials provided, otherwise join as anonymous guest
4. Enable captions/audio capture and start scraping
5. Connect back via WebSocket to send transcripts
"""
from . import interfaceFeatureTeamsbot as interfaceDb
@ -123,6 +125,9 @@ class TeamsbotService:
gatewayHost = gatewayBaseUrl.replace("https://", "").replace("http://", "").rstrip("/")
fullGatewayWsUrl = f"{wsScheme}://{gatewayHost}/api/teamsbot/{self.instanceId}/bot/ws/{sessionId}"
hasAuth = bool(botAccountEmail and botAccountPassword)
logger.info(f"Joining meeting for session {sessionId}: auth={hasAuth}, email={botAccountEmail or 'N/A'}, transferMode={self.config.transferMode}")
result = await self.browserBotConnector.joinMeeting(
sessionId=sessionId,
meetingUrl=meetingLink,
@ -130,8 +135,8 @@ class TeamsbotService:
instanceId=self.instanceId,
gatewayWsUrl=fullGatewayWsUrl,
language=self.config.language,
botAccountEmail=self.config.botAccountEmail if hasattr(self.config, 'botAccountEmail') else None,
botAccountPassword=self.config.botAccountPassword if hasattr(self.config, 'botAccountPassword') else None,
botAccountEmail=botAccountEmail,
botAccountPassword=botAccountPassword,
transferMode=self.config.transferMode if hasattr(self.config, 'transferMode') else "auto",
)