restrict playlist actions by permission

This commit is contained in:
jeffvli
2025-12-07 17:53:37 -08:00
parent c82762a3fc
commit 20aa65f16a
3 changed files with 18 additions and 6 deletions
@@ -13,10 +13,11 @@ import { toast } from '/@/shared/components/toast/toast';
import { Playlist } from '/@/shared/types/domain-types'; import { Playlist } from '/@/shared/types/domain-types';
interface DeletePlaylistActionProps { interface DeletePlaylistActionProps {
disabled?: boolean;
items: Playlist[]; items: Playlist[];
} }
export const DeletePlaylistAction = ({ items }: DeletePlaylistActionProps) => { export const DeletePlaylistAction = ({ disabled, items }: DeletePlaylistActionProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate(); const navigate = useNavigate();
const serverId = useCurrentServerId(); const serverId = useCurrentServerId();
@@ -65,7 +66,7 @@ export const DeletePlaylistAction = ({ items }: DeletePlaylistActionProps) => {
if (items.length === 0) return null; if (items.length === 0) return null;
return ( return (
<ContextMenu.Item leftIcon="remove" onSelect={openDeletePlaylistModal}> <ContextMenu.Item disabled={disabled} leftIcon="remove" onSelect={openDeletePlaylistModal}>
{t('action.deletePlaylist', { postProcess: 'sentenceCase' })} {t('action.deletePlaylist', { postProcess: 'sentenceCase' })}
</ContextMenu.Item> </ContextMenu.Item>
); );
@@ -11,10 +11,11 @@ import { toast } from '/@/shared/components/toast/toast';
import { Playlist } from '/@/shared/types/domain-types'; import { Playlist } from '/@/shared/types/domain-types';
interface EditPlaylistActionProps { interface EditPlaylistActionProps {
disabled?: boolean;
items: Playlist[]; items: Playlist[];
} }
export const EditPlaylistAction = ({ items }: EditPlaylistActionProps) => { export const EditPlaylistAction = ({ disabled, items }: EditPlaylistActionProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const server = useCurrentServer(); const server = useCurrentServer();
@@ -52,7 +53,7 @@ export const EditPlaylistAction = ({ items }: EditPlaylistActionProps) => {
if (items.length === 0 || items.length > 1) return null; if (items.length === 0 || items.length > 1) return null;
return ( return (
<ContextMenu.Item leftIcon="edit" onSelect={handleEditPlaylist}> <ContextMenu.Item disabled={disabled} leftIcon="edit" onSelect={handleEditPlaylist}>
{t('action.editPlaylist', { postProcess: 'sentenceCase' })} {t('action.editPlaylist', { postProcess: 'sentenceCase' })}
</ContextMenu.Item> </ContextMenu.Item>
); );
@@ -5,6 +5,7 @@ import { DeletePlaylistAction } from '/@/renderer/features/context-menu/actions/
import { EditPlaylistAction } from '/@/renderer/features/context-menu/actions/edit-playlist-action'; import { EditPlaylistAction } from '/@/renderer/features/context-menu/actions/edit-playlist-action';
import { GetInfoAction } from '/@/renderer/features/context-menu/actions/get-info-action'; import { GetInfoAction } from '/@/renderer/features/context-menu/actions/get-info-action';
import { PlayAction } from '/@/renderer/features/context-menu/actions/play-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 { ContextMenu } from '/@/shared/components/context-menu/context-menu';
import { ContextMenuPreview } from '/@/shared/components/context-menu/context-menu-preview'; import { ContextMenuPreview } from '/@/shared/components/context-menu/context-menu-preview';
import { LibraryItem, Playlist } from '/@/shared/types/domain-types'; import { LibraryItem, Playlist } from '/@/shared/types/domain-types';
@@ -20,6 +21,15 @@ export const PlaylistContextMenu = ({ items, type }: PlaylistContextMenuProps) =
return { ids }; return { ids };
}, [items]); }, [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 ( return (
<ContextMenu.Content <ContextMenu.Content
bottomStickyContent={<ContextMenuPreview items={items} itemType={type} />} bottomStickyContent={<ContextMenuPreview items={items} itemType={type} />}
@@ -30,8 +40,8 @@ export const PlaylistContextMenu = ({ items, type }: PlaylistContextMenuProps) =
<ContextMenu.Divider /> <ContextMenu.Divider />
<GetInfoAction disabled={items.length === 0} items={items} /> <GetInfoAction disabled={items.length === 0} items={items} />
<ContextMenu.Divider /> <ContextMenu.Divider />
<EditPlaylistAction items={items} /> <EditPlaylistAction disabled={!canEditPlaylist} items={items} />
<DeletePlaylistAction items={items} /> <DeletePlaylistAction disabled={!canDeletePlaylist} items={items} />
</ContextMenu.Content> </ContextMenu.Content>
); );
}; };