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:
@@ -2,7 +2,7 @@
|
||||
// Callbacks: CRUD management
|
||||
// ============================================================
|
||||
|
||||
import { t, showToast, escapeHtml, closeDialog, showConfirm } from './core.js';
|
||||
import { t, showToast, escapeHtml, closeDialog, showConfirm, getAuthHeaders, hasCredentials } from './core.js';
|
||||
|
||||
export let callbackFormDirty = false;
|
||||
export function setCallbackFormDirty(value) { callbackFormDirty = value; }
|
||||
@@ -16,12 +16,11 @@ export async function loadCallbacksTable() {
|
||||
}
|
||||
|
||||
async function _loadCallbacksTableImpl() {
|
||||
const token = localStorage.getItem('media_server_token');
|
||||
const tbody = document.getElementById('callbacksTableBody');
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/callbacks/list', {
|
||||
headers: { 'Authorization': `Bearer ${token}` }
|
||||
headers: getAuthHeaders()
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -79,13 +78,12 @@ export function showAddCallbackDialog() {
|
||||
}
|
||||
|
||||
export async function showEditCallbackDialog(callbackName) {
|
||||
const token = localStorage.getItem('media_server_token');
|
||||
const dialog = document.getElementById('callbackDialog');
|
||||
const title = document.getElementById('callbackDialogTitle');
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/callbacks/list', {
|
||||
headers: { 'Authorization': `Bearer ${token}` }
|
||||
headers: getAuthHeaders()
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -137,7 +135,6 @@ export async function saveCallback(event) {
|
||||
const submitBtn = event.target.querySelector('button[type="submit"]');
|
||||
if (submitBtn) submitBtn.disabled = true;
|
||||
|
||||
const token = localStorage.getItem('media_server_token');
|
||||
const isEdit = document.getElementById('callbackIsEdit').value === 'true';
|
||||
const callbackName = document.getElementById('callbackName').value;
|
||||
|
||||
@@ -157,10 +154,7 @@ export async function saveCallback(event) {
|
||||
try {
|
||||
const response = await fetch(endpoint, {
|
||||
method,
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
headers: { 'Content-Type': 'application/json', ...getAuthHeaders() },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
@@ -187,14 +181,10 @@ export async function deleteCallbackConfirm(callbackName) {
|
||||
return;
|
||||
}
|
||||
|
||||
const token = localStorage.getItem('media_server_token');
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/callbacks/delete/${callbackName}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
headers: getAuthHeaders()
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
Reference in New Issue
Block a user