mirror of
https://github.com/openwrt/luci.git
synced 2026-10-14 06:56:45 +04:00
luci-app-strongswan-swanctl: add legacy ipsec config migration overlay
The strongswan-swanctl view now checks on load whether a legacy ipsec configuration exists in '/etc/config/ipsec'. If no uci globals section is present, a blocking overlay is shown on the connection page which offers to run the command '/etc/init.d/swanctl migrate'. While the migration is pending, the page action footer (Save & Apply, Apply and Revert buttons) is disabled and the main content area is not clickable, so that no changes can be made to the ipsec configuration before the migration has finished. A successful migration reloads the page, while a failed migration is reported with the option to retry. If a legacy configuration can be found and to trigger the migration, the rpc ACLs are extended with the need permissions. Signed-off-by: Florian Eckert <fe@dev.tdt.de>
This commit is contained in:
1 parent
8afbea7e0c
commit
6cbaf78428
2 files changed
+78
-1
No files matched your search
+76
-1
@@ -4,6 +4,7 @@
|
||||
'require rpc';
|
||||
'require uci';
|
||||
'require ui';
|
||||
'require fs';
|
||||
|
||||
const callListAlgorithms = rpc.declare({
|
||||
object: 'luci.swanctl',
|
||||
@@ -53,20 +54,90 @@ function sectionNameCheck(extra_class) {
|
||||
return el;
|
||||
};
|
||||
|
||||
let migrationOverlay = null;
|
||||
|
||||
function renderMigrationContent(errorMessage) {
|
||||
const dialog = migrationOverlay.firstElementChild;
|
||||
const migrateButton = E('button', {
|
||||
'class': 'btn cbi-button cbi-button-apply',
|
||||
'click': handleMigrate
|
||||
}, [_('Migrate')]);
|
||||
|
||||
const content = E([], [
|
||||
E('h4', _('Migrate IPsec configuration')),
|
||||
E('p', _('A legacy IPsec configuration was found.') + ' ' +
|
||||
_('It must be migrated to the new swanctl uci schema in ' +
|
||||
'\'/etc/config/ipsec\' before it can be managed here.')),
|
||||
E('p', _('Before migration, the file \'/etc/config/ipsec\' is moved to \'/etc/config/ipsec_bak\'.') + ' ' +
|
||||
_('The migration may require manual intervention.') + ' ' +
|
||||
_('Therefore, the VPN is not restarted.')),
|
||||
E('p', _('Warning: The migration will drop all IPsec VPN connections.'))
|
||||
]);
|
||||
|
||||
if (errorMessage)
|
||||
content.appendChild(E('p', errorMessage));
|
||||
|
||||
content.appendChild(E('div', { 'class': 'right' }, [migrateButton]));
|
||||
|
||||
dialog.replaceChildren(content);
|
||||
}
|
||||
|
||||
function showMigrationOverlay(viewNode) {
|
||||
if (migrationOverlay)
|
||||
return;
|
||||
|
||||
const dialog = E('div', { 'class': 'modal', 'style': 'margin:0;' });
|
||||
migrationOverlay = E('div', {
|
||||
'class': 'migration-overlay',
|
||||
'style': 'position:absolute;top:0;right:0;bottom:0;left:0;z-index:900;display:flex;align-items:center;justify-content:center;padding:1em;pointer-events:all;'
|
||||
}, [dialog]);
|
||||
|
||||
viewNode.style.position = 'relative';
|
||||
viewNode.appendChild(migrationOverlay);
|
||||
|
||||
const maincontent = document.getElementById('maincontent');
|
||||
if (maincontent)
|
||||
maincontent.style.pointerEvents = 'none';
|
||||
|
||||
renderMigrationContent(null);
|
||||
}
|
||||
|
||||
function handleMigrate() {
|
||||
const dialog = migrationOverlay.firstElementChild;
|
||||
|
||||
dialog.replaceChildren(E([], [
|
||||
E('h4', _('Migrate IPsec configuration')),
|
||||
E('p', _('Migrating IPsec configuration…'))
|
||||
]));
|
||||
|
||||
fs.exec('/etc/init.d/swanctl', ['migrate', L.env.sessionid]).then(function (result) {
|
||||
if (result.code != 0)
|
||||
renderMigrationContent(_('Migration failed: %s').format(result.stderr || result.stdout || _('unknown error')));
|
||||
else
|
||||
window.location.reload();
|
||||
}).catch(function (e) {
|
||||
renderMigrationContent(_('Migration failed: %s').format(e.message));
|
||||
});
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
load: function () {
|
||||
return Promise.all([
|
||||
callListAlgorithms(),
|
||||
L.resolveDefault(uci.load('network'), null),
|
||||
L.resolveDefault(uci.load('ipsec'), null),
|
||||
]).then(function (data) {
|
||||
let hasNoGlobals = uci.sections('ipsec', 'globals').length === 0;
|
||||
return {
|
||||
algorithms: data[0],
|
||||
legacyConfig: hasNoGlobals,
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
render: function (result) {
|
||||
let m, s, o;
|
||||
const legacyConfig = result.legacyConfig;
|
||||
const algorithms = result.algorithms.data ?? {};
|
||||
const error = result.algorithms.error;
|
||||
|
||||
@@ -576,6 +647,10 @@ return view.extend({
|
||||
o.depends({'is_esp': '0', 'use_custom_proposal': '0'});
|
||||
addAlgorithms(o, algorithms.prf);
|
||||
|
||||
return m.render();
|
||||
return m.render().then(function (node) {
|
||||
if (legacyConfig)
|
||||
showMigrationOverlay(node);
|
||||
return node;
|
||||
});
|
||||
}
|
||||
});
|
||||
+2
@@ -3,6 +3,7 @@
|
||||
"description": "Grant access to luci-app-strongswan-swanctl",
|
||||
"read": {
|
||||
"file": {
|
||||
"/etc/config/ipsec": [ "list" ],
|
||||
"/usr/sbin/swanmon version": [ "exec" ],
|
||||
"/usr/sbin/swanmon stats": [ "exec" ]
|
||||
},
|
||||
@@ -13,6 +14,7 @@
|
||||
},
|
||||
"write": {
|
||||
"file": {
|
||||
"/etc/init.d/swanctl migrate *": [ "exec" ],
|
||||
"/usr/sbin/swanctl --initiate --ike *": [ "exec" ],
|
||||
"/usr/sbin/swanctl --initiate --child *": [ "exec" ],
|
||||
"/usr/sbin/swanctl --terminate --ike *": [ "exec" ],
|
||||
|
||||
Reference in new issue
Block a user