feat: make authentication optional — no tokens = no auth
Lint & Test / test (push) Successful in 10s
Lint & Test / test (push) Successful in 10s
When no api_tokens are configured (the new default), all endpoints are accessible without authentication. The frontend detects this via /api/health's auth_required field and skips the login form. - Backend: auth.py skips verification when api_tokens is empty - Frontend: shared getAuthHeaders()/hasCredentials() helpers replace scattered token logic across all JS modules - Health endpoint exposes auth_required for frontend discovery - config.example.yaml ships with tokens commented out - CLI --show-token and startup log reflect disabled state Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
currentPosition, setCurrentPosition, isUserAdjustingVolume,
|
||||
lastStatus, setLastStatus, currentPlayState, setCurrentPlayState,
|
||||
POSITION_INTERPOLATION_MS, seek,
|
||||
getAuthHeaders, hasCredentials,
|
||||
} from './core.js';
|
||||
import { updateBackgroundColors } from './background.js';
|
||||
import { loadDisplayMonitors } from './links.js';
|
||||
@@ -282,9 +283,8 @@ const VISUALIZER_SMOOTHING = 0.15;
|
||||
|
||||
export async function checkVisualizerAvailability() {
|
||||
try {
|
||||
const token = localStorage.getItem('media_server_token');
|
||||
const resp = await fetch('/api/media/visualizer/status', {
|
||||
headers: { 'Authorization': `Bearer ${token}` }
|
||||
headers: getAuthHeaders()
|
||||
});
|
||||
if (resp.ok) {
|
||||
const data = await resp.json();
|
||||
@@ -428,14 +428,12 @@ export async function loadAudioDevices() {
|
||||
if (!section || !select) return;
|
||||
|
||||
try {
|
||||
const token = localStorage.getItem('media_server_token');
|
||||
|
||||
const [devicesResp, statusResp] = await Promise.all([
|
||||
fetch('/api/media/visualizer/devices', {
|
||||
headers: { 'Authorization': `Bearer ${token}` }
|
||||
headers: getAuthHeaders()
|
||||
}),
|
||||
fetch('/api/media/visualizer/status', {
|
||||
headers: { 'Authorization': `Bearer ${token}` }
|
||||
headers: getAuthHeaders()
|
||||
})
|
||||
]);
|
||||
|
||||
@@ -495,15 +493,11 @@ export async function onAudioDeviceChanged() {
|
||||
if (!select) return;
|
||||
|
||||
const deviceName = select.value || null;
|
||||
const token = localStorage.getItem('media_server_token');
|
||||
|
||||
try {
|
||||
const resp = await fetch('/api/media/visualizer/device', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
headers: { 'Content-Type': 'application/json', ...getAuthHeaders() },
|
||||
body: JSON.stringify({ device_name: deviceName })
|
||||
});
|
||||
|
||||
@@ -612,9 +606,8 @@ export function updateUI(status) {
|
||||
const placeholderArt = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 300'%3E%3Crect fill='%23282828' width='300' height='300'/%3E%3Cpath fill='%236a6a6a' d='M150 80c-38.66 0-70 31.34-70 70s31.34 70 70 70 70-31.34 70-70-31.34-70-70-70zm0 20c27.614 0 50 22.386 50 50s-22.386 50-50 50-50-22.386-50-50 22.386-50 50-50zm0 30a20 20 0 100 40 20 20 0 000-40z'/%3E%3C/svg%3E";
|
||||
const placeholderGlow = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 300'%3E%3Crect fill='%23282828' width='300' height='300'/%3E%3C/svg%3E";
|
||||
if (artworkSource) {
|
||||
const token = localStorage.getItem('media_server_token');
|
||||
fetch(`/api/media/artwork?_=${Date.now()}`, {
|
||||
headers: { 'Authorization': `Bearer ${token}` }
|
||||
headers: getAuthHeaders()
|
||||
})
|
||||
.then(r => r.ok ? r.blob() : null)
|
||||
.then(blob => {
|
||||
|
||||
Reference in New Issue
Block a user