Use nested config structure
This commit is contained in:
1 parent
581a510960
commit
30dbf0cf40
15 files changed
+366
-251
No files matched your search
@@ -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),
|
||||||
|
|||||||
@@ -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
@@ -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,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))
|
||||||
|
|||||||
@@ -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
@@ -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));
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
@@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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
@@ -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
@@ -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
@@ -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}`);
|
||||||
});
|
});
|
||||||
Reference in new issue
Block a user