mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-05-07 05:55:27 +03:00
split users and roles into separate tabs in settings
This commit is contained in:
parent
e888a08fd1
commit
56dc5773e1
@ -564,15 +564,15 @@
|
||||
},
|
||||
"roles": {
|
||||
"management": {
|
||||
"title": "Role Management",
|
||||
"desc": "Manage roles and their camera access permissions for this Frigate instance."
|
||||
"title": "Viewer Role Management",
|
||||
"desc": "Manage custom viewer roles and their camera access permissions for this Frigate instance."
|
||||
},
|
||||
"addRole": "Add Role",
|
||||
"table": {
|
||||
"role": "Role",
|
||||
"cameras": "Cameras",
|
||||
"actions": "Actions",
|
||||
"noRoles": "No roles found.",
|
||||
"noRoles": "No custom roles found.",
|
||||
"editCameras": "Edit Cameras",
|
||||
"deleteRole": "Delete Role"
|
||||
},
|
||||
@ -581,7 +581,7 @@
|
||||
"createRole": "Role {{role}} created successfully",
|
||||
"updateCameras": "Cameras updated for role {{role}}",
|
||||
"deleteRole": "Role {{role}} deleted successfully",
|
||||
"userRolesUpdated": "{{count}} user(s) assigned to this role have been updated to 'viewer'."
|
||||
"userRolesUpdated": "{{count}} user(s) assigned to this role have been updated to 'viewer', which has access to all cameras."
|
||||
},
|
||||
"error": {
|
||||
"createRoleFailed": "Failed to create role: {{errorMessage}}",
|
||||
@ -601,7 +601,7 @@
|
||||
},
|
||||
"deleteRole": {
|
||||
"title": "Delete Role",
|
||||
"desc": "This action cannot be undone. This will permanently delete the role and assign any users with this role to the 'viewer' role.",
|
||||
"desc": "This action cannot be undone. This will permanently delete the role and assign any users with this role to the 'viewer' role, which will give viewer access to all cameras.",
|
||||
"warn": "Are you sure you want to delete <strong>{{role}}</strong>?",
|
||||
"deleting": "Deleting..."
|
||||
},
|
||||
|
||||
@ -33,7 +33,8 @@ import CameraSettingsView from "@/views/settings/CameraSettingsView";
|
||||
import ObjectSettingsView from "@/views/settings/ObjectSettingsView";
|
||||
import MotionTunerView from "@/views/settings/MotionTunerView";
|
||||
import MasksAndZonesView from "@/views/settings/MasksAndZonesView";
|
||||
import AuthenticationView from "@/views/settings/AuthenticationView";
|
||||
import UsersView from "@/views/settings/UsersView";
|
||||
import RolesView from "@/views/settings/RolesView";
|
||||
import NotificationView from "@/views/settings/NotificationsSettingsView";
|
||||
import EnrichmentsSettingsView from "@/views/settings/EnrichmentsSettingsView";
|
||||
import UiSettingsView from "@/views/settings/UiSettingsView";
|
||||
@ -57,6 +58,7 @@ const allSettingsViews = [
|
||||
"triggers",
|
||||
"debug",
|
||||
"users",
|
||||
"roles",
|
||||
"notifications",
|
||||
"frigateplus",
|
||||
] as const;
|
||||
@ -288,7 +290,8 @@ export default function Settings() {
|
||||
setUnsavedChanges={setUnsavedChanges}
|
||||
/>
|
||||
)}
|
||||
{page == "users" && <AuthenticationView />}
|
||||
{page == "users" && <UsersView />}
|
||||
{page == "roles" && <RolesView />}
|
||||
{page == "notifications" && (
|
||||
<NotificationView setUnsavedChanges={setUnsavedChanges} />
|
||||
)}
|
||||
|
||||
@ -38,7 +38,13 @@ import DeleteRoleDialog from "@/components/overlay/DeleteRoleDialog";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { CameraNameLabel } from "@/components/camera/CameraNameLabel";
|
||||
|
||||
export default function AuthenticationView() {
|
||||
type AuthenticationViewProps = {
|
||||
section?: "users" | "roles";
|
||||
};
|
||||
|
||||
export default function AuthenticationView({
|
||||
section,
|
||||
}: AuthenticationViewProps) {
|
||||
const { t } = useTranslation("views/settings");
|
||||
const { data: config, mutate: updateConfig } =
|
||||
useSWR<FrigateConfig>("config");
|
||||
@ -377,7 +383,9 @@ export default function AuthenticationView() {
|
||||
|
||||
const roles = useMemo(() => {
|
||||
return config?.auth?.roles
|
||||
? Object.entries(config.auth.roles).map(([name, data]) => ({
|
||||
? Object.entries(config.auth.roles)
|
||||
.filter(([name]) => name !== "admin")
|
||||
.map(([name, data]) => ({
|
||||
name,
|
||||
cameras: Array.isArray(data) ? data : [],
|
||||
}))
|
||||
@ -396,10 +404,9 @@ export default function AuthenticationView() {
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex size-full flex-col">
|
||||
<Toaster position="top-center" closeButton={true} />
|
||||
<div className="scrollbar-container order-last mb-10 mt-2 flex h-full w-full flex-col overflow-y-auto rounded-lg border-[1px] border-secondary-foreground bg-background_alt p-2 md:order-none md:mb-0 md:mr-2 md:mt-0">
|
||||
// Users section
|
||||
const UsersSection = (
|
||||
<>
|
||||
<div className="mb-5 flex flex-row items-center justify-between gap-2">
|
||||
<div className="flex flex-col items-start">
|
||||
<Heading as="h3" className="my-2">
|
||||
@ -557,9 +564,38 @@ export default function AuthenticationView() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<SetPasswordDialog
|
||||
show={showSetPassword}
|
||||
onCancel={() => setShowSetPassword(false)}
|
||||
onSave={(password) => onSavePassword(selectedUser!, password)}
|
||||
/>
|
||||
<DeleteUserDialog
|
||||
show={showDelete}
|
||||
username={selectedUser ?? "this user"}
|
||||
onCancel={() => setShowDelete(false)}
|
||||
onDelete={() => onDelete(selectedUser!)}
|
||||
/>
|
||||
<CreateUserDialog
|
||||
show={showCreate}
|
||||
onCreate={onCreate}
|
||||
onCancel={() => setShowCreate(false)}
|
||||
/>
|
||||
{selectedUser && selectedUserRole && (
|
||||
<RoleChangeDialog
|
||||
show={showRoleChange}
|
||||
username={selectedUser}
|
||||
currentRole={selectedUserRole}
|
||||
availableRoles={availableRoles}
|
||||
onSave={(role) => onChangeRole(selectedUser!, role)}
|
||||
onCancel={() => setShowRoleChange(false)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
<Separator className="my-6 flex bg-secondary" />
|
||||
|
||||
// Roles section
|
||||
const RolesSection = (
|
||||
<>
|
||||
<div className="mb-5 flex flex-row items-center justify-between gap-2">
|
||||
<div className="flex flex-col items-start">
|
||||
<Heading as="h3" className="my-2">
|
||||
@ -707,34 +743,6 @@ export default function AuthenticationView() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SetPasswordDialog
|
||||
show={showSetPassword}
|
||||
onCancel={() => setShowSetPassword(false)}
|
||||
onSave={(password) => onSavePassword(selectedUser!, password)}
|
||||
/>
|
||||
<DeleteUserDialog
|
||||
show={showDelete}
|
||||
username={selectedUser ?? "this user"}
|
||||
onCancel={() => setShowDelete(false)}
|
||||
onDelete={() => onDelete(selectedUser!)}
|
||||
/>
|
||||
<CreateUserDialog
|
||||
show={showCreate}
|
||||
onCreate={onCreate}
|
||||
onCancel={() => setShowCreate(false)}
|
||||
/>
|
||||
{selectedUser && selectedUserRole && (
|
||||
<RoleChangeDialog
|
||||
show={showRoleChange}
|
||||
username={selectedUser}
|
||||
currentRole={selectedUserRole}
|
||||
availableRoles={availableRoles}
|
||||
onSave={(role) => onChangeRole(selectedUser!, role)}
|
||||
onCancel={() => setShowRoleChange(false)}
|
||||
/>
|
||||
)}
|
||||
<CreateRoleDialog
|
||||
show={showCreateRole}
|
||||
config={config}
|
||||
@ -772,6 +780,23 @@ export default function AuthenticationView() {
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex size-full flex-col">
|
||||
<Toaster position="top-center" closeButton={true} />
|
||||
<div className="scrollbar-container order-last mb-10 mt-2 flex h-full w-full flex-col overflow-y-auto rounded-lg border-[1px] border-secondary-foreground bg-background_alt p-2 md:order-none md:mb-0 md:mr-2 md:mt-0">
|
||||
{section === "users" && UsersSection}
|
||||
{section === "roles" && RolesSection}
|
||||
{!section && (
|
||||
<>
|
||||
{UsersSection}
|
||||
<Separator className="my-6 flex bg-secondary" />
|
||||
{RolesSection}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
5
web/src/views/settings/RolesView.tsx
Normal file
5
web/src/views/settings/RolesView.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import AuthenticationView from "./AuthenticationView";
|
||||
|
||||
export default function RolesView() {
|
||||
return <AuthenticationView section="roles" />;
|
||||
}
|
||||
5
web/src/views/settings/UsersView.tsx
Normal file
5
web/src/views/settings/UsersView.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import AuthenticationView from "./AuthenticationView";
|
||||
|
||||
export default function UsersView() {
|
||||
return <AuthenticationView section="users" />;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user