mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-09-30 11:33:14 +00:00
feat: make web threads readable by any org user (#1425)
* feat: make web threads viewable by any org user Reads (get/stream) now allow any logged-in org user to view a thread whose source is surfaced (dashboard/github/slack/linear/schedule), instead of requiring ownership. Internal reviewer/analyzer threads stay hidden via the same source filter. Writes (send/cancel/delete) remain owner-only. Adds GET /threads?all=true to list every surfaced thread; the default list stays per-user. * feat: make all web threads readable by any org user Drop the per-thread source/owner gate on reads: any logged-in org user can now view and stream any thread, including reviewer/analyzer threads. GET /threads?all=true returns every thread regardless of source. Writes (send/cancel/delete) stay owner-only. All routes remain behind the session + org-login gate.
This commit is contained in:
parent
3a91fbfabc
commit
bbe449244a
2 changed files with 7 additions and 10 deletions
|
|
@ -755,9 +755,10 @@ async def api_delete_schedule(
|
|||
|
||||
@router.get("/threads")
|
||||
async def api_list_threads(
|
||||
all: bool = False,
|
||||
session: dict[str, Any] = _SESSION_DEP,
|
||||
) -> list[dict[str, Any]]:
|
||||
return await list_dashboard_threads(session["sub"], email=session.get("email"))
|
||||
return await list_dashboard_threads(session["sub"], email=session.get("email"), include_all=all)
|
||||
|
||||
|
||||
@router.post("/threads")
|
||||
|
|
|
|||
|
|
@ -205,11 +205,11 @@ async def _latest_run_status(thread_id: str) -> str | None:
|
|||
|
||||
|
||||
async def list_dashboard_threads(
|
||||
login: str, *, email: str | None = None, limit: int = 50
|
||||
login: str, *, email: str | None = None, limit: int = 50, include_all: bool = False
|
||||
) -> list[dict[str, Any]]:
|
||||
client = langgraph_client()
|
||||
searches: list[dict[str, Any]] = [{"github_login": login}]
|
||||
if email and email.strip():
|
||||
searches: list[dict[str, Any]] = [{}] if include_all else [{"github_login": login}]
|
||||
if not include_all and email and email.strip():
|
||||
searches.append({"triggering_user_email": email.strip().lower()})
|
||||
|
||||
seen: dict[str, dict[str, Any]] = {}
|
||||
|
|
@ -224,7 +224,7 @@ async def list_dashboard_threads(
|
|||
if not isinstance(thread, dict):
|
||||
continue
|
||||
meta = thread.get("metadata") if isinstance(thread.get("metadata"), dict) else {}
|
||||
if not _user_owns_thread(meta, login, email):
|
||||
if not include_all and not _user_owns_thread(meta, login, email):
|
||||
continue
|
||||
thread_id = thread.get("thread_id") or thread.get("id")
|
||||
if isinstance(thread_id, str) and thread_id not in seen:
|
||||
|
|
@ -246,7 +246,6 @@ async def get_dashboard_thread(
|
|||
raise HTTPException(404, "thread not found") from exc
|
||||
|
||||
metadata = thread.get("metadata") if isinstance(thread.get("metadata"), dict) else {}
|
||||
_assert_thread_owner(metadata, login, email)
|
||||
|
||||
messages: list[dict[str, Any]] = []
|
||||
try:
|
||||
|
|
@ -480,13 +479,10 @@ async def stream_dashboard_thread(
|
|||
thread_id: str, login: str, *, email: str | None = None, last_event_id: str | None = None
|
||||
) -> AsyncIterator[str]:
|
||||
try:
|
||||
thread = await langgraph_client().threads.get(thread_id)
|
||||
await langgraph_client().threads.get(thread_id)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
raise HTTPException(404, "thread not found") from exc
|
||||
|
||||
metadata = thread.get("metadata") if isinstance(thread.get("metadata"), dict) else {}
|
||||
_assert_thread_owner(metadata, login, email)
|
||||
|
||||
stream = await langgraph_client().threads.join_stream(
|
||||
thread_id,
|
||||
last_event_id=last_event_id,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue