fix: Navidrome REST auth for playlist cover — use JWT Bearer token
POST /auth/login to get JWT token, then X-Nd-Authorization: Bearer <token> for cover upload/delete. Resets cached token on auth failure. Bump SW to ns-v32. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
23d7c62045
commit
729e9d260c
2 files changed
+30
-10
No files matched your search
@@ -481,6 +481,20 @@ async function saveEditPlaylist(){
|
||||
finally{btn.disabled=false;btn.textContent='Speichern';}
|
||||
}
|
||||
|
||||
let _ndToken=null;
|
||||
async function ndAuth(){
|
||||
if(_ndToken)return _ndToken;
|
||||
const res=await fetch(`${cfg.url}/auth/login`,{
|
||||
method:'POST',
|
||||
headers:{'Content-Type':'application/json'},
|
||||
body:JSON.stringify({username:cfg.user,password:cfg.pass})
|
||||
});
|
||||
if(!res.ok)throw new Error('Navidrome login fehlgeschlagen');
|
||||
const d=await res.json();
|
||||
_ndToken=d.token;
|
||||
return _ndToken;
|
||||
}
|
||||
|
||||
function editPlUploadCover(){document.getElementById('edit-pl-file').click()}
|
||||
|
||||
async function editPlCoverSelected(input){
|
||||
@@ -489,18 +503,20 @@ async function editPlCoverSelected(input){
|
||||
const preview=URL.createObjectURL(file);
|
||||
document.getElementById('edit-pl-cover').innerHTML=`<img src="${preview}" style="width:100%;height:100%;object-fit:cover">`;
|
||||
try{
|
||||
const token=await ndAuth();
|
||||
const form=new FormData();form.append('image',file);
|
||||
const auth='Basic '+btoa(`${cfg.user}:${cfg.pass}`);
|
||||
const res=await fetch(`${cfg.url}/api/playlist/${_currentPlaylist.id}/image`,{method:'POST',headers:{Authorization:auth},body:form});
|
||||
const res=await fetch(`${cfg.url}/api/playlist/${_currentPlaylist.id}/image`,{
|
||||
method:'POST',headers:{'X-Nd-Authorization':'Bearer '+token},body:form
|
||||
});
|
||||
if(!res.ok)throw new Error(res.status);
|
||||
toast('Cover aktualisiert');
|
||||
// Refresh cover in detail view
|
||||
setTimeout(()=>{
|
||||
const cv=document.getElementById('playlist-cover');
|
||||
const img=cv?.querySelector('img');if(img)img.src=img.src.split('?')[0]+'?t='+Date.now();
|
||||
},500);
|
||||
}catch{
|
||||
toast('Cover-Upload nicht unterstützt (Navidrome-Version)');
|
||||
},800);
|
||||
}catch(e){
|
||||
_ndToken=null;
|
||||
toast('Cover-Upload fehlgeschlagen: '+e.message);
|
||||
document.getElementById('edit-pl-cover').innerHTML=
|
||||
(coverUrl(_currentPlaylist.coverArt,300)
|
||||
?`<img src="${coverUrl(_currentPlaylist.coverArt,300)}" style="width:100%;height:100%;object-fit:cover">`
|
||||
@@ -511,12 +527,16 @@ async function editPlCoverSelected(input){
|
||||
async function editPlRemoveCover(){
|
||||
if(!_currentPlaylist)return;
|
||||
try{
|
||||
const auth='Basic '+btoa(`${cfg.user}:${cfg.pass}`);
|
||||
const res=await fetch(`${cfg.url}/api/playlist/${_currentPlaylist.id}/image`,{method:'DELETE',headers:{Authorization:auth}});
|
||||
const token=await ndAuth();
|
||||
const res=await fetch(`${cfg.url}/api/playlist/${_currentPlaylist.id}/image`,{
|
||||
method:'DELETE',headers:{'X-Nd-Authorization':'Bearer '+token}
|
||||
});
|
||||
if(!res.ok)throw new Error(res.status);
|
||||
toast('Cover entfernt');
|
||||
_currentPlaylist.coverArt=null;
|
||||
document.getElementById('edit-pl-cover').innerHTML='<div class="no-art" style="width:100%;height:100%;display:flex;align-items:center;justify-content:center;font-size:36px">🎶</div>';
|
||||
}catch{toast('Entfernen nicht unterstützt (Navidrome-Version)')}
|
||||
document.getElementById('playlist-cover').innerHTML='<div class="no-art">🎶</div>';
|
||||
}catch(e){_ndToken=null;toast('Fehler: '+e.message)}
|
||||
}
|
||||
|
||||
// ─── RADIO MODE (endloser Shuffle aus der eigenen Bibliothek) ───
|
||||
|
||||
Reference in new issue
Block a user