Enhance user roles to limit camera access (#20024)

* update config for roles and add validator

* ensure admin and viewer are never overridden

* add class method to user to retrieve all allowed cameras

* enforce config roles in auth api endpoints

* add camera access api dependency functions

* protect review endpoints

* protect preview endpoints

* rename param name for better fastapi injection matching

* remove unneeded

* protect export endpoints

* protect event endpoints

* protect media endpoints

* update auth hook for allowed cameras

* update default app view

* ensure anonymous user always returns all cameras

* limit cameras in explore

* cameras is already a list

* limit cameras in review/history

* limit cameras in live view

* limit cameras in camera groups

* only show face library and classification in sidebar for admin

* remove check in delete reviews

since admin role is required, no need to check camera access. fixes failing test

* pass request with camera access for tests

* more async

* camera access tests

* fix proxy auth tests

* allowed cameras for review tests

* combine event tests and refactor for camera access

* fix post validation for roles

* don't limit roles in create user dialog

* fix triggers endpoints

no need to run require camera access dep since the required role is admin

* fix type

* create and edit role dialogs

* delete role dialog

* fix role change dialog

* update settings view for roles

* i18n changes

* minor spacing tweaks

* docs

* use badges and camera name label component

* clarify docs

* display all cameras badge for admin and viewer

* i18n fix

* use validator to prevent reserved and empty roles from being assigned

* split users and roles into separate tabs in settings

* tweak docs

* clarify docs

* change icon

* don't memoize roles

always recalculate on component render
This commit is contained in:
Josh Hawkins
2025-09-12 05:19:29 -06:00
committed by GitHub
parent ba650af6f2
commit ed1e3a7c9a
41 changed files with 2286 additions and 739 deletions
+16 -7
View File
@@ -112,7 +112,7 @@ class BaseTestHttp(unittest.TestCase):
except OSError:
pass
def create_app(self, stats=None):
def create_app(self, stats=None, event_metadata_publisher=None):
return create_fastapi_app(
FrigateConfig(**self.minimal_config),
self.db,
@@ -121,7 +121,7 @@ class BaseTestHttp(unittest.TestCase):
None,
None,
stats,
None,
event_metadata_publisher,
None,
)
@@ -134,12 +134,13 @@ class BaseTestHttp(unittest.TestCase):
top_score: int = 100,
score: int = 0,
data: Json = {},
camera: str = "front_door",
) -> Event:
"""Inserts a basic event model with a given id."""
return Event.insert(
id=id,
label="Mock",
camera="front_door",
camera=camera,
start_time=start_time,
end_time=end_time,
top_score=top_score,
@@ -158,15 +159,23 @@ class BaseTestHttp(unittest.TestCase):
def insert_mock_review_segment(
self,
id: str,
start_time: float = datetime.datetime.now().timestamp(),
end_time: float = datetime.datetime.now().timestamp() + 20,
start_time: float | None = None,
end_time: float | None = None,
severity: SeverityEnum = SeverityEnum.alert,
data: Json = {},
data: dict | None = None,
camera: str = "front_door",
) -> ReviewSegment:
"""Inserts a review segment model with a given id."""
if start_time is None:
start_time = datetime.datetime.now().timestamp()
if end_time is None:
end_time = start_time + 20
if data is None:
data = {}
return ReviewSegment.insert(
id=id,
camera="front_door",
camera=camera,
start_time=start_time,
end_time=end_time,
severity=severity,