From 20aa65f16aca2481de663ae6060f7fc5ae962727 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Sun, 7 Dec 2025 17:53:37 -0800 Subject: [PATCH] restrict playlist actions by permission --- .../actions/delete-playlist-action.tsx | 5 +++-- .../context-menu/actions/edit-playlist-action.tsx | 5 +++-- .../context-menu/menus/playlist-context-menu.tsx | 14 ++++++++++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/renderer/features/context-menu/actions/delete-playlist-action.tsx b/src/renderer/features/context-menu/actions/delete-playlist-action.tsx index ac0f20008..f3b98e31f 100644 --- a/src/renderer/features/context-menu/actions/delete-playlist-action.tsx +++ b/src/renderer/features/context-menu/actions/delete-playlist-action.tsx @@ -13,10 +13,11 @@ import { toast } from '/@/shared/components/toast/toast'; import { Playlist } from '/@/shared/types/domain-types'; interface DeletePlaylistActionProps { + disabled?: boolean; items: Playlist[]; } -export const DeletePlaylistAction = ({ items }: DeletePlaylistActionProps) => { +export const DeletePlaylistAction = ({ disabled, items }: DeletePlaylistActionProps) => { const { t } = useTranslation(); const navigate = useNavigate(); const serverId = useCurrentServerId(); @@ -65,7 +66,7 @@ export const DeletePlaylistAction = ({ items }: DeletePlaylistActionProps) => { if (items.length === 0) return null; return ( - + {t('action.deletePlaylist', { postProcess: 'sentenceCase' })} ); diff --git a/src/renderer/features/context-menu/actions/edit-playlist-action.tsx b/src/renderer/features/context-menu/actions/edit-playlist-action.tsx index 8a70df931..f693f9c59 100644 --- a/src/renderer/features/context-menu/actions/edit-playlist-action.tsx +++ b/src/renderer/features/context-menu/actions/edit-playlist-action.tsx @@ -11,10 +11,11 @@ import { toast } from '/@/shared/components/toast/toast'; import { Playlist } from '/@/shared/types/domain-types'; interface EditPlaylistActionProps { + disabled?: boolean; items: Playlist[]; } -export const EditPlaylistAction = ({ items }: EditPlaylistActionProps) => { +export const EditPlaylistAction = ({ disabled, items }: EditPlaylistActionProps) => { const { t } = useTranslation(); const server = useCurrentServer(); @@ -52,7 +53,7 @@ export const EditPlaylistAction = ({ items }: EditPlaylistActionProps) => { if (items.length === 0 || items.length > 1) return null; return ( - + {t('action.editPlaylist', { postProcess: 'sentenceCase' })} ); diff --git a/src/renderer/features/context-menu/menus/playlist-context-menu.tsx b/src/renderer/features/context-menu/menus/playlist-context-menu.tsx index 86ef6ed98..608309292 100644 --- a/src/renderer/features/context-menu/menus/playlist-context-menu.tsx +++ b/src/renderer/features/context-menu/menus/playlist-context-menu.tsx @@ -5,6 +5,7 @@ import { DeletePlaylistAction } from '/@/renderer/features/context-menu/actions/ import { EditPlaylistAction } from '/@/renderer/features/context-menu/actions/edit-playlist-action'; import { GetInfoAction } from '/@/renderer/features/context-menu/actions/get-info-action'; import { PlayAction } from '/@/renderer/features/context-menu/actions/play-action'; +import { usePermissions } from '/@/renderer/store'; import { ContextMenu } from '/@/shared/components/context-menu/context-menu'; import { ContextMenuPreview } from '/@/shared/components/context-menu/context-menu-preview'; import { LibraryItem, Playlist } from '/@/shared/types/domain-types'; @@ -20,6 +21,15 @@ export const PlaylistContextMenu = ({ items, type }: PlaylistContextMenuProps) = return { ids }; }, [items]); + const { userId, ...permissions } = usePermissions(); + + const canEditPublic = permissions.playlists.editPublic; + + const includesNonOwnedPublic = items.some((item) => item.public && item.ownerId !== userId); + + const canEditPlaylist = canEditPublic || !includesNonOwnedPublic; + const canDeletePlaylist = canEditPublic || !includesNonOwnedPublic; + return ( } @@ -30,8 +40,8 @@ export const PlaylistContextMenu = ({ items, type }: PlaylistContextMenuProps) = - - + + ); };