chore(exposure): Remove obsolete view files replaced by KISS redesign

Delete overview.js, tor.js, ssl.js — all functionality is now in the
single services.js view.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2026-02-04 14:27:46 +01:00
parent 9def2ad15a
commit c6de8b2b1b
3 changed files with 0 additions and 1514 deletions

View File

@ -1,222 +0,0 @@
'use strict';
'require view';
'require dom';
'require ui';
'require exposure/api as api';
return view.extend({
load: function() {
return Promise.all([
api.sslList(),
api.scan()
]);
},
render: function(data) {
var sslResult = data[0] || {};
var scanResult = data[1] || {};
var sslBackends = Array.isArray(sslResult) ? sslResult : (sslResult.backends || []);
var allServices = Array.isArray(scanResult) ? scanResult : (scanResult.services || []);
var self = this;
// Inject CSS
var cssLink = document.querySelector('link[href*="exposure/dashboard.css"]');
if (!cssLink) {
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = L.resource('exposure/dashboard.css');
document.head.appendChild(link);
}
var view = E('div', { 'class': 'exposure-dashboard' }, [
E('h2', {}, '\ud83d\udd12 HAProxy SSL Backends'),
E('p', { 'style': 'color: #8892b0; margin-bottom: 1.5rem;' },
'Configure HTTPS reverse proxy for your services'),
// Add new backend form
E('div', { 'class': 'exposure-section' }, [
E('div', { 'class': 'exposure-section-header' }, [
E('div', { 'class': 'exposure-section-title' }, [
E('span', { 'class': 'icon' }, '\u2795'),
'Add SSL Backend'
])
]),
E('div', { 'class': 'exposure-form' }, [
E('div', { 'class': 'exposure-form-group' }, [
E('label', {}, 'Service'),
E('select', { 'id': 'new-ssl-service' },
[E('option', { 'value': '' }, '-- Select --')].concat(
allServices.filter(function(s) { return s.external; }).map(function(s) {
var name = s.name || s.process;
return E('option', {
'value': s.process,
'data-port': s.port,
'data-name': name.toLowerCase().replace(/\s+/g, '')
}, name + ' (:' + s.port + ')');
})
)
)
]),
E('div', { 'class': 'exposure-form-group' }, [
E('label', {}, 'Domain'),
E('input', {
'type': 'text',
'id': 'new-ssl-domain',
'placeholder': 'service.example.com'
})
]),
E('div', { 'class': 'exposure-form-group' }, [
E('label', {}, 'Backend Port'),
E('input', { 'type': 'number', 'id': 'new-ssl-port', 'placeholder': '3000' })
]),
E('button', {
'class': 'btn-action btn-primary',
'click': ui.createHandlerFn(self, 'handleAdd')
}, 'Add Backend')
])
]),
// Info box
E('div', {
'class': 'exposure-section',
'style': 'background: rgba(0, 212, 255, 0.1); border-color: #00d4ff;'
}, [
E('p', { 'style': 'margin: 0; color: #ccd6f6;' }, [
E('strong', {}, '\u2139\ufe0f SSL Certificate: '),
'After adding a backend, upload the SSL certificate to ',
E('code', {}, '/srv/lxc/haproxy/rootfs/etc/haproxy/certs/'),
'. The certificate file should be named ',
E('code', {}, 'domain.pem'),
' and contain both the certificate and private key.'
])
]),
// Existing backends
E('div', { 'class': 'exposure-section' }, [
E('div', { 'class': 'exposure-section-header' }, [
E('div', { 'class': 'exposure-section-title' }, [
E('span', { 'class': 'icon' }, '\ud83d\udd12'),
'Active SSL Backends (' + sslBackends.length + ')'
]),
E('button', {
'class': 'btn-action btn-primary',
'click': function() { location.reload(); }
}, 'Refresh')
]),
sslBackends.length > 0 ?
E('table', { 'class': 'exposure-table' }, [
E('thead', {}, [
E('tr', {}, [
E('th', {}, 'Service'),
E('th', {}, 'Domain'),
E('th', {}, 'Backend'),
E('th', {}, 'Actions')
])
]),
E('tbody', {},
sslBackends.map(function(b) {
return E('tr', {}, [
E('td', { 'style': 'font-weight: 600;' }, b.service),
E('td', {}, [
E('a', {
'href': 'https://' + b.domain,
'target': '_blank',
'style': 'color: #00d4ff;'
}, b.domain),
E('span', { 'style': 'margin-left: 0.5rem;' }, '\ud83d\udd17')
]),
E('td', { 'style': 'font-family: monospace;' }, b.backend || 'N/A'),
E('td', {}, [
E('button', {
'class': 'btn-action btn-danger',
'click': ui.createHandlerFn(self, 'handleRemove', b.service)
}, 'Remove')
])
]);
})
)
]) :
E('div', { 'class': 'exposure-empty' }, [
E('div', { 'class': 'icon' }, '\ud83d\udd12'),
E('p', {}, 'No SSL backends configured'),
E('p', { 'style': 'font-size: 0.85rem;' }, 'Select a service above to add HTTPS access')
])
])
]);
// Wire up service selector
setTimeout(function() {
var sel = document.getElementById('new-ssl-service');
var portInput = document.getElementById('new-ssl-port');
var domainInput = document.getElementById('new-ssl-domain');
if (sel && portInput) {
sel.addEventListener('change', function() {
var opt = sel.options[sel.selectedIndex];
portInput.value = opt.dataset.port || '';
if (opt.dataset.name) {
domainInput.placeholder = opt.dataset.name + '.example.com';
}
});
}
}, 100);
return view;
},
handleAdd: function(ev) {
var service = document.getElementById('new-ssl-service').value;
var domain = document.getElementById('new-ssl-domain').value;
var port = parseInt(document.getElementById('new-ssl-port').value);
if (!service) {
ui.addNotification(null, E('p', {}, 'Please select a service'), 'warning');
return;
}
if (!domain) {
ui.addNotification(null, E('p', {}, 'Please enter a domain'), 'warning');
return;
}
if (!port) {
ui.addNotification(null, E('p', {}, 'Please specify the backend port'), 'warning');
return;
}
api.sslAdd(service, domain, port).then(function(res) {
if (res.success) {
ui.addNotification(null, E('p', {}, [
'SSL backend configured for ',
E('strong', {}, domain),
E('br'),
'Remember to upload the SSL certificate!'
]), 'success');
location.reload();
} else {
ui.addNotification(null, E('p', {}, 'Error: ' + (res.error || 'Unknown error')), 'danger');
}
}).catch(function(err) {
ui.addNotification(null, E('p', {}, 'Error: ' + err.message), 'danger');
});
},
handleRemove: function(service, ev) {
if (!confirm('Remove SSL backend for ' + service + '?')) {
return;
}
api.sslRemove(service).then(function(res) {
if (res.success) {
ui.addNotification(null, E('p', {}, 'SSL backend removed'), 'success');
location.reload();
} else {
ui.addNotification(null, E('p', {}, 'Error: ' + (res.error || 'Unknown error')), 'danger');
}
});
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});

View File

@ -1,201 +0,0 @@
'use strict';
'require view';
'require dom';
'require ui';
'require exposure/api as api';
return view.extend({
load: function() {
return Promise.all([
api.torList(),
api.scan()
]);
},
render: function(data) {
var torResult = data[0] || {};
var scanResult = data[1] || {};
var torServices = Array.isArray(torResult) ? torResult : (torResult.services || []);
var allServices = Array.isArray(scanResult) ? scanResult : (scanResult.services || []);
var self = this;
// Inject CSS
var cssLink = document.querySelector('link[href*="exposure/dashboard.css"]');
if (!cssLink) {
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = L.resource('exposure/dashboard.css');
document.head.appendChild(link);
}
var view = E('div', { 'class': 'exposure-dashboard' }, [
E('h2', {}, '\ud83e\uddc5 Tor Hidden Services'),
E('p', { 'style': 'color: #8892b0; margin-bottom: 1.5rem;' },
'Expose services on the Tor network with .onion addresses'),
// Add new service form
E('div', { 'class': 'exposure-section' }, [
E('div', { 'class': 'exposure-section-header' }, [
E('div', { 'class': 'exposure-section-title' }, [
E('span', { 'class': 'icon' }, '\u2795'),
'Add Hidden Service'
])
]),
E('div', { 'class': 'exposure-form' }, [
E('div', { 'class': 'exposure-form-group' }, [
E('label', {}, 'Service'),
E('select', { 'id': 'new-tor-service' },
[E('option', { 'value': '' }, '-- Select --')].concat(
allServices.filter(function(s) { return s.external; }).map(function(s) {
var name = s.name || s.process;
return E('option', { 'value': s.process, 'data-port': s.port },
name + ' (:' + s.port + ')');
})
)
)
]),
E('div', { 'class': 'exposure-form-group' }, [
E('label', {}, 'Local Port'),
E('input', { 'type': 'number', 'id': 'new-tor-port', 'placeholder': '3000' })
]),
E('div', { 'class': 'exposure-form-group' }, [
E('label', {}, 'Onion Port'),
E('input', { 'type': 'number', 'id': 'new-tor-onion-port', 'value': '80' })
]),
E('button', {
'class': 'btn-action btn-primary',
'click': ui.createHandlerFn(self, 'handleAdd')
}, 'Create .onion')
])
]),
// Existing services
E('div', { 'class': 'exposure-section' }, [
E('div', { 'class': 'exposure-section-header' }, [
E('div', { 'class': 'exposure-section-title' }, [
E('span', { 'class': 'icon' }, '\ud83e\uddc5'),
'Active Hidden Services (' + torServices.length + ')'
]),
E('button', {
'class': 'btn-action btn-primary',
'click': function() { location.reload(); }
}, 'Refresh')
]),
torServices.length > 0 ?
E('table', { 'class': 'exposure-table' }, [
E('thead', {}, [
E('tr', {}, [
E('th', {}, 'Service'),
E('th', {}, 'Onion Address'),
E('th', {}, 'Port'),
E('th', {}, 'Backend'),
E('th', {}, 'Actions')
])
]),
E('tbody', {},
torServices.map(function(svc) {
return E('tr', {}, [
E('td', { 'style': 'font-weight: 600;' }, svc.service),
E('td', {}, [
E('code', { 'class': 'onion-address' }, svc.onion),
E('button', {
'class': 'btn-action',
'style': 'margin-left: 0.5rem; padding: 0.25rem 0.5rem;',
'click': function() {
navigator.clipboard.writeText(svc.onion);
ui.addNotification(null, E('p', {}, 'Copied to clipboard'), 'info');
}
}, '\ud83d\udccb')
]),
E('td', {}, svc.port || '80'),
E('td', { 'style': 'font-family: monospace;' }, svc.backend || 'N/A'),
E('td', {}, [
E('button', {
'class': 'btn-action btn-danger',
'click': ui.createHandlerFn(self, 'handleRemove', svc.service)
}, 'Remove')
])
]);
})
)
]) :
E('div', { 'class': 'exposure-empty' }, [
E('div', { 'class': 'icon' }, '\ud83e\uddc5'),
E('p', {}, 'No Tor hidden services configured'),
E('p', { 'style': 'font-size: 0.85rem;' }, 'Select a service above to create a .onion address')
])
])
]);
// Wire up service selector
setTimeout(function() {
var sel = document.getElementById('new-tor-service');
var portInput = document.getElementById('new-tor-port');
if (sel && portInput) {
sel.addEventListener('change', function() {
var opt = sel.options[sel.selectedIndex];
portInput.value = opt.dataset.port || '';
});
}
}, 100);
return view;
},
handleAdd: function(ev) {
var service = document.getElementById('new-tor-service').value;
var port = parseInt(document.getElementById('new-tor-port').value);
var onionPort = parseInt(document.getElementById('new-tor-onion-port').value) || 80;
if (!service) {
ui.addNotification(null, E('p', {}, 'Please select a service'), 'warning');
return;
}
if (!port) {
ui.addNotification(null, E('p', {}, 'Please specify the local port'), 'warning');
return;
}
ui.showModal('Creating Hidden Service...', [
E('p', { 'class': 'spinning' }, 'Please wait, generating .onion address (this may take a moment)...')
]);
api.torAdd(service, port, onionPort).then(function(res) {
ui.hideModal();
if (res.success) {
ui.addNotification(null, E('p', {}, [
'Hidden service created! ',
E('br'),
E('code', { 'style': 'word-break: break-all;' }, res.onion || 'Refresh to see address')
]), 'success');
location.reload();
} else {
ui.addNotification(null, E('p', {}, 'Error: ' + (res.error || 'Unknown error')), 'danger');
}
}).catch(function(err) {
ui.hideModal();
ui.addNotification(null, E('p', {}, 'Error: ' + err.message), 'danger');
});
},
handleRemove: function(service, ev) {
if (!confirm('Remove hidden service for ' + service + '?\n\nThe .onion address will be permanently lost.')) {
return;
}
api.torRemove(service).then(function(res) {
if (res.success) {
ui.addNotification(null, E('p', {}, 'Hidden service removed'), 'success');
location.reload();
} else {
ui.addNotification(null, E('p', {}, 'Error: ' + (res.error || 'Unknown error')), 'danger');
}
});
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});