Refactor Omada proxy for v4/v5

pull/704/head
Michael Shamoon 2 years ago
parent a9cc0100f6
commit 4a3f836020

@ -9,40 +9,26 @@ const proxyName = "omadaProxyHandler";
const logger = createLogger(proxyName); const logger = createLogger(proxyName);
async function login(loginUrl, username, password, cversion) { async function login(loginUrl, username, password, controllerVersionMajor) {
let params; const params = {
if (cversion < "4.0.0") { username: username,
// change the parameters of the query string password: password
params = JSON.stringify({
"method": "login",
"params": {
"name": username,
"password": password
}
});
} else {
params = JSON.stringify({
"username": username,
"password": password
});
} }
const authResponse = await httpProxy(loginUrl, {
method: "POST",
body: params,
headers: {
"Content-Type": "application/json",
},
});
const data = JSON.parse(authResponse[2]); if (controllerVersionMajor < 4) {
const status = authResponse[0]; params.method = "login";
let token; params.name = username;
if (data.errorCode === 0) {
token = data.result.token;
} else {
token = null;
} }
return [status, token ?? data];
const [status, contentType, data] = await httpProxy(loginUrl, {
method: "POST",
body: JSON.stringify(params),
headers: {
"Content-Type": "application/json",
},
});
return [status, JSON.parse(data.toString())];
} }
@ -57,108 +43,121 @@ export default async function omadaProxyHandler(req, res) {
} }
if (widget) { if (widget) {
let cid;
let cversion;
let connectedAp;
let activeuser;
let connectedSwitches;
let connectedGateways;
let alerts;
let loginUrl;
let siteName;
let requestresponse;
const {url} = widget; const {url} = widget;
const controllerInfoUrl = `${widget.url}/api/info`; const controllerInfoURL = `${widget.url}/api/info`;
const cInfoResponse = await httpProxy(controllerInfoUrl, { let [status, contentType, data] = await httpProxy(controllerInfoURL, {
method: "GET",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
}); });
if (status !== 200) {
if (cInfoResponse[0] === 500) { logger.error("Unable to retrieve Omada controller info");
logger.debug("Getting controller version ends with Error 500"); return res.status(status).json({error: {message: `HTTP Error ${status}`, url: controllerInfoURL, data: data}});
return res.status(cInfoResponse[0]).json({error: {message: "HTTP Error", controllerInfoUrl, data: cInfoResponse[2]}});
} }
const cidresult = cInfoResponse[2];
const cId = JSON.parse(data).result.omadacId;
let controllerVersion;
try { try {
cid = JSON.parse(cidresult).result.omadacId; controllerVersion = JSON.parse(data).result.controllerVer;
cversion = JSON.parse(cidresult).result.controllerVer;
} catch (e) { } catch (e) {
cversion = "3.2.17" // fallback to this random version?
controllerVersion = "3.2.17"
} }
if (cversion < "4.0.0") {
loginUrl = `${widget.url}/api/user/login?ajax`; const controllerVersionMajor = parseInt(controllerVersion.split('.')[0], 10)
} else if (cversion < "5.0.0") {
loginUrl = `${widget.url}/api/v2/login`; if (![3,4,5].includes(controllerVersionMajor)) {
} else { return res.status(500).json({error: {message: "Error determining controller version", data}});
loginUrl = `${widget.url}/${cid}/api/v2/login`; }
let loginUrl;
switch (controllerVersionMajor) {
case 3:
loginUrl = `${widget.url}/api/user/login?ajax`;
break;
case 4:
loginUrl = `${widget.url}/api/v2/login`;
break;
case 5:
loginUrl = `${widget.url}/${cId}/api/v2/login`;
break;
default:
break;
} }
requestresponse = await login(loginUrl, widget.username, widget.password, cversion);
const [loginStatus, loginResponseData] = await login(loginUrl, widget.username, widget.password, controllerVersionMajor);
if (requestresponse[1].errorCode) { if (loginStatus !== 200 || loginResponseData.errorCode > 0) {
return res.status(requestresponse[0]).json({error: {message: "Error logging in", url, data: requestresponse[1]}}); return res.status(requestresponse[0]).json({error: {message: "Error logging in to Oamda controller", url: loginUrl, data: loginResponseData}});
} }
const token = requestresponse[1]; const token = loginResponseData.result.token;
// Switching to the site we want to gather stats from
// First, we get the list of sites // List sites
let sitesUrl; let sitesUrl;
let body; let body = {};
let params; let params = { token };
let headers; let headers = { "Csrf-Token": token };
let method; let method = "GET";
let sitetoswitch;
if (cversion < "4.0.0") { switch (controllerVersionMajor) {
sitesUrl = `${widget.url}/web/v1/controller?ajax=&token=${token}`; case 3:
body = JSON.stringify({ sitesUrl = `${widget.url}/web/v1/controller?ajax=&token=${token}`;
"method": "getUserSites", body = {
"params": { "method": "getUserSites",
"userName": widget.username "params": {
}}); "userName": widget.username
params = { "token": token }; }
headers = { }; };
method = "POST"; method = "POST";
} else if (cversion < "5.0.0") { break;
sitesUrl = `${widget.url}/api/v2/sites?token=${token}&currentPage=1&currentPageSize=1000`; case 4:
body = {}; sitesUrl = `${widget.url}/api/v2/sites?token=${token}&currentPage=1&currentPageSize=1000`;
params = {"token": token}; break;
headers = {"Csrf-Token": token }; case 5:
method = "GET"; sitesUrl = `${widget.url}/${cId}/api/v2/sites?token=${token}&currentPage=1&currentPageSize=1000`;
break;
} else {
sitesUrl = `${widget.url}/${cid}/api/v2/sites?token=${token}&currentPage=1&currentPageSize=1000`;
body = {};
headers = { "Csrf-Token": token };
method = "GET";
params = { };
} }
requestresponse = await httpProxy(sitesUrl, {
[status, contentType, data] = await httpProxy(sitesUrl, {
method, method,
params, params,
body: body.toString(), body: JSON.stringify(body),
headers, headers,
}); });
const listresult = JSON.parse(requestresponse[2]);
if (listresult.errorCode !== 0) { const sitesResponseData = JSON.parse(data);
logger.debug(`HTTTP ${requestresponse[0]} getting sites list: ${requestresponse[2].msg}`);
return res.status(requestresponse[0]).json({error: {message: "Error getting sites list", url, data: requestresponse[2]}}); let site;
let connectedAp;
let activeUser;
let connectedSwitches;
let connectedGateways;
let alerts;
if (sitesResponseData.errorCode > 0) {
logger.debug(`HTTTP ${status} getting sites list: ${requestresponse[2].msg}`);
return res.status(status).json({error: {message: "Error getting sites list", url, data: requestresponse[2]}});
} }
// Switching site is really needed only for Omada 3.x.x controllers // on modern controller, we need to call two different endpoints
// on older controller, we can call one endpoint
let switchUrl; if (controllerVersionMajor === 3) {
if (cversion < "4.0.0") { // Switching site is really needed only for Omada 3.x.x controllers
sitetoswitch = listresult.result.siteList.filter(site => site.name === widget.site);
siteName = sitetoswitch[0].siteName; let switchUrl;
site = listresult.result.siteList.filter(site => site.name === widget.site);
siteName = site[0].siteName;
switchUrl = `${widget.url}/web/v1/controller?ajax=&token=${token}`; switchUrl = `${widget.url}/web/v1/controller?ajax=&token=${token}`;
method = "POST"; method = "POST";
body = JSON.stringify({ body = JSON.stringify({
@ -181,12 +180,7 @@ export default async function omadaProxyHandler(req, res) {
logger.debug(`HTTTP ${requestresponse[0]} getting sites list: ${requestresponse[2]}`); logger.debug(`HTTTP ${requestresponse[0]} getting sites list: ${requestresponse[2]}`);
return res.status(requestresponse[0]).json({error: {message: "Error switching site", url, data: requestresponse[2]}}); return res.status(requestresponse[0]).json({error: {message: "Error switching site", url, data: requestresponse[2]}});
} }
}
// OK now we are on the correct site. Let's get the stats
// on modern controller, we need to call two different endpoints
// on older controller, we can call one endpoint
if (cversion < "4.0.0") {
const statsUrl = `${widget.url}/web/v1/controller?getGlobalStat=&token=${token}`; const statsUrl = `${widget.url}/web/v1/controller?getGlobalStat=&token=${token}`;
const statResponse = await httpProxy(statsUrl, { const statResponse = await httpProxy(statsUrl, {
method: "POST", method: "POST",
@ -205,68 +199,61 @@ export default async function omadaProxyHandler(req, res) {
return res.status(statResponse[0]).json({error: {message: "Error getting stats", url, data: statResponse[2]}}); return res.status(statResponse[0]).json({error: {message: "Error getting stats", url, data: statResponse[2]}});
} }
connectedAp = data.result.connectedAp; connectedAp = data.result.connectedAp;
activeuser = data.result.activeUser; activeUser = data.result.activeUser;
alerts = data.result.alerts; alerts = data.result.alerts;
} else { } else if (controllerVersionMajor === 4 || controllerVersionMajor === 5) {
let siteStatsUrl; site = sitesResponseData.result.data.find(site => site.name === widget.site);
let response;
sitetoswitch = listresult.result.data.filter(site => site.name === widget.site);
if (sitetoswitch.length === 0) { if (site.length === 0) {
return res.status(requestresponse[0]).json({error: {message: `Site ${widget.site} is not found`, url, data: requestresponse[2]}}); return res.status(requestresponse[0]).json({error: {message: `Site ${widget.site} is not found`, url, data}});
} }
// On 5.0.0, the field we need is id, on 4.x.x, it's key ... const siteName = (controllerVersionMajor === 5) ? site.id : site.key;
siteName = sitetoswitch[0].id ?? sitetoswitch[0].key; const siteStatsUrl = (controllerVersionMajor === 4) ?
if (cversion < "5.0.0") { `${url}/api/v2/sites/${siteName}/dashboard/overviewDiagram?token=${token}&currentPage=1&currentPageSize=1000` :
siteStatsUrl = `${url}/api/v2/sites/${siteName}/dashboard/overviewDiagram?token=${token}&currentPage=1&currentPageSize=1000`; `${url}/${cId}/api/v2/sites/${siteName}/dashboard/overviewDiagram?token=${token}&currentPage=1&currentPageSize=1000`;
} else {
siteStatsUrl = `${url}/${cid}/api/v2/sites/${siteName}/dashboard/overviewDiagram?token=${token}&currentPage=1&currentPageSize=1000`; [status, contentType, data] = await httpProxy(siteStatsUrl, {
}
response = await httpProxy(siteStatsUrl, {
method: "GET",
headers: { headers: {
"Csrf-Token": token, "Csrf-Token": token,
}, },
}); });
const clientresult = JSON.parse(response[2]); const siteResponseData = JSON.parse(data);
if (clientresult.errorCode !== 0) {
logger.debug(`HTTTP ${listresult.errorCode} getting clients stats for site ${widget.site} with message ${listresult.msg}`); if (status !== 200 || siteResponseData.errorCode > 0) {
return res.status(500).send(response[2]); logger.debug(`HTTP ${status} getting stats for site ${widget.site} with message ${listresult.msg}`);
return res.status(500).send(data);
} }
activeuser = clientresult.result.totalClientNum; activeUser = siteResponseData.result.totalClientNum;
connectedAp = clientresult.result.connectedApNum; connectedAp = siteResponseData.result.connectedApNum;
connectedGateways = clientresult.result.connectedGatewayNum; connectedGateways = siteResponseData.result.connectedGatewayNum;
connectedSwitches = clientresult.result.connectedSwitchNum; connectedSwitches = siteResponseData.result.connectedSwitchNum;
const alertUrl = (controllerVersionMajor === 4) ?
`${url}/api/v2/sites/${siteName}/alerts/num?token=${token}&currentPage=1&currentPageSize=1000` :
`${url}/${cId}/api/v2/sites/${siteName}/alerts/num?token=${token}&currentPage=1&currentPageSize=1000`;
let alertUrl; [status, contentType, data] = await httpProxy(alertUrl, {
if (cversion >= "5.0.0") {
alertUrl = `${url}/${cid}/api/v2/sites/${siteName}/alerts/num?token=${token}&currentPage=1&currentPageSize=1000`;
} else {
alertUrl = `${url}/api/v2/sites/${siteName}/alerts/num?token=${token}&currentPage=1&currentPageSize=1000`;
}
response = await httpProxy(alertUrl, {
method: "GET",
headers: { headers: {
"Csrf-Token": token, "Csrf-Token": token,
}, },
}); });
const alertresult = JSON.parse(response[2]); const alertResponseData = JSON.parse(data);
alerts = alertresult.result.alertNum; alerts = alertResponseData.result.alertNum;
} }
return res.send(JSON.stringify({ return res.send(JSON.stringify({
"connectedAp": connectedAp, connectedAp,
"activeUser": activeuser, activeUser,
"alerts": alerts, alerts,
"connectedGateways": connectedGateways, connectedGateways,
"connectedSwitches": connectedSwitches, connectedSwitches,
})); }));
} }
} }
return res.status(400).json({ error: "Invalid proxy service type" }); return res.status(400).json({ error: "Invalid proxy service type" });
} }

Loading…
Cancel
Save