fix: harden agent startup and websocket auth
This commit is contained in:
@@ -20,7 +20,6 @@ import asyncio
|
||||
from contextlib import asynccontextmanager
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
# project_root is used for static files mounting
|
||||
@@ -669,28 +668,52 @@ def _authorize_websocket(websocket: WebSocket, resource: str, action: str) -> bo
|
||||
try:
|
||||
from .core.auth.jwt import decode_token
|
||||
from .core.database import SessionLocal
|
||||
from .models.auth import User, Role
|
||||
from .models.auth import User
|
||||
|
||||
payload = decode_token(ws_token)
|
||||
username = payload.get("sub")
|
||||
if not isinstance(username, str) or not username:
|
||||
logger.explore(
|
||||
"WebSocket authorization — token missing 'sub' claim",
|
||||
payload={"resource": resource, "action": action},
|
||||
error="JWT payload has no valid subject",
|
||||
)
|
||||
return False
|
||||
|
||||
db = SessionLocal()
|
||||
try:
|
||||
user = db.query(User).filter(User.username == username).first()
|
||||
if not user:
|
||||
logger.explore(
|
||||
"WebSocket authorization — user not found in database",
|
||||
payload={"resource": resource, "action": action, "username": username},
|
||||
error="Authenticated user missing from local DB",
|
||||
)
|
||||
return False
|
||||
if not getattr(user, "is_active", True):
|
||||
logger.explore(
|
||||
"WebSocket authorization — user is inactive",
|
||||
payload={"resource": resource, "action": action, "username": username},
|
||||
error="User account is disabled",
|
||||
)
|
||||
return False
|
||||
|
||||
# Admin bypass via is_admin flag
|
||||
# is_admin is the sole administrative authority. The database migration
|
||||
# backfills the legacy Admin role before this authorization path runs.
|
||||
for role in user.roles:
|
||||
if getattr(role, "is_admin", False):
|
||||
return True
|
||||
for perm in role.permissions:
|
||||
if perm.resource == resource and perm.action == action:
|
||||
return True
|
||||
|
||||
logger.explore(
|
||||
"WebSocket authorization denied — no matching permission or admin role",
|
||||
payload={"resource": resource, "action": action, "user": username,
|
||||
"roles": [r.name for r in user.roles],
|
||||
"is_active": getattr(user, "is_active", True)},
|
||||
error="No matching RBAC permission",
|
||||
)
|
||||
return False
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
Reference in New Issue
Block a user