diff --git a/web/src/pages/AdminUsers.tsx b/web/src/pages/AdminUsers.tsx
index 5c277324..8d490466 100644
--- a/web/src/pages/AdminUsers.tsx
+++ b/web/src/pages/AdminUsers.tsx
@@ -59,6 +59,7 @@ import {
playbackQualityValueFromPreset,
type PlaybackQualityPreset,
} from "@/lib/playback-quality";
+import { PERMISSION_METADATA_CURATION } from "@/lib/permissions";
const PAGE_SIZE_OPTIONS = ["25", "50", "100"] as const;
type UserSortField = "username" | "email" | "role" | "enabled" | "created_at" | "last_active_at";
@@ -514,6 +515,20 @@ function formatRelativeTime(value?: string | null, fallback = "-") {
return fallback;
}
+function hasAssignedPermission(permissions: string[] | undefined, permission: string) {
+ return Array.isArray(permissions) && permissions.includes(permission);
+}
+
+function setAssignedPermission(permissions: string[], permission: string, enabled: boolean) {
+ const next = new Set(permissions);
+ if (enabled) {
+ next.add(permission);
+ } else {
+ next.delete(permission);
+ }
+ return Array.from(next).sort();
+}
+
function UserForm({ user, onClose }: { user: AdminUser | null; onClose: () => void }) {
const { data: settings } = useAdminServerSettings();
const { data: libraries = [] } = useAdminLibraries();
@@ -522,6 +537,7 @@ function UserForm({ user, onClose }: { user: AdminUser | null; onClose: () => vo
const [password, setPassword] = useState("");
const [role, setRole] = useState(user?.role ?? "user");
const [enabled, setEnabled] = useState(user?.enabled ?? true);
+ const [permissions, setPermissions] = useState
(user?.permissions ?? []);
const [libraryIDs, setLibraryIDs] = useState(user?.library_ids ?? null);
const [maxStreams, setMaxStreams] = useState(
user?.max_streams ?? Number(settings?.["defaults.max_streams"] ?? "6"),
@@ -549,6 +565,7 @@ function UserForm({ user, onClose }: { user: AdminUser | null; onClose: () => vo
const passwordId = useId();
const roleId = useId();
const enabledId = useId();
+ const metadataCurationId = useId();
const downloadAllowedId = useId();
const downloadTranscodeAllowedId = useId();
const maxStreamsId = useId();
@@ -566,6 +583,7 @@ function UserForm({ user, onClose }: { user: AdminUser | null; onClose: () => vo
username,
email,
role,
+ permissions,
enabled,
library_ids: libraryIDs,
max_streams: maxStreams,
@@ -583,6 +601,7 @@ function UserForm({ user, onClose }: { user: AdminUser | null; onClose: () => vo
email,
password,
role,
+ permissions,
create_default_profile: true,
max_streams: maxStreams,
max_transcodes: maxTranscodes,
@@ -682,6 +701,23 @@ function UserForm({ user, onClose }: { user: AdminUser | null; onClose: () => vo
value={libraryIDs}
onChange={setLibraryIDs}
/>
+
+
+
+
+ Edit, refresh, and rematch metadata within assigned libraries.
+
+
+
+ setPermissions((current) =>
+ setAssignedPermission(current, PERMISSION_METADATA_CURATION, checked),
+ )
+ }
+ />
+