Remove UI dependance on NBI
This commit is contained in:
1 parent
520cc43972
commit
d46d133878
5 files changed
+285
-341
No files matched your search
+2
-1
@@ -434,7 +434,8 @@ export function getConfig(snapshotKey, key, context, now) {
|
|||||||
"cwmp.booleanLiteral": "BOOLEAN_LITERAL",
|
"cwmp.booleanLiteral": "BOOLEAN_LITERAL",
|
||||||
"cwmp.connectionRequestAllowBasicAuth":
|
"cwmp.connectionRequestAllowBasicAuth":
|
||||||
"CONNECTION_REQUEST_ALLOW_BASIC_AUTH",
|
"CONNECTION_REQUEST_ALLOW_BASIC_AUTH",
|
||||||
"cwmp.maxCommitIterations": "MAX_COMMIT_ITERATIONS"
|
"cwmp.maxCommitIterations": "MAX_COMMIT_ITERATIONS",
|
||||||
|
"cwmp.deviceOnlineThreshold": "DEVICE_ONLINE_THRESHOLD"
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!(key in snapshot.config)) {
|
if (!(key in snapshot.config)) {
|
||||||
|
|||||||
+156
-312
@@ -1,340 +1,184 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
import http from "http";
|
|
||||||
import https from "https";
|
|
||||||
import url from "url";
|
|
||||||
import * as config from "../config";
|
|
||||||
import * as db from "./db";
|
import * as db from "./db";
|
||||||
import * as cache from "../cache";
|
import { del } from "../cache";
|
||||||
import * as mongodbFunctions from "./mongodb-functions";
|
import { ObjectID } from "mongodb";
|
||||||
|
import { exec } from "child_process";
|
||||||
|
import {
|
||||||
|
insertTasks,
|
||||||
|
watchTask,
|
||||||
|
connectionRequest,
|
||||||
|
deleteDevice
|
||||||
|
} from "../api-functions";
|
||||||
|
|
||||||
export function deleteResource(resource, id) {
|
function deleteFault(id) {
|
||||||
|
const deviceId = id.split(":", 1)[0];
|
||||||
|
const channel = id.slice(deviceId.length + 1);
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (resource === "config") {
|
Promise.all([
|
||||||
db.deleteConfig(id)
|
db.deleteFault(id),
|
||||||
.then(() => {
|
channel.startsWith("task_")
|
||||||
cache.del("presets_hash", err => {
|
? db.deleteTask(new ObjectID(channel.slice(5)))
|
||||||
if (err) return void reject(err);
|
: null
|
||||||
resolve();
|
])
|
||||||
});
|
.then(() => {
|
||||||
})
|
del(`${deviceId}_tasks_faults_operations`, err => {
|
||||||
.catch(reject);
|
err ? reject(err) : resolve();
|
||||||
return;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
const resourceUrl =
|
|
||||||
resource === "virtualParameters" ? "virtual_parameters" : resource;
|
|
||||||
const options = url.parse(
|
|
||||||
`http://127.0.0.1:${config.get(
|
|
||||||
"NBI_PORT"
|
|
||||||
)}/${resourceUrl}/${encodeURIComponent(id)}`
|
|
||||||
);
|
|
||||||
|
|
||||||
options.method = "DELETE";
|
|
||||||
|
|
||||||
const _http = options.protocol === "https:" ? https : http;
|
|
||||||
|
|
||||||
_http
|
|
||||||
.request(options, res => {
|
|
||||||
res.resume();
|
|
||||||
if (res.statusCode === 200) resolve(true);
|
|
||||||
else if (res.statusCode === 404) resolve(false);
|
|
||||||
else reject(new Error(`Unexpected status code ${res.statusCode}`));
|
|
||||||
})
|
|
||||||
.end();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function postTask(task, connectionRequest, callback) {
|
|
||||||
const options = url.parse(
|
|
||||||
`http://127.0.0.1:${config.get("NBI_PORT")}/devices/${encodeURIComponent(
|
|
||||||
task.device
|
|
||||||
)}/tasks${connectionRequest ? "?connection_request" : ""}`
|
|
||||||
);
|
|
||||||
options.method = "POST";
|
|
||||||
const _http = options.protocol === "https:" ? https : http;
|
|
||||||
|
|
||||||
_http
|
|
||||||
.request(options, res => {
|
|
||||||
if (res.statusCode !== 200 && res.statusCode !== 202) {
|
|
||||||
callback(new Error(`Unexpected status code ${res.statusCode}`));
|
|
||||||
res.resume();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const chunks = [];
|
|
||||||
let bytes = 0;
|
|
||||||
res.on("data", chunk => {
|
|
||||||
chunks.push(chunk);
|
|
||||||
bytes += chunk.length;
|
|
||||||
});
|
|
||||||
|
|
||||||
res.on("end", () => {
|
|
||||||
const buf = Buffer.allocUnsafe(bytes);
|
|
||||||
let o = 0;
|
|
||||||
for (const c of chunks) {
|
|
||||||
c.copy(buf, o, 0, c.length);
|
|
||||||
o += c.length;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const t = JSON.parse(buf);
|
|
||||||
let connectionRequestStatus;
|
|
||||||
if (connectionRequest) {
|
|
||||||
connectionRequestStatus = "OK";
|
|
||||||
if (
|
|
||||||
res.statusCode === 202 &&
|
|
||||||
res.statusMessage !== "Task queued but not processed" &&
|
|
||||||
res.statusMessage !== "Task faulted"
|
|
||||||
)
|
|
||||||
connectionRequestStatus = res.statusMessage;
|
|
||||||
}
|
|
||||||
callback(null, t, connectionRequestStatus);
|
|
||||||
} catch (err) {
|
|
||||||
callback(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.end(JSON.stringify(task));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function postTasks(deviceId, tasks) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let connectionRequestStatus;
|
|
||||||
const promises = [];
|
|
||||||
for (const [idx, task] of tasks.entries()) {
|
|
||||||
task.device = deviceId;
|
|
||||||
promises.push(
|
|
||||||
new Promise((res, rej) => {
|
|
||||||
const conReq = idx === tasks.length - 1;
|
|
||||||
delete task._id;
|
|
||||||
task.expiry = 5;
|
|
||||||
postTask(task, conReq, (err, t, crs) => {
|
|
||||||
if (err) return void rej(err);
|
|
||||||
if (conReq) connectionRequestStatus = crs;
|
|
||||||
res({ _id: t._id, status: "pending" });
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Promise.all(promises)
|
|
||||||
.then(statuses => {
|
|
||||||
if (connectionRequestStatus !== "OK") {
|
|
||||||
return void resolve({
|
|
||||||
connectionRequest: connectionRequestStatus,
|
|
||||||
tasks: statuses
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const promises2 = [];
|
|
||||||
for (const s of statuses) {
|
|
||||||
promises2.push(db.query("tasks", ["=", ["PARAM", "_id"], s._id]));
|
|
||||||
promises2.push(
|
|
||||||
db.query("faults", [
|
|
||||||
"=",
|
|
||||||
["PARAM", "_id"],
|
|
||||||
`${deviceId}:task_${s._id}`
|
|
||||||
])
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Promise.all(promises2)
|
|
||||||
.then(res => {
|
|
||||||
for (const [i, r] of statuses.entries()) {
|
|
||||||
if (res[i * 2].length === 0) {
|
|
||||||
r.status = "done";
|
|
||||||
} else if (res[i * 2 + 1].length === 1) {
|
|
||||||
r.status = "fault";
|
|
||||||
r.fault = res[i * 2 + 1][0];
|
|
||||||
}
|
|
||||||
deleteResource("tasks", r._id);
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve({
|
|
||||||
connectionRequest: connectionRequestStatus,
|
|
||||||
tasks: statuses
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(reject);
|
|
||||||
})
|
})
|
||||||
.catch(reject);
|
.catch(reject);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateTags(deviceId, tags) {
|
export function deleteResource(resource, id) {
|
||||||
return Promise.all(
|
return new Promise((resolve, reject) => {
|
||||||
Object.entries(tags).map(
|
let promise;
|
||||||
([tag, onOff]) =>
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
const options = url.parse(
|
|
||||||
`http://127.0.0.1:${config.get(
|
|
||||||
"NBI_PORT"
|
|
||||||
)}/devices/${encodeURIComponent(
|
|
||||||
deviceId
|
|
||||||
)}/tags/${encodeURIComponent(tag)}`
|
|
||||||
);
|
|
||||||
if (onOff) options.method = "POST";
|
|
||||||
else options.method = "DELETE";
|
|
||||||
const _http = options.protocol === "https:" ? https : http;
|
|
||||||
|
|
||||||
_http
|
switch (resource) {
|
||||||
.request(options, res => {
|
case "devices":
|
||||||
res.resume();
|
promise = new Promise((res, rej) => {
|
||||||
if (res.statusCode === 200) resolve();
|
deleteDevice(id, err => {
|
||||||
else
|
if (err) return void rej(err);
|
||||||
reject(new Error(`Unexpected status code ${res.statusCode}`));
|
res();
|
||||||
})
|
});
|
||||||
.end();
|
});
|
||||||
})
|
break;
|
||||||
)
|
|
||||||
);
|
case "files":
|
||||||
|
promise = db.deleteFile(id);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "faults":
|
||||||
|
promise = deleteFault(id);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "provisions":
|
||||||
|
promise = db.deleteProvision(id);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "presets":
|
||||||
|
promise = db.deletePreset(id);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "virtualParameters":
|
||||||
|
promise = db.deleteVirtualParameter(id);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "config":
|
||||||
|
promise = db.deleteConfig(id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
promise
|
||||||
|
.then(() => {
|
||||||
|
del("presets_hash", err => {
|
||||||
|
if (err) return void reject(err);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function postTasks(deviceId, tasks, timeout) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
for (const task of tasks) task.device = deviceId;
|
||||||
|
|
||||||
|
insertTasks(tasks, err => {
|
||||||
|
if (err) return void reject(err);
|
||||||
|
const statuses = tasks.map(t => {
|
||||||
|
return { _id: t._id, status: "pending" };
|
||||||
|
});
|
||||||
|
del(`${deviceId}_tasks_faults_operations`, err => {
|
||||||
|
if (err) return void reject(err);
|
||||||
|
connectionRequest(deviceId, err => {
|
||||||
|
if (err) {
|
||||||
|
return void resolve({
|
||||||
|
connectionRequest: err.message,
|
||||||
|
tasks: statuses
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const sample = tasks[tasks.length - 1];
|
||||||
|
|
||||||
|
// Waiting for session to finish or timeout
|
||||||
|
watchTask(deviceId, sample._id, timeout, err => {
|
||||||
|
if (err) return void reject(err);
|
||||||
|
|
||||||
|
const promises2 = [];
|
||||||
|
for (const s of statuses) {
|
||||||
|
promises2.push(db.query("tasks", ["=", ["PARAM", "_id"], s._id]));
|
||||||
|
promises2.push(
|
||||||
|
db.query("faults", [
|
||||||
|
"=",
|
||||||
|
["PARAM", "_id"],
|
||||||
|
`${deviceId}:task_${s._id}`
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise.all(promises2)
|
||||||
|
.then(res => {
|
||||||
|
for (const [i, r] of statuses.entries()) {
|
||||||
|
if (res[i * 2].length === 0) {
|
||||||
|
r.status = "done";
|
||||||
|
} else if (res[i * 2 + 1].length === 1) {
|
||||||
|
r.status = "fault";
|
||||||
|
r.fault = res[i * 2 + 1][0];
|
||||||
|
}
|
||||||
|
db.deleteTask(r._id);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve({ connectionRequest: "OK", tasks: statuses });
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ping(host) {
|
export function ping(host) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const options = url.parse(
|
exec(`ping -w 1 -i 0.2 -c 3 ${host}`, (err, stdout) => {
|
||||||
`http://127.0.0.1:${config.get("NBI_PORT")}/ping/${encodeURIComponent(
|
if (err) return void reject(err);
|
||||||
host
|
|
||||||
)}`
|
|
||||||
);
|
|
||||||
|
|
||||||
const _http = options.protocol === "https:" ? https : http;
|
const m = stdout.match(
|
||||||
_http
|
/(\d) packets transmitted, (\d) received, ([\d.%]+) packet loss[^]*([\d.]+)\/([\d.]+)\/([\d.]+)\/([\d.]+)/
|
||||||
.request(options, res => {
|
);
|
||||||
if (res.statusCode === 404) {
|
if (!m) return void reject(new Error("Could not parse ping response"));
|
||||||
res.resume();
|
|
||||||
return void resolve({});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res.statusCode !== 200) {
|
resolve({
|
||||||
res.resume();
|
packetsTransmitted: +m[1],
|
||||||
return void reject(
|
packetsReceived: +m[2],
|
||||||
new Error(`Unexpected status code ${res.statusCode}`)
|
packetLoss: m[3],
|
||||||
);
|
min: +m[4],
|
||||||
}
|
avg: +m[5],
|
||||||
|
max: +m[6],
|
||||||
const chunks = [];
|
mdev: +m[7]
|
||||||
let bytes = 0;
|
});
|
||||||
res.on("data", chunk => {
|
});
|
||||||
chunks.push(chunk);
|
|
||||||
bytes += chunk.length;
|
|
||||||
});
|
|
||||||
|
|
||||||
res.on("end", () => {
|
|
||||||
const buf = Buffer.allocUnsafe(bytes);
|
|
||||||
let o = 0;
|
|
||||||
for (const c of chunks) {
|
|
||||||
c.copy(buf, o, 0, c.length);
|
|
||||||
o += c.length;
|
|
||||||
}
|
|
||||||
const m = buf
|
|
||||||
.toString()
|
|
||||||
.match(
|
|
||||||
/(\d) packets transmitted, (\d) received, ([\d.%]+) packet loss[^]*([\d.]+)\/([\d.]+)\/([\d.]+)\/([\d.]+)/
|
|
||||||
);
|
|
||||||
if (!m)
|
|
||||||
return void reject(new Error("Could not parse ping response"));
|
|
||||||
|
|
||||||
resolve({
|
|
||||||
packetsTransmitted: +m[1],
|
|
||||||
packetsReceived: +m[2],
|
|
||||||
packetLoss: m[3],
|
|
||||||
min: +m[4],
|
|
||||||
avg: +m[5],
|
|
||||||
max: +m[6],
|
|
||||||
mdev: +m[7]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.end();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function putResource(resource, id, data) {
|
export function putResource(resource, id, data) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (resource === "config") {
|
let promise;
|
||||||
db.putConfig(id, data)
|
|
||||||
.then(() => {
|
|
||||||
cache.del("presets_hash", err => {
|
|
||||||
if (err) return void reject(err);
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(reject);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const resourceUrl =
|
if (resource === "presets") promise = db.putPreset(id, data);
|
||||||
resource === "virtualParameters" ? "virtual_parameters" : resource;
|
else if (resource === "provisions") promise = db.putProvision(id, data);
|
||||||
const options = url.parse(
|
else if (resource === "virtualParameters")
|
||||||
`http://127.0.0.1:${config.get(
|
promise = db.putVirtualParameter(id, data);
|
||||||
"NBI_PORT"
|
else if (resource === "config") promise = db.putConfig(id, data);
|
||||||
)}/${resourceUrl}/${encodeURIComponent(id)}`
|
|
||||||
);
|
|
||||||
|
|
||||||
options.method = "PUT";
|
promise
|
||||||
|
.then(() => {
|
||||||
const _http = options.protocol === "https:" ? https : http;
|
del("presets_hash", err => {
|
||||||
|
if (err) return void reject(err);
|
||||||
if (resource === "presets") data = mongodbFunctions.preProcessPreset(data);
|
resolve();
|
||||||
|
|
||||||
if (resource === "provisions")
|
|
||||||
data = mongodbFunctions.preProcessProvision(data);
|
|
||||||
|
|
||||||
if (resource === "virtualParameters")
|
|
||||||
data = mongodbFunctions.preProcessVirtualParameters(data);
|
|
||||||
|
|
||||||
const body = typeof data !== "string" ? JSON.stringify(data) : data;
|
|
||||||
_http
|
|
||||||
.request(options, res => {
|
|
||||||
const chunks = [];
|
|
||||||
let bytes = 0;
|
|
||||||
res.on("data", chunk => {
|
|
||||||
chunks.push(chunk);
|
|
||||||
bytes += chunk.length;
|
|
||||||
});
|
|
||||||
|
|
||||||
res.on("end", () => {
|
|
||||||
if (res.statusCode === 200) {
|
|
||||||
return void resolve();
|
|
||||||
} else if (res.statusCode !== 400) {
|
|
||||||
return void reject(
|
|
||||||
new Error(`Unexpected status code ${res.statusCode}`)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const buf = Buffer.allocUnsafe(bytes);
|
|
||||||
let o = 0;
|
|
||||||
for (const c of chunks) {
|
|
||||||
c.copy(buf, o, 0, c.length);
|
|
||||||
o += c.length;
|
|
||||||
}
|
|
||||||
resolve(buf.toString());
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.end(body);
|
.catch(reject);
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function putFile(id, metadata, fileStream) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const options = url.parse(
|
|
||||||
`http://127.0.0.1:${config.get("NBI_PORT")}/files/${encodeURIComponent(
|
|
||||||
id
|
|
||||||
)}`
|
|
||||||
);
|
|
||||||
|
|
||||||
options.method = "PUT";
|
|
||||||
options.headers = Object.assign({}, metadata);
|
|
||||||
const _http = options.protocol === "https:" ? https : http;
|
|
||||||
const req = _http.request(options, res => {
|
|
||||||
res.resume();
|
|
||||||
if (res.statusCode === 201) {
|
|
||||||
return void resolve();
|
|
||||||
} else {
|
|
||||||
return void reject(
|
|
||||||
new Error(`Unexpected status code ${res.statusCode}`)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
fileStream.pipe(req);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
+21
-12
@@ -7,6 +7,7 @@ import * as apiFunctions from "./api-functions";
|
|||||||
import { evaluate, and, extractParams } from "../common/expression";
|
import { evaluate, and, extractParams } from "../common/expression";
|
||||||
import { parse } from "../common/expression-parser";
|
import { parse } from "../common/expression-parser";
|
||||||
import * as logger from "../logger";
|
import * as logger from "../logger";
|
||||||
|
import { getConfig } from "../local-cache";
|
||||||
|
|
||||||
const router = new Router();
|
const router = new Router();
|
||||||
export default router;
|
export default router;
|
||||||
@@ -400,15 +401,7 @@ router.put("/files/:id", async (ctx, next) => {
|
|||||||
return void (ctx.status = 403);
|
return void (ctx.status = 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
const err = await apiFunctions.putFile(id, metadata, ctx.req);
|
await db.putFile(id, metadata, ctx.req);
|
||||||
|
|
||||||
if (err) {
|
|
||||||
log.message += " failed";
|
|
||||||
logger.accessWarn(log);
|
|
||||||
ctx.body = err;
|
|
||||||
return void (ctx.status = 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
log.metadata = metadata;
|
log.metadata = metadata;
|
||||||
logger.accessInfo(log);
|
logger.accessInfo(log);
|
||||||
|
|
||||||
@@ -439,7 +432,17 @@ router.post("/devices/:id/tasks", async (ctx, next) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await apiFunctions.postTasks(ctx.params.id, ctx.request.body);
|
// TODO Pass context and timestamp
|
||||||
|
const onlineThreshold = getConfig(
|
||||||
|
ctx.state.configSnapshot,
|
||||||
|
"cwmp.deviceOnlineThreshold"
|
||||||
|
);
|
||||||
|
|
||||||
|
const res = await apiFunctions.postTasks(
|
||||||
|
ctx.params.id,
|
||||||
|
ctx.request.body,
|
||||||
|
onlineThreshold
|
||||||
|
);
|
||||||
|
|
||||||
log.tasks = res.tasks.map(t => t._id).join(",");
|
log.tasks = res.tasks.map(t => t._id).join(",");
|
||||||
|
|
||||||
@@ -472,7 +475,7 @@ router.post("/devices/:id/tags", async (ctx, next) => {
|
|||||||
return void (ctx.status = 403);
|
return void (ctx.status = 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
await apiFunctions.updateTags(ctx.params.id, ctx.request.body);
|
await db.updateDeviceTags(ctx.params.id, ctx.request.body);
|
||||||
|
|
||||||
logger.accessInfo(log);
|
logger.accessInfo(log);
|
||||||
|
|
||||||
@@ -480,5 +483,11 @@ router.post("/devices/:id/tags", async (ctx, next) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.get("/ping/:host", async ctx => {
|
router.get("/ping/:host", async ctx => {
|
||||||
ctx.body = await apiFunctions.ping(ctx.params.host);
|
try {
|
||||||
|
ctx.body = await apiFunctions.ping(ctx.params.host);
|
||||||
|
} catch (err) {
|
||||||
|
ctx.status = 404;
|
||||||
|
ctx.response.headers["Cache-Control"] = "no-cache";
|
||||||
|
ctx.body = `${err.name}: ${err.message}`;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
+106
-8
@@ -1,9 +1,10 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
import { MongoClient } from "mongodb";
|
import { MongoClient, GridFSBucket } from "mongodb";
|
||||||
import * as config from "../config";
|
import * as config from "../config";
|
||||||
import * as mongodbFunctions from "./mongodb-functions";
|
import * as mongodbFunctions from "./mongodb-functions";
|
||||||
import * as expression from "../common/expression";
|
import * as expression from "../common/expression";
|
||||||
|
import { preProcessPreset } from "./mongodb-functions";
|
||||||
|
|
||||||
const CACHE_TTL = 300000;
|
const CACHE_TTL = 300000;
|
||||||
|
|
||||||
@@ -187,14 +188,23 @@ export function count(resource, filter) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteConfig(id) {
|
export function updateDeviceTags(deviceId, tags) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
const add = [];
|
||||||
|
const pull = [];
|
||||||
|
|
||||||
|
for (const [tag, onOff] of Object.entries(tags)) {
|
||||||
|
if (onOff) add.push(tag);
|
||||||
|
else pull.push(tag);
|
||||||
|
}
|
||||||
getClient()
|
getClient()
|
||||||
.then(client => {
|
.then(client => {
|
||||||
const collection = client
|
const collection = client.db().collection("devices");
|
||||||
.db()
|
|
||||||
.collection(RESOURCE_COLLECTION["config"] || "config");
|
const object = {};
|
||||||
collection.deleteOne({ _id: id }, err => {
|
if (add && add.length) object["$addToSet"] = { _tags: { $each: add } };
|
||||||
|
if (pull && pull.length) object["$pullAll"] = { _tags: pull };
|
||||||
|
collection.updateOne({ _id: deviceId }, object, err => {
|
||||||
if (err) return void reject(err);
|
if (err) return void reject(err);
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
@@ -203,13 +213,13 @@ export function deleteConfig(id) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function putConfig(id, object) {
|
function putResource(resource, id, object) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
getClient()
|
getClient()
|
||||||
.then(client => {
|
.then(client => {
|
||||||
const collection = client
|
const collection = client
|
||||||
.db()
|
.db()
|
||||||
.collection(RESOURCE_COLLECTION["config"] || "config");
|
.collection(RESOURCE_COLLECTION[resource] || resource);
|
||||||
collection.replaceOne({ _id: id }, object, { upsert: true }, err => {
|
collection.replaceOne({ _id: id }, object, { upsert: true }, err => {
|
||||||
if (err) return void reject(err);
|
if (err) return void reject(err);
|
||||||
resolve();
|
resolve();
|
||||||
@@ -219,6 +229,94 @@ export function putConfig(id, object) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deleteResource(resource, id) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
getClient()
|
||||||
|
.then(client => {
|
||||||
|
const collection = client
|
||||||
|
.db()
|
||||||
|
.collection(RESOURCE_COLLECTION[resource] || resource);
|
||||||
|
collection.deleteOne({ _id: id }, err => {
|
||||||
|
if (err) return void reject(err);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function putPreset(id, object) {
|
||||||
|
object = preProcessPreset(object);
|
||||||
|
return putResource("presets", id, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deletePreset(id) {
|
||||||
|
return deleteResource("presets", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function putProvision(id, object) {
|
||||||
|
return putResource("provisions", id, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteProvision(id) {
|
||||||
|
return deleteResource("provisions", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function putVirtualParameter(id, object) {
|
||||||
|
return putResource("virtualParameters", id, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteVirtualParameter(id) {
|
||||||
|
return deleteResource("virtualParameters", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function putConfig(id, object) {
|
||||||
|
return putResource("config", id, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteConfig(id) {
|
||||||
|
return deleteResource("config", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function putFile(filename, metadata, contentStream) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
getClient()
|
||||||
|
.then(client => {
|
||||||
|
const bucket = new GridFSBucket(client.db());
|
||||||
|
const uploadStream = bucket.openUploadStreamWithId(filename, filename, {
|
||||||
|
metadata: metadata
|
||||||
|
});
|
||||||
|
uploadStream.on("error", reject);
|
||||||
|
contentStream.on("error", reject);
|
||||||
|
uploadStream.on("finish", resolve);
|
||||||
|
contentStream.pipe(uploadStream);
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteFile(filename) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
getClient()
|
||||||
|
.then(client => {
|
||||||
|
const bucket = new GridFSBucket(client.db());
|
||||||
|
bucket.delete(filename, err => {
|
||||||
|
if (err) return void reject(err);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteFault(id) {
|
||||||
|
return deleteResource("faults", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteTask(id) {
|
||||||
|
return deleteResource("tasks", id);
|
||||||
|
}
|
||||||
|
|
||||||
export function disconnect() {
|
export function disconnect() {
|
||||||
if (_clientPromise) {
|
if (_clientPromise) {
|
||||||
_clientPromise.then(client => {
|
_clientPromise.then(client => {
|
||||||
|
|||||||
@@ -572,11 +572,3 @@ export function preProcessPreset(data) {
|
|||||||
preset.configurations = [configuration];
|
preset.configurations = [configuration];
|
||||||
return preset;
|
return preset;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function preProcessProvision(data) {
|
|
||||||
return data.script;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function preProcessVirtualParameters(data) {
|
|
||||||
return data.script;
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user