mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-29 20:19:24 +08:00
Fix: bind memory message user_id to authenticated user for JWT auth (#14745)
### Related issues Closes #14744 ### What problem does this PR solve? The Memory REST endpoint `POST /api/v1/messages` previously persisted whatever `user_id` the client sent in the JSON body. Memory rows were therefore attributed to an arbitrary string, even when the caller authenticated as a normal workspace user via JWT (browser/session-style bearer token decoded into an access token). That broke attribution and audit semantics for shared memories (team visibility): any authorized writer could spoof another subject id. The Python SDK already sends an optional `user_id` for integrations using **API keys** (`APIToken`) to tag an external subject distinct from the tenant owner user. ### Solution - Record **`g.auth_via_api_token`** in `_load_user` (`api/apps/__init__.py`): set `True` only when authentication resolves via `APIToken`, otherwise `False` after JWT-based login succeeds. - In **`POST /messages`** (`memory_api.add_message`): if the request was authenticated with an API key, keep accepting optional `user_id` from the body (default empty string). For JWT-authenticated users, **always** set stored `user_id` to **`current_user.id`** and ignore the client field. - Guard reads of `g` with **`RuntimeError`** handling so isolated imports or tests without a Quart application context do not fail when resolving `user_id`. - Document on **`RAGFlow.add_message`** that `user_id` is only meaningful for API-key authentication. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) - [ ] New Feature (non-breaking change which adds functionality) - [ ] Documentation Update - [ ] Refactoring - [ ] Performance Improvement - [ ] Other (please describe): ### Testing - `python -m py_compile` on modified modules (`api/apps/__init__.py`, `api/apps/restful_apis/memory_api.py`). - Recommended: run web/SDK memory message tests (`test_add_message`, `test_message_routes_unit`) against a full environment with `quart` and configured services. ### Notes for reviewers - Behavior change **only** for callers using JWT-style authorization on `POST /messages`; API-key callers keep prior optional `user_id` semantics. Co-authored-by: jony376 <jony376@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -130,6 +130,7 @@ def _load_user():
|
||||
jwt = Serializer(secret_key=settings.get_secret_key())
|
||||
authorization = request.headers.get("Authorization")
|
||||
g.user = None
|
||||
g.auth_via_api_token = False
|
||||
if not authorization:
|
||||
return _load_user_from_session()
|
||||
|
||||
@@ -175,6 +176,7 @@ def _load_user():
|
||||
if not user[0].access_token or not user[0].access_token.strip():
|
||||
logging.warning(f"User {user[0].email} has empty access_token in database")
|
||||
return _load_user_from_session()
|
||||
g.auth_via_api_token = True
|
||||
g.user = user[0]
|
||||
return user[0]
|
||||
logging.warning(f"load_user: No user found for tenant_id={objs[0].tenant_id} from APIToken")
|
||||
|
||||
Reference in New Issue
Block a user