2026-08-30 22:22:11 +08:00
|
|
|
from django.http import HttpResponseRedirect, JsonResponse
|
|
|
|
|
from app.security import verify_internal_request
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from django.utils.deprecation import MiddlewareMixin
|
|
|
|
|
except ImportError:
|
|
|
|
|
MiddlewareMixin = object
|
|
|
|
|
|
|
|
|
|
PUBLIC_EXACT_PATHS = frozenset(('/login', '/logout', '/user/openCaptcha'))
|
|
|
|
|
PUBLIC_PREFIXES = ('/static/',)
|
|
|
|
|
|
|
|
|
|
ROLE_SYSTEM_ADMIN = "system_admin"
|
|
|
|
|
ROLE_ALGORITHM_ADMIN = "algorithm_admin"
|
|
|
|
|
ROLE_OPERATOR = "operator"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _required_role(path, method):
|
|
|
|
|
if path.startswith(("/system/", "/user/")) or path == "/index/openMediaControl":
|
|
|
|
|
return ROLE_SYSTEM_ADMIN
|
|
|
|
|
if path.startswith(("/smallmodel/", "/algorithm/", "/llm/")):
|
|
|
|
|
return ROLE_ALGORITHM_ADMIN
|
|
|
|
|
if method != "GET" and path.startswith(("/stream/", "/nvr/", "/control/", "/zone/", "/alarm/")):
|
|
|
|
|
return ROLE_OPERATOR
|
2026-09-06 22:26:35 +08:00
|
|
|
if method != "GET" and path.startswith("/workshop/"):
|
|
|
|
|
return ROLE_OPERATOR
|
2026-08-30 22:22:11 +08:00
|
|
|
if path.startswith(("/analysis/openStart", "/analysis/openStop", "/analysis/openReload")):
|
|
|
|
|
return ROLE_OPERATOR
|
2026-09-04 18:16:14 +08:00
|
|
|
if path.startswith(("/analysis/openPreviewStart", "/analysis/openPreviewStop")):
|
|
|
|
|
return ROLE_OPERATOR
|
2026-08-30 22:22:11 +08:00
|
|
|
if path.startswith(("/analysis/openUpdate", "/analysis/openToggle", "/analysis/openRestart")):
|
|
|
|
|
return ROLE_ALGORITHM_ADMIN
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _has_role(user, required):
|
|
|
|
|
if user.is_superuser:
|
|
|
|
|
return True
|
|
|
|
|
roles = set(user.groups.values_list("name", flat=True))
|
|
|
|
|
if ROLE_SYSTEM_ADMIN in roles:
|
|
|
|
|
return True
|
|
|
|
|
if required == ROLE_ALGORITHM_ADMIN:
|
|
|
|
|
return ROLE_ALGORITHM_ADMIN in roles
|
|
|
|
|
if required == ROLE_OPERATOR:
|
|
|
|
|
return ROLE_OPERATOR in roles or ROLE_ALGORITHM_ADMIN in roles
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SimpleMiddleware(MiddlewareMixin):
|
|
|
|
|
def process_request(self, request):
|
|
|
|
|
path = request.path_info
|
|
|
|
|
|
2026-09-04 18:16:14 +08:00
|
|
|
if path in ('/setup', '/license', '/license/status', '/license/request', '/license/import'):
|
|
|
|
|
from monitor_runtime.paths import DESKTOP
|
|
|
|
|
if DESKTOP:
|
|
|
|
|
return None # Dedicated views enforce local bootstrap/admin access.
|
|
|
|
|
|
2026-08-30 22:22:11 +08:00
|
|
|
if path.startswith('/inner/'):
|
|
|
|
|
if verify_internal_request(request):
|
|
|
|
|
return None
|
|
|
|
|
return JsonResponse({"code": 0, "msg": "forbidden"}, status=403)
|
|
|
|
|
|
|
|
|
|
if path in PUBLIC_EXACT_PATHS or any(path.startswith(prefix) for prefix in PUBLIC_PREFIXES):
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
if getattr(request, "user", None) is not None and request.user.is_authenticated:
|
|
|
|
|
if path.startswith("/login"):
|
|
|
|
|
return HttpResponseRedirect("/")
|
|
|
|
|
required = _required_role(path, request.method)
|
|
|
|
|
if required and not _has_role(request.user, required):
|
|
|
|
|
if "/open" in path:
|
|
|
|
|
return JsonResponse({"code": 0, "msg": "forbidden"}, status=403)
|
|
|
|
|
return HttpResponseRedirect("/forbidden")
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
return HttpResponseRedirect("/login")
|
|
|
|
|
|
|
|
|
|
def process_response(self, request, response):
|
|
|
|
|
return response
|