Files
Magent/backend/app/feature_guards.py
T

76 lines
3.0 KiB
Python

from fastapi import Depends, HTTPException, Request
from .auth import get_current_user, get_current_user_event_stream
from .db import get_portal_item
def check(user: dict, *features: str) -> None:
access = user.get("features") or {}
if user.get("role") == "admin":
return
if not any(access.get(feature, False) for feature in features):
raise HTTPException(status_code=403, detail="This feature is disabled for your account")
def require_stats(user: dict = Depends(get_current_user)) -> dict:
check(user, "stats")
return user
def require_invites(user: dict = Depends(get_current_user)) -> dict:
check(user, "invites")
return user
def require_request_access(request: Request, user: dict = Depends(get_current_user)) -> None:
path = request.url.path.rstrip("/")
if path.endswith("/search") and "/actions/" not in path:
# The issue picker uses the same media search; creation is checked separately.
check(user, "new_requests", "issues")
elif path.endswith(("/create", "/request-options")):
check(user, "new_requests")
elif path.endswith(("/issue-options", "/replacement-options", "/actions/replace", "/actions/search-missing", "/actions/repair-subtitles")):
check(user, "issues")
else:
check(user, "requests")
async def require_portal_access(request: Request, user: dict = Depends(get_current_user)) -> None:
if user.get("role") == "admin":
return
path = request.url.path.rstrip("/")
access = user.get("features", {})
if access.get("requests") and access.get("issues") and access.get("new_requests"):
return
if "/issues" in path:
check(user, "issues")
elif path.endswith("/requests") or path.endswith("/pipeline"):
check(user, "requests")
elif "item_id" in request.path_params:
try:
item = get_portal_item(int(request.path_params["item_id"]))
except (ValueError, TypeError):
item = None
if not item:
raise HTTPException(status_code=404, detail="Item not found")
check(user, "requests" if item.get("kind") == "request" else "issues")
elif path.endswith("/items") and request.method == "POST":
payload = await request.json()
kind = str(payload.get("kind") or "").strip().lower() if isinstance(payload, dict) else ""
check(user, "new_requests" if not kind or kind == "request" else "issues")
elif path.endswith(("/items", "/overview")) and request.query_params.get("kind"):
kind = request.query_params["kind"].strip().lower()
if not kind:
check(user, "requests")
check(user, "issues")
else:
check(user, "requests" if kind == "request" else "issues")
else:
# Unfiltered lists/overview can include both kinds.
check(user, "requests")
check(user, "issues")
def require_request_stream(user: dict = Depends(get_current_user_event_stream)) -> dict:
check(user, "requests")
return user