From 172b404a935cd6ab315af68c5af98785b30ebb11 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Sat, 22 Aug 2026 09:12:27 -0600 Subject: [PATCH] Require camera access to delete review for camera --- frigate/api/review.py | 3 +++ .../test/http_api/test_http_camera_access.py | 23 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/frigate/api/review.py b/frigate/api/review.py index 08705e3f9e..f904e03744 100644 --- a/frigate/api/review.py +++ b/frigate/api/review.py @@ -709,6 +709,7 @@ async def get_review(request: Request, review_id: str): dependencies=[Depends(allow_any_authenticated())], ) async def set_not_reviewed( + request: Request, review_id: str, current_user: dict = Depends(get_current_user), ): @@ -727,6 +728,8 @@ async def set_not_reviewed( status_code=404, ) + await require_camera_access(review.camera, request=request) + try: user_review = UserReviewStatus.get( UserReviewStatus.user_id == user_id, diff --git a/frigate/test/http_api/test_http_camera_access.py b/frigate/test/http_api/test_http_camera_access.py index 44520d79f5..1e571b37d4 100644 --- a/frigate/test/http_api/test_http_camera_access.py +++ b/frigate/test/http_api/test_http_camera_access.py @@ -166,6 +166,29 @@ class TestCameraAccessEventReview(BaseTestHttp): resp = client.get("/review/rev1") assert resp.status_code == 403 + def test_review_not_reviewed_access(self): + super().insert_mock_review_segment("rev1", camera="front_door") + + # Allowed + async def mock_require_allowed(camera: str, request: Request = None): + if camera == "front_door": + return + raise HTTPException(status_code=403, detail="Access denied") + + with patch("frigate.api.review.require_camera_access", mock_require_allowed): + with AuthTestClient(self.app) as client: + resp = client.delete("/review/rev1/viewed") + assert resp.status_code == 200 + + # Disallowed + async def mock_require_disallowed(camera: str, request: Request = None): + raise HTTPException(status_code=403, detail="Access denied") + + with patch("frigate.api.review.require_camera_access", mock_require_disallowed): + with AuthTestClient(self.app) as client: + resp = client.delete("/review/rev1/viewed") + assert resp.status_code == 403 + def test_event_search_access(self): super().insert_mock_event("event1", camera="front_door") super().insert_mock_event("event2", camera="back_door")