v0.34.5
This commit is contained in:
1 parent
3776edf4fc
commit
7cfc3a6da1
35 files changed
+1377
-875
No files matched your search
@@ -37,23 +37,25 @@ function load(value = defaults(), migrationIds = [], show = true) {
|
||||
draftEpoch++; stagedCertificates = []; uploading = false; backendHealthEditorControl = null;
|
||||
editing = value.id || null; revision = envelope?.revision ?? null; dirty = false; initialized = true;
|
||||
container.replaceChildren(); $("vhost-editing").textContent = t(editing ? "vhEditLabel" : "vhNewLabel");
|
||||
let g = group("vhEditor"); field(g, "id", "vhId", value.id, "text", { required: true, maxLength: 64, pattern: "[A-Za-z0-9_-]{1,64}" }); if (editing) note(g, "vhIdRenameHelp");
|
||||
let g = group("vhEditor"); const basicFields = subsection(g, "vhGeneralDetailsSection");
|
||||
field(basicFields, "id", "vhId", value.id, "text", { required: true, maxLength: 64, pattern: "[A-Za-z0-9_-]{1,64}" }); if (editing) note(basicFields, "vhIdRenameHelp");
|
||||
let refreshCanonical = () => { };
|
||||
const enabledControl = field(g, "enabled", "vhEnabled", value.enabled !== false, "checkbox");
|
||||
const enabledControl = field(basicFields, "enabled", "vhEnabled", value.enabled !== false, "checkbox");
|
||||
window.rustProxyEnableControl(enabledControl, "vhEnableHint");
|
||||
const enabledLabel = enabledControl.closest("label");
|
||||
enabledLabel?.querySelector(".vh-enable-hint")?.remove();
|
||||
enabledLabel?.classList.add("vh-enable-no-hint");
|
||||
const mainSource = field(g, "source-type", "sourceType", value.source?.type || "reverse_proxy", "select", { values: [["reverse_proxy", "sourceReverseProxy"], ["web_server", "sourceWebServer"]] });
|
||||
const mainWebService = field(g, "source-web-service", "webService", value.source?.web_service_id || "", "select"); fillWebServices(mainWebService, value.source?.web_service_id || "");
|
||||
const mainSource = field(basicFields, "source-type", "sourceType", value.source?.type || "reverse_proxy", "select", { values: [["reverse_proxy", "sourceReverseProxy"], ["web_server", "sourceWebServer"]] });
|
||||
const mainWebService = field(basicFields, "source-web-service", "webService", value.source?.web_service_id || "", "select"); fillWebServices(mainWebService, value.source?.web_service_id || "");
|
||||
const syncMainSource = () => { const web = mainSource.value === "web_server"; mainWebService.disabled = !web; mainWebService.required = web; }; mainSource.addEventListener("change", syncMainSource); syncMainSource();
|
||||
note(g, "sourceHelp");
|
||||
const websocketEnabled = field(g, "websockets", "vhWebsockets", value.websockets !== false, "checkbox");
|
||||
note(basicFields, "sourceHelp");
|
||||
const websocketFields = subsection(g, "vhWebsocketOptionsSection");
|
||||
const websocketEnabled = field(websocketFields, "websockets", "vhWebsockets", value.websockets !== false, "checkbox");
|
||||
const websocketModeValue = value.websocket_rfc8441 === true && value.websocket_rfc9220 === true ? "h2h3" : value.websocket_rfc8441 === true ? "h2" : value.websocket_rfc9220 === true ? "h3" : "h1";
|
||||
const websocketMode = field(g, "websocket-mode", "vhWebsocketMode", websocketModeValue, "select", { values: [["h1", "vhWebsocketH1"], ["h2", "vhWebsocketH2Fallback"], ["h3", "vhWebsocketH3Fallback"], ["h2h3", "vhWebsocketH2H3Fallback"]] });
|
||||
note(g, "vhWebsocketTransportHelp");
|
||||
const websocketLegacy = field(g, "websocket-legacy-support", "vhWebsocketLegacySupport", value.websocket_legacy_support === true, "checkbox");
|
||||
note(g, "vhWebsocketLegacySupportHelp");
|
||||
const websocketMode = field(websocketFields, "websocket-mode", "vhWebsocketMode", websocketModeValue, "select", { values: [["h1", "vhWebsocketH1"], ["h2", "vhWebsocketH2Fallback"], ["h3", "vhWebsocketH3Fallback"], ["h2h3", "vhWebsocketH2H3Fallback"]] });
|
||||
note(websocketFields, "vhWebsocketTransportHelp");
|
||||
const websocketLegacy = field(websocketFields, "websocket-legacy-support", "vhWebsocketLegacySupport", value.websocket_legacy_support === true, "checkbox");
|
||||
note(websocketFields, "vhWebsocketLegacySupportHelp");
|
||||
g = group("vhFrontends");
|
||||
readHosts = hostTagEditor(g, value.frontend?.hosts || [], hosts => refreshCanonical(hosts));
|
||||
const bindingControl = window.rustProxyIntegrations.bindings(g, value.frontend?.listener_ids || [], !editing); readBindings = bindingControl.read;
|
||||
@@ -182,21 +184,25 @@ function load(value = defaults(), migrationIds = [], show = true) {
|
||||
field(g, "proxy-send-timeout", "vhProxySendTimeout", proxyTimeouts.send_timeout_seconds ?? 60, "number", { required: true, min: 1, max: 86400 });
|
||||
note(g, "vhProxyTimeoutsHelp");
|
||||
const settings = value.load_balancing || {}, health = settings.health_check || {}, keepalive = settings.keepalive || {}, retry = settings.retry || {}, sticky = settings.sticky || {};
|
||||
g = group("vhBalancing"); field(g, "algorithm", "vhAlgorithm", settings.algorithm || "least_connections", "select", { values: [["round_robin", "vhRoundRobin"], ["least_connections", "vhLeastConnections"], ["least_traffic", "vhLeastTraffic"], ["adaptive", "vhAdaptive"], ["ip_hash", "vhIpHash"]] });
|
||||
field(g, "slow-start", "vhSlowStart", settings.slow_start_seconds ?? 10, "number", { required: true, min: 0, max: 300 });
|
||||
field(g, "retry-max", "vhRetryMax", retry.max_retries ?? 1, "number", { required: true, min: 0, max: 3 });
|
||||
field(g, "retry-connect", "vhRetryConnect", retry.retry_connect_errors !== false, "checkbox");
|
||||
field(g, "retry-timeouts", "vhRetryTimeouts", retry.retry_timeouts !== false, "checkbox");
|
||||
field(g, "retry-statuses", "vhRetryStatuses", (retry.retry_statuses || [502, 503, 504]).join(", "), "text", { maxLength: 64 });
|
||||
note(g, "vhRetryHelp");
|
||||
field(g, "keepalive", "vhKeepalive", keepalive.enabled !== false, "checkbox");
|
||||
field(g, "idle-timeout", "vhIdleTimeout", keepalive.idle_timeout_seconds ?? 30, "number", { required: true, min: 1, max: 3600 });
|
||||
field(g, "max-idle", "vhMaxIdle", keepalive.max_idle_per_host ?? 64, "number", { required: true, min: 1, max: 64 });
|
||||
field(g, "tcp-keepalive", "vhTcpKeepalive", keepalive.tcp_keepalive_seconds ?? 30, "number", { required: true, min: 1, max: 3600 });
|
||||
field(g, "pool-recycle-requests", "vhPoolRecycleRequests", keepalive.pool_recycle_requests ?? 25000, "number", { required: true, min: 0, max: 10000000 });
|
||||
field(g, "pool-recycle-seconds", "vhPoolRecycleSeconds", keepalive.pool_recycle_seconds ?? 3600, "number", { required: true, min: 0, max: 604800 });
|
||||
field(g, "http1-max-buffer", "vhHttp1MaxBuffer", keepalive.http1_max_buffer_bytes ?? 131072, "number", { required: true, min: 8192, max: 1048576 });
|
||||
note(g, "vhPoolRecycleHelp");
|
||||
g = group("vhBalancing");
|
||||
const schedulingFields = subsection(g, "vhBalancerAlgorithmSection");
|
||||
field(schedulingFields, "algorithm", "vhAlgorithm", settings.algorithm || "least_connections", "select", { values: [["round_robin", "vhRoundRobin"], ["least_connections", "vhLeastConnections"], ["least_traffic", "vhLeastTraffic"], ["adaptive", "vhAdaptive"], ["ip_hash", "vhIpHash"]] });
|
||||
field(schedulingFields, "slow-start", "vhSlowStart", settings.slow_start_seconds ?? 10, "number", { required: true, min: 0, max: 300 });
|
||||
const retryFields = subsection(g, "vhBalancerRetrySection");
|
||||
field(retryFields, "retry-max", "vhRetryMax", retry.max_retries ?? 1, "number", { required: true, min: 0, max: 3 });
|
||||
field(retryFields, "retry-connect", "vhRetryConnect", retry.retry_connect_errors !== false, "checkbox");
|
||||
field(retryFields, "retry-timeouts", "vhRetryTimeouts", retry.retry_timeouts !== false, "checkbox");
|
||||
field(retryFields, "retry-statuses", "vhRetryStatuses", (retry.retry_statuses || [502, 503, 504]).join(", "), "text", { maxLength: 64 });
|
||||
note(retryFields, "vhRetryHelp");
|
||||
const keepaliveFields = subsection(g, "vhBalancerKeepaliveSection");
|
||||
field(keepaliveFields, "keepalive", "vhKeepalive", keepalive.enabled !== false, "checkbox");
|
||||
field(keepaliveFields, "idle-timeout", "vhIdleTimeout", keepalive.idle_timeout_seconds ?? 30, "number", { required: true, min: 1, max: 3600 });
|
||||
field(keepaliveFields, "max-idle", "vhMaxIdle", keepalive.max_idle_per_host ?? 64, "number", { required: true, min: 1, max: 64 });
|
||||
field(keepaliveFields, "tcp-keepalive", "vhTcpKeepalive", keepalive.tcp_keepalive_seconds ?? 30, "number", { required: true, min: 1, max: 3600 });
|
||||
field(keepaliveFields, "pool-recycle-requests", "vhPoolRecycleRequests", keepalive.pool_recycle_requests ?? 25000, "number", { required: true, min: 0, max: 10000000 });
|
||||
field(keepaliveFields, "pool-recycle-seconds", "vhPoolRecycleSeconds", keepalive.pool_recycle_seconds ?? 3600, "number", { required: true, min: 0, max: 604800 });
|
||||
field(keepaliveFields, "http1-max-buffer", "vhHttp1MaxBuffer", keepalive.http1_max_buffer_bytes ?? 131072, "number", { required: true, min: 8192, max: 1048576 });
|
||||
note(keepaliveFields, "vhPoolRecycleHelp");
|
||||
g = group("vhHealth"); const healthMode = field(g, "health-mode", "vhHealthMode", health.mode || "tcp", "select", { values: [["off", "vhOff"], ["tcp", "vhTcp"], ["http", "vhHttp"]] });
|
||||
const healthOffWarning = note(g, "vhHealthOffWarning"); const syncHealthWarning = () => { healthOffWarning.hidden = healthMode.value !== "off"; }; healthMode.addEventListener("change", syncHealthWarning); syncHealthWarning();
|
||||
field(g, "health-path", "vhHealthPath", health.path || "/", "text", { required: true, maxLength: 1024 });
|
||||
@@ -234,36 +240,60 @@ function load(value = defaults(), migrationIds = [], show = true) {
|
||||
field(g, "cookie-ttl", "vhCookieTtl", sticky.ttl_seconds ?? 3600, "number", { required: true, min: 60, max: 604800 }); note(g, "vhStickyNote");
|
||||
const rate = value.rate_limit || {}, access = rate.country_access || {}, methodPolicy = value.method_policy || {};
|
||||
g = group("vhTrafficPolicy");
|
||||
// Policies share their original form/data model; the boundaries are presentational only.
|
||||
const aclFields = subsection(g, "vhAclProfile");
|
||||
const selectedProfiles = new Set([value.acl_profile_id, ...(value.acl_profile_ids || [])].filter(Boolean));
|
||||
const profileBox = el("div", undefined, "vh-wide vh-acl-profile-picker");
|
||||
profileBox.append(text("strong", "vhAclProfile"));
|
||||
const choices = window.rustProxyAclPicker.create([...selectedProfiles], "vh-acl-profile-choices");
|
||||
profileBox.append(choices);
|
||||
const multiWarning = text("p", "multiAclWarning", "fine acl-stack-warning");
|
||||
const syncMultiWarning = () => { multiWarning.hidden = choices.querySelectorAll('input:checked').length < 2; };
|
||||
choices.addEventListener("change", syncMultiWarning); syncMultiWarning();
|
||||
profileBox.append(multiWarning); g.append(profileBox); note(g, "vhAclProfileHelp");
|
||||
field(g, "method-mode", "vhMethodMode", methodPolicy.mode || "off", "select", { values: [["off", "vhOff"], ["allow", "locationMethodAllow"], ["block", "locationMethodBlock"]] });
|
||||
field(g, "method-list", "vhMethodList", (methodPolicy.methods || []).join("\n"), "textarea", { rows: 3, maxLength: 1024 });
|
||||
note(g, "vhMethodHelp");
|
||||
field(g, "rate-enabled", "vhRateEnabled", rate.enabled === true, "checkbox");
|
||||
field(g, "rate-requests", "vhRateRequests", rate.requests ?? 120, "number", { required: true, min: 1, max: 1000000 });
|
||||
field(g, "rate-window", "vhRateWindow", rate.window_seconds ?? 60, "number", { required: true, min: 1, max: 3600 });
|
||||
field(g, "rate-burst", "vhRateBurst", rate.burst ?? 30, "number", { required: true, min: 0, max: 1000000 });
|
||||
field(g, "country-mode", "vhCountryMode", access.mode || "off", "select", { values: [["off", "vhOff"], ["block", "vhCountryBlock"], ["allow", "vhCountryAllow"]] });
|
||||
field(g, "country-list", "vhCountryList", (access.countries || []).join("\n"), "textarea", { rows: 3, maxLength: 1024 });
|
||||
note(g, "vhCountryPolicyHelp"); countryRatesReader = countryRateEditor(g, rate.country_limits || []); uaRatesReader = userAgentRateEditor(g, rate.user_agent_limits || []); note(g, "vhRateHelp");
|
||||
profileBox.append(multiWarning); aclFields.append(profileBox); note(aclFields, "vhAclProfileHelp");
|
||||
|
||||
const inlineAclFields = subsection(g, "vhIpAccess");
|
||||
aclControl = aclEditor(inlineAclFields, value.acl, () => { if (aclControl) read("acl").value = JSON.stringify(aclControl.read(), null, 2); });
|
||||
note(inlineAclFields, "vhInlineAclHelp");
|
||||
|
||||
const methodFields = subsection(g, "vhTrafficMethodsSection");
|
||||
field(methodFields, "method-mode", "vhMethodMode", methodPolicy.mode || "off", "select", { values: [["off", "vhOff"], ["allow", "locationMethodAllow"], ["block", "locationMethodBlock"]] });
|
||||
field(methodFields, "method-list", "vhMethodList", (methodPolicy.methods || []).join("\n"), "textarea", { rows: 3, maxLength: 1024 });
|
||||
note(methodFields, "vhMethodHelp");
|
||||
|
||||
const rateFields = subsection(g, "vhTrafficRateSection");
|
||||
field(rateFields, "rate-enabled", "vhRateEnabled", rate.enabled === true, "checkbox");
|
||||
field(rateFields, "rate-requests", "vhRateRequests", rate.requests ?? 120, "number", { required: true, min: 1, max: 1000000 });
|
||||
field(rateFields, "rate-window", "vhRateWindow", rate.window_seconds ?? 60, "number", { required: true, min: 1, max: 3600 });
|
||||
field(rateFields, "rate-burst", "vhRateBurst", rate.burst ?? 30, "number", { required: true, min: 0, max: 1000000 });
|
||||
note(rateFields, "vhRateHelp");
|
||||
|
||||
const countryFields = subsection(g, "vhTrafficCountrySection");
|
||||
field(countryFields, "country-mode", "vhCountryMode", access.mode || "off", "select", { values: [["off", "vhOff"], ["block", "vhCountryBlock"], ["allow", "vhCountryAllow"]] });
|
||||
field(countryFields, "country-list", "vhCountryList", (access.countries || []).join("\n"), "textarea", { rows: 3, maxLength: 1024 });
|
||||
note(countryFields, "vhCountryPolicyHelp");
|
||||
|
||||
const countryRateFields = subsection(g, "vhTrafficCountryRatesSection");
|
||||
countryRatesReader = countryRateEditor(countryRateFields, rate.country_limits || []);
|
||||
const uaRateFields = subsection(g, "vhUaRateTitle");
|
||||
uaRatesReader = userAgentRateEditor(uaRateFields, rate.user_agent_limits || [], false);
|
||||
const security = value.security_headers || {}, hsts = security.hsts || {};
|
||||
g = group("vhSecurity"); field(g, "hsts", "vhHsts", hsts.enabled, "checkbox"); field(g, "hsts-age", "vhHstsAge", hsts.max_age_seconds ?? 31536000, "number", { required: true, min: 0, max: 63072000 });
|
||||
field(g, "hsts-sub", "vhHstsSub", hsts.include_subdomains, "checkbox"); field(g, "hsts-preload", "vhHstsPreload", hsts.preload, "checkbox"); field(g, "nosniff", "vhNosniff", security.nosniff, "checkbox");
|
||||
field(g, "frame", "vhFrame", security.frame_options || "preserve", "select", { values: [["preserve", "vhPreserve"], ["deny", "vhDeny"], ["sameorigin", "vhSameorigin"]] });
|
||||
field(g, "referrer", "vhReferrer", security.referrer_policy || "", "text", { maxLength: 8192 });
|
||||
field(g, "csp", "vhCsp", security.content_security_policy || "", "textarea", { rows: 2, maxLength: 8192 });
|
||||
field(g, "permissions", "vhPermissions", security.permissions_policy || "", "text", { maxLength: 8192 });
|
||||
g = group("vhSecurity");
|
||||
const hstsFields = subsection(g, "vhSecurityHstsSection");
|
||||
field(hstsFields, "hsts", "vhHsts", hsts.enabled, "checkbox");
|
||||
field(hstsFields, "hsts-age", "vhHstsAge", hsts.max_age_seconds ?? 31536000, "number", { required: true, min: 0, max: 63072000 });
|
||||
field(hstsFields, "hsts-sub", "vhHstsSub", hsts.include_subdomains, "checkbox");
|
||||
field(hstsFields, "hsts-preload", "vhHstsPreload", hsts.preload, "checkbox");
|
||||
const headersFields = subsection(g, "vhSecurityHeadersSection");
|
||||
field(headersFields, "nosniff", "vhNosniff", security.nosniff, "checkbox");
|
||||
field(headersFields, "frame", "vhFrame", security.frame_options || "preserve", "select", { values: [["preserve", "vhPreserve"], ["deny", "vhDeny"], ["sameorigin", "vhSameorigin"]] });
|
||||
field(headersFields, "referrer", "vhReferrer", security.referrer_policy || "", "text", { maxLength: 8192 });
|
||||
field(headersFields, "csp", "vhCsp", security.content_security_policy || "", "textarea", { rows: 2, maxLength: 8192 });
|
||||
field(headersFields, "permissions", "vhPermissions", security.permissions_policy || "", "text", { maxLength: 8192 });
|
||||
const uaBlock = value.user_agent_blocking || {};
|
||||
field(g, "ua-block-enabled", "vhUaBlockEnabled", uaBlock.enabled === true, "checkbox");
|
||||
field(g, "ua-block-patterns", "vhUaBlockPatterns", (uaBlock.patterns || []).join("\n"), "textarea", { rows: 4, maxLength: 32768 });
|
||||
note(g, "vhUaBlockHelp");
|
||||
const uaBlockingFields = subsection(g, "vhUaBlockSection");
|
||||
field(uaBlockingFields, "ua-block-enabled", "vhUaBlockEnabled", uaBlock.enabled === true, "checkbox");
|
||||
field(uaBlockingFields, "ua-block-patterns", "vhUaBlockPatterns", (uaBlock.patterns || []).join("\n"), "textarea", { rows: 4, maxLength: 32768 });
|
||||
note(uaBlockingFields, "vhUaBlockHelp");
|
||||
g = group("vhAdvanced", true); field(g, "paths", "vhPaths", JSON.stringify(value.routes || [], null, 2), "textarea", { rows: 5, maxLength: 131072 });
|
||||
field(g, "acl", "vhAcl", JSON.stringify(value.acl ?? null, null, 2), "textarea", { rows: 5, maxLength: 32768 });
|
||||
field(g, "headers", "vhHeaders", JSON.stringify(value.headers || {}, null, 2), "textarea", { rows: 5, maxLength: 65536 });
|
||||
@@ -273,13 +303,16 @@ function load(value = defaults(), migrationIds = [], show = true) {
|
||||
note(g, "vhErrorFallbackHelp");
|
||||
locationsReader = locationsEditor(g, value.routes || []);
|
||||
g = group("vhSsl");
|
||||
const selector = field(g, "certificate-id", "vhCertificate", value.certificate_id || "", "select");
|
||||
const certificateRow = el("div", undefined, "vh-wide vh-certificate-select-row"); g.append(certificateRow);
|
||||
const selector = field(certificateRow, "certificate-id", "vhCertificate", value.certificate_id || "", "select");
|
||||
const fillCertificates = () => { const selected = selector.value || value.certificate_id || ""; const inherit = text("option", "vhCertificateDefault"); inherit.value = ""; selector.replaceChildren(inherit, ...[...(envelope?.config.tls?.certificates || []), ...stagedCertificates].map(c => { const o = el("option", c.id); o.value = c.id; return o; })); selector.value = selected; }; fillCertificates();
|
||||
g.append(button("certManage", async () => { if (!(await closeEditor())) return; setPanel("tls"); })); note(g, "certSelectHint");
|
||||
certificateRow.append(button("certManage", async () => { if (!(await closeEditor())) return; setPanel("tls"); }));
|
||||
note(g, "certSelectHint");
|
||||
const mismatch = field(g, "allow-certificate-mismatch", "vhCertificateMismatchForce", value.allow_certificate_mismatch === true, "checkbox");
|
||||
const mismatchHint = note(g, "vhCertificateMismatchWarning");
|
||||
const syncMismatch = () => { mismatch.disabled = !selector.value; if (!selector.value) mismatch.checked = false; mismatchHint.hidden = !mismatch.checked; };
|
||||
selector.addEventListener("change", syncMismatch); mismatch.addEventListener("change", syncMismatch); syncMismatch();
|
||||
g = group("vhSslSettings");
|
||||
const inheritedTlsPolicy = envelope?.config.tls?.policy || { tls12: true, tls13: true, cipher_suites: [] };
|
||||
const tlsPolicy = value.tls_policy || inheritedTlsPolicy;
|
||||
const customTlsPolicy = field(g, "tls-policy-custom", "vhTlsOverride", value.tls_policy != null, "checkbox");
|
||||
@@ -288,15 +321,11 @@ function load(value = defaults(), migrationIds = [], show = true) {
|
||||
const tlsCiphers = field(g, "tls-policy-ciphers", "tlsCiphers", (tlsPolicy.cipher_suites || []).join("\n"), "textarea", { rows: 7, maxLength: 8192 });
|
||||
const syncTlsPolicy = () => { for (const input of [tls12, tls13, tlsCiphers]) input.disabled = !customTlsPolicy.checked; };
|
||||
customTlsPolicy.addEventListener("change", syncTlsPolicy); syncTlsPolicy(); note(g, "vhTlsOverrideHelp");
|
||||
g = group("vhTinyauth"); const auth = value.tinyauth || {}, authRoot = g;
|
||||
g = group("vhTinyauth"); const auth = value.tinyauth || {};
|
||||
const authMode = field(g, "auth-mode", "authMode", value.basic_auth?.enabled ? "basic" : auth.enabled ? "tinyauth" : "none", "select", { values: [["none", "authNone"], ["tinyauth", "authTinyauth"], ["basic", "authBasic"]] });
|
||||
note(g, "authModeHelp");
|
||||
|
||||
const aclBody = el("section", undefined, "vh-wide auth-subcard auth-ip-card"); authRoot.append(aclBody);
|
||||
aclBody.append(text("h3", "vhIpAccess"));
|
||||
aclControl = aclEditor(aclBody, value.acl, () => { if (aclControl) read("acl").value = JSON.stringify(aclControl.read(), null, 2); });
|
||||
|
||||
const taBody = el("section", undefined, "vh-wide auth-subcard"), basicBody = el("section", undefined, "vh-wide auth-subcard"); authRoot.append(taBody, basicBody);
|
||||
const taBody = el("section", undefined, "vh-wide auth-subcard"), basicBody = el("section", undefined, "vh-wide auth-subcard"); g.append(taBody, basicBody);
|
||||
taBody.append(text("h3", "authTinyauth"));
|
||||
const taPrimary = el("div", undefined, "vh-grid"); taBody.append(taPrimary);
|
||||
const authEnable = field(taPrimary, "auth-enabled", "taEnable", auth.enabled, "checkbox");
|
||||
@@ -361,16 +390,21 @@ function load(value = defaults(), migrationIds = [], show = true) {
|
||||
field(cacheOptions, "vh-cache-object", "vhCacheObject", cache.max_object_bytes == null ? "" : cache.max_object_bytes / 1024, "number", { min: 1, step: "any", max: (envelope?.config.cache?.max_object_bytes ?? 1048576) / 1024 });
|
||||
tri(cacheOptions, "vh-cache-query", "cacheBypassQuery", cache.bypass_query);
|
||||
tri(cacheOptions, "vh-cache-static-cookie", "vhCacheStaticCookie", cache.static_ignore_cookies);
|
||||
const customStatic = field(cacheOptions, "vh-cache-static-custom", "vhCacheStaticCustom", cache.static_extensions != null, "checkbox");
|
||||
const staticExtensions = field(cacheOptions, "vh-cache-static-extensions", "vhCacheStaticExtensions", (cache.static_extensions || envelope?.config.cache?.static_extensions || []).join("\n"), "textarea", { rows: 5, maxLength: 2048 });
|
||||
const syncStatic = () => { staticExtensions.disabled = !customStatic.checked; }; customStatic.addEventListener("change", syncStatic); syncStatic(); note(cacheOptions, "vhCacheStaticHelp");
|
||||
const staticExtensionFields = el("div", undefined, "vh-wide vh-override-fields"); cacheOptions.append(staticExtensionFields);
|
||||
const customStatic = field(staticExtensionFields, "vh-cache-static-custom", "vhCacheStaticCustom", cache.static_extensions != null, "checkbox");
|
||||
const staticExtensions = field(staticExtensionFields, "vh-cache-static-extensions", "vhCacheStaticExtensions", (cache.static_extensions || envelope?.config.cache?.static_extensions || []).join("\n"), "textarea", { rows: 5, maxLength: 2048 });
|
||||
const syncStatic = () => { staticExtensions.disabled = !customStatic.checked; }; customStatic.addEventListener("change", syncStatic); syncStatic(); note(staticExtensionFields, "vhCacheStaticHelp");
|
||||
tri(cacheOptions, "vh-cache-status", "cacheStatusHeader", cache.expose_status); tri(cacheOptions, "vh-cache-hits", "cacheHitsHeader", cache.expose_hits); tri(cacheOptions, "vh-cache-rfc", "cacheRfcHeader", cache.expose_cache_status); tri(cacheOptions, "vh-cache-resident-age", "cacheResidentAge", cache.expose_resident_age); tri(cacheOptions, "vh-cache-only-hits", "cacheOnlyHits", cache.expose_only_hits);
|
||||
field(cacheOptions, "vh-cache-prefix-custom", "vhCacheCustomPrefixes", cache.bypass_prefixes != null, "checkbox");
|
||||
field(cacheOptions, "vh-cache-prefixes", "cacheBypassPrefixes", (cache.bypass_prefixes || []).join("\n"), "textarea", { rows: 2, maxLength: 32768 }); note(cacheOptions, "vhCacheHint");
|
||||
const forceCache = field(cacheOptions, "vh-cache-force-enabled", "vhCacheForceEnabled", cache.unsafe_force?.enabled === true, "checkbox");
|
||||
const forceTargets = field(cacheOptions, "vh-cache-force-targets", "vhCacheForceTargets", (cache.unsafe_force?.targets || []).join("\n"), "textarea", { rows: 3, maxLength: 65536 });
|
||||
const bypassFields = el("div", undefined, "vh-wide vh-override-fields"); cacheOptions.append(bypassFields);
|
||||
const customCachePrefixes = field(bypassFields, "vh-cache-prefix-custom", "vhCacheCustomPrefixes", cache.bypass_prefixes != null, "checkbox");
|
||||
const bypassPrefixes = field(bypassFields, "vh-cache-prefixes", "cacheBypassPrefixes", (cache.bypass_prefixes || []).join("\n"), "textarea", { rows: 2, maxLength: 32768 });
|
||||
const syncBypassPrefixes = () => { bypassPrefixes.disabled = !customCachePrefixes.checked; };
|
||||
customCachePrefixes.addEventListener("change", syncBypassPrefixes); syncBypassPrefixes(); note(bypassFields, "vhCacheHint");
|
||||
const unsafeCacheFields = el("div", undefined, "vh-wide vh-override-fields"); cacheOptions.append(unsafeCacheFields);
|
||||
const forceCache = field(unsafeCacheFields, "vh-cache-force-enabled", "vhCacheForceEnabled", cache.unsafe_force?.enabled === true, "checkbox");
|
||||
const forceTargets = field(unsafeCacheFields, "vh-cache-force-targets", "vhCacheForceTargets", (cache.unsafe_force?.targets || []).join("\n"), "textarea", { rows: 3, maxLength: 65536 });
|
||||
const syncForceCache = () => { forceTargets.disabled = !forceCache.checked; }; forceCache.addEventListener("change", async () => { if (forceCache.checked && !(await appConfirm(t("vhCacheForceConfirm"), { danger: true }))) forceCache.checked = false; syncForceCache(); }); syncForceCache();
|
||||
note(cacheOptions, "vhCacheForceHelp");
|
||||
note(unsafeCacheFields, "vhCacheForceHelp");
|
||||
if (editing) cacheOptions.append(button("vhPurgeCache", () => purge(editing)));
|
||||
const syncCacheVisibility = () => {
|
||||
const enabled = envelope?.config.cache?.enabled === true && cacheToggle.value !== "off";
|
||||
@@ -381,8 +415,9 @@ function load(value = defaults(), migrationIds = [], show = true) {
|
||||
const transformEnabled = field(g, "vh-transform-enabled", "vhTransformEnable", transform.enabled === true, "checkbox");
|
||||
const transformOptions = el("div", undefined, "vh-wide vh-grid vh-transform-options"); g.append(transformOptions);
|
||||
for (const [name, key] of [["javascript", "transformJavascript"], ["css", "transformCss"], ["html", "transformHtml"], ["svg", "transformSvg"], ["json", "transformJson"]]) tri(transformOptions, `vh-transform-${name}`, key, transform[name]);
|
||||
const customTransformExtensions = field(transformOptions, "vh-transform-extensions-custom", "vhTransformExtensionsCustom", transform.extensions != null, "checkbox");
|
||||
const transformExtensions = field(transformOptions, "vh-transform-extensions", "transformExtensions", (transform.extensions || envelope?.config.transform?.extensions || []).join("\n"), "textarea", { rows: 5, maxLength: 2048 });
|
||||
const transformExtensionFields = el("div", undefined, "vh-wide vh-override-fields"); transformOptions.append(transformExtensionFields);
|
||||
const customTransformExtensions = field(transformExtensionFields, "vh-transform-extensions-custom", "vhTransformExtensionsCustom", transform.extensions != null, "checkbox");
|
||||
const transformExtensions = field(transformExtensionFields, "vh-transform-extensions", "transformExtensions", (transform.extensions || envelope?.config.transform?.extensions || []).join("\n"), "textarea", { rows: 5, maxLength: 2048 });
|
||||
const syncTransform = () => {
|
||||
transformOptions.hidden = !transformEnabled.checked;
|
||||
transformExtensions.disabled = !customTransformExtensions.checked;
|
||||
|
||||
Reference in new issue
Block a user