mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-09-30 08:03:15 +00:00
* fix: tag Slack threads with stored identity so they surface in web process_slack_mention gated the run on mapped_login (resolved from the stable Slack user id), but upsert_agent_thread_owner_metadata independently re-resolved the GitHub login from the Slack profile email. When that email differs from the user's mapping email (e.g. a personal vs work address), the lookup returned None, so github_login was never stamped on the thread and the thread never surfaced in the web Agents UI (which searches by github_login / triggering_user_email). Resolve the GitHub user from the store via the Slack id, pass that login through to the owner metadata, and use the mapping's stored work email (falling back to the Slack profile email for unmapped users) for both the run config and the thread tagging, so Slack-started threads reliably appear in web. * fix: stamp github_login on Slack threads so they surface in web process_slack_mention gated the run on mapped_login (resolved from the stable Slack user id) but upsert_agent_thread_owner_metadata re-resolved the login from the Slack profile email; when that email isn't the user's mapping email the lookup returns None and github_login is never stamped, so the thread is invisible in the web Agents UI (which searches by github_login / triggering_user_email). Pass the already-resolved mapped_login through to the owner metadata. The dashboard match keys on the stable GitHub login, so this is sufficient; the triggering email stays the live Slack profile value. * fix: preserve Slack email during account mapping * fix: require Slack OIDC for email mappings * chore: format Slack OIDC mapping cleanup
75 lines
2.3 KiB
Python
75 lines
2.3 KiB
Python
"""Tests for the Slack account-link prompt."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _jwt_secret(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
monkeypatch.setenv("DASHBOARD_JWT_SECRET", "test-secret")
|
|
|
|
|
|
def test_account_link_prompt_posts_generic_token_free_link(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
"""The prompt posts a plain settings link in the thread — no per-user token."""
|
|
import asyncio
|
|
|
|
from agent import webapp
|
|
|
|
monkeypatch.setenv("DASHBOARD_BASE_URL", "https://app.example.com")
|
|
calls: dict[str, object] = {}
|
|
|
|
async def fake_reply(channel_id, thread_ts, text):
|
|
calls["reply"] = {"channel_id": channel_id, "thread_ts": thread_ts, "text": text}
|
|
return True
|
|
|
|
monkeypatch.setattr(webapp, "post_slack_thread_reply", fake_reply)
|
|
|
|
asyncio.run(webapp._post_account_link_prompt("C1", "1.1", "U1", "d@x.com", reason="unlinked"))
|
|
assert calls["reply"]["channel_id"] == "C1"
|
|
assert calls["reply"]["thread_ts"] == "1.1"
|
|
assert "https://app.example.com/my-settings" in calls["reply"]["text"]
|
|
# No signed account-link token may appear in the public thread.
|
|
assert "link=" not in calls["reply"]["text"]
|
|
|
|
|
|
def test_account_link_prompt_revoked_wording(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
import asyncio
|
|
|
|
from agent import webapp
|
|
|
|
monkeypatch.setenv("DASHBOARD_BASE_URL", "https://app.example.com")
|
|
calls: dict[str, object] = {}
|
|
|
|
async def fake_reply(channel_id, thread_ts, text):
|
|
calls["text"] = text
|
|
return True
|
|
|
|
monkeypatch.setattr(webapp, "post_slack_thread_reply", fake_reply)
|
|
|
|
asyncio.run(webapp._post_account_link_prompt("C1", "1.1", "U1", "d@x.com", reason="revoked"))
|
|
assert "no longer valid" in calls["text"]
|
|
assert "link=" not in calls["text"]
|
|
|
|
|
|
def test_account_link_prompt_skips_when_dashboard_url_unset(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
import asyncio
|
|
|
|
from agent import webapp
|
|
|
|
monkeypatch.delenv("DASHBOARD_BASE_URL", raising=False)
|
|
posted = False
|
|
|
|
async def fake_reply(channel_id, thread_ts, text):
|
|
nonlocal posted
|
|
posted = True
|
|
return True
|
|
|
|
monkeypatch.setattr(webapp, "post_slack_thread_reply", fake_reply)
|
|
|
|
asyncio.run(webapp._post_account_link_prompt("C1", "1.1", "U1", "d@x.com", reason="unlinked"))
|
|
assert posted is False
|