ensure viewer roles are available in create user dialog

This commit is contained in:
Josh Hawkins 2025-11-17 08:55:11 -06:00
parent fbf4388b37
commit ff90dbf208

View File

@ -13,7 +13,8 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { z } from "zod"; import { z } from "zod";
import ActivityIndicator from "../indicators/activity-indicator"; import ActivityIndicator from "../indicators/activity-indicator";
import { useEffect, useState } from "react"; import { useEffect, useState, useMemo } from "react";
import useSWR from "swr";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@ -35,6 +36,7 @@ import { LuCheck, LuX } from "react-icons/lu";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { isDesktop, isMobile } from "react-device-detect"; import { isDesktop, isMobile } from "react-device-detect";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { FrigateConfig } from "@/types/frigateConfig";
import { import {
MobilePage, MobilePage,
MobilePageContent, MobilePageContent,
@ -54,9 +56,15 @@ export default function CreateUserDialog({
onCreate, onCreate,
onCancel, onCancel,
}: CreateUserOverlayProps) { }: CreateUserOverlayProps) {
const { data: config } = useSWR<FrigateConfig>("config");
const { t } = useTranslation(["views/settings"]); const { t } = useTranslation(["views/settings"]);
const [isLoading, setIsLoading] = useState<boolean>(false); const [isLoading, setIsLoading] = useState<boolean>(false);
const roles = useMemo(() => {
const existingRoles = config ? Object.keys(config.auth?.roles || {}) : [];
return Array.from(new Set(["admin", "viewer", ...(existingRoles || [])]));
}, [config]);
const formSchema = z const formSchema = z
.object({ .object({
user: z user: z
@ -69,7 +77,7 @@ export default function CreateUserDialog({
confirmPassword: z confirmPassword: z
.string() .string()
.min(1, t("users.dialog.createUser.confirmPassword")), .min(1, t("users.dialog.createUser.confirmPassword")),
role: z.enum(["admin", "viewer"]), role: z.string().min(1),
}) })
.refine((data) => data.password === data.confirmPassword, { .refine((data) => data.password === data.confirmPassword, {
message: t("users.dialog.form.password.notMatch"), message: t("users.dialog.form.password.notMatch"),
@ -246,24 +254,22 @@ export default function CreateUserDialog({
</SelectTrigger> </SelectTrigger>
</FormControl> </FormControl>
<SelectContent> <SelectContent>
<SelectItem {roles.map((r) => (
value="admin" <SelectItem
className="flex items-center gap-2" value={r}
> key={r}
<div className="flex items-center gap-2"> className="flex items-center gap-2"
<Shield className="h-4 w-4 text-primary" /> >
<span>{t("role.admin", { ns: "common" })}</span> <div className="flex items-center gap-2">
</div> {r === "admin" ? (
</SelectItem> <Shield className="h-4 w-4 text-primary" />
<SelectItem ) : (
value="viewer" <User className="h-4 w-4 text-muted-foreground" />
className="flex items-center gap-2" )}
> <span>{t(`role.${r}`, { ns: "common" }) || r}</span>
<div className="flex items-center gap-2"> </div>
<User className="h-4 w-4 text-muted-foreground" /> </SelectItem>
<span>{t("role.viewer", { ns: "common" })}</span> ))}
</div>
</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
<FormDescription className="text-xs text-muted-foreground"> <FormDescription className="text-xs text-muted-foreground">