From ed43df9c13e7d0d67c11080101b4da1439c95cf3 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Wed, 4 Jun 2025 20:48:26 -0500 Subject: [PATCH] Fixes (#18552) * Ensure config editor recalculates layout on error * ensure empty lists are returned when lpr recognition model fails * Add docs section for session_length * clarify Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * clarify Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * Catch missing file * Improve graph axis colors * Ensure playback rate controls are portaled to the video container in history view On larger tablets in landscape view, the playback rate dropdown disappeared underneath the bottom bar. This small change ensures we use the correct container on the DropdownMenuContent so that the div is portaled correctly. The VideoControls are also used in motion review which does not pass in a container ref, so we can just fall back to the existing controlsContainer ref when it's undefined. --------- Co-authored-by: Nicolas Mowen --- docs/docs/configuration/authentication.md | 15 ++++++++++ .../common/license_plate/mixin.py | 2 ++ frigate/data_processing/real_time/face.py | 3 +- web/src/components/graph/LineGraph.tsx | 16 +++++++++-- web/src/components/graph/SystemGraph.tsx | 8 +++++- web/src/components/player/VideoControls.tsx | 4 ++- web/src/pages/ConfigEditor.tsx | 28 +++++++++++++------ 7 files changed, 63 insertions(+), 13 deletions(-) diff --git a/docs/docs/configuration/authentication.md b/docs/docs/configuration/authentication.md index 143c17e74..97fcb3721 100644 --- a/docs/docs/configuration/authentication.md +++ b/docs/docs/configuration/authentication.md @@ -52,6 +52,21 @@ auth: - 172.18.0.0/16 # <---- this is the subnet for the internal Docker Compose network ``` +## Session Length + +The default session length for user authentication in Frigate is 24 hours. This setting determines how long a user's authenticated session remains active before a token refresh is required — otherwise, the user will need to log in again. + +While the default provides a balance of security and convenience, you can customize this duration to suit your specific security requirements and user experience preferences. The session length is configured in seconds. + +The default value of `86400` will expire the authentication session after 24 hours. Some other examples: +- `0`: Setting the session length to 0 will require a user to log in every time they access the application or after a very short, immediate timeout. +- `604800`: Setting the session length to 604800 will require a user to log in if the token is not refreshed for 7 days. + +```yaml +auth: + session_length: 86400 +``` + ## JWT Token Secret The JWT token secret needs to be kept secure. Anyone with this secret can generate valid JWT tokens to authenticate with Frigate. This should be a cryptographically random string of at least 64 characters. diff --git a/frigate/data_processing/common/license_plate/mixin.py b/frigate/data_processing/common/license_plate/mixin.py index d0888bd74..55cd002a2 100644 --- a/frigate/data_processing/common/license_plate/mixin.py +++ b/frigate/data_processing/common/license_plate/mixin.py @@ -167,6 +167,8 @@ class LicensePlateProcessingMixin: outputs = self.model_runner.recognition_model(norm_images) except Exception as e: logger.warning(f"Error running LPR recognition model: {e}") + return [], [] + return self.ctc_decoder(outputs) def _process_license_plate( diff --git a/frigate/data_processing/real_time/face.py b/frigate/data_processing/real_time/face.py index 2bd8546a6..f6a25080e 100644 --- a/frigate/data_processing/real_time/face.py +++ b/frigate/data_processing/real_time/face.py @@ -6,6 +6,7 @@ import json import logging import os import shutil +from pathlib import Path from typing import Any, Optional import cv2 @@ -538,4 +539,4 @@ class FaceRealTimeProcessor(RealTimeProcessorApi): # delete oldest face image if maximum is reached if len(files) > self.config.face_recognition.save_attempts: - os.unlink(os.path.join(folder, files[-1])) + Path(os.path.join(folder, files[-1])).unlink(missing_ok=True) diff --git a/web/src/components/graph/LineGraph.tsx b/web/src/components/graph/LineGraph.tsx index 76c9c2ce3..ad841dea2 100644 --- a/web/src/components/graph/LineGraph.tsx +++ b/web/src/components/graph/LineGraph.tsx @@ -106,6 +106,9 @@ export function CameraLineGraph({ labels: { rotate: 0, formatter: formatTime, + style: { + colors: "#6B6B6B", + }, }, axisBorder: { show: false, @@ -118,6 +121,9 @@ export function CameraLineGraph({ show: true, labels: { formatter: (val: number) => Math.ceil(val).toString(), + style: { + colors: "#6B6B6B", + }, }, min: 0, }, @@ -138,7 +144,7 @@ export function CameraLineGraph({ className="size-2" style={{ color: GRAPH_COLORS[labelIdx] }} /> -
+
{t("cameras.label." + label)}
@@ -243,6 +249,9 @@ export function EventsPerSecondsLineGraph({ labels: { rotate: 0, formatter: formatTime, + style: { + colors: "#6B6B6B", + }, }, axisBorder: { show: false, @@ -255,6 +264,9 @@ export function EventsPerSecondsLineGraph({ show: true, labels: { formatter: (val: number) => Math.ceil(val).toString(), + style: { + colors: "#6B6B6B", + }, }, min: 0, }, @@ -268,7 +280,7 @@ export function EventsPerSecondsLineGraph({ return (
-
{name}
+
{name}
{lastValue} {unit} diff --git a/web/src/components/graph/SystemGraph.tsx b/web/src/components/graph/SystemGraph.tsx index b77231aa7..fcafeda22 100644 --- a/web/src/components/graph/SystemGraph.tsx +++ b/web/src/components/graph/SystemGraph.tsx @@ -138,6 +138,9 @@ export function ThresholdBarGraph({ labels: { rotate: 0, formatter: formatTime, + style: { + colors: "#6B6B6B", + }, }, axisBorder: { show: false, @@ -150,6 +153,9 @@ export function ThresholdBarGraph({ show: true, labels: { formatter: (val: number) => Math.ceil(val).toString(), + style: { + colors: "#6B6B6B", + }, }, min: 0, max: yMax, @@ -180,7 +186,7 @@ export function ThresholdBarGraph({ return (
-
{name}
+
{name}
{lastValue} {unit} diff --git a/web/src/components/player/VideoControls.tsx b/web/src/components/player/VideoControls.tsx index 3beca352c..12e6a75d8 100644 --- a/web/src/components/player/VideoControls.tsx +++ b/web/src/components/player/VideoControls.tsx @@ -250,7 +250,9 @@ export default function VideoControls({ > {`${playbackRate}x`} onSetPlaybackRate(parseFloat(rate))} diff --git a/web/src/pages/ConfigEditor.tsx b/web/src/pages/ConfigEditor.tsx index 01d76303d..8d828cee2 100644 --- a/web/src/pages/ConfigEditor.tsx +++ b/web/src/pages/ConfigEditor.tsx @@ -209,13 +209,24 @@ function ConfigEditor() { }; }, [hasChanges, t]); + useEffect(() => { + if (editorRef.current) { + // Small delay to ensure DOM has updated + const timeoutId = setTimeout(() => { + editorRef.current?.layout(); + }, 0); + + return () => clearTimeout(timeoutId); + } + }, [error]); + if (!config) { return ; } return (
-
+
{t("configEditor")} @@ -254,13 +265,14 @@ function ConfigEditor() {
- {error && ( -
- {error} -
- )} - -
+
+ {error && ( +
+ {error} +
+ )} +
+