feat: rebuild as multi-user web agent

This commit is contained in:
wuyang
2026-07-26 06:52:12 +08:00
parent 45792c8fd5
commit 37f83eaac7
634 changed files with 5060 additions and 139619 deletions
+70
View File
@@ -0,0 +1,70 @@
from __future__ import annotations
import hmac
from dataclasses import dataclass
from typing import Annotated
import jwt
from fastapi import Header, HTTPException, status
from agent_platform.config import get_settings
@dataclass(frozen=True, slots=True)
class UserIdentity:
user_id: str
email: str
name: str
role: str
def verify_service_bearer(authorization: str | None, expected: str) -> None:
if not expected:
raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Service secret is not configured")
scheme, _, token = (authorization or "").partition(" ")
if scheme.lower() != "bearer" or not hmac.compare_digest(token, expected):
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid service credentials")
def decode_openwebui_identity(token: str | None, secret: str) -> UserIdentity:
if not secret:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail="Identity verification is unavailable",
)
if not token:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Missing signed user identity")
try:
claims = jwt.decode(
token,
secret,
algorithms=["HS256"],
issuer="open-webui",
options={"require": ["sub", "iss", "iat", "exp"]},
)
except jwt.PyJWTError as exc:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid signed user identity") from exc
user_id = str(claims.get("sub", "")).strip()
if not user_id:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Signed identity has no subject")
return UserIdentity(
user_id=user_id,
email=str(claims.get("email", "")),
name=str(claims.get("name", "")),
role=str(claims.get("role", "user")),
)
def require_gateway_identity(
authorization: Annotated[
str | None,
Header(alias="Authorization", include_in_schema=False),
] = None,
user_jwt: Annotated[
str | None,
Header(alias="X-OpenWebUI-User-Jwt", include_in_schema=False),
] = None,
) -> UserIdentity:
settings = get_settings()
verify_service_bearer(authorization, settings.internal_gateway_key)
return decode_openwebui_identity(user_jwt, settings.openwebui_forward_jwt_secret)