Loading admin/static/app.js +53 −0 Changes for admin/static/app.js: 53 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -274,6 +274,56 @@ const ProxyPlusAdmin = (() => { } } async function refreshPluginConfigs() { const configs = await api("GET", "/api/v1/plugins/config"); const body = document.querySelector("#plugin-configs tbody"); body.innerHTML = ""; for (const c of configs) { const tr = document.createElement("tr"); tr.innerHTML = `<td>${c.plugin_name}</td><td><pre>${c.config_blob}</pre></td><td>${c.enabled ? "ja" : "nein"}</td><td></td>`; addEditButton(tr, () => editPluginConfig(c)); addDeleteButton(tr, () => deletePluginConfig(c.plugin_name)); body.appendChild(tr); } } function editPluginConfig(c) { showNewPluginConfigForm(); document.getElementById("plugin-config-name").value = c.plugin_name; document.getElementById("plugin-config-name").readOnly = true; document.getElementById("plugin-config-blob").value = c.config_blob; document.getElementById("plugin-config-enabled").checked = c.enabled; } async function deletePluginConfig(pluginName) { if (!confirm("Plugin-Konfiguration '" + pluginName + "' wirklich löschen?")) return; try { await api("DELETE", "/api/v1/plugins/config", { plugin_name: pluginName }); await refreshPluginConfigs(); } catch (e) { document.getElementById("plugin-config-error").textContent = e.message; } } function showNewPluginConfigForm() { document.getElementById("plugin-config-name").readOnly = false; document.getElementById("new-plugin-config-form").hidden = false; } async function createPluginConfig() { document.getElementById("plugin-config-error").textContent = ""; try { await api("POST", "/api/v1/plugins/config", { plugin_name: document.getElementById("plugin-config-name").value, config_blob: document.getElementById("plugin-config-blob").value, enabled: document.getElementById("plugin-config-enabled").checked, }); await refreshPluginConfigs(); } catch (e) { document.getElementById("plugin-config-error").textContent = e.message; } } async function refreshAll() { await Promise.all([ refreshStatus(), Loading @@ -282,6 +332,7 @@ const ProxyPlusAdmin = (() => { refreshPools(), refreshTlsProfiles(), refreshDkimKeys(), refreshPluginConfigs(), ]); } Loading Loading @@ -475,6 +526,8 @@ const ProxyPlusAdmin = (() => { createDkimKey, showNewPoolForm, createPool, showNewPluginConfigForm, createPluginConfig, exportConfig, importConfig, }; Loading admin/static/index.html +15 −0 Changes for admin/static/index.html: 15 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -103,6 +103,21 @@ <div id="pool-error" class="error"></div> </div> <h2>Plugin-Konfiguration</h2> <p>Wirkt erst nach einem Neustart (Plugins werden nur beim Start neu geladen). Fuer ZeroSSL-Konten, die nicht ueber die kostenlose eab-credentials-email-Schnittstelle laufen: eab_kid und eab_hmac_key aus dem ZeroSSL-Dashboard ("Verify Domain" -> API) eintragen, um den automatischen Abruf per E-Mail zu ueberschreiben.</p> <table id="plugin-configs"><thead><tr><th>Plugin</th><th>Konfiguration</th><th>Aktiv</th><th>Aktionen</th></tr></thead><tbody></tbody></table> <button onclick="ProxyPlusAdmin.showNewPluginConfigForm()">Neue Plugin-Konfiguration</button> <div id="new-plugin-config-form" hidden> <input id="plugin-config-name" placeholder="Plugin-Name, z.B. zerossl"> <textarea id="plugin-config-blob" placeholder="key=value, eine pro Zeile, z.B.: eab_kid=... eab_hmac_key=..." rows="4"></textarea> <label><input type="checkbox" id="plugin-config-enabled" checked> Aktiv</label> <button onclick="ProxyPlusAdmin.createPluginConfig()">Speichern</button> <div id="plugin-config-error" class="error"></div> </div> <h2>Konfiguration Export/Import</h2> <p>Umfasst HTTP-Routen, SMTP-Relays, TLS-Profile (inkl. versiegeltem Schluesselmaterial fuer eigene Zertifikate), Pools und DKIM-Schluessel. Import ergaenzt/ueberschreibt nur die Loading Loading
admin/static/app.js +53 −0 Changes for admin/static/app.js: 53 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -274,6 +274,56 @@ const ProxyPlusAdmin = (() => { } } async function refreshPluginConfigs() { const configs = await api("GET", "/api/v1/plugins/config"); const body = document.querySelector("#plugin-configs tbody"); body.innerHTML = ""; for (const c of configs) { const tr = document.createElement("tr"); tr.innerHTML = `<td>${c.plugin_name}</td><td><pre>${c.config_blob}</pre></td><td>${c.enabled ? "ja" : "nein"}</td><td></td>`; addEditButton(tr, () => editPluginConfig(c)); addDeleteButton(tr, () => deletePluginConfig(c.plugin_name)); body.appendChild(tr); } } function editPluginConfig(c) { showNewPluginConfigForm(); document.getElementById("plugin-config-name").value = c.plugin_name; document.getElementById("plugin-config-name").readOnly = true; document.getElementById("plugin-config-blob").value = c.config_blob; document.getElementById("plugin-config-enabled").checked = c.enabled; } async function deletePluginConfig(pluginName) { if (!confirm("Plugin-Konfiguration '" + pluginName + "' wirklich löschen?")) return; try { await api("DELETE", "/api/v1/plugins/config", { plugin_name: pluginName }); await refreshPluginConfigs(); } catch (e) { document.getElementById("plugin-config-error").textContent = e.message; } } function showNewPluginConfigForm() { document.getElementById("plugin-config-name").readOnly = false; document.getElementById("new-plugin-config-form").hidden = false; } async function createPluginConfig() { document.getElementById("plugin-config-error").textContent = ""; try { await api("POST", "/api/v1/plugins/config", { plugin_name: document.getElementById("plugin-config-name").value, config_blob: document.getElementById("plugin-config-blob").value, enabled: document.getElementById("plugin-config-enabled").checked, }); await refreshPluginConfigs(); } catch (e) { document.getElementById("plugin-config-error").textContent = e.message; } } async function refreshAll() { await Promise.all([ refreshStatus(), Loading @@ -282,6 +332,7 @@ const ProxyPlusAdmin = (() => { refreshPools(), refreshTlsProfiles(), refreshDkimKeys(), refreshPluginConfigs(), ]); } Loading Loading @@ -475,6 +526,8 @@ const ProxyPlusAdmin = (() => { createDkimKey, showNewPoolForm, createPool, showNewPluginConfigForm, createPluginConfig, exportConfig, importConfig, }; Loading
admin/static/index.html +15 −0 Changes for admin/static/index.html: 15 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -103,6 +103,21 @@ <div id="pool-error" class="error"></div> </div> <h2>Plugin-Konfiguration</h2> <p>Wirkt erst nach einem Neustart (Plugins werden nur beim Start neu geladen). Fuer ZeroSSL-Konten, die nicht ueber die kostenlose eab-credentials-email-Schnittstelle laufen: eab_kid und eab_hmac_key aus dem ZeroSSL-Dashboard ("Verify Domain" -> API) eintragen, um den automatischen Abruf per E-Mail zu ueberschreiben.</p> <table id="plugin-configs"><thead><tr><th>Plugin</th><th>Konfiguration</th><th>Aktiv</th><th>Aktionen</th></tr></thead><tbody></tbody></table> <button onclick="ProxyPlusAdmin.showNewPluginConfigForm()">Neue Plugin-Konfiguration</button> <div id="new-plugin-config-form" hidden> <input id="plugin-config-name" placeholder="Plugin-Name, z.B. zerossl"> <textarea id="plugin-config-blob" placeholder="key=value, eine pro Zeile, z.B.: eab_kid=... eab_hmac_key=..." rows="4"></textarea> <label><input type="checkbox" id="plugin-config-enabled" checked> Aktiv</label> <button onclick="ProxyPlusAdmin.createPluginConfig()">Speichern</button> <div id="plugin-config-error" class="error"></div> </div> <h2>Konfiguration Export/Import</h2> <p>Umfasst HTTP-Routen, SMTP-Relays, TLS-Profile (inkl. versiegeltem Schluesselmaterial fuer eigene Zertifikate), Pools und DKIM-Schluessel. Import ergaenzt/ueberschreibt nur die Loading