secubox-openwrt/luci-app-network-modes/htdocs/luci-static/resources/view/network-modes/dmz.js

214 lines
8.2 KiB
JavaScript

'use strict';
'require view';
'require dom';
'require ui';
'require network-modes.api as api';
'require network-modes.helpers as helpers';
'require secubox-theme/theme as Theme';
var lang = (typeof L !== 'undefined' && L.env && L.env.lang) ||
(document.documentElement && document.documentElement.getAttribute('lang')) ||
(navigator.language ? navigator.language.split('-')[0] : 'en');
Theme.init({ language: lang });
function buildToggle(id, icon, title, desc, enabled) {
return E('div', { 'class': 'nm-toggle' }, [
E('div', { 'class': 'nm-toggle-info' }, [
E('span', { 'class': 'nm-toggle-icon' }, icon),
E('div', {}, [
E('div', { 'class': 'nm-toggle-label' }, title),
E('div', { 'class': 'nm-toggle-desc' }, desc)
])
]),
E('div', {
'class': 'nm-toggle-switch' + (enabled ? ' active' : ''),
'id': id
})
]);
}
return view.extend({
title: _('DMZ Mode'),
load: function() {
return Promise.all([
api.getDmzConfig(),
api.getStatus()
]);
},
render: function(payload) {
var config = (payload && payload[0]) || {};
var status = (payload && payload[1]) || {};
var wan = config.wan || {};
var lan = config.lan || {};
var dmz = config.dmz || {};
var hero = helpers.createHero({
icon: '🛡️',
title: _('Router + DMZ Mode'),
subtitle: _('Create an isolated DMZ network that only reaches the WAN while keeping your LAN protected. Perfect for exposing servers without risking the internal network.'),
gradient: 'linear-gradient(135deg,#1e293b,#0ea5e9)',
meta: [
{ label: _('WAN Interface'), value: wan.interface || 'eth1' },
{ label: _('LAN Gateway'), value: lan.ip_address || '192.168.1.1' },
{ label: _('DMZ Gateway'), value: dmz.ip_address || '192.168.50.1' }
],
actions: [
E('button', { 'class': 'nm-btn nm-btn-primary', 'type': 'button', 'data-action': 'dmz-save' }, ['💾 ', _('Save Template')]),
E('button', { 'class': 'nm-btn', 'type': 'button', 'data-action': 'dmz-apply' }, ['🚀 ', _('Apply DMZ Mode')]),
E('button', { 'class': 'nm-btn', 'type': 'button', 'data-action': 'dmz-preview' }, ['📝 ', _('Preview Config')])
]
});
var wanSection = helpers.createSection({
title: _('WAN Settings'),
icon: '🌍',
badge: (wan.interface || 'eth1').toUpperCase(),
body: [
E('div', { 'class': 'nm-form-grid' }, [
E('div', { 'class': 'nm-form-group' }, [
E('label', { 'class': 'nm-form-label' }, _('WAN Interface')),
E('input', { 'class': 'nm-input', 'id': 'dmz-wan-if', 'value': wan.interface || 'eth1' })
]),
E('div', { 'class': 'nm-form-group' }, [
E('label', { 'class': 'nm-form-label' }, _('WAN Protocol')),
E('select', { 'class': 'nm-select', 'id': 'dmz-wan-proto' },
(wan.protocols || ['dhcp', 'static', 'pppoe']).map(function(proto) {
return E('option', {
'value': proto,
'selected': (proto === wan.protocol)
}, proto.toUpperCase());
})
)
])
])
]
});
var lanSection = helpers.createSection({
title: _('LAN Network'),
icon: '🏠',
badge: lan.interface || 'br-lan',
body: [
E('div', { 'class': 'nm-form-grid' }, [
E('div', { 'class': 'nm-form-group' }, [
E('label', { 'class': 'nm-form-label' }, _('LAN Interface')),
E('input', { 'class': 'nm-input', 'id': 'dmz-lan-if', 'value': lan.interface || 'br-lan' })
]),
E('div', { 'class': 'nm-form-group' }, [
E('label', { 'class': 'nm-form-label' }, _('LAN IP Address')),
E('input', { 'class': 'nm-input', 'id': 'dmz-lan-ip', 'value': lan.ip_address || '192.168.1.1' })
]),
E('div', { 'class': 'nm-form-group' }, [
E('label', { 'class': 'nm-form-label' }, _('Netmask')),
E('input', { 'class': 'nm-input', 'id': 'dmz-lan-mask', 'value': lan.netmask || '255.255.255.0' })
])
])
]
});
var dmzSection = helpers.createSection({
title: _('DMZ Segment'),
icon: '🧱',
badge: dmz.interface || 'eth2',
body: [
E('div', { 'class': 'nm-form-grid' }, [
E('div', { 'class': 'nm-form-group' }, [
E('label', { 'class': 'nm-form-label' }, _('DMZ Interface')),
E('input', { 'class': 'nm-input', 'id': 'dmz-if', 'value': dmz.interface || 'eth2' })
]),
E('div', { 'class': 'nm-form-group' }, [
E('label', { 'class': 'nm-form-label' }, _('DMZ IP Address')),
E('input', { 'class': 'nm-input', 'id': 'dmz-ip', 'value': dmz.ip_address || '192.168.50.1' })
]),
E('div', { 'class': 'nm-form-group' }, [
E('label', { 'class': 'nm-form-label' }, _('Netmask')),
E('input', { 'class': 'nm-input', 'id': 'dmz-mask', 'value': dmz.netmask || '255.255.255.0' })
]),
E('div', { 'class': 'nm-form-group' }, [
E('label', { 'class': 'nm-form-label' }, _('DHCP Start')),
E('input', { 'class': 'nm-input', 'type': 'number', 'id': 'dmz-dhcp-start', 'value': dmz.dhcp_start || 50 })
]),
E('div', { 'class': 'nm-form-group' }, [
E('label', { 'class': 'nm-form-label' }, _('DHCP Pool Size')),
E('input', { 'class': 'nm-input', 'type': 'number', 'id': 'dmz-dhcp-limit', 'value': dmz.dhcp_limit || 80 })
])
]),
E('div', { 'style': 'margin-top:12px;' }, [
buildToggle('dmz-isolated-toggle', '🚧', _('Isolate DMZ from LAN'), _('Block DMZ clients from reaching the LAN'), dmz.isolated !== false)
]),
E('p', { 'class': 'nm-alert nm-alert-info', 'style': 'margin-top:12px;' }, _('DMZ clients will reach the WAN by default. Toggle isolation to prevent DMZ → LAN access.'))
]
});
var container = E('div', { 'class': 'nm-container' }, [
E('link', { 'rel': 'stylesheet', 'href': L.resource('secubox-theme/secubox-theme.css') }),
helpers.createNavigationTabs('dmz'),
hero,
wanSection,
lanSection,
dmzSection
]);
container.querySelectorAll('.nm-toggle-switch').forEach(function(toggle) {
toggle.addEventListener('click', function() {
this.classList.toggle('active');
});
});
this.bindActions(container);
return container;
},
bindActions: function(container) {
var saveBtn = container.querySelector('[data-action="dmz-save"]');
var applyBtn = container.querySelector('[data-action="dmz-apply"]');
var previewBtn = container.querySelector('[data-action="dmz-preview"]');
if (saveBtn)
saveBtn.addEventListener('click', ui.createHandlerFn(this, 'saveSettings', container));
if (applyBtn)
applyBtn.addEventListener('click', ui.createHandlerFn(this, 'applyMode'));
if (previewBtn)
previewBtn.addEventListener('click', ui.createHandlerFn(helpers, helpers.showGeneratedConfig, 'dmz'));
},
saveSettings: function(container) {
var payload = {
wan_interface: (container.querySelector('#dmz-wan-if') || {}).value || 'eth1',
wan_protocol: (container.querySelector('#dmz-wan-proto') || {}).value || 'dhcp',
lan_interface: (container.querySelector('#dmz-lan-if') || {}).value || 'br-lan',
lan_ip: (container.querySelector('#dmz-lan-ip') || {}).value || '192.168.1.1',
lan_netmask: (container.querySelector('#dmz-lan-mask') || {}).value || '255.255.255.0',
dmz_interface: (container.querySelector('#dmz-if') || {}).value || 'eth2',
dmz_ip: (container.querySelector('#dmz-ip') || {}).value || '192.168.50.1',
dmz_netmask: (container.querySelector('#dmz-mask') || {}).value || '255.255.255.0',
dmz_dhcp_start: (container.querySelector('#dmz-dhcp-start') || {}).value || '50',
dmz_dhcp_limit: (container.querySelector('#dmz-dhcp-limit') || {}).value || '80',
dmz_isolated: helpers.isToggleActive(container.querySelector('#dmz-isolated-toggle')) ? 1 : 0
};
return helpers.persistSettings('dmz', payload);
},
applyMode: function() {
ui.showModal(_('Applying DMZ mode'), [
E('p', { 'class': 'spinning' }, _('Backing up current config and switching to DMZ mode...'))
]);
return api.applyMode('dmz').then(function(result) {
ui.hideModal();
if (result && result.success) {
ui.addNotification(null, E('p', {}, _('DMZ mode applied. Confirm within rollback window.')), 'info');
window.location.reload();
} else {
ui.addNotification(null, E('p', {}, (result && result.error) || _('Unable to apply DMZ mode')), 'error');
}
}).catch(function(err) {
ui.hideModal();
ui.addNotification(null, E('p', {}, err.message || err), 'error');
});
}
});