|
@@ -1,6 +1,6 @@
|
|
|
/*
|
|
|
ztncui - ZeroTier network controller UI
|
|
|
- Copyright (C) 2017 Key Networks (https://key-networks.com)
|
|
|
+ Copyright (C) 2017-2018 Key Networks (https://key-networks.com)
|
|
|
Licensed under GPLv3 - see LICENSE for details.
|
|
|
*/
|
|
|
|
|
@@ -13,52 +13,68 @@ storage.initSync({dir: 'etc/storage'});
|
|
|
|
|
|
// ZT network controller home page
|
|
|
exports.index = async function(req, res) {
|
|
|
- const page = 'controller_home';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'controller_home',
|
|
|
+ }
|
|
|
|
|
|
try {
|
|
|
zt_address = await zt.get_zt_address();
|
|
|
- res.render('index', {title: 'ztncui', page: page, zt_address: zt_address});
|
|
|
+ res.render('index', {title: 'ztncui', nav: nav, zt_address: zt_address});
|
|
|
} catch (err) {
|
|
|
res.render('index', {title: 'ztncui',
|
|
|
- page: page, error: 'ERROR resolving ZT address: ' + err});
|
|
|
+ nav: nav, error: 'ERROR resolving ZT address: ' + err});
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// Display list of all networks on this ZT network controller
|
|
|
exports.network_list = async function(req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ }
|
|
|
|
|
|
try {
|
|
|
networks = await zt.network_list();
|
|
|
- res.render('networks', {title: 'Networks on this controller', page: page, networks: networks});
|
|
|
+ res.render('networks', {title: 'Networks on this controller', nav: nav, networks: networks});
|
|
|
} catch (err) {
|
|
|
- res.render('networks', {title: 'Networks on this controller', page: page, error: 'Error retrieving list of networks on this controller: ' + err});
|
|
|
+ res.render('networks', {title: 'Networks on this controller', nav: nav, error: 'Error retrieving list of networks on this controller: ' + err});
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// Display detail page for specific network
|
|
|
exports.network_detail = async function(req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: '/controller/networks'
|
|
|
+ }
|
|
|
|
|
|
try {
|
|
|
const network = await zt.network_detail(req.params.nwid);
|
|
|
const members = await zt.members(req.params.nwid);
|
|
|
- res.render('network_detail', {title: 'Detail for network', page: page, network: network, members: members});
|
|
|
+ res.render('network_detail', {title: 'Detail for network', nav: nav, network: network, members: members});
|
|
|
} catch (err) {
|
|
|
- res.render('network_detail', {title: 'Detail for network', page: page, error: 'Error resolving detail for network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render('network_detail', {title: 'Detail for network', nav: nav, error: 'Error resolving detail for network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// Display Network create form on GET
|
|
|
exports.network_create_get = function(req, res) {
|
|
|
- const page = 'add_network';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'add_network',
|
|
|
+ }
|
|
|
|
|
|
- res.render('network_create', {title: 'Create network', page: page});
|
|
|
+ res.render('network_create', {title: 'Create network', nav: nav});
|
|
|
};
|
|
|
|
|
|
// Handle Network create on POST
|
|
|
exports.network_create_post = async function(req, res) {
|
|
|
- const page = 'add_network';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'add_network',
|
|
|
+ }
|
|
|
|
|
|
req.checkBody('name', 'Network name required').notEmpty();
|
|
|
|
|
@@ -70,66 +86,83 @@ exports.network_create_post = async function(req, res) {
|
|
|
const name = { name: req.body.name };
|
|
|
|
|
|
if (errors) {
|
|
|
- res.render('network_create', {title: 'Create Network', page: page, name: name, errors: errors});
|
|
|
+ res.render('network_create', {title: 'Create Network', nav: nav, name: name, errors: errors});
|
|
|
return;
|
|
|
} else {
|
|
|
try {
|
|
|
const network = await zt.network_create(name);
|
|
|
res.redirect('/controller/networks');
|
|
|
} catch (err) {
|
|
|
- res.render('network_detail', {title: 'Create Network - error', page: page, error: 'Error creating network ' + name.name});
|
|
|
+ res.render('network_detail', {title: 'Create Network - error', nav: nav, error: 'Error creating network ' + name.name});
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// Display Network delete form on GET
|
|
|
exports.network_delete_get = async function(req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: '/controller/networks'
|
|
|
+ }
|
|
|
|
|
|
try {
|
|
|
const network = await zt.network_detail(req.params.nwid);
|
|
|
- res.render('network_delete', {title: 'Delete network', page: page,
|
|
|
+ res.render('network_delete', {title: 'Delete network', nav: nav,
|
|
|
nwid: req.params.nwid, network: network});
|
|
|
} catch (err) {
|
|
|
- res.render('network_delete', {title: 'Delete network', page: page, error: 'Error resolving network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render('network_delete', {title: 'Delete network', nav: nav, error: 'Error resolving network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// Handle Network delete on POST
|
|
|
exports.network_delete_post = async function(req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: '/controller/networks'
|
|
|
+ }
|
|
|
|
|
|
try {
|
|
|
const network = await zt.network_delete(req.params.nwid);
|
|
|
- res.render('network_delete', {title: 'Delete network', page: page, network: network});
|
|
|
+ res.render('network_delete', {title: 'Delete network', nav: nav, network: network});
|
|
|
} catch (err) {
|
|
|
- res.render('network_delete', {title: 'Delete network', page: page, error: 'Error deleting network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render('network_delete', {title: 'Delete network', nav: nav, error: 'Error deleting network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// Network object GET
|
|
|
exports.network_object = async function(req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: ''
|
|
|
+ }
|
|
|
|
|
|
try {
|
|
|
const network = await zt.network_detail(req.params.nwid);
|
|
|
- res.render(req.params.object, {title: req.params.object, page: page, network: network}, function(err, html) {
|
|
|
+ nav.whence = '/controller/network/' + network.nwid;
|
|
|
+ res.render(req.params.object, {title: req.params.object, nav: nav, network: network}, function(err, html) {
|
|
|
if (err) {
|
|
|
if (err.message.indexOf('Failed to lookup view') !== -1 ) {
|
|
|
- return res.render('not_implemented', {title: req.params.object, page: page, network: network});
|
|
|
+ return res.render('not_implemented', {title: req.params.object, nav: nav, network: network});
|
|
|
}
|
|
|
throw err;
|
|
|
}
|
|
|
res.send(html);
|
|
|
});
|
|
|
} catch (err) {
|
|
|
- res.render(req.params.object, {title: req.params.object, page: page, error: 'Error resolving detail for network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render(req.params.object, {title: req.params.object, nav: nav, error: 'Error resolving detail for network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Handle Network rename form on POST
|
|
|
exports.name = async function(req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: '/controller/networks'
|
|
|
+ }
|
|
|
|
|
|
req.checkBody('name', 'Network name required').notEmpty();
|
|
|
req.sanitize('name').escape();
|
|
@@ -142,16 +175,16 @@ exports.name = async function(req, res) {
|
|
|
if (errors) {
|
|
|
try {
|
|
|
const network = await zt.network_detail(req.params.nwid);
|
|
|
- res.render('name', {title: 'Rename network', page: page, network: network, name: name, errors: errors});
|
|
|
+ res.render('name', {title: 'Rename network', nav: nav, network: network, name: name, errors: errors});
|
|
|
} catch (err) {
|
|
|
- res.render('name', {title: 'Rename network', page: page, error: 'Error resolving network detail for network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render('name', {title: 'Rename network', nav: nav, error: 'Error resolving network detail for network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
} else {
|
|
|
try {
|
|
|
const network = await zt.network_object(req.params.nwid, name);
|
|
|
res.redirect('/controller/networks');
|
|
|
} catch ( err) {
|
|
|
- res.render('name', {title: 'Rename network', page: page, error: 'Error renaming network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render('name', {title: 'Rename network', nav: nav, error: 'Error renaming network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -159,7 +192,11 @@ exports.name = async function(req, res) {
|
|
|
|
|
|
// ipAssignmentPools POST
|
|
|
exports.ipAssignmentPools = async function(req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: ''
|
|
|
+ }
|
|
|
|
|
|
req.checkBody('ipRangeStart', 'IP range start required').notEmpty();
|
|
|
req.checkBody('ipRangeStart', 'IP range start needs a valid IPv4 or IPv6 address').isIP();
|
|
@@ -181,16 +218,18 @@ exports.ipAssignmentPools = async function(req, res) {
|
|
|
if (errors) {
|
|
|
try {
|
|
|
const network = await zt.network_detail(req.params.nwid);
|
|
|
- res.render('ipAssignmentPools', {title: 'ipAssignmentPools', page: page, ipAssignmentPool: ipAssignmentPool, network: network, errors: errors});
|
|
|
+ nav.whence = '/controller/network/' + network.nwid;
|
|
|
+ res.render('ipAssignmentPools', {title: 'ipAssignmentPools', nav: nav, ipAssignmentPool: ipAssignmentPool, network: network, errors: errors});
|
|
|
} catch (err) {
|
|
|
- res.render('ipAssignmentPools', {title: 'ipAssignmentPools', page: page, error: 'Error resolving network detail for network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render('ipAssignmentPools', {title: 'ipAssignmentPools', nav: nav, error: 'Error resolving network detail for network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
} else {
|
|
|
try {
|
|
|
const network = await zt.ipAssignmentPools(req.params.nwid, ipAssignmentPool, 'add');
|
|
|
- res.render('ipAssignmentPools', {title: 'ipAssignmentPools', page: page, ipAssignmentPool: ipAssignmentPool, network: network});
|
|
|
+ nav.whence = '/controller/network/' + network.nwid;
|
|
|
+ res.render('ipAssignmentPools', {title: 'ipAssignmentPools', nav: nav, ipAssignmentPool: ipAssignmentPool, network: network});
|
|
|
} catch (err) {
|
|
|
- res.render('ipAssignmentPools', {title: 'ipAssignmentPools', page: page, error: 'Error applying IP Assignment Pools for network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render('ipAssignmentPools', {title: 'ipAssignmentPools', nav: nav, error: 'Error applying IP Assignment Pools for network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -202,7 +241,11 @@ isValidPrefix = function(str, max) {
|
|
|
|
|
|
// routes POST
|
|
|
exports.routes = async function (req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: ''
|
|
|
+ }
|
|
|
|
|
|
req.checkBody('target', 'Target network is required').notEmpty();
|
|
|
req.sanitize('target').trim();
|
|
@@ -242,16 +285,18 @@ exports.routes = async function (req, res) {
|
|
|
if (errors) {
|
|
|
try {
|
|
|
const network = await zt.network_detail(req.params.nwid);
|
|
|
- res.render('routes', {title: 'routes', page: page, route: route, network: network, errors: errors});
|
|
|
+ nav.whence = '/controller/network/' + network.nwid;
|
|
|
+ res.render('routes', {title: 'routes', nav: nav, route: route, network: network, errors: errors});
|
|
|
} catch (err) {
|
|
|
- res.render('routes', {title: 'routes', page: page, error: 'Error resolving network detail'});
|
|
|
+ res.render('routes', {title: 'routes', nav: nav, error: 'Error resolving network detail'});
|
|
|
}
|
|
|
} else {
|
|
|
try {
|
|
|
const network = await zt.routes(req.params.nwid, route, 'add');
|
|
|
- res.render('routes', {title: 'routes', page: page, route: route, network: network});
|
|
|
+ nav.whence = '/controller/network/' + network.nwid;
|
|
|
+ res.render('routes', {title: 'routes', nav: nav, route: route, network: network});
|
|
|
} catch (err) {
|
|
|
- res.render('routes', {title: 'routes', page: page, error: 'Error adding route for network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render('routes', {title: 'routes', nav: nav, error: 'Error adding route for network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -259,7 +304,11 @@ exports.routes = async function (req, res) {
|
|
|
|
|
|
// route_delete GET
|
|
|
exports.route_delete = async function (req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: ''
|
|
|
+ }
|
|
|
|
|
|
const route =
|
|
|
{
|
|
@@ -270,15 +319,20 @@ exports.route_delete = async function (req, res) {
|
|
|
|
|
|
try {
|
|
|
const network = await zt.routes(req.params.nwid, route, 'delete');
|
|
|
- res.render('routes', {title: 'routes', page: page, route: route, network: network});
|
|
|
+ nav.whence = '/controller/network/' + network.nwid;
|
|
|
+ res.render('routes', {title: 'routes', nav: nav, route: route, network: network});
|
|
|
} catch (err) {
|
|
|
- res.render('routes', {title: 'routes', page: page, error: 'Error deleting route for network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render('routes', {title: 'routes', nav: nav, error: 'Error deleting route for network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// ipAssignmentPool_delete GET
|
|
|
exports.ipAssignmentPool_delete = async function (req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: ''
|
|
|
+ }
|
|
|
|
|
|
const ipAssignmentPool =
|
|
|
{
|
|
@@ -289,15 +343,20 @@ exports.ipAssignmentPool_delete = async function (req, res) {
|
|
|
|
|
|
try {
|
|
|
const network = await zt.ipAssignmentPools(req.params.nwid, ipAssignmentPool, 'delete');
|
|
|
- res.render('ipAssignmentPools', {title: 'ipAssignmentPools', page: page, ipAssignmentPool: ipAssignmentPool, network: network});
|
|
|
+ nav.whence = '/controller/network/' + network.nwid;
|
|
|
+ res.render('ipAssignmentPools', {title: 'ipAssignmentPools', nav: nav, ipAssignmentPool: ipAssignmentPool, network: network});
|
|
|
} catch (err) {
|
|
|
- res.render('ipAssignmentPools', {title: 'ipAssignmentPools', page: page, error: 'Error deleting IP Assignment Pool for network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render('ipAssignmentPools', {title: 'ipAssignmentPools', nav: nav, error: 'Error deleting IP Assignment Pool for network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// v4AssignMode POST
|
|
|
exports.v4AssignMode = async function (req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: ''
|
|
|
+ }
|
|
|
|
|
|
const v4AssignMode =
|
|
|
{
|
|
@@ -306,15 +365,20 @@ exports.v4AssignMode = async function (req, res) {
|
|
|
|
|
|
try {
|
|
|
const network = await zt.network_object(req.params.nwid, v4AssignMode);
|
|
|
- res.render('v4AssignMode', {title: 'v4AssignMode', page: page, network: network});
|
|
|
+ nav.whence = '/controller/network/' + network.nwid;
|
|
|
+ res.render('v4AssignMode', {title: 'v4AssignMode', nav: nav, network: network});
|
|
|
} catch (err) {
|
|
|
- res.render('v4AssignMode', {title: 'v4AssignMode', page: page, error: 'Error applying v4AssignMode for network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render('v4AssignMode', {title: 'v4AssignMode', nav: nav, error: 'Error applying v4AssignMode for network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// v6AssignMode POST
|
|
|
exports.v6AssignMode = async function (req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: ''
|
|
|
+ }
|
|
|
|
|
|
const v6AssignMode =
|
|
|
{
|
|
@@ -328,76 +392,103 @@ exports.v6AssignMode = async function (req, res) {
|
|
|
|
|
|
try {
|
|
|
const network = await zt.network_object(req.params.nwid, v6AssignMode);
|
|
|
- res.render('v6AssignMode', {title: 'v6AssignMode', page: page, network: network});
|
|
|
+ nav.whence = '/controller/network/' + network.nwid;
|
|
|
+ res.render('v6AssignMode', {title: 'v6AssignMode', nav: nav, network: network});
|
|
|
} catch (err) {
|
|
|
- res.render('v6AssignMode', {title: 'v6AssignMode', page: page, error: 'Error applying v6AssignMode for network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render('v6AssignMode', {title: 'v6AssignMode', nav: nav, error: 'Error applying v6AssignMode for network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Display detail page for specific member
|
|
|
exports.member_detail = async function(req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: ''
|
|
|
+ }
|
|
|
|
|
|
try {
|
|
|
const network = await zt.network_detail(req.params.nwid);
|
|
|
const member = await zt.member_detail(req.params.nwid, req.params.id);
|
|
|
- res.render('member_detail', {title: 'Network member detail', page: page, network: network, member: member});
|
|
|
+ nav.whence = '/controller/network/' + network.nwid + '/members';
|
|
|
+ res.render('member_detail', {title: 'Network member detail', nav: nav, network: network, member: member});
|
|
|
} catch (err) {
|
|
|
- res.render(req.params.object, {title: req.params.object, page: page, error: 'Error resolving detail for member ' + req.params.id + ' of network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render(req.params.object, {title: req.params.object, nav: nav, error: 'Error resolving detail for member ' + req.params.id + ' of network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// Member object GET
|
|
|
exports.member_object = async function(req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: ''
|
|
|
+ }
|
|
|
|
|
|
try {
|
|
|
const network = await zt.network_detail(req.params.nwid);
|
|
|
const member = await zt.member_detail(req.params.nwid, req.params.id);
|
|
|
- res.render(req.params.object, {title: req.params.object, page: page, network: network, member: member}, function(err, html) {
|
|
|
+ const name = await storage.getItem(member.id);
|
|
|
+ if (!name) name = '';
|
|
|
+ member.name = name;
|
|
|
+ nav.whence = '/controller/network/' + network.nwid + '/members';
|
|
|
+ res.render(req.params.object, {title: req.params.object, nav: nav, network: network, member: member}, function(err, html) {
|
|
|
if (err) {
|
|
|
if (err.message.indexOf('Failed to lookup view') !== -1 ) {
|
|
|
- return res.render('not_implemented', {title: req.params.object, page: page, network: network, member: member});
|
|
|
+ return res.render('not_implemented', {title: req.params.object, nav: nav, network: network, member: member});
|
|
|
}
|
|
|
throw err;
|
|
|
}
|
|
|
res.send(html);
|
|
|
});
|
|
|
} catch (err) {
|
|
|
- res.render(req.params.object, {title: req.params.object, page: page, error: 'Error resolving detail for member ' + req.params.id + ' of network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render(req.params.object, {title: req.params.object, nav: nav, error: 'Error resolving detail for member ' + req.params.id + ' of network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Member authorized POST
|
|
|
exports.member_authorized = async function(req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: ''
|
|
|
+ }
|
|
|
|
|
|
const authorized = { authorized: req.body.authorized };
|
|
|
|
|
|
try {
|
|
|
const network = await zt.network_detail(req.params.nwid);
|
|
|
const member = await zt.member_object(req.params.nwid, req.params.id, authorized);
|
|
|
- res.render('authorized', {title: 'authorized', page: page, network: network, member: member});
|
|
|
+ nav.whence = '/controller/network/' + network.nwid + '/members';
|
|
|
+ res.render('authorized', {title: 'authorized', nav: nav, network: network, member: member});
|
|
|
} catch (err) {
|
|
|
- res.render('authorized', {title: 'authorized', page: page, error: 'Error authorizing member ' + req.params.id + ' on network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render('authorized', {title: 'authorized', nav: nav, error: 'Error authorizing member ' + req.params.id + ' on network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Easy network setup GET
|
|
|
exports.easy_get = async function(req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: '/controller/networks'
|
|
|
+ }
|
|
|
|
|
|
try {
|
|
|
const network = await zt.network_detail(req.params.nwid);
|
|
|
- res.render('network_easy', {title: 'Easy setup of network', page: page, network: network});
|
|
|
+ res.render('network_easy', {title: 'Easy setup of network', nav: nav, network: network});
|
|
|
} catch (err) {
|
|
|
- res.render('network_easy', {title: 'Easy setup of network', page: page, error: 'Error resolving detail for network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render('network_easy', {title: 'Easy setup of network', nav: nav, error: 'Error resolving detail for network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Easy network setup POST
|
|
|
exports.easy_post = async function(req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: '/controller/networks'
|
|
|
+ }
|
|
|
|
|
|
req.checkBody('networkCIDR', 'Network address is required').notEmpty();
|
|
|
req.sanitize('networkCIDR').trim();
|
|
@@ -447,23 +538,27 @@ exports.easy_post = async function(req, res) {
|
|
|
v4AssignMode: v4AssignMode
|
|
|
};
|
|
|
|
|
|
- res.render('network_easy', {title: 'Easy setup of network', page: page, network: network, errors: errors});
|
|
|
+ res.render('network_easy', {title: 'Easy setup of network', nav: nav, network: network, errors: errors});
|
|
|
} else {
|
|
|
try {
|
|
|
const network = await zt.network_easy_setup(req.params.nwid,
|
|
|
routes,
|
|
|
ipAssignmentPools,
|
|
|
v4AssignMode);
|
|
|
- res.render('network_easy', {title: 'Easy setup of network', page: page, network: network, message: 'Network setup succeeded'});
|
|
|
+ res.render('network_easy', {title: 'Easy setup of network', nav: nav, network: network, message: 'Network setup succeeded'});
|
|
|
} catch (err) {
|
|
|
- res.render('network_easy', {title: 'Easy setup of network', page: page, error: 'Error resolving detail for network ' + req.params.nwid + ': ' + err});
|
|
|
+ res.render('network_easy', {title: 'Easy setup of network', nav: nav, error: 'Error resolving detail for network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Easy members auth GET or POST
|
|
|
exports.members = async function(req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: '/controller/networks'
|
|
|
+ }
|
|
|
|
|
|
let errors = null;
|
|
|
|
|
@@ -520,18 +615,22 @@ exports.members = async function(req, res) {
|
|
|
members.push(member);
|
|
|
}
|
|
|
|
|
|
- res.render('members', {title: 'Members of this network', page: page,
|
|
|
+ res.render('members', {title: 'Members of this network', nav: nav,
|
|
|
network: network, members: members, errors: errors});
|
|
|
} catch (err) {
|
|
|
- res.render('members', {title: 'Members of this network', page: page,
|
|
|
+ res.render('members', {title: 'Members of this network', nav: nav,
|
|
|
error: 'Error resolving detail for network ' + req.params.nwid
|
|
|
+ ': ' + err});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// Member delete GET and POST
|
|
|
+// Member delete GET or POST
|
|
|
exports.member_delete = async function(req, res) {
|
|
|
- const page = 'networks';
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: ''
|
|
|
+ }
|
|
|
|
|
|
try {
|
|
|
const network = await zt.network_detail(req.params.nwid);
|
|
@@ -548,12 +647,109 @@ exports.member_delete = async function(req, res) {
|
|
|
}
|
|
|
if (!name) name = '';
|
|
|
member.name = name;
|
|
|
+
|
|
|
+ nav.whence = '/controller/network/' + network.nwid + '/members';
|
|
|
res.render('member_delete', {title: 'Delete member from ' + network.name,
|
|
|
network: network, member: member});
|
|
|
} catch (err) {
|
|
|
- res.render('member_delete', {title: 'Delete member from network', page: page,
|
|
|
+ res.render('member_delete', {title: 'Delete member from network', nav: nav,
|
|
|
+ error: 'Error resolving detail for member ' + req.params.id
|
|
|
+ + ' of network ' + req.params.nwid + ': ' + err});
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// ipAssignment delete GET
|
|
|
+exports.delete_ip = async function(req, res) {
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: ''
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ const network = await zt.network_detail(req.params.nwid);
|
|
|
+ let member = await zt.member_detail(req.params.nwid, req.params.id);
|
|
|
+ nav.whence = '/controller/network/' + network.nwid + '/members';
|
|
|
+ const name = await storage.getItem(member.id);
|
|
|
+ if (!name) name = '';
|
|
|
+ member.name = name;
|
|
|
+ if (req.params.index) {
|
|
|
+ member = await zt.ipAssignmentDelete(network.nwid, member.id,
|
|
|
+ req.params.index);
|
|
|
+ res.redirect('/controller/network/' + network.nwid + '/member/' +
|
|
|
+ member.id + '/ipAssignments');
|
|
|
+ }
|
|
|
+ res.render('ipAssignments', {title: 'ipAssignments ' + network.name,
|
|
|
+ index: req.params.index, network: network, member: member});
|
|
|
+ } catch (err) {
|
|
|
+ res.render('ipAssignments', {title: 'ipAssignments', nav: nav,
|
|
|
error: 'Error resolving detail for member ' + req.params.id
|
|
|
+ ' of network ' + req.params.nwid + ': ' + err});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// ipAssignments POST
|
|
|
+exports.assign_ip = async function(req, res) {
|
|
|
+ const nav =
|
|
|
+ {
|
|
|
+ active: 'networks',
|
|
|
+ whence: ''
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ var network = await zt.network_detail(req.params.nwid);
|
|
|
+ } catch (err) {
|
|
|
+ throw err;
|
|
|
+ }
|
|
|
+
|
|
|
+ req.checkBody('ipAddress', 'IP address required').notEmpty();
|
|
|
+ req.checkBody('ipAddress', 'IP address must be a valid IPv4 or IPv6 address').isIP();
|
|
|
+ req.checkBody('ipAddress', 'IP address must fall within a managed route')
|
|
|
+ .custom(value => {
|
|
|
+ let ipAddressInManagedRoute = false;
|
|
|
+ network.routes.forEach(function(item) {
|
|
|
+ let ipv4 = new ipaddr.Address4(value);
|
|
|
+ console.log('ipv4 = ' + JSON.stringify(ipv4));
|
|
|
+ let target4 = new ipaddr.Address4(item.target);
|
|
|
+ console.log('target4 = ' + JSON.stringify(target4));
|
|
|
+ if (ipv4.isValid() && target4.isValid()) {
|
|
|
+ if (ipv4.isInSubnet(target4)) ipAddressInManagedRoute = true;
|
|
|
+ }
|
|
|
+ let ipv6 = new ipaddr.Address6(value);
|
|
|
+ console.log('ipv6 = ' + JSON.stringify(ipv6));
|
|
|
+ let target6 = new ipaddr.Address6(item.target);
|
|
|
+ console.log('target6 = ' + JSON.stringify(target6));
|
|
|
+ if (ipv6.isValid() && target6.isValid()) {
|
|
|
+ if (ipv6.isInSubnet(target6)) ipAddressInManagedRoute = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return ipAddressInManagedRoute;
|
|
|
+ });
|
|
|
+ req.sanitize('ipAddress').escape();
|
|
|
+ req.sanitize('ipAddress').trim();
|
|
|
+
|
|
|
+ const errors = req.validationErrors();
|
|
|
+
|
|
|
+ const ipAssignment = { ipAddress: req.body.ipAddress };
|
|
|
+
|
|
|
+ try {
|
|
|
+ let member = await zt.member_detail(req.params.nwid, req.params.id);
|
|
|
+ nav.whence = '/controller/network/' + network.nwid + '/members';
|
|
|
+
|
|
|
+ if (!errors) {
|
|
|
+ member = await zt.ipAssignmentAdd(network.nwid, member.id, ipAssignment);
|
|
|
+ }
|
|
|
+
|
|
|
+ const name = await storage.getItem(member.id);
|
|
|
+ if (!name) name = '';
|
|
|
+ member.name = name;
|
|
|
+
|
|
|
+ res.render('ipAssignments', {title: 'ipAssignments', nav: nav,
|
|
|
+ ipAssignment: ipAssignment, network: network, member: member,
|
|
|
+ errors: errors});
|
|
|
+ } catch (err) {
|
|
|
+ res.render('ipAssignments', {title: 'ipAssignments', nav: nav,
|
|
|
+ error: 'Error resolving detail for member ' + req.params.id
|
|
|
+ + ' of network ' + req.params.nwid + ': ' + err});
|
|
|
+ }
|
|
|
+}
|