Refactor: split monolith into cmd/palette + internal/{store,api,web,lang} (#35)
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
{{template "head" .}}
|
||||
{{template "topbar" .}}
|
||||
<div class="page">
|
||||
<div class="float">
|
||||
<div class="settings-head">
|
||||
<h1>Admin</h1>
|
||||
</div>
|
||||
<div class="settings-body">
|
||||
<p>Enter the admin key to manage server settings. The key is kept in
|
||||
sessionStorage for this tab only and is sent as a request header — it is
|
||||
never stored in a cookie, so it will not accompany normal paste requests.</p>
|
||||
<form id="admin-key-form">
|
||||
<label for="admin-key">Admin key</label><br>
|
||||
<input type="password" id="admin-key" autocomplete="off" style="width:100%">
|
||||
<button type="submit">Unlock</button>
|
||||
<span id="admin-key-status"></span>
|
||||
</form>
|
||||
<div id="admin-panel" style="display:none">
|
||||
<h2>Settings</h2>
|
||||
<form id="admin-settings-form">
|
||||
<table>
|
||||
<tr><td>Rate-limit burst</td><td><input type="number" id="rl-burst" min="1" step="1"></td></tr>
|
||||
<tr><td>Rate-limit refill per minute</td><td><input type="number" id="rl-refill" min="0.1" step="0.1"></td></tr>
|
||||
<tr><td>Max content bytes</td><td><input type="number" id="max-content" min="1" step="1"></td></tr>
|
||||
<tr><td>Default expiry</td><td><input type="text" id="default-expiry" placeholder="e.g. 168h, 30m, 0 = never"></td></tr>
|
||||
<tr><td>Custom URL reservation days</td><td><input type="number" id="slug-days" min="1" step="1"></td></tr>
|
||||
<tr><td>Burn viewer window (minutes)</td><td><input type="number" id="burn-window" min="1" step="1"></td></tr>
|
||||
</table>
|
||||
<button type="submit">Save</button>
|
||||
<span id="admin-save-status"></span>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
(function () {
|
||||
var KEY = 'palette_admin_key';
|
||||
var keyInput = document.getElementById('admin-key');
|
||||
var status = document.getElementById('admin-key-status');
|
||||
var panel = document.getElementById('admin-panel');
|
||||
|
||||
function key() { return sessionStorage.getItem(KEY) || ''; }
|
||||
|
||||
function api(path, opts) {
|
||||
opts = opts || {};
|
||||
opts.headers = { 'X-Admin-Key': key() };
|
||||
if (opts.body) opts.headers['Content-Type'] = 'application/json';
|
||||
return fetch(path, opts);
|
||||
}
|
||||
|
||||
function loadSettings() {
|
||||
api('/admin/api/settings').then(function (r) {
|
||||
if (r.status !== 200) { showLock(); return; }
|
||||
return r.json();
|
||||
}).then(function (s) {
|
||||
if (!s) return;
|
||||
document.getElementById('rl-burst').value = s.rate_limit_burst;
|
||||
document.getElementById('rl-refill').value = s.rate_limit_per_minute;
|
||||
document.getElementById('max-content').value = s.max_content_bytes;
|
||||
document.getElementById('default-expiry').value = s.default_expiry;
|
||||
document.getElementById('slug-days').value = s.custom_slug_reservation_days;
|
||||
document.getElementById('burn-window').value = s.burn_viewer_window_minutes;
|
||||
panel.style.display = '';
|
||||
});
|
||||
}
|
||||
|
||||
function showLock() {
|
||||
panel.style.display = 'none';
|
||||
sessionStorage.removeItem(KEY);
|
||||
}
|
||||
|
||||
document.getElementById('admin-key-form').addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
sessionStorage.setItem(KEY, keyInput.value);
|
||||
api('/admin/api/settings').then(function (r) {
|
||||
if (r.status === 200) {
|
||||
status.textContent = '✓';
|
||||
keyInput.value = '';
|
||||
loadSettings();
|
||||
} else {
|
||||
status.textContent = 'invalid key';
|
||||
showLock();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('admin-settings-form').addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
var body = {
|
||||
rate_limit_burst: parseFloat(document.getElementById('rl-burst').value),
|
||||
rate_limit_per_minute: parseFloat(document.getElementById('rl-refill').value),
|
||||
max_content_bytes: parseInt(document.getElementById('max-content').value, 10),
|
||||
default_expiry: document.getElementById('default-expiry').value,
|
||||
custom_slug_reservation_days: parseInt(document.getElementById('slug-days').value, 10),
|
||||
burn_viewer_window_minutes: parseInt(document.getElementById('burn-window').value, 10)
|
||||
};
|
||||
api('/admin/api/settings', { method: 'POST', body: JSON.stringify(body) }).then(function (r) {
|
||||
document.getElementById('admin-save-status').textContent = r.status === 200 ? 'saved' : 'error';
|
||||
if (r.status !== 200) showLock();
|
||||
});
|
||||
});
|
||||
|
||||
if (key()) loadSettings();
|
||||
})();
|
||||
</script>
|
||||
{{template "foot" .}}
|
||||
Reference in New Issue
Block a user