Use nested config structure

This commit is contained in:
Zaid Abdulla committed 2018-12-26 00:22:07 -08:00
1 parent 581a510960
commit 30dbf0cf40
15 files changed
+366 -251

No files matched your search

+3
View File
@@ -11,6 +11,7 @@ import * as devicePage from "./device-page";
import * as errorPage from "./error-page"; import * as errorPage from "./error-page";
import * as faultsPage from "./faults-page"; import * as faultsPage from "./faults-page";
import Authorizer from "../common/authorizer"; import Authorizer from "../common/authorizer";
import * as funcCache from "../common/func-cache";
window.authorizer = new Authorizer(window.permissionSets); window.authorizer = new Authorizer(window.permissionSets);
@@ -68,6 +69,8 @@ function pagify(pageName, page) {
return component; return component;
} }
setInterval(funcCache.purge, 120000);
m.route(document.body, "/overview", { m.route(document.body, "/overview", {
"/login": pagify("login", loginPage), "/login": pagify("login", loginPage),
"/overview": pagify("overview", overviewPage), "/overview": pagify("overview", overviewPage),
+7 -3
View File
@@ -1,17 +1,21 @@
"use strict"; "use strict";
import m from "mithril"; import m from "mithril";
import * as config from "../config"; import config from "../config";
import * as store from "../store"; import * as store from "../store";
import * as funcCache from "../../common/func-cache";
import Filter from "../../common/filter";
const CHARTS = config.get("ui.overview.charts"); const CHARTS = config.ui.overview.charts;
const component = { const component = {
view: vnode => { view: vnode => {
const device = vnode.attrs.device; const device = vnode.attrs.device;
const chart = CHARTS[vnode.attrs.chart]; const chart = CHARTS[vnode.attrs.chart];
for (let slice of Object.values(chart.slices)) { for (let slice of Object.values(chart.slices)) {
const filter = store.unpackFilter(slice.filter); const filter = store.unpackFilter(
funcCache.get(Filter.parse, slice.filter)
);
if (filter.test(device)) { if (filter.test(device)) {
const dot = m( const dot = m(
"svg", "svg",
+1 -38
View File
@@ -1,40 +1,3 @@
"use strict"; "use strict";
import * as Filter from "../common/filter"; export default window.clientConfig;
const configFile = window.clientConfig;
const cache = {};
function parse(name, value) {
if (/^ui\.overview\.charts\.[^.]+\.slices\.[^.]+\.filter$/.test(name))
return new Filter(value);
return value;
}
function get(name) {
let v = cache[name];
if (v === undefined) {
v = configFile[name];
if (v != null) {
v = parse(name, v);
} else {
const prefix = `${name}.`;
for (let k of Object.keys(configFile))
if (k.startsWith(prefix)) {
v = v || {};
let ar = k.slice(prefix.length).split(".");
let ref = v;
for (let a of ar.slice(0, -1)) ref = ref[a] = ref[a] || {};
ref[ar[ar.length - 1]] = parse(k, configFile[k]);
}
}
if (v) cache[name] = v;
else cache[name] = null;
}
return v;
}
export { get };
+2 -2
View File
@@ -2,7 +2,7 @@
import m from "mithril"; import m from "mithril";
import * as config from "./config"; import config from "./config";
import Filter from "../common/filter"; import Filter from "../common/filter";
import * as store from "./store"; import * as store from "./store";
import * as components from "./components"; import * as components from "./components";
@@ -25,7 +25,7 @@ const component = {
let dev = store.fetch("devices", vnode.attrs.deviceFilter).value; let dev = store.fetch("devices", vnode.attrs.deviceFilter).value;
if (!dev.length) return "Loading"; if (!dev.length) return "Loading";
const conf = config.get("ui.device"); const conf = config.ui.device;
const cmps = []; const cmps = [];
for (let c of Object.values(conf)) for (let c of Object.values(conf))
+3 -3
View File
@@ -2,7 +2,7 @@
import m from "mithril"; import m from "mithril";
import * as config from "./config"; import config from "./config";
import filterComponent from "./filter-component"; import filterComponent from "./filter-component";
import * as filterParser from "../common/filter-parser"; import * as filterParser from "../common/filter-parser";
import Filter from "../common/filter"; import Filter from "../common/filter";
@@ -17,7 +17,7 @@ function init(args) {
return reject(new Error("You are not authorized to view this page")); return reject(new Error("You are not authorized to view this page"));
let filter = new Filter(args.filter); let filter = new Filter(args.filter);
let indexParameters = Object.values(config.get("ui.index")).map(p => let indexParameters = Object.values(config.ui.index).map(p =>
Object.assign({}, p, { Object.assign({}, p, {
parameter: filterParser.parseParameter(p.parameter) parameter: filterParser.parseParameter(p.parameter)
}) })
@@ -302,7 +302,7 @@ const component = {
return [ return [
m("h1", "Listing devices"), m("h1", "Listing devices"),
m(filterComponent, { m(filterComponent, {
predefined: Object.values(config.get("ui.filters")), predefined: Object.values(config.ui.filters),
filter: vnode.attrs.filter ? vnode.attrs.filter.ast : null, filter: vnode.attrs.filter ? vnode.attrs.filter.ast : null,
onChange: onFilterChanged onChange: onFilterChanged
}), }),
+10 -6
View File
@@ -1,23 +1,27 @@
"use strict"; "use strict";
import m from "mithril"; import m from "mithril";
import * as config from "./config"; import config from "./config";
import * as store from "./store"; import * as store from "./store";
import pieChartComponent from "./pie-chart-component"; import pieChartComponent from "./pie-chart-component";
import Filter from "../common/filter";
import * as funcCache from "../common/func-cache";
const GROUPS = config.get("ui.overview.groups"); const GROUPS = config.ui.overview.groups;
const CHARTS = {}; const CHARTS = {};
for (let group of Object.values(GROUPS)) for (let group of Object.values(GROUPS))
for (let chartName of Object.values(group["charts"])) for (let chartName of Object.values(group["charts"]))
CHARTS[chartName] = config.get("ui.overview.charts")[chartName]; CHARTS[chartName] = config.ui.overview.charts[chartName];
function queryCharts(charts) { function queryCharts(charts) {
charts = Object.assign({}, charts); charts = Object.assign({}, charts);
for (let [chartName, chart] of Object.entries(charts)) { for (let [chartName, chart] of Object.entries(charts)) {
charts[chartName] = chart = Object.assign({}, chart); charts[chartName] = chart = Object.assign({}, chart);
chart.slices = Object.assign({}, chart.slices);
for (let [sliceName, slice] of Object.entries(chart.slices)) { for (let [sliceName, slice] of Object.entries(chart.slices)) {
const filter = funcCache.get(Filter.parse, slice.filter);
chart.slices[sliceName] = slice = Object.assign({}, slice); chart.slices[sliceName] = slice = Object.assign({}, slice);
slice.count = store.count("devices", slice.filter); slice.count = store.count("devices", filter);
} }
} }
return charts; return charts;
@@ -33,7 +37,7 @@ const init = function() {
}; };
const component = { const component = {
view: () => { view: vnode => {
document.title = "Overview - GenieACS"; document.title = "Overview - GenieACS";
let children = []; let children = [];
for (let group of Object.values(GROUPS)) { for (let group of Object.values(GROUPS)) {
@@ -41,7 +45,7 @@ const component = {
let groupChildren = []; let groupChildren = [];
for (let chartName of Object.values(group.charts)) { for (let chartName of Object.values(group.charts)) {
const chart = CHARTS[chartName]; const chart = vnode.attrs.charts[chartName];
let chartChildren = []; let chartChildren = [];
if (chart.label) chartChildren.push(m("h2", chart.label)); if (chart.label) chartChildren.push(m("h2", chart.label));
+2 -2
View File
@@ -28,7 +28,7 @@ const drawChart = function(chartData) {
"a", "a",
{ {
href: `/#!/devices/?${m.buildQueryString({ href: `/#!/devices/?${m.buildQueryString({
filter: slice.filter.toString() filter: slice.filter
})}` })}`
}, },
slice.count.value || 0 slice.count.value || 0
@@ -68,7 +68,7 @@ const drawChart = function(chartData) {
"a", "a",
{ {
href: `/#!/devices/?${m.buildQueryString({ href: `/#!/devices/?${m.buildQueryString({
filter: slice.filter.toString() filter: slice.filter
})}` })}`
}, },
[ [
+2 -1
View File
@@ -2,8 +2,9 @@
import m from "mithril"; import m from "mithril";
import Filter from "../common/filter"; import Filter from "../common/filter";
import * as config from "./config"; import config from "./config";
import * as filterParser from "../common/filter-parser"; import * as filterParser from "../common/filter-parser";
import * as funcCache from "../common/func-cache";
let fulfillTimestamp = 0; let fulfillTimestamp = 0;
+5
View File
@@ -3,6 +3,7 @@
const filterParser = require("./filter-parser"); const filterParser = require("./filter-parser");
const filterCnf = require("./filter-cnf"); const filterCnf = require("./filter-cnf");
const satSolver = require("./sat-solver"); const satSolver = require("./sat-solver");
const funcCache = require("./func-cache");
function* permute(arr) { function* permute(arr) {
if (arr.length <= 1) { if (arr.length <= 1) {
@@ -24,6 +25,10 @@ class Filter {
else this.ast = filterParser.parse(str); else this.ast = filterParser.parse(str);
} }
static parse(str) {
return new Filter(str);
}
toString() { toString() {
if (!this.string) if (!this.string)
if (this.ast) this.string = filterParser.stringify(this.ast); if (this.ast) this.string = filterParser.stringify(this.ast);
+27
View File
@@ -0,0 +1,27 @@
"use strict";
let cache1 = new WeakMap();
let cache2 = new WeakMap();
function get(func, k) {
let c1 = cache1.get(func);
if (!c1) cache1.set(func, (c1 = new Map()));
if (c1.has(k)) return c1.get(k);
const c2 = cache2.get(func);
const v = c2 && c2.has(k) ? c2.get(k) : func(k);
c1.set(k, v);
return v;
}
function getter(func) {
return k => get(func, k);
}
function purge() {
cache2 = cache1;
cache1 = new WeakMap();
}
exports.get = get;
exports.getter = getter;
exports.purge = purge;
+257 -117
View File
@@ -1,119 +1,259 @@
{ {
"server.port": 3000, "server": {
"server.nbi": "http://127.0.0.1:7557/", "port": 3000,
"server.mongodbConnectionUrl": "mongodb://127.0.0.1:27017", "nbi": "http://127.0.0.1:7557/",
"server.jwtSecret": "jwtSecret", "mongodbConnectionUrl": "mongodb://127.0.0.1:27017",
"auth.simple.users.admin.password": "admin", "jwtSecret": "jwtSecret"
"auth.simple.users.admin.roles": "admin", },
"auth.simple.users.view.password": "view", "auth": {
"auth.simple.users.view.roles": "view", "simple": {
"permissions.admin.1.devices.access": 3, "users": {
"permissions.admin.1.devices.validate.pass": true, "admin": {
"permissions.admin.1.faults.access": 3, "password": "admin",
"permissions.admin.1.faults.validate.pass": true, "roles": "admin"
"permissions.admin.1.files.access": 3, },
"permissions.view.1.devices.access": 2, "view": {
"permissions.view.1.faults.access": 2, "password": "view",
"permissions.view.1.files.access": 2, "roles": "view"
"ui.pageSize": 10, }
"ui.filters.1.label": "Serial number", }
"ui.filters.1.parameter": "DeviceID.SerialNumber", }
"ui.filters.1.type": "string", },
"ui.filters.2.label": "Product class", "permissions": {
"ui.filters.2.parameter": "DeviceID.ProductClass", "admin": [
"ui.filters.2.type": "string", {
"ui.filters.3.label": "Tag", "devices": {
"ui.filters.3.parameter": "tag", "access": 3,
"ui.filters.3.type": "string", "validate": {
"ui.index.1.label": "Serial number", "pass": true
"ui.index.1.parameter": "DeviceID.SerialNumber", }
"ui.index.2.label": "Product class", },
"ui.index.2.parameter": "DeviceID.ProductClass", "faults": {
"ui.index.3.label": "Software version", "access": 3,
"ui.index.3.parameter": "InternetGatewayDevice.DeviceInfo.SoftwareVersion", "validate": {
"ui.index.4.label": "MAC", "pass": true
"ui.index.4.parameter": "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.MACAddress", }
"ui.index.4.label": "IP", },
"ui.index.4.parameter": "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.ExternalIPAddress", "files": {
"ui.index.5.label": "SSID", "access": 3
"ui.index.5.parameter": "InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.SSID", }
"ui.index.6.label": "Last inform", }
"ui.index.6.parameter": "Events.Inform", ],
"ui.index.6.type": "container", "view": [
"ui.index.6.element": "span.inform", {
"ui.index.6.components.1.type": "parameter", "devices": {
"ui.index.6.components.2.type": "overview-dot", "access": 2
"ui.index.6.components.2.chart": "online", },
"ui.index.7.label": "Tags", "faults": {
"ui.index.7.parameter": "Tags", "access": 2
"ui.index.7.type": "tags", },
"ui.index.7.writable": false, "files": {
"ui.overview.groups.online.label": "", "access": 2
"ui.overview.groups.online.charts.1": "online", }
"ui.overview.charts.online.label": "Online status", }
"ui.overview.charts.online.slices.onlineNow.label": "Online now", ]
"ui.overview.charts.online.slices.onlineNow.color": "#31a354", },
"ui.overview.charts.online.slices.onlineNow.filter": "Events.Inform > NOW() - 5 * 60 * 1000", "ui": {
"ui.overview.charts.online.slices.past24.label": "Past 24 hours", "pageSize": 10,
"ui.overview.charts.online.slices.past24.color": "#addd8e", "filters": [
"ui.overview.charts.online.slices.past24.filter": "Events.Inform > (NOW() - 5 * 60 * 1000) - (24 * 60 * 60 * 1000) AND Events.Inform < (NOW() - 5 * 60 * 1000)", {
"ui.overview.charts.online.slices.others.label": "Others", "label": "Serial number",
"ui.overview.charts.online.slices.others.color": "#f7fcb9", "parameter": "DeviceID.SerialNumber",
"ui.overview.charts.online.slices.others.filter": "Events.Inform < (NOW() - 5 * 60 * 1000) - (24 * 60 * 60 * 1000)", "type": "string"
"ui.device.10.type": "tags", },
"ui.device.25.type": "ping", {
"ui.device.30.type": "parameter-list", "label": "Product class",
"ui.device.30.parameters.1.type": "container", "parameter": "DeviceID.ProductClass",
"ui.device.30.parameters.1.label": "Last inform", "type": "string"
"ui.device.30.parameters.1.element": "span.inform", },
"ui.device.30.parameters.1.parameter": "Events.Inform", {
"ui.device.30.parameters.1.components.1.type": "parameter", "label": "Tag",
"ui.device.30.parameters.1.components.2.type": "overview-dot", "parameter": "tag",
"ui.device.30.parameters.1.components.2.chart": "online", "type": "string"
"ui.device.30.parameters.1.components.3.type": "summon-button", }
"ui.device.30.parameters.1.components.3.parameters.1": "InternetGatewayDevice.DeviceInfo.HardwareVersion", ],
"ui.device.30.parameters.1.components.3.parameters.2": "InternetGatewayDevice.DeviceInfo.SoftwareVersion", "index": [
"ui.device.30.parameters.1.components.3.parameters.3": "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.MACAddress", {
"ui.device.30.parameters.1.components.3.parameters.4": "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.ExternalIPAddress", "label": "Serial number",
"ui.device.30.parameters.1.components.3.parameters.5": "InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.SSID", "parameter": "DeviceID.SerialNumber"
"ui.device.30.parameters.1.components.3.parameters.6": "InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.KeyPassphrase", },
"ui.device.30.parameters.1.components.3.parameters.7": "InternetGatewayDevice.LANDevice.1.Hosts.Host", {
"ui.device.30.parameters.2.label": "Last boot", "label": "Product class",
"ui.device.30.parameters.2.parameter": "Events.1_BOOT", "parameter": "DeviceID.ProductClass"
"ui.device.30.parameters.3.label": "Last bootstrap", },
"ui.device.30.parameters.3.parameter": "Events.0_BOOTSTRAP", {
"ui.device.30.parameters.4.label": "Registered", "label": "Software version",
"ui.device.30.parameters.4.parameter": "Events.Registered", "parameter": "InternetGatewayDevice.DeviceInfo.SoftwareVersion"
"ui.device.30.parameters.2.label": "Serial number", },
"ui.device.30.parameters.2.parameter": "InternetGatewayDevice.DeviceInfo.SerialNumber", {
"ui.device.30.parameters.3.label": "Product class", "label": "IP",
"ui.device.30.parameters.3.parameter": "InternetGatewayDevice.DeviceInfo.ProductClass", "parameter": "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.ExternalIPAddress"
"ui.device.30.parameters.4.label": "OUI", },
"ui.device.30.parameters.4.parameter": "InternetGatewayDevice.DeviceInfo.ManufacturerOUI", {
"ui.device.30.parameters.5.label": "Manufacturer", "label": "SSID",
"ui.device.30.parameters.5.parameter": "InternetGatewayDevice.DeviceInfo.Manufacturer", "parameter": "InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.SSID"
"ui.device.30.parameters.6.label": "Hardware version", },
"ui.device.30.parameters.6.parameter": "InternetGatewayDevice.DeviceInfo.HardwareVersion", {
"ui.device.30.parameters.7.label": "Software version", "label": "Last inform",
"ui.device.30.parameters.7.parameter": "InternetGatewayDevice.DeviceInfo.SoftwareVersion", "parameter": "Events.Inform",
"ui.device.30.parameters.8.label": "MAC", "type": "container",
"ui.device.30.parameters.8.parameter": "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.MACAddress", "element": "span.inform",
"ui.device.30.parameters.9.label": "IP", "components": [
"ui.device.30.parameters.9.parameter": "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.ExternalIPAddress", {
"ui.device.30.parameters.10.label": "WLAN SSID", "type": "parameter"
"ui.device.30.parameters.10.parameter": "InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.SSID", },
"ui.device.30.parameters.11.label": "WLAN passphrase", {
"ui.device.30.parameters.11.parameter": "InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.KeyPassphrase", "type": "overview-dot",
"ui.device.40.type": "parameter-table", "chart": "online"
"ui.device.40.label": "WLAN hosts", }
"ui.device.40.parameter": "InternetGatewayDevice.LANDevice.1.Hosts.Host", ]
"ui.device.40.childParameters.1.label": "Host name", },
"ui.device.40.childParameters.1.parameter": "HostName", {
"ui.device.40.childParameters.2.label": "IP address", "label": "Tags",
"ui.device.40.childParameters.2.parameter": "IPAddress", "parameter": "Tags",
"ui.device.40.childParameters.3.label": "MAC address", "type": "tags",
"ui.device.40.childParameters.3.parameter": "MACAddress", "writable": false
"ui.device.50.type": "device-faults", }
"ui.device.60.type": "all-parameters", ],
"ui.device.70.type": "device-actions" "overview": {
"groups": {
"online": {
"label": "",
"charts": [
"online"
]
}
},
"charts": {
"online": {
"label": "Online status",
"slices": {
"onlineNow": {
"label": "Online now",
"color": "#31a354",
"filter": "Events.Inform > NOW() - 5 * 60 * 1000"
},
"past24": {
"label": "Past 24 hours",
"color": "#addd8e",
"filter": "Events.Inform > (NOW() - 5 * 60 * 1000) - (24 * 60 * 60 * 1000) AND Events.Inform < (NOW() - 5 * 60 * 1000)"
},
"others": {
"label": "Others",
"color": "#f7fcb9",
"filter": "Events.Inform < (NOW() - 5 * 60 * 1000) - (24 * 60 * 60 * 1000)"
}
}
}
}
},
"device": [
{
"type": "tags"
},
{
"type": "ping"
},
{
"type": "parameter-list",
"parameters": [
{
"type": "container",
"label": "Last inform",
"element": "span.inform",
"parameter": "Events.Inform",
"components": [
{
"type": "parameter"
},
{
"type": "overview-dot",
"chart": "online"
},
{
"type": "summon-button",
"parameters": [
"InternetGatewayDevice.DeviceInfo.HardwareVersion",
"InternetGatewayDevice.DeviceInfo.SoftwareVersion",
"InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.MACAddress",
"InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.ExternalIPAddress",
"InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.SSID",
"InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.KeyPassphrase",
"InternetGatewayDevice.LANDevice.1.Hosts.Host"
]
}
]
},
{
"label": "Serial number",
"parameter": "InternetGatewayDevice.DeviceInfo.SerialNumber"
},
{
"label": "Product class",
"parameter": "InternetGatewayDevice.DeviceInfo.ProductClass"
},
{
"label": "OUI",
"parameter": "InternetGatewayDevice.DeviceInfo.ManufacturerOUI"
},
{
"label": "Manufacturer",
"parameter": "InternetGatewayDevice.DeviceInfo.Manufacturer"
},
{
"label": "Hardware version",
"parameter": "InternetGatewayDevice.DeviceInfo.HardwareVersion"
},
{
"label": "Software version",
"parameter": "InternetGatewayDevice.DeviceInfo.SoftwareVersion"
},
{
"label": "MAC",
"parameter": "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.MACAddress"
},
{
"label": "IP",
"parameter": "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.ExternalIPAddress"
},
{
"label": "WLAN SSID",
"parameter": "InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.SSID"
},
{
"label": "WLAN passphrase",
"parameter": "InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.KeyPassphrase"
}
]
},
{
"type": "parameter-table",
"label": "WLAN hosts",
"parameter": "InternetGatewayDevice.LANDevice.1.Hosts.Host",
"childParameters": [
{
"label": "Host name",
"parameter": "HostName"
},
{
"label": "IP address",
"parameter": "IPAddress"
},
{
"label": "MAC address",
"parameter": "MACAddress"
}
]
},
{
"type": "device-faults"
},
{
"type": "all-parameters"
},
{
"type": "device-actions"
}
]
}
} }
+8 -8
View File
@@ -92,7 +92,7 @@ function count(resource, filter, limit) {
if (limit) qs.limit = limit; if (limit) qs.limit = limit;
let options = url.parse( let options = url.parse(
`${config.get("server.nbi")}${resource}?${querystring.stringify(qs)}` `${config.server.nbi}${resource}?${querystring.stringify(qs)}`
); );
options.method = "HEAD"; options.method = "HEAD";
@@ -133,7 +133,7 @@ function query(resource, filter, limit, skip, projection, callback) {
qs.sort = JSON.stringify({ _id: 1 }); qs.sort = JSON.stringify({ _id: 1 });
let options = url.parse( let options = url.parse(
`${config.get("server.nbi")}${resource}?${querystring.stringify(qs)}` `${config.server.nbi}${resource}?${querystring.stringify(qs)}`
); );
let _http = options.protocol === "https:" ? https : http; let _http = options.protocol === "https:" ? https : http;
@@ -209,7 +209,7 @@ function query(resource, filter, limit, skip, projection, callback) {
function deleteResource(resource, id) { function deleteResource(resource, id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let options = url.parse( let options = url.parse(
`${config.get("server.nbi")}${resource}/${encodeURIComponent(id)}` `${config.server.nbi}${resource}/${encodeURIComponent(id)}`
); );
options.method = "DELETE"; options.method = "DELETE";
@@ -229,7 +229,7 @@ function deleteResource(resource, id) {
function postTask(task, connectionRequest, callback) { function postTask(task, connectionRequest, callback) {
let options = url.parse( let options = url.parse(
`${config.get("server.nbi")}devices/${task.device}/tasks${ `${config.server.nbi}devices/${task.device}/tasks${
connectionRequest ? "?connection_request" : "" connectionRequest ? "?connection_request" : ""
}` }`
); );
@@ -346,9 +346,9 @@ function updateTags(deviceId, tags) {
([tag, onOff]) => ([tag, onOff]) =>
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
const options = url.parse( const options = url.parse(
`${config.get( `${config.server.nbi}devices/${deviceId}/tags/${encodeURIComponent(
"server.nbi" tag
)}devices/${deviceId}/tags/${encodeURIComponent(tag)}` )}`
); );
if (onOff) options.method = "POST"; if (onOff) options.method = "POST";
else options.method = "DELETE"; else options.method = "DELETE";
@@ -370,7 +370,7 @@ function updateTags(deviceId, tags) {
function ping(host) { function ping(host) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const options = url.parse( const options = url.parse(
`${config.get("server.nbi")}ping/${encodeURIComponent(host)}` `${config.server.nbi}ping/${encodeURIComponent(host)}`
); );
let _http = options.protocol === "https:" ? https : http; let _http = options.protocol === "https:" ? https : http;
+29 -64
View File
@@ -1,72 +1,37 @@
"use strict"; "use strict";
const filterParser = require("../common/filter-parser.js");
const Filter = require("../common/filter.js");
const configFile = require("../config.json"); const configFile = require("../config.json");
const cache = {}; let config;
function parse(name, value) {
if (/^ui\.overview\.charts\.[^.]+\.slices\.[^.]+\.filter$/.test(name))
return new Filter(value);
else if (/^permissions\.[^.]+\.[^.]+\.devices\.filter$/.test(name))
return new Filter(value);
else if (/^auth\.[^.]+\.users\.[^.]+\.roles$/.test(name))
return value
.split(",")
.map(x => x.trim())
.sort();
return value;
}
function get(name) {
let v = cache[name];
if (v === undefined) {
v = configFile[name];
if (v != null) {
v = parse(name, v);
} else {
const prefix = `${name}.`;
for (let k of Object.keys(configFile))
if (k.startsWith(prefix)) {
v = v || {};
let ar = k.slice(prefix.length).split(".");
let ref = v;
for (let a of ar.slice(0, -1)) ref = ref[a] = ref[a] || {};
ref[ar[ar.length - 1]] = parse(k, configFile[k]);
}
}
if (v) cache[name] = v;
else cache[name] = null;
}
return v;
}
function getClientConfig() { function getClientConfig() {
const regex = [ return Object.assign({}, config, {
/^ui\.pageSize$/, server: null,
/^ui\.filters\.[^.]+\.label$/, auth: null,
/^ui\.filters\.[^.]+\.parameter$/, permissions: null
/^ui\.filters\.[^.]+\.type$/, });
/^ui\.index\./,
/^ui\.overview\.groups\./,
/^ui\.overview\.charts\./,
/^ui\.device/
];
const clientConfig = {};
for (let [k, v] of Object.entries(configFile))
for (let r of regex)
if (r.test(k)) {
clientConfig[k] = v;
break;
}
return clientConfig;
} }
exports.get = get; function loadConfig(conf, root = {}) {
exports.getClientConfig = getClientConfig; for (const [key, value] of Object.entries(conf)) {
const keys = key.split(".");
let ref = root;
while (keys.length > 1) {
const k = keys.shift();
if (typeof ref[k] !== "object") ref[k] = {};
ref = ref[k];
}
if (typeof value === "object") {
if (typeof ref[keys[0]] !== "object") ref[keys[0]] = {};
loadConfig(value, ref[keys[0]]);
} else {
ref[keys[0]] = value;
}
}
return root;
}
config = loadConfig(configFile);
module.exports = Object.assign({}, config, { getClientConfig });
+1 -1
View File
@@ -10,7 +10,7 @@ function getClient() {
if (_client) return Promise.resolve(_client); if (_client) return Promise.resolve(_client);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const CONNECTION_URL = config.get("server.mongodbConnectionUrl"); const CONNECTION_URL = config.server.mongodbConnectionUrl;
MongoClient.connect(CONNECTION_URL, (err, client) => { MongoClient.connect(CONNECTION_URL, (err, client) => {
if (err) return reject(err); if (err) return reject(err);
resolve((_client = client.db("genieacs-ui"))); resolve((_client = client.db("genieacs-ui")));
+9 -6
View File
@@ -15,11 +15,11 @@ const Authorizer = require("../common/authorizer");
const koa = new Koa(); const koa = new Koa();
const router = new Router(); const router = new Router();
const JWT_SECRET = config.get("server.jwtSecret"); const JWT_SECRET = config.server.jwtSecret;
const JWT_COOKIE = "genieacs-ui-jwt"; const JWT_COOKIE = "genieacs-ui-jwt";
function getPermissionSets(roles) { function getPermissionSets(roles) {
const allPermissions = config.get("permissions"); const allPermissions = config.permissions;
const permissionSets = roles.map(r => Object.values(allPermissions[r] || {})); const permissionSets = roles.map(r => Object.values(allPermissions[r] || {}));
return permissionSets; return permissionSets;
} }
@@ -46,7 +46,7 @@ router.post("/login", async ctx => {
const username = ctx.request.body.username; const username = ctx.request.body.username;
const password = ctx.request.body.password; const password = ctx.request.body.password;
const user = config.get(`auth.simple.users.${username}`); const user = config.auth.simple.users[username];
if (!user || user.password !== password) { if (!user || user.password !== password) {
ctx.status = 400; ctx.status = 400;
@@ -54,7 +54,10 @@ router.post("/login", async ctx => {
return; return;
} }
let token = jwt.sign({ username: username, roles: user.roles }, JWT_SECRET); let token = jwt.sign(
{ username: username, roles: user.roles.split(",") },
JWT_SECRET
);
ctx.cookies.set(JWT_COOKIE, token); ctx.cookies.set(JWT_COOKIE, token);
ctx.body = JSON.stringify(token); ctx.body = JSON.stringify(token);
}); });
@@ -101,7 +104,7 @@ koa.use(
koa.use(router.routes()); koa.use(router.routes());
koa.use(koaStatic("./public")); koa.use(koaStatic("./public"));
koa.listen(config.get("server.port"), () => { koa.listen(config.server.port, () => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(`Server listening on port ${config.get("server.port")}`); console.log(`Server listening on port ${config.server.port}`);
}); });