Add customer file browser, configurable WebDAV URL and harden both
- /u/:token/files lists files in the customer folder, /u/:token/file streams a download. Iterative walker with depth limit; symlinks are rejected at enumeration and via realpath containment on download; Content-Disposition filename is sanitized with an RFC 5987 fallback - New "Private WebDAV-URL" field in admin settings, displayed under the customer table. Served via authenticated /status (not public /branding) so it does not leak to upload visitors Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+12
-2
@@ -404,7 +404,11 @@
|
||||
<form id="settingsForm">
|
||||
<div class="field"><label>Öffentliche Basis-URL</label>
|
||||
<input name="public_base_url" placeholder="z. B. https://upload.example.com" />
|
||||
<p class="small" style="margin:.35rem 0 0">Leer lassen, um aus jedem Request die aktuelle URL zu nutzen.</p>
|
||||
<p class="small" style="margin:.35rem 0 0">Wird in den Kunden-Upload-Links eingesetzt. Leer lassen = aus dem Request abgeleitet.</p>
|
||||
</div>
|
||||
<div class="field"><label>Private WebDAV-URL</label>
|
||||
<input name="webdav_url" placeholder="z. B. webdav://upload.example.com:1900/" />
|
||||
<p class="small" style="margin:.35rem 0 0">Wird im Adminportal unter der Kundenliste angezeigt. Leer lassen = <code>webdav://<host>:1900/</code>.</p>
|
||||
</div>
|
||||
<div class="field"><label>Cron-Intervall (Minuten)</label>
|
||||
<input name="janitor_interval_minutes" type="number" min="1" style="max-width: 8rem" />
|
||||
@@ -547,7 +551,8 @@ async function bootstrap() {
|
||||
} else {
|
||||
document.getElementById('createCustomerCard').style.display = '';
|
||||
}
|
||||
document.getElementById('webdavUrl').textContent = `webdav://${location.hostname}:1900/`;
|
||||
document.getElementById('webdavUrl').textContent =
|
||||
(status.webdav_url || '').trim() || `webdav://${location.hostname}:1900/`;
|
||||
show('view-app');
|
||||
loadCustomers();
|
||||
}
|
||||
@@ -754,6 +759,7 @@ async function loadSettings() {
|
||||
const s = await api.get('/settings');
|
||||
const form = document.getElementById('settingsForm');
|
||||
form.public_base_url.value = s.public_base_url || '';
|
||||
form.webdav_url.value = s.webdav_url || '';
|
||||
form.janitor_interval_minutes.value = s.janitor_interval_minutes || 30;
|
||||
setSlider('logoWidth', s.logo_width_px || 0);
|
||||
setSlider('logoHeight', s.logo_height_px || 0);
|
||||
@@ -806,10 +812,14 @@ document.getElementById('settingsForm').addEventListener('submit', async (e) =>
|
||||
try {
|
||||
await api.send('PUT', '/settings', {
|
||||
public_base_url: fd.get('public_base_url') || '',
|
||||
webdav_url: fd.get('webdav_url') || '',
|
||||
janitor_interval_minutes: parseInt(fd.get('janitor_interval_minutes') || '30', 10),
|
||||
logo_width_px: getSlider('logoWidth'),
|
||||
logo_height_px: getSlider('logoHeight'),
|
||||
});
|
||||
// Refresh main view in case the WebDAV-URL display needs an update.
|
||||
document.getElementById('webdavUrl').textContent =
|
||||
(fd.get('webdav_url') || '').trim() || `webdav://${location.hostname}:1900/`;
|
||||
const msg = document.getElementById('settingsMsg');
|
||||
msg.textContent = '✓ Gespeichert';
|
||||
setTimeout(() => msg.textContent = '', 2000);
|
||||
|
||||
Reference in New Issue
Block a user