mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-09-30 20:06:51 +03:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
743fef2782 | ||
|
|
17e1d5e094 |
+12
-17
@@ -127,23 +127,18 @@ def require_admin_by_default():
|
|||||||
if path.startswith(EXEMPT_PREFIXES):
|
if path.startswith(EXEMPT_PREFIXES):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Dynamic camera path exemption:
|
# Camera routes enforce per-camera access via route-level dependencies
|
||||||
# Any path whose first segment matches a configured camera name should
|
# (e.g. require_camera_access). Match on the route template, not the raw
|
||||||
# bypass the global admin requirement. These endpoints enforce access
|
# path, so a camera named like another namespace (e.g. "faces") can't
|
||||||
# via route-level dependencies (e.g. require_camera_access) to ensure
|
# waive the admin check for that namespace's routes.
|
||||||
# per-camera authorization. This allows non-admin authenticated users
|
route = request.scope.get("route")
|
||||||
# (e.g. viewer role) to access camera-specific resources without
|
if (
|
||||||
# needing admin privileges.
|
route is not None
|
||||||
try:
|
and route.path.startswith("/{camera_name}")
|
||||||
if path.startswith("/"):
|
and request.path_params.get("camera_name")
|
||||||
first_segment = path.split("/", 2)[1]
|
in request.app.frigate_config.cameras
|
||||||
if (
|
):
|
||||||
first_segment
|
return
|
||||||
and first_segment in request.app.frigate_config.cameras
|
|
||||||
):
|
|
||||||
return
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# For all other paths, require admin role
|
# For all other paths, require admin role
|
||||||
# Internal port requests have admin role set automatically
|
# Internal port requests have admin role set automatically
|
||||||
|
|||||||
@@ -144,7 +144,9 @@ class BaseTestHttp(unittest.TestCase):
|
|||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def create_app(self, stats=None, event_metadata_publisher=None):
|
def create_app(
|
||||||
|
self, stats=None, event_metadata_publisher=None, enforce_default_admin=False
|
||||||
|
):
|
||||||
from frigate.api.auth import get_allowed_cameras_for_filter, get_current_user
|
from frigate.api.auth import get_allowed_cameras_for_filter, get_current_user
|
||||||
|
|
||||||
app = create_fastapi_app(
|
app = create_fastapi_app(
|
||||||
@@ -158,7 +160,7 @@ class BaseTestHttp(unittest.TestCase):
|
|||||||
event_metadata_publisher,
|
event_metadata_publisher,
|
||||||
None,
|
None,
|
||||||
DebugReplayManager(),
|
DebugReplayManager(),
|
||||||
enforce_default_admin=False,
|
enforce_default_admin=enforce_default_admin,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Default test mocks for authentication
|
# Default test mocks for authentication
|
||||||
|
|||||||
@@ -47,6 +47,25 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.json()["front_door"]["usage_percent"] == 25.0
|
assert response.json()["front_door"]["usage_percent"] == 25.0
|
||||||
|
|
||||||
|
def test_camera_name_collision_keeps_admin_default(self):
|
||||||
|
self.minimal_config["cameras"]["faces"] = self.minimal_config["cameras"].pop(
|
||||||
|
"front_door"
|
||||||
|
)
|
||||||
|
app = super().create_app(enforce_default_admin=True)
|
||||||
|
viewer = {"remote-user": "viewer", "remote-role": "viewer"}
|
||||||
|
|
||||||
|
with AuthTestClient(app) as client:
|
||||||
|
assert client.get("/faces", headers=viewer).status_code == 403
|
||||||
|
assert client.get("/faces").status_code == 200
|
||||||
|
assert (
|
||||||
|
client.post("/faces/train/person/classify", headers=viewer).status_code
|
||||||
|
== 403
|
||||||
|
)
|
||||||
|
|
||||||
|
# Camera routes for the same name stay reachable by viewers
|
||||||
|
response = client.get("/faces/recordings/summary", headers=viewer)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
def test_config_set_in_memory_replaces_objects_track_list(self):
|
def test_config_set_in_memory_replaces_objects_track_list(self):
|
||||||
self.minimal_config["cameras"]["front_door"]["objects"] = {
|
self.minimal_config["cameras"]["front_door"]["objects"] = {
|
||||||
"track": ["person", "car"],
|
"track": ["person", "car"],
|
||||||
|
|||||||
Reference in New Issue
Block a user