Skip to content

Commit 11c0af4

Browse files
fix: require active user for monitor endpoints (#10568)
Require active user for monitor endpoints
1 parent ec679c9 commit 11c0af4

2 files changed

Lines changed: 86 additions & 3 deletions

File tree

src/backend/base/langflow/api/v1/monitor.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ async def get_message_sessions(
5858
raise HTTPException(status_code=500, detail=str(e)) from e
5959

6060

61-
@router.get("/messages")
61+
@router.get("/messages", dependencies=[Depends(get_current_active_user)])
6262
async def get_messages(
6363
session: DbSession,
6464
flow_id: Annotated[UUID | None, Query()] = None,
@@ -162,7 +162,7 @@ async def update_session_id(
162162
return message_responses
163163

164164

165-
@router.delete("/messages/session/{session_id}", status_code=204)
165+
@router.delete("/messages/session/{session_id}", status_code=204, dependencies=[Depends(get_current_active_user)])
166166
async def delete_messages_session(
167167
session_id: str,
168168
session: DbSession,
@@ -180,7 +180,7 @@ async def delete_messages_session(
180180
return {"message": "Messages deleted successfully"}
181181

182182

183-
@router.get("/transactions")
183+
@router.get("/transactions", dependencies=[Depends(get_current_active_user)])
184184
async def get_transactions(
185185
flow_id: Annotated[UUID, Query()],
186186
session: DbSession,
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
"""Security tests for monitor endpoints requiring authentication."""
2+
3+
import pytest
4+
from fastapi import status
5+
from httpx import AsyncClient
6+
7+
8+
async def test_get_messages_requires_auth(client: AsyncClient):
9+
"""Test that GET /monitor/messages requires authentication."""
10+
response = await client.get("api/v1/monitor/messages")
11+
# Langflow returns 403 for missing/invalid authentication
12+
assert response.status_code == status.HTTP_403_FORBIDDEN
13+
14+
15+
async def test_get_transactions_requires_auth(client: AsyncClient):
16+
"""Test that GET /monitor/transactions requires authentication."""
17+
# Include required query parameter
18+
response = await client.get("api/v1/monitor/transactions?flow_id=00000000-0000-0000-0000-000000000000")
19+
# Langflow returns 403 for missing/invalid authentication
20+
assert response.status_code == status.HTTP_403_FORBIDDEN
21+
22+
23+
async def test_delete_messages_session_requires_auth(client: AsyncClient):
24+
"""Test that DELETE /monitor/messages/session/{session_id} requires authentication."""
25+
response = await client.delete("api/v1/monitor/messages/session/test-session")
26+
# Langflow returns 403 for missing/invalid authentication
27+
assert response.status_code == status.HTTP_403_FORBIDDEN
28+
29+
30+
async def test_get_messages_with_fake_token(client: AsyncClient):
31+
"""Test that GET /monitor/messages rejects fake tokens."""
32+
response = await client.get("api/v1/monitor/messages", headers={"Authorization": "Bearer fake-token"})
33+
# Langflow returns 401 for invalid Bearer tokens (JWT validation fails)
34+
assert response.status_code == status.HTTP_401_UNAUTHORIZED
35+
36+
37+
async def test_get_transactions_with_fake_token(client: AsyncClient):
38+
"""Test that GET /monitor/transactions rejects fake tokens."""
39+
response = await client.get(
40+
"api/v1/monitor/transactions?flow_id=00000000-0000-0000-0000-000000000000",
41+
headers={"Authorization": "Bearer fake-token"},
42+
)
43+
# Langflow returns 401 for invalid Bearer tokens (JWT validation fails)
44+
assert response.status_code == status.HTTP_401_UNAUTHORIZED
45+
46+
47+
async def test_delete_messages_session_with_fake_token(client: AsyncClient):
48+
"""Test that DELETE /monitor/messages/session/{session_id} rejects fake tokens."""
49+
response = await client.delete(
50+
"api/v1/monitor/messages/session/test-session", headers={"Authorization": "Bearer fake-token"}
51+
)
52+
# Langflow returns 401 for invalid Bearer tokens (JWT validation fails)
53+
assert response.status_code == status.HTTP_401_UNAUTHORIZED
54+
55+
56+
@pytest.mark.usefixtures("active_user")
57+
async def test_get_messages_with_valid_auth(client: AsyncClient, logged_in_headers):
58+
"""Test that GET /monitor/messages works with valid authentication."""
59+
response = await client.get("api/v1/monitor/messages", headers=logged_in_headers)
60+
# Should return 200 OK (even if empty list)
61+
assert response.status_code == status.HTTP_200_OK
62+
assert isinstance(response.json(), list)
63+
64+
65+
@pytest.mark.usefixtures("active_user")
66+
async def test_get_transactions_with_valid_auth(client: AsyncClient, logged_in_headers):
67+
"""Test that GET /monitor/transactions works with valid authentication."""
68+
response = await client.get(
69+
"api/v1/monitor/transactions?flow_id=00000000-0000-0000-0000-000000000000", headers=logged_in_headers
70+
)
71+
# Should return 200 OK with pagination structure
72+
assert response.status_code == status.HTTP_200_OK
73+
result = response.json()
74+
assert "items" in result
75+
assert "total" in result
76+
77+
78+
@pytest.mark.usefixtures("active_user")
79+
async def test_delete_messages_session_with_valid_auth(client: AsyncClient, logged_in_headers):
80+
"""Test that DELETE /monitor/messages/session/{session_id} works with valid authentication."""
81+
response = await client.delete("api/v1/monitor/messages/session/test-session", headers=logged_in_headers)
82+
# Should return 204 No Content
83+
assert response.status_code == status.HTTP_204_NO_CONTENT

0 commit comments

Comments
 (0)