diff --git a/www/caddy/pkg-descr b/www/caddy/pkg-descr index c86f8a3f8..9fa23bafa 100644 --- a/www/caddy/pkg-descr +++ b/www/caddy/pkg-descr @@ -18,6 +18,19 @@ Plugin Changelog * Add: basic_auth per handler (opnsense/plugins/issues/4619) * Change: the ACL has been changed to "page-caddy" in "System: Access: Privileges". Privilege must be reassigned if used. (opnsense/plugins/issues/4623) * Change: standalone certificate widget has been removed, use system default certificate widget instead. (opnsense/plugins/pull/4637) +* Cleanup: UI improvements (opnsense/plugins/pull/4634) + * Cleanup of styles, formatters, and dialog layouts + * Dialog element hiding logic was improved + * "Filter by Domain" can filter subdomains + * "Filter by Domain" will preselect domain and subdomain in handler add dialog + * Grids are now responsive with automatic overflow on small screens + * Grids now lazy load on tab switch for improved performance + * Grids format domains and upstreams with protocol, domain, port and path in a single line + * "Layer4 Proxy" and "Reverse Proxy" now use the same volt template + * "Search Handler" and "Add Handler" buttons added to domain and subdomain grids + * Step buttons (Add Domain, Add Handler) have been removed since they are redundant + * Success messages on configuration apply have been removed, only errors will be shown + * Tabs use URL hash to preserve selection on refresh 1.8.4 diff --git a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/Api/ReverseProxyController.php b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/Api/ReverseProxyController.php index 742fb4e17..e6970cfa0 100644 --- a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/Api/ReverseProxyController.php +++ b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/Api/ReverseProxyController.php @@ -38,77 +38,94 @@ class ReverseProxyController extends ApiMutableModelControllerBase protected static $internalModelUseSafeDelete = true; /** - * Function for search filter dropdown - * - * @return array containing rows of domain and port combinations. + * Return selectpicker options for reverse proxy domains and ports */ public function getAllReverseDomainsAction() { - $result = array("rows" => array()); + $result = [ + 'domains' => [ + 'label' => gettext('Domains'), + 'icon' => 'fa fa-fw fa-globe text-success', + 'items' => [] + ], + 'subdomains' => [ + 'label' => gettext('Subdomains'), + 'icon' => 'fa fa-fw fa-globe text-warning', + 'items' => [] + ], + ]; - $mdlCaddy = new \OPNsense\Caddy\Caddy(); - $reverseNodes = $mdlCaddy->reverseproxy->reverse->iterateItems(); + foreach ((new \OPNsense\Caddy\Caddy())->reverseproxy->reverse->iterateItems() as $reverse) { + if (!empty($reverse->FromDomain)) { + $port = (string)$reverse->FromPort; + $combined = (string)$reverse->FromDomain . ($port !== '' ? ':' . $port : ''); - foreach ($reverseNodes as $item) { - if (!empty($item->FromDomain)) { - // Conditionally concatenate port if it exists - $domain = (string)$item->FromDomain; - $port = (string)$item->FromPort; - $combinedDomainPort = $domain . (!empty($port) ? ':' . $port : ''); - - $result['rows'][] = array( - 'id' => (string)$item->getAttributes()['uuid'], - 'domainPort' => $combinedDomainPort // Combined domain and port, conditionally adding port - ); + $result['domains']['items'][] = [ + 'value' => (string)$reverse->getAttributes()['uuid'], + 'label' => $combined + ]; } } + foreach ((new \OPNsense\Caddy\Caddy())->reverseproxy->subdomain->iterateItems() as $subdomain) { + if (!empty($subdomain->FromDomain)) { + + $result['subdomains']['items'][] = [ + 'value' => (string)$subdomain->getAttributes()['uuid'], + 'label' => (string)$subdomain->FromDomain + ]; + } + } + + foreach (array_keys($result) as $key) { + usort($result[$key]['items'], fn($a, $b) => strcasecmp($a['label'], $b['label'])); + } + return $result; } /** - * Generalized helper function for searching across different sections of the reverse proxy setup. - * This function mostly helps when model relation fields are used. - * It filters entries based on UUIDs provided as an argument. The section or key used for the UUID - * can be specified, allowing for direct or indirect UUID referencing. + * Build a UUID filter function. * - * @param string $modelPath The data model path identifier, pointing to section of model being searched. - * @param string $uuidSearchBase The request parameter name for the comma-separated list of UUIDs. - * @param string|null $uuidReferenceKey Attribute key used to fetch the UUID for filtering. - * If null, uses item's own UUID. - * @return array Filtered search results. + * @return callable|null */ - private function searchActionHelper($modelPath, $uuidSearchBase, $uuidReferenceKey = null) + private function buildFilterFunction(): ?callable { - // Fetch the comma-separated UUIDs string from the request using the provided parameter name. - $uuidList = $this->request->get($uuidSearchBase); - // Ensure the retrieved UUID list is a string and not empty before attempting to explode it. - $uuidArray = (!empty($uuidList) && is_string($uuidList)) ? explode(',', $uuidList) : []; + $domainUuids = $this->request->get('domainUuids'); + if (empty($domainUuids)) { + return null; + } - // Define a filter function to determine which items to include based on the UUID. - $filterFunction = function ($modelItem) use ($uuidArray, $uuidReferenceKey) { - // Extract UUID from the item, using the specified UUID key if provided, else default to direct UUID access. - if ($uuidReferenceKey !== null) { - $modelUUID = (string)$modelItem->$uuidReferenceKey; - } else { - $modelUUID = (string)$modelItem->getAttributes()['uuid']; + return function ($record) use ($domainUuids): bool { + $fieldsToCheck = ['reverse', 'subdomain']; + $uuids = []; + + // Add the record's own UUID + $uuidAttr = $record->getAttributes()['uuid'] ?? null; + if (is_scalar($uuidAttr)) { + $uuids[] = trim((string)$uuidAttr); } - // Include the item if the UUID array is empty or if the item's UUID is in the array. - return empty($uuidArray) || in_array($modelUUID, $uuidArray, true); + + // Add UUIDs from model relation fields + foreach ($fieldsToCheck as $field) { + $value = $record->{$field} ?? null; + + foreach ((array)$value as $item) { + if (is_scalar($item)) { + $uuids[] = trim((string)$item); + } + } + } + + return (bool) array_intersect($uuids, $domainUuids); }; - - // Perform the search using the specified model path and the filter function, returning the results. - // Note: This uses the existing search function of the ApiMutableModelControllerBase - return $this->searchBase($modelPath, null, 'description', $filterFunction); } - // ReverseProxy Section public function searchReverseProxyAction() { - // For domains, use their domain UUIDs directly, $uuidReferenceKey null added for explicit clarity - return $this->searchActionHelper("reverseproxy.reverse", "reverseUuids", null); + return $this->searchBase('reverseproxy.reverse', null, null, $this->buildFilterFunction()); } public function setReverseProxyAction($uuid) @@ -141,9 +158,7 @@ class ReverseProxyController extends ApiMutableModelControllerBase public function searchSubdomainAction() { - // For subdomains, compare 'reverseUuids' (which contain domain UUIDs) - // to 'reverse' (which contain the same domain UUIDs due to model relation field) - return $this->searchActionHelper("reverseproxy.subdomain", "reverseUuids", "reverse"); + return $this->searchBase('reverseproxy.subdomain', null, null, $this->buildFilterFunction()); } public function setSubdomainAction($uuid) @@ -174,12 +189,9 @@ class ReverseProxyController extends ApiMutableModelControllerBase // Handler Section - // Adjusted for search filter dropdown, using helper function public function searchHandleAction() { - // For handles, compare 'reverseUuids' (which contain domain UUIDs) - // to 'reverse' (which contain the same domain UUIDs due to model relation field) - return $this->searchActionHelper("reverseproxy.handle", "reverseUuids", "reverse"); + return $this->searchBase('reverseproxy.handle', null, null, $this->buildFilterFunction()); } public function setHandleAction($uuid) @@ -211,7 +223,7 @@ class ReverseProxyController extends ApiMutableModelControllerBase public function searchAccessListAction() { - return $this->searchBase("reverseproxy.accesslist", null, 'description'); + return $this->searchBase("reverseproxy.accesslist"); } public function setAccessListAction($uuid) @@ -239,7 +251,7 @@ class ReverseProxyController extends ApiMutableModelControllerBase public function searchBasicAuthAction() { - return $this->searchBase("reverseproxy.basicauth", null, 'description'); + return $this->searchBase("reverseproxy.basicauth"); } public function setBasicAuthAction($uuid) @@ -291,7 +303,7 @@ class ReverseProxyController extends ApiMutableModelControllerBase public function searchHeaderAction() { - return $this->searchBase("reverseproxy.header", null, 'description'); + return $this->searchBase("reverseproxy.header"); } public function setHeaderAction($uuid) @@ -319,7 +331,7 @@ class ReverseProxyController extends ApiMutableModelControllerBase public function searchLayer4Action() { - return $this->searchBase("reverseproxy.layer4", null, 'description'); + return $this->searchBase("reverseproxy.layer4"); } public function setLayer4Action($uuid) @@ -352,7 +364,7 @@ class ReverseProxyController extends ApiMutableModelControllerBase public function searchLayer4OpenvpnAction() { - return $this->searchBase("reverseproxy.layer4openvpn", null, 'description'); + return $this->searchBase("reverseproxy.layer4openvpn"); } public function setLayer4OpenvpnAction($uuid) diff --git a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/Layer4Controller.php b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/Layer4Controller.php index b1366ab72..7ea9478e1 100644 --- a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/Layer4Controller.php +++ b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/Layer4Controller.php @@ -36,12 +36,13 @@ class Layer4Controller extends IndexController { public function indexAction() { - $this->view->pick('OPNsense/Caddy/layer4'); + $this->view->entrypoint = 'layer4'; + $this->view->pick('OPNsense/Caddy/reverse_proxy'); $this->view->formDialogLayer4 = $this->getForm('dialogLayer4'); - $this->view->formGridLayer4 = $this->getFormGrid('dialogLayer4', null, 'ConfChangeMessage'); + $this->view->formGridLayer4 = $this->getFormGrid('dialogLayer4', 'Layer4'); $this->view->formDialogLayer4Openvpn = $this->getForm('dialogLayer4Openvpn'); - $this->view->formGridLayer4Openvpn = $this->getFormGrid('dialogLayer4Openvpn', null, 'ConfChangeMessage'); + $this->view->formGridLayer4Openvpn = $this->getFormGrid('dialogLayer4Openvpn', 'Layer4Openvpn'); } } diff --git a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/ReverseProxyController.php b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/ReverseProxyController.php index e30315299..dc780dcd6 100644 --- a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/ReverseProxyController.php +++ b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/ReverseProxyController.php @@ -36,24 +36,25 @@ class ReverseProxyController extends IndexController { public function indexAction() { + $this->view->entrypoint = 'reverse_proxy'; $this->view->pick('OPNsense/Caddy/reverse_proxy'); $this->view->formDialogReverseProxy = $this->getForm("dialogReverseProxy"); - $this->view->formGridReverseProxy = $this->getFormGrid('dialogReverseProxy', null, 'ConfChangeMessage'); + $this->view->formGridReverseProxy = $this->getFormGrid('dialogReverseProxy', 'ReverseProxy'); $this->view->formDialogSubdomain = $this->getForm("dialogSubdomain"); - $this->view->formGridSubdomain = $this->getFormGrid('dialogSubdomain', null, 'ConfChangeMessage'); + $this->view->formGridSubdomain = $this->getFormGrid('dialogSubdomain', 'Subdomain'); $this->view->formDialogHandle = $this->getForm("dialogHandle"); - $this->view->formGridHandle = $this->getFormGrid('dialogHandle', null, 'ConfChangeMessage'); + $this->view->formGridHandle = $this->getFormGrid('dialogHandle', 'Handle'); $this->view->formDialogAccessList = $this->getForm("dialogAccessList"); - $this->view->formGridAccessList = $this->getFormGrid('dialogAccessList', null, 'ConfChangeMessage'); + $this->view->formGridAccessList = $this->getFormGrid('dialogAccessList', 'AccessList'); $this->view->formDialogBasicAuth = $this->getForm("dialogBasicAuth"); - $this->view->formGridBasicAuth = $this->getFormGrid('dialogBasicAuth', null, 'ConfChangeMessage'); + $this->view->formGridBasicAuth = $this->getFormGrid('dialogBasicAuth', 'BasicAuth'); $this->view->formDialogHeader = $this->getForm("dialogHeader"); - $this->view->formGridHeader = $this->getFormGrid('dialogHeader', null, 'ConfChangeMessage'); + $this->view->formGridHeader = $this->getFormGrid('dialogHeader', 'Header'); } } diff --git a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogHandle.xml b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogHandle.xml index 52fd8618e..d80d495cf 100644 --- a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogHandle.xml +++ b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogHandle.xml @@ -5,17 +5,11 @@ checkbox - 6em + 2em boolean rowtoggle - - handle.description - - text - - header @@ -25,17 +19,22 @@ dropdown + + model_relation_domain + handle.subdomain dropdown + + model_relation_domain + header - true handle.HandleType @@ -53,7 +52,6 @@ text any - true false @@ -61,14 +59,15 @@ header - true + true + handle.accesslist dropdown + - true false @@ -78,6 +77,7 @@ select_multiple 5 + false @@ -87,8 +87,8 @@ handle.ForwardAuth checkbox + - true false boolean @@ -107,7 +107,9 @@ header - + + true + handle.HttpVersion @@ -115,7 +117,6 @@ dropdown - true false @@ -128,7 +129,6 @@ 5 - true false @@ -140,16 +140,22 @@ 120 - true false + + header + + handle.HttpTls dropdown + + false + handle.ToDomain @@ -158,19 +164,24 @@ true + + to_domain + handle.ToPort text + + false + handle.ToPath text - true false @@ -179,7 +190,7 @@ handle.HttpTlsInsecureSkipVerify checkbox - + false @@ -191,7 +202,7 @@ handle.HttpTlsTrustedCaCerts dropdown - + false @@ -201,7 +212,7 @@ handle.HttpTlsServerName text - + false @@ -211,7 +222,7 @@ handle.HttpNtlm checkbox - + false @@ -219,10 +230,17 @@ boolean + + handle.description + + text + + header - true + true + handle.lb_policy @@ -230,7 +248,6 @@ dropdown - true false @@ -242,7 +259,6 @@ off - true false @@ -254,7 +270,6 @@ 0 - true false @@ -266,7 +281,6 @@ 250 - true false @@ -278,7 +292,6 @@ off - true false @@ -290,7 +303,6 @@ 1 - true false @@ -302,7 +314,6 @@ off - true false @@ -314,7 +325,6 @@ off - true false @@ -326,7 +336,6 @@ off - true false diff --git a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogLayer4.xml b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogLayer4.xml index 9a24f737d..4a691fbe7 100644 --- a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogLayer4.xml +++ b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogLayer4.xml @@ -5,7 +5,7 @@ checkbox - 6em + 2em boolean rowtoggle @@ -15,12 +15,9 @@ text - - - layer4.description - - text - + + false + header @@ -41,6 +38,9 @@ dropdown + + false + layer4.FromPort @@ -66,7 +66,7 @@ layer4.FromDomain select_multiple - + true @@ -74,7 +74,7 @@ layer4.FromOpenvpnModes dropdown - + false @@ -84,7 +84,7 @@ layer4.FromOpenvpnStaticKey select_multiple - + Any 5 @@ -108,7 +108,7 @@ layer4.TerminateTls checkbox - + false @@ -127,35 +127,45 @@ true + + to_domain + layer4.ToPort text + + false + layer4.ProxyProtocol dropdown - true false + + layer4.description + + text + + header - true + true layer4.lb_policy dropdown - + - true false @@ -164,7 +174,6 @@ layer4.PassiveHealthFailDuration text - off true @@ -176,7 +185,6 @@ layer4.PassiveHealthMaxFails text - 1 true diff --git a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogReverseProxy.xml b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogReverseProxy.xml index ab5f3e971..c9a7ff26d 100644 --- a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogReverseProxy.xml +++ b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogReverseProxy.xml @@ -5,17 +5,11 @@ checkbox - 6em + 2em boolean rowtoggle - - reverse.description - - text - - header @@ -25,24 +19,33 @@ dropdown + + false + reverse.FromDomain text + + from_domain + reverse.FromPort text + + false + reverse.CustomCertificate dropdown - + false @@ -62,7 +65,7 @@ reverse.DnsChallenge checkbox - + false @@ -81,6 +84,12 @@ boolean + + reverse.description + + text + + header diff --git a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogSubdomain.xml b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogSubdomain.xml index 5db43f6f2..558c702a2 100644 --- a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogSubdomain.xml +++ b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogSubdomain.xml @@ -5,17 +5,11 @@ checkbox - 6em + 2em boolean rowtoggle - - subdomain.description - - text - - header @@ -25,6 +19,10 @@ dropdown + + false + model_relation_domain + subdomain.FromDomain @@ -54,6 +52,12 @@ false + + subdomain.description + + text + + header diff --git a/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/general.volt b/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/general.volt index ef58bada0..46c0ea63f 100644 --- a/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/general.volt +++ b/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/general.volt @@ -1,5 +1,5 @@ {# - # Copyright (c) 2023-2024 Cedrik Pischem + # Copyright (c) 2023-2025 Cedrik Pischem # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, @@ -72,7 +72,6 @@ if (status !== "success" || data.status !== 'ok') { showAlert("{{ lang._('Error applying configuration: ') }}" + JSON.stringify(data), "error"); } else { - showAlert("{{ lang._('Configuration applied successfully.') }}", "success"); updateServiceControlUI('caddy'); } setSpinner(generalId, 'stop'); diff --git a/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/layer4.volt b/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/layer4.volt deleted file mode 100644 index be371635c..000000000 --- a/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/layer4.volt +++ /dev/null @@ -1,181 +0,0 @@ -{# - # Copyright (c) 2024-2025 Cedrik Pischem - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without modification, - # are permitted provided that the following conditions are met: - # - # 1. Redistributions of source code must retain the above copyright notice, - # this list of conditions and the following disclaimer. - # - # 2. Redistributions in binary form must reproduce the above copyright notice, - # this list of conditions and the following disclaimer in the documentation - # and/or other materials provided with the distribution. - # - # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - # OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - # POSSIBILITY OF SUCH DAMAGE. - #} - - - - - - - -
- -
-
-

{{ lang._('Layer4 Routes') }}

-
- {{ partial('layout_partials/base_bootgrid_table', formGridLayer4)}} -
-
-
- - -
-
- -

{{ lang._('OpenVPN Static Keys') }}

-
- {{ partial('layout_partials/base_bootgrid_table', formGridLayer4Openvpn)}} -
-
-
-
- - - -
-
-
-
- -

- - - - -
-
-
- -{{ partial("layout_partials/base_dialog",['fields':formDialogLayer4,'id':formGridLayer4['edit_dialog_id'],'label':lang._('Edit Layer4 Route')])}} -{{ partial("layout_partials/base_dialog",['fields':formDialogLayer4Openvpn,'id':formGridLayer4Openvpn['edit_dialog_id'],'label':lang._('Edit OpenVPN Static Key')])}} diff --git a/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/reverse_proxy.volt b/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/reverse_proxy.volt index cf3010b4e..672cd81aa 100644 --- a/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/reverse_proxy.volt +++ b/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/reverse_proxy.volt @@ -26,89 +26,228 @@ + +
- -
- -
- - -
- - -
+ +{% if entrypoint == 'reverse_proxy' %} -
+

{{ lang._('Domains') }}

- {{ partial('layout_partials/base_bootgrid_table', formGridReverseProxy)}} + {{ partial('layout_partials/base_bootgrid_table', formGridReverseProxy + {'command_width': '11em'})}}
@@ -354,13 +495,13 @@

{{ lang._('Subdomains') }}

- {{ partial('layout_partials/base_bootgrid_table', formGridSubdomain)}} + {{ partial('layout_partials/base_bootgrid_table', formGridSubdomain + {'command_width': '11em'})}}
-
+

{{ lang._('Handlers') }}

@@ -370,7 +511,7 @@
-
+

{{ lang._('Access Lists') }}

@@ -389,7 +530,7 @@
-
+

{{ lang._('Headers') }}

@@ -397,29 +538,37 @@
-
- -
-
-
-
- -

- - - -
+ + +
+
+ +

{{ lang._('OpenVPN Static Keys') }}

+
+ {{ partial('layout_partials/base_bootgrid_table', formGridLayer4Openvpn)}} +
+
+
+ +{% endif %} + +
+ +{{ partial('layout_partials/base_apply_button', {'data_endpoint': '/api/caddy/service/reconfigure'}) }} + +{% if entrypoint == 'reverse_proxy' %} {{ partial("layout_partials/base_dialog",['fields':formDialogReverseProxy,'id':formGridReverseProxy['edit_dialog_id'],'label':lang._('Edit Domain')])}} {{ partial("layout_partials/base_dialog",['fields':formDialogSubdomain,'id':formGridSubdomain['edit_dialog_id'],'label':lang._('Edit Subdomain')])}} @@ -427,3 +576,10 @@ {{ partial("layout_partials/base_dialog",['fields':formDialogAccessList,'id':formGridAccessList['edit_dialog_id'],'label':lang._('Edit Access List')])}} {{ partial("layout_partials/base_dialog",['fields':formDialogBasicAuth,'id':formGridBasicAuth['edit_dialog_id'],'label':lang._('Edit Basic Auth')])}} {{ partial("layout_partials/base_dialog",['fields':formDialogHeader,'id':formGridHeader['edit_dialog_id'],'label':lang._('Edit Header')])}} + +{% elseif entrypoint == 'layer4' %} + +{{ partial("layout_partials/base_dialog",['fields':formDialogLayer4,'id':formGridLayer4['edit_dialog_id'],'label':lang._('Edit Layer4 Route')])}} +{{ partial("layout_partials/base_dialog",['fields':formDialogLayer4Openvpn,'id':formGridLayer4Openvpn['edit_dialog_id'],'label':lang._('Edit OpenVPN Static Key')])}} + +{% endif %}