From ff90dbf208476f351daba70d55a046c7983bfcf3 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Mon, 17 Nov 2025 08:55:11 -0600 Subject: [PATCH] ensure viewer roles are available in create user dialog --- .../components/overlay/CreateUserDialog.tsx | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/web/src/components/overlay/CreateUserDialog.tsx b/web/src/components/overlay/CreateUserDialog.tsx index 0b2e3a89e..6f2b3ecf3 100644 --- a/web/src/components/overlay/CreateUserDialog.tsx +++ b/web/src/components/overlay/CreateUserDialog.tsx @@ -13,7 +13,8 @@ import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form"; import { z } from "zod"; import ActivityIndicator from "../indicators/activity-indicator"; -import { useEffect, useState } from "react"; +import { useEffect, useState, useMemo } from "react"; +import useSWR from "swr"; import { Dialog, DialogContent, @@ -35,6 +36,7 @@ import { LuCheck, LuX } from "react-icons/lu"; import { useTranslation } from "react-i18next"; import { isDesktop, isMobile } from "react-device-detect"; import { cn } from "@/lib/utils"; +import { FrigateConfig } from "@/types/frigateConfig"; import { MobilePage, MobilePageContent, @@ -54,9 +56,15 @@ export default function CreateUserDialog({ onCreate, onCancel, }: CreateUserOverlayProps) { + const { data: config } = useSWR("config"); const { t } = useTranslation(["views/settings"]); const [isLoading, setIsLoading] = useState(false); + const roles = useMemo(() => { + const existingRoles = config ? Object.keys(config.auth?.roles || {}) : []; + return Array.from(new Set(["admin", "viewer", ...(existingRoles || [])])); + }, [config]); + const formSchema = z .object({ user: z @@ -69,7 +77,7 @@ export default function CreateUserDialog({ confirmPassword: z .string() .min(1, t("users.dialog.createUser.confirmPassword")), - role: z.enum(["admin", "viewer"]), + role: z.string().min(1), }) .refine((data) => data.password === data.confirmPassword, { message: t("users.dialog.form.password.notMatch"), @@ -246,24 +254,22 @@ export default function CreateUserDialog({ - -
- - {t("role.admin", { ns: "common" })} -
-
- -
- - {t("role.viewer", { ns: "common" })} -
-
+ {roles.map((r) => ( + +
+ {r === "admin" ? ( + + ) : ( + + )} + {t(`role.${r}`, { ns: "common" }) || r} +
+
+ ))}