feat(routes): add TLS configuration controls for route create and edit flows
This commit is contained in:
@@ -1,5 +1,12 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-04-04 - 12.10.0 - feat(routes)
|
||||||
|
add TLS configuration controls for route create and edit flows
|
||||||
|
|
||||||
|
- Adds TLS mode and certificate selection to the route create and edit dialogs, including support for custom PEM key/certificate input.
|
||||||
|
- Allows route updates to explicitly remove nested TLS settings by treating null action properties as deletions during route patch merging.
|
||||||
|
- Bumps @design.estate/dees-catalog to ^3.55.6 and @serve.zone/catalog to ^2.11.1.
|
||||||
|
|
||||||
## 2026-04-04 - 12.9.4 - fix(deps)
|
## 2026-04-04 - 12.9.4 - fix(deps)
|
||||||
bump @push.rocks/smartdb to ^2.3.1
|
bump @push.rocks/smartdb to ^2.3.1
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
"@api.global/typedserver": "^8.4.6",
|
"@api.global/typedserver": "^8.4.6",
|
||||||
"@api.global/typedsocket": "^4.1.2",
|
"@api.global/typedsocket": "^4.1.2",
|
||||||
"@apiclient.xyz/cloudflare": "^7.1.0",
|
"@apiclient.xyz/cloudflare": "^7.1.0",
|
||||||
"@design.estate/dees-catalog": "^3.55.5",
|
"@design.estate/dees-catalog": "^3.55.6",
|
||||||
"@design.estate/dees-element": "^2.2.4",
|
"@design.estate/dees-element": "^2.2.4",
|
||||||
"@push.rocks/lik": "^6.4.0",
|
"@push.rocks/lik": "^6.4.0",
|
||||||
"@push.rocks/projectinfo": "^5.1.0",
|
"@push.rocks/projectinfo": "^5.1.0",
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
"@push.rocks/smartunique": "^3.0.9",
|
"@push.rocks/smartunique": "^3.0.9",
|
||||||
"@push.rocks/smartvpn": "1.19.1",
|
"@push.rocks/smartvpn": "1.19.1",
|
||||||
"@push.rocks/taskbuffer": "^8.0.2",
|
"@push.rocks/taskbuffer": "^8.0.2",
|
||||||
"@serve.zone/catalog": "^2.11.0",
|
"@serve.zone/catalog": "^2.11.1",
|
||||||
"@serve.zone/interfaces": "^5.3.0",
|
"@serve.zone/interfaces": "^5.3.0",
|
||||||
"@serve.zone/remoteingress": "^4.15.3",
|
"@serve.zone/remoteingress": "^4.15.3",
|
||||||
"@tsclass/tsclass": "^9.5.0",
|
"@tsclass/tsclass": "^9.5.0",
|
||||||
|
|||||||
24
pnpm-lock.yaml
generated
24
pnpm-lock.yaml
generated
@@ -24,8 +24,8 @@ importers:
|
|||||||
specifier: ^7.1.0
|
specifier: ^7.1.0
|
||||||
version: 7.1.0
|
version: 7.1.0
|
||||||
'@design.estate/dees-catalog':
|
'@design.estate/dees-catalog':
|
||||||
specifier: ^3.55.5
|
specifier: ^3.55.6
|
||||||
version: 3.55.5(@tiptap/pm@2.27.2)
|
version: 3.55.6(@tiptap/pm@2.27.2)
|
||||||
'@design.estate/dees-element':
|
'@design.estate/dees-element':
|
||||||
specifier: ^2.2.4
|
specifier: ^2.2.4
|
||||||
version: 2.2.4
|
version: 2.2.4
|
||||||
@@ -102,8 +102,8 @@ importers:
|
|||||||
specifier: ^8.0.2
|
specifier: ^8.0.2
|
||||||
version: 8.0.2
|
version: 8.0.2
|
||||||
'@serve.zone/catalog':
|
'@serve.zone/catalog':
|
||||||
specifier: ^2.11.0
|
specifier: ^2.11.1
|
||||||
version: 2.11.0(@tiptap/pm@2.27.2)
|
version: 2.11.1(@tiptap/pm@2.27.2)
|
||||||
'@serve.zone/interfaces':
|
'@serve.zone/interfaces':
|
||||||
specifier: ^5.3.0
|
specifier: ^5.3.0
|
||||||
version: 5.3.0
|
version: 5.3.0
|
||||||
@@ -350,8 +350,8 @@ packages:
|
|||||||
'@configvault.io/interfaces@1.0.17':
|
'@configvault.io/interfaces@1.0.17':
|
||||||
resolution: {integrity: sha512-bEcCUR2VBDJsTin8HQh8Uw/mlYl2v8A3jMIaQ+MTB9Hrqd6CZL2dL7iJdWyFl/3EIX+LDxWFR+Oq7liIq7w+1Q==}
|
resolution: {integrity: sha512-bEcCUR2VBDJsTin8HQh8Uw/mlYl2v8A3jMIaQ+MTB9Hrqd6CZL2dL7iJdWyFl/3EIX+LDxWFR+Oq7liIq7w+1Q==}
|
||||||
|
|
||||||
'@design.estate/dees-catalog@3.55.5':
|
'@design.estate/dees-catalog@3.55.6':
|
||||||
resolution: {integrity: sha512-NAMUkTVqdZZmwI/g1xKOxOYM9QUd9FHODh6MYkP6LhLjD0NOGh3bITCnNN9Z3x8/mI7vQQOlSe9tyTtxCP1itQ==}
|
resolution: {integrity: sha512-aBuofV18v2X9U+WXQcwx/uOMofDECYRoqGovpB2cD2gpf5eCvaD2Y6HZetocKeW/VeOFlzwgykeSxAY8KvfiKQ==}
|
||||||
|
|
||||||
'@design.estate/dees-comms@1.0.30':
|
'@design.estate/dees-comms@1.0.30':
|
||||||
resolution: {integrity: sha512-KchMlklJfKAjQiJiR0xmofXtQ27VgZtBIxcMwPE9d+h3jJRv+lPZxzBQVOM0eyM0uS44S5vJMZ11IeV4uDXSHg==}
|
resolution: {integrity: sha512-KchMlklJfKAjQiJiR0xmofXtQ27VgZtBIxcMwPE9d+h3jJRv+lPZxzBQVOM0eyM0uS44S5vJMZ11IeV4uDXSHg==}
|
||||||
@@ -1583,8 +1583,8 @@ packages:
|
|||||||
'@selderee/plugin-htmlparser2@0.11.0':
|
'@selderee/plugin-htmlparser2@0.11.0':
|
||||||
resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==}
|
resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==}
|
||||||
|
|
||||||
'@serve.zone/catalog@2.11.0':
|
'@serve.zone/catalog@2.11.1':
|
||||||
resolution: {integrity: sha512-4DFDewp1PFRhw5P+yQAoAw+i6gG2lfR3h+uPgbNxB5jCfW14eNDXi3nuwTMBQWRHL9jv8o0BokASjV9A0+q66g==}
|
resolution: {integrity: sha512-KeeShLELKANWEAY3Z4h+Kx1bmatWLa0nvtw8wa7iHLxV6Vm3rRJNdRyh91ozuWPgFYMC48V8/4REA8zJsdDcbg==}
|
||||||
|
|
||||||
'@serve.zone/interfaces@5.3.0':
|
'@serve.zone/interfaces@5.3.0':
|
||||||
resolution: {integrity: sha512-venO7wtDR9ixzD9NhdERBGjNKbFA5LL0yHw4eqGh0UpmvtXVc3SFG0uuHDilOKMZqZ8bttV88qVsFy1aSTJrtA==}
|
resolution: {integrity: sha512-venO7wtDR9ixzD9NhdERBGjNKbFA5LL0yHw4eqGh0UpmvtXVc3SFG0uuHDilOKMZqZ8bttV88qVsFy1aSTJrtA==}
|
||||||
@@ -4355,7 +4355,7 @@ snapshots:
|
|||||||
'@api.global/typedrequest-interfaces': 3.0.19
|
'@api.global/typedrequest-interfaces': 3.0.19
|
||||||
'@api.global/typedsocket': 4.1.2(@push.rocks/smartserve@2.0.3)
|
'@api.global/typedsocket': 4.1.2(@push.rocks/smartserve@2.0.3)
|
||||||
'@cloudflare/workers-types': 4.20260317.1
|
'@cloudflare/workers-types': 4.20260317.1
|
||||||
'@design.estate/dees-catalog': 3.55.5(@tiptap/pm@2.27.2)
|
'@design.estate/dees-catalog': 3.55.6(@tiptap/pm@2.27.2)
|
||||||
'@design.estate/dees-comms': 1.0.30
|
'@design.estate/dees-comms': 1.0.30
|
||||||
'@push.rocks/lik': 6.4.0
|
'@push.rocks/lik': 6.4.0
|
||||||
'@push.rocks/smartdelay': 3.0.5
|
'@push.rocks/smartdelay': 3.0.5
|
||||||
@@ -4884,7 +4884,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@api.global/typedrequest-interfaces': 3.0.19
|
'@api.global/typedrequest-interfaces': 3.0.19
|
||||||
|
|
||||||
'@design.estate/dees-catalog@3.55.5(@tiptap/pm@2.27.2)':
|
'@design.estate/dees-catalog@3.55.6(@tiptap/pm@2.27.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@design.estate/dees-domtools': 2.5.4
|
'@design.estate/dees-domtools': 2.5.4
|
||||||
'@design.estate/dees-element': 2.2.4
|
'@design.estate/dees-element': 2.2.4
|
||||||
@@ -6922,9 +6922,9 @@ snapshots:
|
|||||||
domhandler: 5.0.3
|
domhandler: 5.0.3
|
||||||
selderee: 0.11.0
|
selderee: 0.11.0
|
||||||
|
|
||||||
'@serve.zone/catalog@2.11.0(@tiptap/pm@2.27.2)':
|
'@serve.zone/catalog@2.11.1(@tiptap/pm@2.27.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@design.estate/dees-catalog': 3.55.5(@tiptap/pm@2.27.2)
|
'@design.estate/dees-catalog': 3.55.6(@tiptap/pm@2.27.2)
|
||||||
'@design.estate/dees-domtools': 2.5.4
|
'@design.estate/dees-domtools': 2.5.4
|
||||||
'@design.estate/dees-element': 2.2.4
|
'@design.estate/dees-element': 2.2.4
|
||||||
'@design.estate/dees-wcctools': 3.8.0
|
'@design.estate/dees-wcctools': 3.8.0
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/dcrouter',
|
name: '@serve.zone/dcrouter',
|
||||||
version: '12.9.4',
|
version: '12.10.0',
|
||||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,7 +132,18 @@ export class RouteConfigManager {
|
|||||||
if (!stored) return false;
|
if (!stored) return false;
|
||||||
|
|
||||||
if (patch.route) {
|
if (patch.route) {
|
||||||
stored.route = { ...stored.route, ...patch.route } as IDcRouterRouteConfig;
|
const mergedAction = patch.route.action
|
||||||
|
? { ...stored.route.action, ...patch.route.action }
|
||||||
|
: stored.route.action;
|
||||||
|
// Handle explicit null to remove nested action properties (e.g., tls: null)
|
||||||
|
if (patch.route.action) {
|
||||||
|
for (const [key, val] of Object.entries(patch.route.action)) {
|
||||||
|
if (val === null) {
|
||||||
|
delete (mergedAction as any)[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stored.route = { ...stored.route, ...patch.route, action: mergedAction } as IDcRouterRouteConfig;
|
||||||
}
|
}
|
||||||
if (patch.enabled !== undefined) {
|
if (patch.enabled !== undefined) {
|
||||||
stored.enabled = patch.enabled;
|
stored.enabled = patch.enabled;
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/dcrouter',
|
name: '@serve.zone/dcrouter',
|
||||||
version: '12.9.4',
|
version: '12.10.0',
|
||||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,40 @@ import {
|
|||||||
type TemplateResult,
|
type TemplateResult,
|
||||||
} from '@design.estate/dees-element';
|
} from '@design.estate/dees-element';
|
||||||
|
|
||||||
|
// TLS dropdown options shared by create and edit dialogs
|
||||||
|
const tlsModeOptions = [
|
||||||
|
{ key: 'none', option: '(none — no TLS)' },
|
||||||
|
{ key: 'passthrough', option: 'Passthrough' },
|
||||||
|
{ key: 'terminate', option: 'Terminate' },
|
||||||
|
{ key: 'terminate-and-reencrypt', option: 'Terminate & Re-encrypt' },
|
||||||
|
];
|
||||||
|
const tlsCertOptions = [
|
||||||
|
{ key: 'auto', option: 'Auto (ACME/Let\'s Encrypt)' },
|
||||||
|
{ key: 'custom', option: 'Custom certificate' },
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle TLS form field visibility based on selected TLS mode and certificate type.
|
||||||
|
*/
|
||||||
|
function setupTlsVisibility(formEl: any) {
|
||||||
|
const updateVisibility = async () => {
|
||||||
|
const data = await formEl.collectFormData();
|
||||||
|
const contentEl = formEl.closest('.content') || formEl.parentElement;
|
||||||
|
if (!contentEl) return;
|
||||||
|
const tlsModeValue = data.tlsMode;
|
||||||
|
const modeKey = typeof tlsModeValue === 'string' ? tlsModeValue : tlsModeValue?.key;
|
||||||
|
const needsCert = modeKey === 'terminate' || modeKey === 'terminate-and-reencrypt';
|
||||||
|
const certGroup = contentEl.querySelector('.tlsCertificateGroup') as HTMLElement;
|
||||||
|
if (certGroup) certGroup.style.display = needsCert ? 'flex' : 'none';
|
||||||
|
const tlsCertValue = data.tlsCertificate;
|
||||||
|
const certKey = typeof tlsCertValue === 'string' ? tlsCertValue : tlsCertValue?.key;
|
||||||
|
const customGroup = contentEl.querySelector('.tlsCustomCertGroup') as HTMLElement;
|
||||||
|
if (customGroup) customGroup.style.display = (needsCert && certKey === 'custom') ? 'flex' : 'none';
|
||||||
|
};
|
||||||
|
formEl.changeSubject.subscribe(() => updateVisibility());
|
||||||
|
updateVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
@customElement('ops-view-routes')
|
@customElement('ops-view-routes')
|
||||||
export class OpsViewRoutes extends DeesElement {
|
export class OpsViewRoutes extends DeesElement {
|
||||||
@state() accessor routeState: appstate.IRouteManagementState = {
|
@state() accessor routeState: appstate.IRouteManagementState = {
|
||||||
@@ -423,7 +457,18 @@ export class OpsViewRoutes extends DeesElement {
|
|||||||
: '';
|
: '';
|
||||||
const currentTargetPort = firstTarget?.port != null ? String(firstTarget.port) : '';
|
const currentTargetPort = firstTarget?.port != null ? String(firstTarget.port) : '';
|
||||||
|
|
||||||
await DeesModal.createAndShow({
|
// Compute current TLS state for pre-population
|
||||||
|
const currentTls = (route.action as any).tls;
|
||||||
|
const currentTlsMode = currentTls?.mode || 'none';
|
||||||
|
const currentTlsCert = currentTls
|
||||||
|
? (currentTls.certificate === 'auto' || !currentTls.certificate ? 'auto' : 'custom')
|
||||||
|
: 'auto';
|
||||||
|
const currentCustomKey = (typeof currentTls?.certificate === 'object') ? currentTls.certificate.key : '';
|
||||||
|
const currentCustomCert = (typeof currentTls?.certificate === 'object') ? currentTls.certificate.cert : '';
|
||||||
|
const needsCert = currentTlsMode === 'terminate' || currentTlsMode === 'terminate-and-reencrypt';
|
||||||
|
const isCustom = currentTlsCert === 'custom';
|
||||||
|
|
||||||
|
const editModal = await DeesModal.createAndShow({
|
||||||
heading: `Edit Route: ${route.name}`,
|
heading: `Edit Route: ${route.name}`,
|
||||||
content: html`
|
content: html`
|
||||||
<dees-form>
|
<dees-form>
|
||||||
@@ -435,6 +480,14 @@ export class OpsViewRoutes extends DeesElement {
|
|||||||
<dees-input-dropdown .key=${'networkTargetRef'} .label=${'Network Target'} .options=${targetOptions} .selectedOption=${targetOptions.find((o) => o.key === (merged.metadata?.networkTargetRef || '')) || null}></dees-input-dropdown>
|
<dees-input-dropdown .key=${'networkTargetRef'} .label=${'Network Target'} .options=${targetOptions} .selectedOption=${targetOptions.find((o) => o.key === (merged.metadata?.networkTargetRef || '')) || null}></dees-input-dropdown>
|
||||||
<dees-input-text .key=${'targetHost'} .label=${'Target Host (if no target selected)'} .value=${currentTargetHost}></dees-input-text>
|
<dees-input-text .key=${'targetHost'} .label=${'Target Host (if no target selected)'} .value=${currentTargetHost}></dees-input-text>
|
||||||
<dees-input-text .key=${'targetPort'} .label=${'Target Port (if no target selected)'} .value=${currentTargetPort}></dees-input-text>
|
<dees-input-text .key=${'targetPort'} .label=${'Target Port (if no target selected)'} .value=${currentTargetPort}></dees-input-text>
|
||||||
|
<dees-input-dropdown .key=${'tlsMode'} .label=${'TLS Mode'} .options=${tlsModeOptions} .selectedOption=${tlsModeOptions.find((o) => o.key === currentTlsMode) || tlsModeOptions[0]}></dees-input-dropdown>
|
||||||
|
<div class="tlsCertificateGroup" style="display: ${needsCert ? 'flex' : 'none'}; flex-direction: column; gap: 16px;">
|
||||||
|
<dees-input-dropdown .key=${'tlsCertificate'} .label=${'Certificate'} .options=${tlsCertOptions} .selectedOption=${tlsCertOptions.find((o) => o.key === currentTlsCert) || tlsCertOptions[0]}></dees-input-dropdown>
|
||||||
|
<div class="tlsCustomCertGroup" style="display: ${needsCert && isCustom ? 'flex' : 'none'}; flex-direction: column; gap: 16px;">
|
||||||
|
<dees-input-text .key=${'tlsCertKey'} .label=${'Private Key (PEM)'} .value=${currentCustomKey}></dees-input-text>
|
||||||
|
<dees-input-text .key=${'tlsCertCert'} .label=${'Certificate (PEM)'} .value=${currentCustomCert}></dees-input-text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</dees-form>
|
</dees-form>
|
||||||
`,
|
`,
|
||||||
menuOptions: [
|
menuOptions: [
|
||||||
@@ -476,6 +529,25 @@ export class OpsViewRoutes extends DeesElement {
|
|||||||
...(priority != null && !isNaN(priority) ? { priority } : {}),
|
...(priority != null && !isNaN(priority) ? { priority } : {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Build TLS config from form
|
||||||
|
const tlsModeValue = formData.tlsMode as any;
|
||||||
|
const tlsModeKey = typeof tlsModeValue === 'string' ? tlsModeValue : tlsModeValue?.key;
|
||||||
|
if (tlsModeKey && tlsModeKey !== 'none') {
|
||||||
|
const tls: any = { mode: tlsModeKey };
|
||||||
|
if (tlsModeKey !== 'passthrough') {
|
||||||
|
const tlsCertValue = formData.tlsCertificate as any;
|
||||||
|
const tlsCertKey = typeof tlsCertValue === 'string' ? tlsCertValue : tlsCertValue?.key;
|
||||||
|
if (tlsCertKey === 'custom' && formData.tlsCertKey && formData.tlsCertCert) {
|
||||||
|
tls.certificate = { key: formData.tlsCertKey, cert: formData.tlsCertCert };
|
||||||
|
} else {
|
||||||
|
tls.certificate = 'auto';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updatedRoute.action.tls = tls;
|
||||||
|
} else {
|
||||||
|
updatedRoute.action.tls = null; // explicit removal
|
||||||
|
}
|
||||||
|
|
||||||
const metadata: any = {};
|
const metadata: any = {};
|
||||||
const profileRefValue = formData.securityProfileRef as any;
|
const profileRefValue = formData.securityProfileRef as any;
|
||||||
const profileKey = typeof profileRefValue === 'string' ? profileRefValue : profileRefValue?.key;
|
const profileKey = typeof profileRefValue === 'string' ? profileRefValue : profileRefValue?.key;
|
||||||
@@ -501,6 +573,12 @@ export class OpsViewRoutes extends DeesElement {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
// Setup conditional TLS field visibility after modal renders
|
||||||
|
const editForm = editModal?.shadowRoot?.querySelector('.content')?.querySelector('dees-form') as any;
|
||||||
|
if (editForm) {
|
||||||
|
await editForm.updateComplete;
|
||||||
|
setupTlsVisibility(editForm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async showCreateRouteDialog() {
|
private async showCreateRouteDialog() {
|
||||||
@@ -524,7 +602,7 @@ export class OpsViewRoutes extends DeesElement {
|
|||||||
})),
|
})),
|
||||||
];
|
];
|
||||||
|
|
||||||
await DeesModal.createAndShow({
|
const createModal = await DeesModal.createAndShow({
|
||||||
heading: 'Add Programmatic Route',
|
heading: 'Add Programmatic Route',
|
||||||
content: html`
|
content: html`
|
||||||
<dees-form>
|
<dees-form>
|
||||||
@@ -536,6 +614,14 @@ export class OpsViewRoutes extends DeesElement {
|
|||||||
<dees-input-dropdown .key=${'networkTargetRef'} .label=${'Network Target'} .options=${targetOptions}></dees-input-dropdown>
|
<dees-input-dropdown .key=${'networkTargetRef'} .label=${'Network Target'} .options=${targetOptions}></dees-input-dropdown>
|
||||||
<dees-input-text .key=${'targetHost'} .label=${'Target Host (if no target selected)'} .value=${'localhost'}></dees-input-text>
|
<dees-input-text .key=${'targetHost'} .label=${'Target Host (if no target selected)'} .value=${'localhost'}></dees-input-text>
|
||||||
<dees-input-text .key=${'targetPort'} .label=${'Target Port (if no target selected)'}></dees-input-text>
|
<dees-input-text .key=${'targetPort'} .label=${'Target Port (if no target selected)'}></dees-input-text>
|
||||||
|
<dees-input-dropdown .key=${'tlsMode'} .label=${'TLS Mode'} .options=${tlsModeOptions} .selectedOption=${tlsModeOptions[0]}></dees-input-dropdown>
|
||||||
|
<div class="tlsCertificateGroup" style="display: none; flex-direction: column; gap: 16px;">
|
||||||
|
<dees-input-dropdown .key=${'tlsCertificate'} .label=${'Certificate'} .options=${tlsCertOptions} .selectedOption=${tlsCertOptions[0]}></dees-input-dropdown>
|
||||||
|
<div class="tlsCustomCertGroup" style="display: none; flex-direction: column; gap: 16px;">
|
||||||
|
<dees-input-text .key=${'tlsCertKey'} .label=${'Private Key (PEM)'}></dees-input-text>
|
||||||
|
<dees-input-text .key=${'tlsCertCert'} .label=${'Certificate (PEM)'}></dees-input-text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</dees-form>
|
</dees-form>
|
||||||
`,
|
`,
|
||||||
menuOptions: [
|
menuOptions: [
|
||||||
@@ -577,6 +663,23 @@ export class OpsViewRoutes extends DeesElement {
|
|||||||
...(priority != null && !isNaN(priority) ? { priority } : {}),
|
...(priority != null && !isNaN(priority) ? { priority } : {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Build TLS config from form
|
||||||
|
const tlsModeValue = formData.tlsMode as any;
|
||||||
|
const tlsModeKey = typeof tlsModeValue === 'string' ? tlsModeValue : tlsModeValue?.key;
|
||||||
|
if (tlsModeKey && tlsModeKey !== 'none') {
|
||||||
|
const tls: any = { mode: tlsModeKey };
|
||||||
|
if (tlsModeKey !== 'passthrough') {
|
||||||
|
const tlsCertValue = formData.tlsCertificate as any;
|
||||||
|
const tlsCertKey = typeof tlsCertValue === 'string' ? tlsCertValue : tlsCertValue?.key;
|
||||||
|
if (tlsCertKey === 'custom' && formData.tlsCertKey && formData.tlsCertCert) {
|
||||||
|
tls.certificate = { key: formData.tlsCertKey, cert: formData.tlsCertCert };
|
||||||
|
} else {
|
||||||
|
tls.certificate = 'auto';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
route.action.tls = tls;
|
||||||
|
}
|
||||||
|
|
||||||
// Build metadata if profile/target selected
|
// Build metadata if profile/target selected
|
||||||
const metadata: any = {};
|
const metadata: any = {};
|
||||||
const profileRefValue = formData.securityProfileRef as any;
|
const profileRefValue = formData.securityProfileRef as any;
|
||||||
@@ -602,6 +705,12 @@ export class OpsViewRoutes extends DeesElement {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
// Setup conditional TLS field visibility after modal renders
|
||||||
|
const createForm = createModal?.shadowRoot?.querySelector('.content')?.querySelector('dees-form') as any;
|
||||||
|
if (createForm) {
|
||||||
|
await createForm.updateComplete;
|
||||||
|
setupTlsVisibility(createForm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private refreshData() {
|
private refreshData() {
|
||||||
|
|||||||
Reference in New Issue
Block a user