diff --git a/src/components/playlist/APlaylistEditor.vue b/src/components/playlist/APlaylistEditor.vue
index 65dba322eab5daaf14aaf97e775c506df0cab7b5..99d5b3fd670ec01d9ceaae3c032317edb3d43964 100644
--- a/src/components/playlist/APlaylistEditor.vue
+++ b/src/components/playlist/APlaylistEditor.vue
@@ -87,50 +87,73 @@
     <fieldset
       v-if="allowAddEntries"
       ref="dropzoneEl"
-      class="tw-rounded tw-bg-gray-50 tw-border-2 tw-border-dashed tw-flex tw-mb-3 tw-p-6"
-      :class="{ 'tw-border-teal-600': isOverDropZone, 'tw-border-gray-200': !isOverDropZone }"
+      class="tw-rounded tw-bg-gray-50 tw-border-2 tw-flex tw-mb-3 tw-p-6"
+      :class="{
+        'tw-border-teal-600': isOverDropZone && isAllowedToAddFiles,
+        'tw-border-gray-200': !isOverDropZone,
+        'tw-border-dashed': isAllowedToAddFiles,
+      }"
     >
       <div class="tw-place-self-center tw-mx-auto tw-flex tw-flex-col tw-gap-2 tw-items-center">
-        <icon-system-uicons-file-upload class="tw-text-xl" />
-        <p class="tw-mb-0">{{ t('playlist.editor.control.dropFiles') }}</p>
-        <p class="tw-text-gray-400 tw-text-sm tw-mb-1.5 tw-leading-none">
-          {{ t('playlist.editor.control._or') }}
-        </p>
+        <template v-if="isAllowedToAddFiles">
+          <icon-system-uicons-file-upload class="tw-text-xl" />
+          <p class="tw-mb-0">{{ t('playlist.editor.control.dropFiles') }}</p>
+          <p class="tw-text-gray-400 tw-text-sm tw-mb-1.5 tw-leading-none">
+            {{ t('playlist.editor.control._or') }}
+          </p>
+        </template>
         <div class="tw-flex tw-flex-wrap tw-justify-center tw-items-center tw-gap-3">
-          <button type="button" class="btn btn-default" @click="openFileDialog()">
+          <button
+            v-if="isAllowedToAddFiles"
+            type="button"
+            class="btn btn-default"
+            @click="openFileDialog()"
+          >
             <icon-iconamoon-file-audio-thin class="tw-flex-none" />
             {{ t('playlist.editor.control.selectFiles') }}
           </button>
-          <button type="button" class="btn btn-default" @click="importFileFromURL()">
-            <icon-formkit-url class="tw-flex-none" />
-            {{ t('playlist.editor.control.importFile') }}
-          </button>
+          <APermissionGuard show-permissions="program.add__import">
+            <button type="button" class="btn btn-default" @click="importFileFromURL()">
+              <icon-formkit-url class="tw-flex-none" />
+              {{ t('playlist.editor.control.importFile') }}
+            </button>
+          </APermissionGuard>
         </div>
         <div class="tw-flex tw-flex-wrap tw-justify-center tw-items-center tw-gap-3 tw-mt-1">
-          <button type="button" class="btn btn-default" @click="addStreamToPlaylist()">
-            <icon-solar-play-stream-bold class="tw-flex-none" />
-            {{ t('playlist.editor.control.addStream') }}
-          </button>
-          <button type="button" class="btn btn-default" @click="addInputToPlaylist">
-            <icon-game-icons-jack-plug class="tw-flex-none" />
-            {{ t('playlist.editor.control.addInput') }}
-          </button>
+          <APermissionGuard show-permissions="program.add__stream">
+            <button type="button" class="btn btn-default" @click="addStreamToPlaylist()">
+              <icon-solar-play-stream-bold class="tw-flex-none" />
+              {{ t('playlist.editor.control.addStream') }}
+            </button>
+          </APermissionGuard>
+          <APermissionGuard show-permissions="program.add__line">
+            <button type="button" class="btn btn-default" @click="addInputToPlaylist">
+              <icon-game-icons-jack-plug class="tw-flex-none" />
+              {{ t('playlist.editor.control.addInput') }}
+            </button>
+          </APermissionGuard>
         </div>
       </div>
     </fieldset>
   </div>
 
-  <GetStreamUrl v-slot="{ resolve, reject }">
-    <AStreamURLDialog @save="resolve($event)" @close="reject(undefined)" />
-  </GetStreamUrl>
+  <APermissionGuard show-permissions="program.add__stream">
+    <GetStreamUrl v-slot="{ resolve, reject }">
+      <AStreamURLDialog @save="resolve($event)" @close="reject(undefined)" />
+    </GetStreamUrl>
+  </APermissionGuard>
 
-  <GetFileImportUrl v-slot="{ resolve, reject }">
-    <AFileUrlDialog @save="resolve($event)" @close="reject(undefined)" />
-  </GetFileImportUrl>
+  <APermissionGuard show-permissions="program.add__import">
+    <GetFileImportUrl v-slot="{ resolve, reject }">
+      <AFileUrlDialog @save="resolve($event)" @close="reject(undefined)" />
+    </GetFileImportUrl>
+  </APermissionGuard>
 
-  <GetInputUrl v-slot="{ resolve, reject }">
-    <AInputUrlDialog @save="resolve($event)" @close="reject(undefined)" />
-  </GetInputUrl>
+  <APermissionGuard show-permissions="program.add__line">
+    <GetInputUrl v-slot="{ resolve, reject }">
+      <AInputUrlDialog @save="resolve($event)" @close="reject(undefined)" />
+    </GetInputUrl>
+  </APermissionGuard>
 </template>
 
 <script lang="ts" setup>
@@ -152,6 +175,8 @@ import AUploadProgress from '@/components/playlist/AUploadProgress.vue'
 import SaveIndicator from '@/components/generic/SaveIndicator.vue'
 import APlaylistDurationCheck from '@/components/playlist/APlaylistDurationCheck.vue'
 import APlaylistEntries from '@/components/playlist/APlaylistEntries.vue'
+import APermissionGuard from '@/components/generic/APermissionGuard.vue'
+import { useHasUserPermission } from '@/stores/auth'
 
 const props = withDefaults(
   defineProps<{
@@ -189,6 +214,8 @@ const entryAddError = ref<Error>()
 const nonAddedEntries = ref<Partial<PlaylistEntry>[]>([])
 const isRetrying = ref(false)
 
+const isAllowedToAddFiles = useHasUserPermission(['program.add__file'])
+
 const uploadedFiles = ref(
   new Map<
     TankFile['id'],
@@ -199,7 +226,11 @@ const dropzoneEl = ref<HTMLDivElement>()
 const { open: openFileDialog, files } = useFileDialog({ accept: 'audio/*', multiple: true })
 watch(files, (newFiles) => uploadFiles(Array.from(newFiles ?? [])))
 const { isOverDropZone } = useDropZone(dropzoneEl, {
-  onDrop: (files) => uploadFiles(files ?? []),
+  onDrop: (files) => {
+    if (isAllowedToAddFiles.value) {
+      uploadFiles(files ?? [])
+    }
+  },
 })
 
 async function retryUpload(tankFile: TankFile, file: File) {