Add functions for DB access
This commit is contained in:
1 parent
327cb78f1a
commit
12cdc8a6f1
6 files changed
+114
-26
No files matched your search
@@ -266,6 +266,11 @@ table.table {
|
|||||||
& td {
|
& td {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0.2em 0.5em;
|
padding: 0.2em 0.5em;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
max-width: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
& tfoot td > a {
|
& tfoot td > a {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"server.port": 3000,
|
"server.port": 3000,
|
||||||
"server.nbi": "http://127.0.0.1:7557/",
|
"server.nbi": "http://127.0.0.1:7557/",
|
||||||
|
"server.mongodbConnectionUrl": "mongodb://127.0.0.1:27017",
|
||||||
"server.jwtSecret": "jwtSecret",
|
"server.jwtSecret": "jwtSecret",
|
||||||
"auth.simple.users.admin.password": "admin",
|
"auth.simple.users.admin.password": "admin",
|
||||||
"auth.simple.users.admin.roles": "admin",
|
"auth.simple.users.admin.roles": "admin",
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
"koa-router": "^7.4.0",
|
"koa-router": "^7.4.0",
|
||||||
"koa-static": "^4.0.2",
|
"koa-static": "^4.0.2",
|
||||||
"mithril": "^1.1.6",
|
"mithril": "^1.1.6",
|
||||||
|
"mongodb": "^3.0.10",
|
||||||
"parsimmon": "^1.7.2"
|
"parsimmon": "^1.7.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -24,20 +24,20 @@ function unpackTimestamps(filter) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterToQuery(filter, negate = false, res = {}) {
|
function filterToMongoQuery(filter, negate = false, res = {}) {
|
||||||
const op = filter[0];
|
const op = filter[0];
|
||||||
|
|
||||||
if ((!negate && op === "AND") || (negate && op === "OR")) {
|
if ((!negate && op === "AND") || (negate && op === "OR")) {
|
||||||
res["$and"] = res["$and"] || [];
|
res["$and"] = res["$and"] || [];
|
||||||
for (let i = 1; i < filter.length; ++i)
|
for (let i = 1; i < filter.length; ++i)
|
||||||
res["$and"].push(filterToQuery(filter[i], negate));
|
res["$and"].push(filterToMongoQuery(filter[i], negate));
|
||||||
} else if ((!negate && op === "OR") || (negate && op === "AND")) {
|
} else if ((!negate && op === "OR") || (negate && op === "AND")) {
|
||||||
res["$or"] = res["$or"] || [];
|
res["$or"] = res["$or"] || [];
|
||||||
|
|
||||||
for (let i = 1; i < filter.length; ++i)
|
for (let i = 1; i < filter.length; ++i)
|
||||||
res["$or"].push(filterToQuery(filter[i], negate));
|
res["$or"].push(filterToMongoQuery(filter[i], negate));
|
||||||
} else if (op === "NOT") {
|
} else if (op === "NOT") {
|
||||||
filterToQuery(filter[1], !negate, res);
|
filterToMongoQuery(filter[1], !negate, res);
|
||||||
} else if (op === "=") {
|
} else if (op === "=") {
|
||||||
let p = (res[filter[1]] = res[filter[1]] || {});
|
let p = (res[filter[1]] = res[filter[1]] || {});
|
||||||
if (negate) p["$ne"] = filter[2];
|
if (negate) p["$ne"] = filter[2];
|
||||||
@@ -84,7 +84,7 @@ function count(resource, filter, limit) {
|
|||||||
filter = filter.evaluateExpressions();
|
filter = filter.evaluateExpressions();
|
||||||
let ast = unpackTimestamps(filter.ast);
|
let ast = unpackTimestamps(filter.ast);
|
||||||
|
|
||||||
let q = filterToQuery(ast);
|
let q = filterToMongoQuery(ast);
|
||||||
if (resource === "devices") q = device.transposeQuery(q);
|
if (resource === "devices") q = device.transposeQuery(q);
|
||||||
qs.query = JSON.stringify(q);
|
qs.query = JSON.stringify(q);
|
||||||
}
|
}
|
||||||
@@ -121,7 +121,7 @@ function query(resource, filter, limit, skip, projection, callback) {
|
|||||||
filter = filter.evaluateExpressions();
|
filter = filter.evaluateExpressions();
|
||||||
let ast = unpackTimestamps(filter.ast);
|
let ast = unpackTimestamps(filter.ast);
|
||||||
|
|
||||||
let q = filterToQuery(ast);
|
let q = filterToMongoQuery(ast);
|
||||||
if (resource === "devices") q = device.transposeQuery(q);
|
if (resource === "devices") q = device.transposeQuery(q);
|
||||||
|
|
||||||
qs.query = JSON.stringify(q);
|
qs.query = JSON.stringify(q);
|
||||||
@@ -372,3 +372,4 @@ exports.count = count;
|
|||||||
exports.postTasks = postTasks;
|
exports.postTasks = postTasks;
|
||||||
exports.deleteResource = deleteResource;
|
exports.deleteResource = deleteResource;
|
||||||
exports.updateTags = updateTags;
|
exports.updateTags = updateTags;
|
||||||
|
exports.filterToMongoQuery = filterToMongoQuery;
|
||||||
+33
-20
@@ -2,22 +2,26 @@
|
|||||||
|
|
||||||
const Router = require("koa-router");
|
const Router = require("koa-router");
|
||||||
|
|
||||||
|
const db = require("./db");
|
||||||
const apiFunctions = require("./api-functions");
|
const apiFunctions = require("./api-functions");
|
||||||
const Filter = require("../common/filter");
|
const Filter = require("../common/filter");
|
||||||
|
|
||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
|
const RESOURCE_DELETE = 1 << 0;
|
||||||
|
const RESOURCE_DB = 1 << 1;
|
||||||
|
|
||||||
const resources = {
|
const resources = {
|
||||||
devices: true,
|
devices: 0 | RESOURCE_DELETE,
|
||||||
presets: true,
|
presets: 0 | RESOURCE_DELETE,
|
||||||
provisions: true,
|
provisions: 0 | RESOURCE_DELETE,
|
||||||
files: true,
|
files: 0 | RESOURCE_DELETE,
|
||||||
virtual_parameters: true,
|
virtual_parameters: 0 | RESOURCE_DELETE,
|
||||||
faults: true,
|
faults: 0 | RESOURCE_DELETE,
|
||||||
tasks: false
|
tasks: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let [resource, update] of Object.entries(resources)) {
|
for (let [resource, flags] of Object.entries(resources)) {
|
||||||
router.head(`/${resource}`, async (ctx, next) => {
|
router.head(`/${resource}`, async (ctx, next) => {
|
||||||
let filter, limit;
|
let filter, limit;
|
||||||
if (ctx.request.query.filter) filter = new Filter(ctx.request.query.filter);
|
if (ctx.request.query.filter) filter = new Filter(ctx.request.query.filter);
|
||||||
@@ -31,16 +35,20 @@ for (let [resource, update] of Object.entries(resources)) {
|
|||||||
filter = f.and(filter);
|
filter = f.and(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
let count = await apiFunctions.count(resource, filter, limit);
|
let count;
|
||||||
|
if (flags & RESOURCE_DB) count = await db.count(resource, filter, limit);
|
||||||
|
else count = await apiFunctions.count(resource, filter, limit);
|
||||||
|
|
||||||
ctx.set("X-Total-Count", count);
|
ctx.set("X-Total-Count", count);
|
||||||
ctx.body = "";
|
ctx.body = "";
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get(`/${resource}`, async (ctx, next) => {
|
router.get(`/${resource}`, async (ctx, next) => {
|
||||||
let filter, limit, skip;
|
let filter, limit, skip, projection;
|
||||||
if (ctx.request.query.filter) filter = new Filter(ctx.request.query.filter);
|
if (ctx.request.query.filter) filter = new Filter(ctx.request.query.filter);
|
||||||
if (ctx.request.query.limit) limit = +ctx.request.query.limit;
|
if (ctx.request.query.limit) limit = +ctx.request.query.limit;
|
||||||
if (ctx.request.query.skip) skip = +ctx.request.query.skip;
|
if (ctx.request.query.skip) skip = +ctx.request.query.skip;
|
||||||
|
if (ctx.request.query.projection) projection = ctx.request.query.projection;
|
||||||
|
|
||||||
if (!ctx.state.authorizer.hasAccess(resource, 2)) return next();
|
if (!ctx.state.authorizer.hasAccess(resource, 2)) return next();
|
||||||
|
|
||||||
@@ -50,20 +58,23 @@ for (let [resource, update] of Object.entries(resources)) {
|
|||||||
filter = f.and(filter);
|
filter = f.and(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.body = await apiFunctions.query(
|
let res;
|
||||||
resource,
|
if (flags & RESOURCE_DB)
|
||||||
filter,
|
res = await db.query(resource, filter, limit, skip);
|
||||||
limit,
|
else
|
||||||
skip,
|
res = await apiFunctions.query(resource, filter, limit, skip, projection);
|
||||||
ctx.request.query.projection
|
|
||||||
);
|
ctx.body = res;
|
||||||
});
|
});
|
||||||
|
|
||||||
router.head(`/${resource}/:id`, async (ctx, next) => {
|
router.head(`/${resource}/:id`, async (ctx, next) => {
|
||||||
let filter = new Filter(`DeviceID.ID = "${ctx.params.id}"`);
|
let filter = new Filter(`DeviceID.ID = "${ctx.params.id}"`);
|
||||||
if (!ctx.state.authorizer.hasAccess(resource, 2)) return next();
|
if (!ctx.state.authorizer.hasAccess(resource, 2)) return next();
|
||||||
|
|
||||||
let res = await apiFunctions.query(resource, filter);
|
let res;
|
||||||
|
if (flags & RESOURCE_DB) res = await db.query(resource, filter);
|
||||||
|
else res = await apiFunctions.query(resource, filter);
|
||||||
|
|
||||||
if (!res.length) return next();
|
if (!res.length) return next();
|
||||||
ctx.body = "";
|
ctx.body = "";
|
||||||
});
|
});
|
||||||
@@ -72,13 +83,15 @@ for (let [resource, update] of Object.entries(resources)) {
|
|||||||
let filter = new Filter(`DeviceID.ID = "${ctx.params.id}"`);
|
let filter = new Filter(`DeviceID.ID = "${ctx.params.id}"`);
|
||||||
if (!ctx.state.authorizer.hasAccess(resource, 2)) return next();
|
if (!ctx.state.authorizer.hasAccess(resource, 2)) return next();
|
||||||
|
|
||||||
let res = await apiFunctions.query(resource, filter);
|
let res;
|
||||||
|
if (flags & RESOURCE_DB) res = await db.query(resource, filter);
|
||||||
|
else res = await apiFunctions.query(resource, filter);
|
||||||
if (!res.length) return next();
|
if (!res.length) return next();
|
||||||
ctx.body = res[0];
|
ctx.body = res[0];
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO add PUT, PATCH routes
|
// TODO add PUT, PATCH routes
|
||||||
if (update)
|
if (flags & RESOURCE_DELETE && !(flags & RESOURCE_DB))
|
||||||
router.delete(`/${resource}/:id`, async (ctx, next) => {
|
router.delete(`/${resource}/:id`, async (ctx, next) => {
|
||||||
const authorizer = ctx.state.authorizer;
|
const authorizer = ctx.state.authorizer;
|
||||||
let filter = new Filter(`DeviceID.ID = "${ctx.params.id}"`);
|
let filter = new Filter(`DeviceID.ID = "${ctx.params.id}"`);
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const MongoClient = require("mongodb").MongoClient;
|
||||||
|
const config = require("./config");
|
||||||
|
const apiFunctions = require("./api-functions");
|
||||||
|
|
||||||
|
let _client = null;
|
||||||
|
|
||||||
|
function getClient() {
|
||||||
|
if (_client) return Promise.resolve(_client);
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const CONNECTION_URL = config.get("server.mongodbConnectionUrl");
|
||||||
|
MongoClient.connect(CONNECTION_URL, (err, client) => {
|
||||||
|
if (err) return reject(err);
|
||||||
|
resolve((_client = client.db("genieacs-ui")));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function query(resource, filter, limit, skip, callback) {
|
||||||
|
let q;
|
||||||
|
if (filter && filter.ast) q = apiFunctions.filterToMongoQuery(filter.ast);
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
getClient().then(client => {
|
||||||
|
const collection = client.collection(resource);
|
||||||
|
if (!callback)
|
||||||
|
collection
|
||||||
|
.find(q)
|
||||||
|
.skip(skip || 0)
|
||||||
|
.limit(limit || 0)
|
||||||
|
.toArray((err, docs) => {
|
||||||
|
if (err) return reject(err);
|
||||||
|
return resolve(docs);
|
||||||
|
});
|
||||||
|
else
|
||||||
|
collection.find(q).forEach(
|
||||||
|
doc => {
|
||||||
|
callback(doc);
|
||||||
|
},
|
||||||
|
err => {
|
||||||
|
if (err) reject(err);
|
||||||
|
else resolve();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function count(resource, filter) {
|
||||||
|
let q;
|
||||||
|
if (filter && filter.ast) q = apiFunctions.filterToMongoQuery(filter.ast);
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
getClient().then(client => {
|
||||||
|
const collection = client.collection(resource);
|
||||||
|
collection.find(q).count((err, c) => {
|
||||||
|
if (err) reject(err);
|
||||||
|
else resolve(c);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.query = query;
|
||||||
|
exports.count = count;
|
||||||
Reference in new issue
Block a user