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
+14 -4
View File
@@ -5,9 +5,10 @@ import os
from datetime import datetime, timedelta, timezone
import pytz
from fastapi import APIRouter
from fastapi import APIRouter, Depends
from fastapi.responses import JSONResponse
from frigate.api.auth import require_camera_access
from frigate.api.defs.tags import Tags
from frigate.const import BASE_DIR, CACHE_DIR, PREVIEW_FRAME_TYPE
from frigate.models import Previews
@@ -18,7 +19,10 @@ logger = logging.getLogger(__name__)
router = APIRouter(tags=[Tags.preview])
@router.get("/preview/{camera_name}/start/{start_ts}/end/{end_ts}")
@router.get(
"/preview/{camera_name}/start/{start_ts}/end/{end_ts}",
dependencies=[Depends(require_camera_access)],
)
def preview_ts(camera_name: str, start_ts: float, end_ts: float):
"""Get all mp4 previews relevant for time period."""
if camera_name != "all":
@@ -71,7 +75,10 @@ def preview_ts(camera_name: str, start_ts: float, end_ts: float):
return JSONResponse(content=clips, status_code=200)
@router.get("/preview/{year_month}/{day}/{hour}/{camera_name}/{tz_name}")
@router.get(
"/preview/{year_month}/{day}/{hour}/{camera_name}/{tz_name}",
dependencies=[Depends(require_camera_access)],
)
def preview_hour(year_month: str, day: int, hour: int, camera_name: str, tz_name: str):
"""Get all mp4 previews relevant for time period given the timezone"""
parts = year_month.split("-")
@@ -86,7 +93,10 @@ def preview_hour(year_month: str, day: int, hour: int, camera_name: str, tz_name
return preview_ts(camera_name, start_ts, end_ts)
@router.get("/preview/{camera_name}/start/{start_ts}/end/{end_ts}/frames")
@router.get(
"/preview/{camera_name}/start/{start_ts}/end/{end_ts}/frames",
dependencies=[Depends(require_camera_access)],
)
def get_preview_frames_from_cache(camera_name: str, start_ts: float, end_ts: float):
"""Get list of cached preview frames"""
preview_dir = os.path.join(CACHE_DIR, "preview_frames")