mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-08-03 01:22:17 +03:00
UI viewer role (#16978)
* db migration * db model * assign admin role on password reset * add role to jwt and api responses * don't restrict api access for admins yet * use json response * frontend auth context * update auth form for profile endpoint * add access denied page * add protected routes * auth hook * dialogs * user settings view * restrict viewer access to settings * restrict camera functions for viewer role * add password dialog to account menu * spacing tweak * migrator default to admin * escape quotes in migrator * ui tweaks * tweaks * colors * colors * fix merge conflict * fix icons * add api layer enforcement * ui tweaks * fix error message * debug * clean up * remove print * guard apis for admin only * fix tests * fix review tests * use correct error responses from api in toasts * add role to account menu
This commit is contained in:
@@ -18,22 +18,52 @@ import {
|
||||
} from "../ui/dropdown-menu";
|
||||
import { Drawer, DrawerContent, DrawerTrigger } from "../ui/drawer";
|
||||
import { DialogClose } from "../ui/dialog";
|
||||
import { LuLogOut } from "react-icons/lu";
|
||||
import { LuLogOut, LuSquarePen } from "react-icons/lu";
|
||||
import useSWR from "swr";
|
||||
import { useState } from "react";
|
||||
import axios from "axios";
|
||||
import { toast } from "sonner";
|
||||
import SetPasswordDialog from "../overlay/SetPasswordDialog";
|
||||
|
||||
type AccountSettingsProps = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export default function AccountSettings({ className }: AccountSettingsProps) {
|
||||
const { data: profile } = useSWR("profile");
|
||||
const { data: config } = useSWR("config");
|
||||
const logoutUrl = config?.proxy?.logout_url || `${baseUrl}api/logout`;
|
||||
|
||||
const [passwordDialogOpen, setPasswordDialogOpen] = useState(false);
|
||||
|
||||
const Container = isDesktop ? DropdownMenu : Drawer;
|
||||
const Trigger = isDesktop ? DropdownMenuTrigger : DrawerTrigger;
|
||||
const Content = isDesktop ? DropdownMenuContent : DrawerContent;
|
||||
const MenuItem = isDesktop ? DropdownMenuItem : DialogClose;
|
||||
|
||||
const handlePasswordSave = async (password: string) => {
|
||||
if (!profile?.username || profile.username === "anonymous") return;
|
||||
axios
|
||||
.put(`users/${profile.username}/password`, { password })
|
||||
.then((response) => {
|
||||
if (response.status === 200) {
|
||||
setPasswordDialogOpen(false);
|
||||
toast.success("Password updated successfully.", {
|
||||
position: "top-center",
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorMessage =
|
||||
error.response?.data?.message ||
|
||||
error.response?.data?.detail ||
|
||||
"Unknown error";
|
||||
toast.error(`Error setting password: ${errorMessage}`, {
|
||||
position: "top-center",
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Container modal={!isDesktop}>
|
||||
<Trigger>
|
||||
@@ -65,9 +95,22 @@ export default function AccountSettings({ className }: AccountSettingsProps) {
|
||||
>
|
||||
<div className="scrollbar-container w-full flex-col overflow-y-auto overflow-x-hidden">
|
||||
<DropdownMenuLabel>
|
||||
Current User: {profile?.username || "anonymous"}
|
||||
Current User: {profile?.username || "anonymous"}{" "}
|
||||
{profile?.role && `(${profile.role})`}
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator className={isDesktop ? "mt-3" : "mt-1"} />
|
||||
{profile?.username && profile.username !== "anonymous" && (
|
||||
<MenuItem
|
||||
className={
|
||||
isDesktop ? "cursor-pointer" : "flex items-center p-2 text-sm"
|
||||
}
|
||||
aria-label="Set Password"
|
||||
onClick={() => setPasswordDialogOpen(true)}
|
||||
>
|
||||
<LuSquarePen className="mr-2 size-4" />
|
||||
<span>Set Password</span>
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem
|
||||
className={
|
||||
isDesktop ? "cursor-pointer" : "flex items-center p-2 text-sm"
|
||||
@@ -81,6 +124,12 @@ export default function AccountSettings({ className }: AccountSettingsProps) {
|
||||
</MenuItem>
|
||||
</div>
|
||||
</Content>
|
||||
<SetPasswordDialog
|
||||
show={passwordDialogOpen}
|
||||
onSave={handlePasswordSave}
|
||||
onCancel={() => setPasswordDialogOpen(false)}
|
||||
username={profile?.username}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user