mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-15 02:16:08 +00:00
fix(pat): align replay scopes, keep 404/405, retire expired names, document the PAT_ENABLED switch
The ASGI message events route now accepts the same scopes as its Flask sibling (conversations:read or chat:run) through a shared constant. A token request that fails routing gets Flask's 404/405 instead of a 403. Creating a token retires an expired token that still held the name. allowed_ids uses is_pat instead of a bare literal. PAT_ENABLED is documented as the master switch it is: turning it off stops every existing token from authenticating. The docs explain that sources are matched by name (oldest wins) and point CI flows at sources upload --replace.
This commit is contained in:
1 parent
934ae1afb3
commit
7ddb5f6400
12 files changed
+105
-15
No files matched your search
@@ -9,7 +9,7 @@ from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from contextvars import Token
|
||||
from typing import Optional, Tuple
|
||||
from typing import Optional, Sequence, Tuple, Union
|
||||
|
||||
import anyio
|
||||
from starlette.requests import Request
|
||||
@@ -23,13 +23,13 @@ from docsgpt.core.settings import settings
|
||||
|
||||
|
||||
async def authenticate(
|
||||
request: Request, *, pat_scope: Optional[str] = None
|
||||
request: Request, *, pat_scope: Union[str, Sequence[str], None] = None
|
||||
) -> Tuple[Optional[dict], Optional[JSONResponse]]:
|
||||
"""Decode the caller's JWT the way Flask's ``authenticate_request`` does.
|
||||
|
||||
Args:
|
||||
request: The incoming Starlette request.
|
||||
pat_scope: Scope a personal access token needs for this route. Left
|
||||
pat_scope: Scope (or any-of scopes) a personal access token needs for this route. Left
|
||||
unset, the route rejects PATs outright (deny by default, matching
|
||||
the Flask rule table in ``docsgpt/api/pat/rules.py``). A token with
|
||||
a resource filter is always rejected.
|
||||
@@ -48,7 +48,8 @@ async def authenticate(
|
||||
if is_pat(decoded):
|
||||
# A PAT lookup already excludes revoked tokens and deactivated users,
|
||||
# so the session denylist below does not apply to it.
|
||||
if pat_scope is None or pat_scope not in (decoded.get("scopes") or []):
|
||||
accepted = (pat_scope,) if isinstance(pat_scope, str) else tuple(pat_scope or ())
|
||||
if not set(accepted).intersection(decoded.get("scopes") or []):
|
||||
return None, JSONResponse(
|
||||
{"success": False, "message": "Token lacks the required scope", "error": "insufficient_scope"},
|
||||
status_code=403,
|
||||
|
||||
Reference in new issue
Block a user