Add ntfy authentication support (username/password and API key)
- Settings table gets ntfy_username, ntfy_password, ntfy_api_key columns - Backend applies Basic or Bearer auth header when sending notifications - Settings page UI lets you toggle between no auth, basic, or token auth - Masked credential display on load to avoid exposing stored secrets - README updated with auth modes documentation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -389,6 +389,11 @@ function renderGarden() {
|
||||
function filterBatches() { renderGarden(); }
|
||||
|
||||
// ===== Settings =====
|
||||
function toggleNtfyAuth(type) {
|
||||
document.getElementById('ntfy-basic-auth').classList.toggle('hidden', type !== 'basic');
|
||||
document.getElementById('ntfy-token-auth').classList.toggle('hidden', type !== 'token');
|
||||
}
|
||||
|
||||
async function loadSettings() {
|
||||
try {
|
||||
state.settings = await api.get('/settings/');
|
||||
@@ -400,6 +405,16 @@ async function loadSettings() {
|
||||
document.getElementById('s-ntfy-server').value = s.ntfy_server || 'https://ntfy.sh';
|
||||
document.getElementById('s-ntfy-topic').value = s.ntfy_topic || '';
|
||||
document.getElementById('s-notif-time').value = s.notification_time || '07:00';
|
||||
|
||||
// Auth type
|
||||
let authType = 'none';
|
||||
if (s.ntfy_api_key) authType = 'token';
|
||||
else if (s.ntfy_username) authType = 'basic';
|
||||
document.querySelector(`input[name="ntfy-auth-type"][value="${authType}"]`).checked = true;
|
||||
toggleNtfyAuth(authType);
|
||||
document.getElementById('s-ntfy-username').value = s.ntfy_username || '';
|
||||
document.getElementById('s-ntfy-password').value = s.ntfy_password ? '••••••••' : '';
|
||||
document.getElementById('s-ntfy-api-key').value = s.ntfy_api_key ? '••••••••' : '';
|
||||
} catch (e) {
|
||||
toast('Failed to load settings: ' + e.message, true);
|
||||
}
|
||||
@@ -407,15 +422,26 @@ async function loadSettings() {
|
||||
|
||||
async function saveSettings() {
|
||||
try {
|
||||
const authType = document.querySelector('input[name="ntfy-auth-type"]:checked').value;
|
||||
const rawPassword = document.getElementById('s-ntfy-password').value;
|
||||
const rawApiKey = document.getElementById('s-ntfy-api-key').value;
|
||||
// If the placeholder mask is still showing, don't overwrite
|
||||
const isMask = v => v === '••••••••';
|
||||
|
||||
const payload = {
|
||||
location_name: document.getElementById('s-location').value || null,
|
||||
last_frost_date: document.getElementById('s-last-frost').value || null,
|
||||
location_name: document.getElementById('s-location').value || null,
|
||||
last_frost_date: document.getElementById('s-last-frost').value || null,
|
||||
first_frost_fall_date: document.getElementById('s-first-frost').value || null,
|
||||
timezone: document.getElementById('s-timezone').value || 'UTC',
|
||||
ntfy_server: document.getElementById('s-ntfy-server').value || 'https://ntfy.sh',
|
||||
ntfy_topic: document.getElementById('s-ntfy-topic').value || null,
|
||||
notification_time: document.getElementById('s-notif-time').value || '07:00',
|
||||
timezone: document.getElementById('s-timezone').value || 'UTC',
|
||||
ntfy_server: document.getElementById('s-ntfy-server').value || 'https://ntfy.sh',
|
||||
ntfy_topic: document.getElementById('s-ntfy-topic').value || null,
|
||||
notification_time: document.getElementById('s-notif-time').value || '07:00',
|
||||
ntfy_username: authType === 'basic' ? (document.getElementById('s-ntfy-username').value || null) : null,
|
||||
ntfy_password: authType === 'basic' && !isMask(rawPassword) ? (rawPassword || null) : (authType === 'basic' ? undefined : null),
|
||||
ntfy_api_key: authType === 'token' && !isMask(rawApiKey) ? (rawApiKey || null) : (authType === 'token' ? undefined : null),
|
||||
};
|
||||
// Remove undefined keys so they are excluded from the PUT (server keeps existing value)
|
||||
Object.keys(payload).forEach(k => payload[k] === undefined && delete payload[k]);
|
||||
await api.put('/settings/', payload);
|
||||
toast('Settings saved!');
|
||||
document.getElementById('settings-status').textContent = 'Saved!';
|
||||
@@ -779,7 +805,7 @@ window.App = {
|
||||
showAddVarietyModal, showEditVarietyModal, submitAddVariety, submitEditVariety, deleteVariety,
|
||||
showAddBatchModal, showEditBatchModal, submitAddBatch, submitEditBatch, deleteBatch,
|
||||
filterVarieties, filterBatches,
|
||||
saveSettings, sendTestNotification, sendDailySummary,
|
||||
saveSettings, toggleNtfyAuth, sendTestNotification, sendDailySummary,
|
||||
closeModal: (e) => closeModal(e),
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user