PTS/ddtrust-backend-master/index.js

407 lines
12 KiB
JavaScript
Raw Normal View History

2024-04-09 12:30:03 +00:00
const express = require('express')
const mariadb = require('mariadb')
const fs = require('fs');
let db_settings = JSON.parse(fs.readFileSync('resources/db_settings.json', 'utf8'));
const app = express()
const pool = mariadb.createPool({
host: db_settings.host,
port: db_settings.port,
user: db_settings.user,
password: db_settings.password,
database: db_settings.database,
supportBigNumbers: true,
})
const PORT = 80
function convert_rights(rights) {
switch (rights) {
case "Super-User":
return 0;
case "PTS-User":
return 1;
case "Premium-User":
return 2;
case "Standard-User":
return 3;
case "Test-User":
return 4;
default:
throw new Error("Could not parse Rights (" + rights + ")");
}
}
// encapsulate db access
async function queryDB(query) {
let conn;
let rows;
try {
conn = await pool.getConnection();
rows = await conn.query(query);
} catch (err) {
throw err;
} finally {
if (conn) {
conn.end();
}
}
return rows;
}
async function queryDevice(device, incoming_rights) {
let config_ids = await queryDB(
"SELECT config_id " +
"FROM api_info " +
"WHERE name=\"Gerät\" AND value LIKE \"" + device + "\""
);
let meta_map = {};
for (let i = 0; i < config_ids.length; i++) {
const config_id = config_ids[i].config_id;
let metas = await queryDB(
"SELECT name, value " +
"FROM api_info " +
"WHERE config_id=\"" + config_id + "\""
);
let m = {};
m["data"] = {};
for (let j = 0; j < metas.length; j++) {
let value = metas[j].value;
let name = metas[j].name;
if (name == "Gerät") {
m["Gerät"] = value;
} else {
let values = JSON.parse(value);
for (let [key, value] of Object.entries(values)) {
if (Array.isArray(value)) {
for (let i = 0; i < value.length; i++) {
let v = value[i];
let rights = convert_rights(v.right);
if (rights < incoming_rights) {
delete values[key];
break;
}
}
} else {
if (value.right === undefined) {
for (let [inner_key, inner_value] of Object.entries(value)) {
if (Array.isArray(inner_value)) {
for (let i = 0; i < inner_value.length; i++) {
let v = inner_value[i];
for (let [inner_inner_key, inner_inner_value] of Object.entries(v)) {
let rights = convert_rights(inner_inner_value.right);
if (rights < incoming_rights) {
delete v[inner_inner_key];
}
}
}
}
else if (inner_value.right !== undefined) {
let rights = convert_rights(inner_value.right);
if (rights < incoming_rights) {
delete value[inner_key];
}
}
else {
for (let [inner_inner_key, inner_inner_value] of Object.entries(inner_value)) {
let rights = convert_rights(inner_inner_value.right);
if (rights < incoming_rights) {
delete inner_value[inner_inner_key];
}
}
}
}
} else {
let rights = convert_rights(value.right);
if (rights < incoming_rights) {
delete values[key];
}
}
}
}
let d = m["data"];
let l = Object.keys(d).length;
if (l != 0) {
m["data"] = { ...d, ...values };
} else {
m["data"] = values;
}
}
}
meta_map[config_id] = m;
}
for (let config_id of Object.keys(meta_map)) {
let results = await queryDB(
"SELECT id " +
"FROM api_results " +
"WHERE config_id=\"" + config_id + "\""
);
for (let j = 0; j < results.length; j++) {
let measurements = await queryDB(
"SELECT name, value, rights " +
"FROM api_measurements " +
"WHERE result_id=\"" + results[j].id + "\""
);
m = {}
for (let k = 0; k < measurements.length; k++) {
let measurement = measurements[k];
let rights = measurement.rights.replace(/['"]+/g, '');
let rights_value = convert_rights(rights);
if (rights_value >= incoming_rights) {
m[measurement.name] = { name: measurement.name, value: measurement.value, rights: rights };
}
}
meta_map[config_id][results[j].id] = m;
}
}
return meta_map;
}
async function calculate(elements, parameter, operation) {
switch (operation) {
case "average":
let tmp = 0;
let count = 0;
for (let param of parameter) {
const value = elements.find(element => element.name == param);
if (value === undefined) {
continue;
}
count += 1;
tmp += value.value;
}
if (count == 0) {
return null;
}
return tmp / count;
case "sum":
let sum = 0;
for (let param of parameter) {
const value = elements.find(element => element.name == param);
if (value === undefined) {
return null;
}
sum += value.value;
}
return sum;
case "divide":
const v1 = elements.find(element => element.name == parameter[0]);
const v2 = elements.find(element => element.name == parameter[1]);
if (v1 === undefined || v2 === undefined || v2 == 0) {
return null;
}
return v1.value / v2.value;
case "multiply":
let p = 1.0;
for (let param of parameter) {
const value = elements.find(element => element.name == param);
if (value === undefined) {
return null;
}
p *= value.value;
}
return p;
case "subtract":
const s1 = elements.find(element => element.name == parameter[0]);
const s2 = elements.find(element => element.name == parameter[1]);
if (s1 === undefined || s2 === undefined) {
return null;
}
return s1.value - s2.value;
case "discard":
const value = elements.find(element => element.name == parameter[0]);
const res = elements.find(element => element.name == parameter[1]);
if (value === undefined || res === undefined) {
return null;
}
if (value.value !== null && !value.value) {
return res.value;
} else {
return 0;
}
default:
throw "unknown operation " + operation;
}
}
async function createResultForEntry(parameters, descriptions, calculations) {
let result = {};
for (let [key, data] of Object.entries(parameters)) {
if (Object.keys(data).length == 0) {
return {};
}
if (key == "Gerät") {
continue;
}
let elements = findAll(data);
for (let [calc_key, calc_value] of Object.entries(calculations)) {
let val = null;
if (calc_value.const !== undefined) {
val = parseFloat(calc_value.const[0]);
} else {
val = await calculate(elements, calc_value.source, calc_value.operation);
}
if (val !== null) {
elements.push({ name: calc_key, value: val });
}
}
console.info(elements);
for (let element of elements) {
let key = String(element.name);
let value = element.value;
let description = descriptions[key];
if (description !== undefined) {
if (value !== null) {
result[key] = {
name: description.name,
value: value,
description: description.description,
unit: description.unit,
}
}
} else {
for (let [description_key, description] of Object.entries(descriptions)) {
if (key.startsWith(description_key)) {
result[key] = {
name: description.name,
value: value,
description: description.description,
unit: description.unit,
}
break;
}
}
}
}
}
return result;
}
async function createResultList(parameters, descriptions, calculations) {
let result = [];
for (let entry of Object.values(parameters)) {
let entry_result = await createResultForEntry(entry, descriptions, calculations);
if (Object.keys(entry_result).length != 0) {
result.push(entry_result);
}
}
return result;
}
function findAll(object) {
let list = [];
if (object === null) {
return list;
}
if (object.name !== undefined) {
if (object.value !== undefined) {
list.push({ name: object.name, value: object.value });
} else {
for (let [key, value] of Object.entries(object)) {
list = list.concat(findAll(value));
}
}
} else {
for (let [key, value] of Object.entries(object)) {
list = list.concat(findAll(value));
}
}
return list;
}
app.get('/ddtrust/cepi/:rights', async (request, response) => {
// read parameters from DB and only return accessible
let deviceParameters = await queryDevice("%Cepi%", convert_rights(request.params.rights));
// read paremeter description file
let descriptions = JSON.parse(fs.readFileSync('resources/variable_description.json', 'utf8'));
// read parameter calculation file,
let calculations = JSON.parse(fs.readFileSync('resources/variable_calculation.json', 'utf8'));
// combine description information with parameters queried from DB
let result = await createResultList(deviceParameters, descriptions, calculations);
response.json(result)
})
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`)
})