security: CORS hardening, path traversal fix, WebSocket auth + cleanup
- Restrict CORS to localhost origins (was allow_origins=[*])
- Require valid JWT on WebSocket /ws (anonymous no longer gets admin view)
- Fix path traversal in delete_cell(): resolve() + parent check
- Validate cell_id format in /charts/download-noaa/{cell_id}
- Exclude charts/ and Cartas/ from git (keep US1GC09M world overview)
- Add NOAA ENC Portal external link in charts catalog tab
- Untrack __pycache__/, .db, .claude/ session files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+13
-5
@@ -793,9 +793,11 @@ document.getElementById('btn-rec-search')?.addEventListener('click', async () =>
|
||||
// ── MODAL LAMP CATALOG ────────────────────────────────────────────────────
|
||||
window._lampCache = []; // exposed so the right panel can populate its dropdown
|
||||
|
||||
function _lampThresholds(vmin, vmax) {
|
||||
function _lampThresholds(vmin, vmax, warn_pct, alarm_pct) {
|
||||
const rng = vmax - vmin;
|
||||
return { warn: +(vmin + rng * 0.20).toFixed(3), alarm: +(vmin + rng * 0.10).toFixed(3) };
|
||||
const wp = ((warn_pct ?? 20) / 100);
|
||||
const ap = ((alarm_pct ?? 10) / 100);
|
||||
return { warn: +(vmin + rng * wp).toFixed(3), alarm: +(vmin + rng * ap).toFixed(3) };
|
||||
}
|
||||
|
||||
async function loadLamps() {
|
||||
@@ -844,20 +846,24 @@ window.editLamp = function(id) {
|
||||
<td><input class="form-input" id="lp-edit-count" type="number" value="${l.lamp_count}" style="width:60px"></td>
|
||||
<td><input class="form-input" id="lp-edit-vmin" type="number" step="0.1" value="${l.voltage_min}" style="width:70px"></td>
|
||||
<td><input class="form-input" id="lp-edit-vmax" type="number" step="0.1" value="${l.voltage_max}" style="width:70px"></td>
|
||||
<td colspan="2" style="font-size:0.7rem;color:var(--text-muted)" id="lp-edit-preview">${l.warn_v} V / ${l.alarm_v} V</td>
|
||||
<td><input class="form-input" id="lp-edit-wpct" type="number" step="1" min="1" max="50" value="${l.warn_pct ?? 20}" style="width:55px" title="Warn %"></td>
|
||||
<td><input class="form-input" id="lp-edit-apct" type="number" step="1" min="1" max="50" value="${l.alarm_pct ?? 10}" style="width:55px" title="Alarm %"></td>
|
||||
<td style="font-size:0.7rem" id="lp-edit-preview">${l.warn_v} V / ${l.alarm_v} V</td>
|
||||
<td><input class="form-input" id="lp-edit-notes" value="${l.notes || ''}"></td>
|
||||
<td style="display:flex;gap:4px">
|
||||
<button class="chart-row-btn" onclick="saveLamp('${id}')">SAVE</button>
|
||||
<button class="chart-row-btn danger" onclick="renderLampsTable()">CANCEL</button>
|
||||
</td>`;
|
||||
// Live preview while editing vmin/vmax
|
||||
['lp-edit-vmin','lp-edit-vmax'].forEach(i =>
|
||||
['lp-edit-vmin','lp-edit-vmax','lp-edit-wpct','lp-edit-apct'].forEach(i =>
|
||||
document.getElementById(i).addEventListener('input', () => {
|
||||
const vmin = parseFloat(document.getElementById('lp-edit-vmin').value);
|
||||
const vmax = parseFloat(document.getElementById('lp-edit-vmax').value);
|
||||
const wpct = parseFloat(document.getElementById('lp-edit-wpct').value);
|
||||
const apct = parseFloat(document.getElementById('lp-edit-apct').value);
|
||||
const cell = document.getElementById('lp-edit-preview');
|
||||
if (isNaN(vmin) || isNaN(vmax) || vmax <= vmin) { cell.textContent = '—'; return; }
|
||||
const t = _lampThresholds(vmin, vmax);
|
||||
const t = _lampThresholds(vmin, vmax, wpct, apct);
|
||||
cell.innerHTML = `<span style="color:var(--yellow)">${t.warn} V</span> / <span style="color:var(--red)">${t.alarm} V</span>`;
|
||||
}));
|
||||
};
|
||||
@@ -870,6 +876,8 @@ window.saveLamp = async function(id) {
|
||||
lamp_count: parseInt(document.getElementById('lp-edit-count').value) || 1,
|
||||
voltage_min: parseFloat(document.getElementById('lp-edit-vmin').value),
|
||||
voltage_max: parseFloat(document.getElementById('lp-edit-vmax').value),
|
||||
warn_pct: parseFloat(document.getElementById('lp-edit-wpct').value) || 20.0,
|
||||
alarm_pct: parseFloat(document.getElementById('lp-edit-apct').value) || 10.0,
|
||||
notes: document.getElementById('lp-edit-notes').value.trim() || null,
|
||||
};
|
||||
if (!payload.manufacturer || !payload.model || isNaN(payload.voltage_min) || isNaN(payload.voltage_max)) {
|
||||
|
||||
Reference in New Issue
Block a user