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:
parent
ad254aafb1
commit
a3c92ae8d5
2 changed files with 41 additions and 17 deletions
|
|
@ -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}")
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue