Convert api-functions.coffee to JS
This commit is contained in:
1 parent
3bde08671d
commit
91fb6c1c5a
3 files changed
+301
-266
No files matched your search
@@ -1,6 +1,5 @@
|
||||
*~
|
||||
lib/*.map
|
||||
lib/api-functions.js
|
||||
lib/cwmp.js
|
||||
lib/db.js
|
||||
lib/nbi.js
|
||||
|
||||
@@ -1,265 +0,0 @@
|
||||
###
|
||||
# Copyright 2013-2017 Zaid Abdulla
|
||||
#
|
||||
# This file is part of GenieACS.
|
||||
#
|
||||
# GenieACS is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# GenieACS is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with GenieACS. If not, see <http://www.gnu.org/licenses/>.
|
||||
###
|
||||
|
||||
crypto = require 'crypto'
|
||||
dgram = require 'dgram'
|
||||
|
||||
config = require './config'
|
||||
db = require './db'
|
||||
http = require 'http'
|
||||
common = require './common'
|
||||
util = require 'util'
|
||||
URL = require 'url'
|
||||
auth = require './auth'
|
||||
cache = require './cache'
|
||||
|
||||
|
||||
udpConReq = (address, un, key, callback) ->
|
||||
return false if not address
|
||||
[host, port] = address.split(':', 2)
|
||||
if port is undefined
|
||||
port = 80
|
||||
else
|
||||
port = parseInt(port)
|
||||
return false if isNaN(port)
|
||||
|
||||
ts = Math.trunc(Date.now() / 1000)
|
||||
id = Math.trunc(Math.random() * 4294967295)
|
||||
cn = crypto.randomBytes(8).toString('hex')
|
||||
sig = crypto.createHmac('sha1', key).update("#{ts}#{id}#{un}#{cn}").digest('hex')
|
||||
uri = "http://#{address}?ts=#{ts}&id=#{id}&un=#{un}&cn=#{cn}&sig=#{sig}"
|
||||
|
||||
message = Buffer.from("GET #{uri} HTTP/1.1\r\nHost: #{address}\r\n\r\n")
|
||||
|
||||
client = dgram.createSocket({type: 'udp4', reuseAddr: true})
|
||||
UDP_CONNECTION_REQUEST_PORT = config.get('UDP_CONNECTION_REQUEST_PORT')
|
||||
if UDP_CONNECTION_REQUEST_PORT
|
||||
# When a device is NAT'ed, the UDP Connection Request must originate from the same address and port used by the STUN server, in order to traverse the firewall.
|
||||
# This does require that the Genieacs NBI and STUN server are allowed to bind to the same address and port.
|
||||
# The STUN server needs to open its UDP port with the SO_REUSEADDR option, allowing the NBI to also bind to the same port.
|
||||
client.bind({port: UDP_CONNECTION_REQUEST_PORT, exclusive: true})
|
||||
|
||||
count = 3
|
||||
client.send(message, 0, message.length, port, host, f = (err) ->
|
||||
if err or -- count <= 0
|
||||
client.close()
|
||||
return callback(err)
|
||||
client.send(message, 0, message.length, port, host, f)
|
||||
)
|
||||
return true
|
||||
|
||||
|
||||
httpConReq = (url, username, password, allowBasicAuth, timeout, callback) ->
|
||||
options = URL.parse(url)
|
||||
|
||||
if options.protocol != 'http:'
|
||||
return callback(new Error('Invalid connection request URL or protocol'))
|
||||
|
||||
# Ensure socket is reused in case of digest authentication
|
||||
options.agent = new http.Agent({maxSockets : 1})
|
||||
|
||||
statusToError = (statusCode) ->
|
||||
switch statusCode
|
||||
when 200, 204
|
||||
null
|
||||
when 401
|
||||
new Error('Incorrect connection request credentials')
|
||||
when 0
|
||||
new Error('Device is offline')
|
||||
else
|
||||
new Error("Unexpected response code from device: #{statusCode}")
|
||||
|
||||
request = http.get(options, (res) ->
|
||||
if res.statusCode == 401 and res.headers['www-authenticate']?
|
||||
authHeader = auth.parseAuthHeader(res.headers['www-authenticate'])
|
||||
if authHeader.method is 'Basic'
|
||||
if not allowBasicAuth
|
||||
request.abort()
|
||||
callback(new Error('Basic HTTP authentication not allowed'))
|
||||
return
|
||||
options.headers = {'Authorization' : auth.basic(username or '', password or '')}
|
||||
else if authHeader.method is 'Digest'
|
||||
options.headers = {
|
||||
'Authorization' : auth.digest(username or '', password or '', options.path, 'GET', null, authHeader)
|
||||
}
|
||||
|
||||
request = http.get(options, (res) ->
|
||||
if res.statusCode == 0
|
||||
# Workaround for some devices unexpectedly closing the connection
|
||||
request = http.get(options, (res) ->
|
||||
callback(statusToError(res.statusCode))
|
||||
res.resume()
|
||||
).on('error', (err) ->
|
||||
request.abort()
|
||||
callback(statusToError(0))
|
||||
).on('socket', (socket) ->
|
||||
socket.setTimeout(timeout)
|
||||
socket.on('timeout', () -> request.abort())
|
||||
)
|
||||
else
|
||||
callback(statusToError(res.statusCode))
|
||||
res.resume()
|
||||
).on('error', (err) ->
|
||||
request.abort()
|
||||
callback(statusToError(0))
|
||||
).on('socket', (socket) ->
|
||||
socket.setTimeout(timeout)
|
||||
socket.on('timeout', () -> request.abort())
|
||||
)
|
||||
else
|
||||
callback(statusToError(res.statusCode))
|
||||
|
||||
# No listener for data so emit resume
|
||||
res.resume()
|
||||
).on('error', (err) ->
|
||||
request.abort()
|
||||
callback(statusToError(0))
|
||||
).on('socket', (socket) ->
|
||||
socket.setTimeout(timeout)
|
||||
socket.on('timeout', () -> request.abort())
|
||||
)
|
||||
|
||||
|
||||
connectionRequest = (deviceId, callback) ->
|
||||
CONNECTION_REQUEST_TIMEOUT = config.get('CONNECTION_REQUEST_TIMEOUT', deviceId)
|
||||
CONNECTION_REQUEST_ALLOW_BASIC_AUTH = config.get('CONNECTION_REQUEST_ALLOW_BASIC_AUTH', deviceId)
|
||||
proj = {
|
||||
'Device.ManagementServer.ConnectionRequestURL._value' : 1,
|
||||
'Device.ManagementServer.UDPConnectionRequestAddress._value' : 1,
|
||||
'Device.ManagementServer.ConnectionRequestUsername._value' : 1,
|
||||
'Device.ManagementServer.ConnectionRequestPassword._value' : 1,
|
||||
'InternetGatewayDevice.ManagementServer.ConnectionRequestURL._value' : 1,
|
||||
'InternetGatewayDevice.ManagementServer.UDPConnectionRequestAddress._value' : 1,
|
||||
'InternetGatewayDevice.ManagementServer.ConnectionRequestUsername._value' : 1,
|
||||
'InternetGatewayDevice.ManagementServer.ConnectionRequestPassword._value' : 1
|
||||
}
|
||||
|
||||
db.devicesCollection.findOne({_id : deviceId}, proj, (err, device)->
|
||||
return callback(err) if err
|
||||
|
||||
if device.Device? # TR-181 data model
|
||||
connectionRequestUrl = device.Device.ManagementServer.ConnectionRequestURL._value
|
||||
udpConnectionRequestAddress = device.Device.ManagementServer?.UDPConnectionRequestAddress?._value
|
||||
username = device.Device.ManagementServer.ConnectionRequestUsername?._value
|
||||
password = device.Device.ManagementServer.ConnectionRequestPassword?._value
|
||||
else # TR-098 data model
|
||||
connectionRequestUrl = device.InternetGatewayDevice.ManagementServer.ConnectionRequestURL._value
|
||||
udpConnectionRequestAddress = device.InternetGatewayDevice.ManagementServer?.UDPConnectionRequestAddress?._value
|
||||
username = device.InternetGatewayDevice.ManagementServer.ConnectionRequestUsername?._value
|
||||
password = device.InternetGatewayDevice.ManagementServer.ConnectionRequestPassword?._value
|
||||
|
||||
conReq = () ->
|
||||
udpSent = udpConReq(udpConnectionRequestAddress, username, password, (err) -> throw err if err)
|
||||
|
||||
httpConReq(connectionRequestUrl, username, password, CONNECTION_REQUEST_ALLOW_BASIC_AUTH, CONNECTION_REQUEST_TIMEOUT, (err) ->
|
||||
if udpSent
|
||||
return callback()
|
||||
callback(err)
|
||||
)
|
||||
|
||||
if config.auth?.connectionRequest?
|
||||
# Callback is optional for backward compatibility
|
||||
if config.auth.connectionRequest.length > 4
|
||||
return config.auth.connectionRequest(deviceId, connectionRequestUrl, username, password, (u, p) ->
|
||||
username = u
|
||||
password = p
|
||||
conReq()
|
||||
)
|
||||
[username, password] = config.auth.connectionRequest(deviceId, connectionRequestUrl, username, password)
|
||||
conReq()
|
||||
)
|
||||
|
||||
|
||||
watchTask = (deviceId, taskId, timeout, callback) ->
|
||||
setTimeout(() ->
|
||||
db.tasksCollection.findOne({_id : taskId}, {'_id' : 1}, (err, task) ->
|
||||
return callback(err) if err
|
||||
|
||||
if not task
|
||||
return callback(null, 'completed')
|
||||
|
||||
db.faultsCollection.findOne({_id : "#{deviceId}:task_#{taskId}"}, {'_id' : 1}, (err, fault) ->
|
||||
return callback(err) if err
|
||||
|
||||
if fault
|
||||
return callback(null, 'fault')
|
||||
|
||||
if (timeout -= 500) <= 0
|
||||
return callback(null, 'timeout')
|
||||
|
||||
watchTask(deviceId, taskId, timeout, callback)
|
||||
)
|
||||
)
|
||||
, 500)
|
||||
|
||||
|
||||
sanitizeTask = (task, callback) ->
|
||||
task.timestamp = new Date(task.timestamp ? Date.now())
|
||||
if task.expiry?
|
||||
if common.typeOf(task.expiry) is common.DATE_TYPE or isNaN(task.expiry)
|
||||
task.expiry = new Date(task.expiry)
|
||||
else
|
||||
task.expiry = new Date(task.timestamp.getTime() + +task.expiry * 1000)
|
||||
|
||||
callback(task)
|
||||
|
||||
|
||||
insertTasks = (tasks, callback) ->
|
||||
if tasks? and common.typeOf(tasks) isnt common.ARRAY_TYPE
|
||||
tasks = [tasks]
|
||||
else if not tasks? or tasks.length == 0
|
||||
return callback(null, tasks or [])
|
||||
|
||||
counter = tasks.length
|
||||
|
||||
for task in tasks
|
||||
sanitizeTask(task, (t) ->
|
||||
if t.uniqueKey?
|
||||
db.tasksCollection.remove({device : t.device, uniqueKey : t.uniqueKey}, (err) ->
|
||||
)
|
||||
|
||||
--counter
|
||||
if counter == 0
|
||||
db.tasksCollection.insert(tasks, (err, _tasks) ->
|
||||
#util.log("#{_task.device}: Added task #{_task.name}(#{_task._id})") for _task in _tasks
|
||||
callback(err, _tasks)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
deleteDevice = (deviceId, callback) ->
|
||||
db.tasksCollection.remove({'device' : deviceId}, (err) ->
|
||||
return callback(err) if err
|
||||
db.devicesCollection.remove({'_id' : deviceId}, (err) ->
|
||||
return callback(err) if err
|
||||
db.faultsCollection.remove({'_id' : {'$regex' : "^#{common.escapeRegExp(deviceId)}\\:"}}, (err) ->
|
||||
return callback(err) if err
|
||||
db.operationsCollection.remove({'_id' : {'$regex' : "^#{common.escapeRegExp(deviceId)}\\:"}}, (err) ->
|
||||
return callback(err) if err
|
||||
cache.del("#{deviceId}_tasks_faults_operations", callback)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
exports.connectionRequest = connectionRequest
|
||||
exports.watchTask = watchTask
|
||||
exports.insertTasks = insertTasks
|
||||
exports.deleteDevice = deleteDevice
|
||||
@@ -0,0 +1,301 @@
|
||||
/**
|
||||
* Copyright 2013-2018 Zaid Abdulla
|
||||
*
|
||||
* This file is part of GenieACS.
|
||||
*
|
||||
* GenieACS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* GenieACS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with GenieACS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const crypto = require("crypto");
|
||||
const dgram = require("dgram");
|
||||
const URL = require("url");
|
||||
const http = require("http");
|
||||
const config = require("./config");
|
||||
const db = require("./db");
|
||||
const common = require("./common");
|
||||
const auth = require("./auth");
|
||||
const cache = require("./cache");
|
||||
|
||||
function udpConReq(address, un, key, callback) {
|
||||
if (!address)
|
||||
return false;
|
||||
|
||||
let [host, port] = address.split(":", 2);
|
||||
|
||||
if (!port) {
|
||||
port = 80;
|
||||
} else {
|
||||
port = parseInt(port);
|
||||
if (isNaN(port))
|
||||
return false;
|
||||
}
|
||||
|
||||
const ts = Math.trunc(Date.now() / 1000);
|
||||
const id = Math.trunc(Math.random() * 4294967295);
|
||||
const cn = crypto.randomBytes(8).toString("hex");
|
||||
const sig = crypto.createHmac("sha1", key).update(`${ts}${id}${un}${cn}`).digest("hex");
|
||||
const uri = `http://${address}?ts=${ts}&id=${id}&un=${un}&cn=${cn}&sig=${sig}`;
|
||||
const message = Buffer.from(`GET ${uri} HTTP/1.1\r\nHost: ${address}\r\n\r\n`);
|
||||
|
||||
const client = dgram.createSocket({type: "udp4", reuseAddr: true});
|
||||
const UDP_CONNECTION_REQUEST_PORT = config.get("UDP_CONNECTION_REQUEST_PORT");
|
||||
|
||||
if (UDP_CONNECTION_REQUEST_PORT)
|
||||
// When a device is NAT'ed, the UDP Connection Request must originate from
|
||||
// the same address and port used by the STUN server, in order to traverse
|
||||
// the firewall. This does require that the Genieacs NBI and STUN server
|
||||
// are allowed to bind to the same address and port. The STUN server needs
|
||||
// to open its UDP port with the SO_REUSEADDR option, allowing the NBI to
|
||||
// also bind to the same port.
|
||||
client.bind({port: UDP_CONNECTION_REQUEST_PORT, exclusive: true});
|
||||
|
||||
let count = 3;
|
||||
const func = (err) => {
|
||||
if (err || --count <= 0) {
|
||||
client.close();
|
||||
return callback(err);
|
||||
}
|
||||
client.send(message, 0, message.length, port, host, func);
|
||||
};
|
||||
client.send(message, 0, message.length, port, host, func);
|
||||
return true;
|
||||
}
|
||||
|
||||
function httpConReq(url, username, password, allowBasicAuth, timeout, callback) {
|
||||
const options = URL.parse(url);
|
||||
if (options.protocol !== "http:")
|
||||
return callback(new Error("Invalid connection request URL or protocol"));
|
||||
options.agent = new http.Agent({maxSockets: 1});
|
||||
|
||||
function statusToError(statusCode) {
|
||||
switch (statusCode) {
|
||||
case 200:
|
||||
case 204:
|
||||
return null;
|
||||
case 401:
|
||||
return new Error("Incorrect connection request credentials");
|
||||
case 0:
|
||||
return new Error("Device is offline");
|
||||
default:
|
||||
return new Error(`Unexpected response code from device: ${statusCode}`);
|
||||
}
|
||||
}
|
||||
|
||||
const request = http.get(options, (res) => {
|
||||
if (res.statusCode === 401 && res.headers["www-authenticate"]) {
|
||||
const authHeader = auth.parseAuthHeader(res.headers["www-authenticate"]);
|
||||
if (authHeader.method === "Basic") {
|
||||
if (!allowBasicAuth) {
|
||||
request.abort();
|
||||
return callback(new Error("Basic HTTP authentication not allowed"));
|
||||
}
|
||||
options.headers = {
|
||||
"Authorization": auth.basic(username || "", password || "")
|
||||
};
|
||||
} else if (authHeader.method === "Digest") {
|
||||
options.headers = {
|
||||
"Authorization": auth.digest(username || "", password || "", options.path, "GET", null, authHeader)
|
||||
};
|
||||
}
|
||||
|
||||
const request = http.get(options, (res) => {
|
||||
if (res.statusCode === 0) {
|
||||
// Workaround for some devices unexpectedly closing the connection
|
||||
request = http.get(options, (res) => {
|
||||
callback(statusToError(res.statusCode));
|
||||
res.resume();
|
||||
}).on("error", () => {
|
||||
request.abort();
|
||||
callback(statusToError(0));
|
||||
}).on("socket", (socket) => {
|
||||
socket.setTimeout(timeout);
|
||||
socket.on("timeout", () => {
|
||||
request.abort();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
callback(statusToError(res.statusCode));
|
||||
}
|
||||
res.resume();
|
||||
}).on("error", () => {
|
||||
request.abort();
|
||||
callback(statusToError(0));
|
||||
}).on("socket", (socket) => {
|
||||
socket.setTimeout(timeout);
|
||||
socket.on("timeout", () => {
|
||||
request.abort();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
callback(statusToError(res.statusCode));
|
||||
}
|
||||
// No listener for data so emit resume
|
||||
res.resume();
|
||||
}).on("error", (err) => {
|
||||
request.abort();
|
||||
callback(statusToError(0));
|
||||
}).on("socket", (socket) => {
|
||||
socket.setTimeout(timeout);
|
||||
socket.on("timeout", () => {
|
||||
request.abort();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function connectionRequest(deviceId, callback) {
|
||||
const CONNECTION_REQUEST_TIMEOUT = config.get("CONNECTION_REQUEST_TIMEOUT", deviceId);
|
||||
const CONNECTION_REQUEST_ALLOW_BASIC_AUTH = config.get("CONNECTION_REQUEST_ALLOW_BASIC_AUTH", deviceId);
|
||||
const proj = {
|
||||
"Device.ManagementServer.ConnectionRequestURL._value": 1,
|
||||
"Device.ManagementServer.UDPConnectionRequestAddress._value": 1,
|
||||
"Device.ManagementServer.ConnectionRequestUsername._value": 1,
|
||||
"Device.ManagementServer.ConnectionRequestPassword._value": 1,
|
||||
"InternetGatewayDevice.ManagementServer.ConnectionRequestURL._value": 1,
|
||||
"InternetGatewayDevice.ManagementServer.UDPConnectionRequestAddress._value": 1,
|
||||
"InternetGatewayDevice.ManagementServer.ConnectionRequestUsername._value": 1,
|
||||
"InternetGatewayDevice.ManagementServer.ConnectionRequestPassword._value": 1
|
||||
};
|
||||
|
||||
db.devicesCollection.findOne({_id: deviceId}, proj, (err, device) => {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
let managementServer, connectionRequestUrl, udpConnectionRequestAddress, username, password;
|
||||
if (device.Device) // TR-181 data model
|
||||
managementServer = device.Device.ManagementServer;
|
||||
else // TR-098 data model
|
||||
managementServer = device.InternetGatewayDevice.ManagementServer;
|
||||
|
||||
connectionRequestUrl = managementServer.ConnectionRequestURL._value;
|
||||
if (managementServer.UDPConnectionRequestAddress)
|
||||
udpConnectionRequestAddress = managementServer.UDPConnectionRequestAddress._value;
|
||||
if (managementServer.ConnectionRequestUsername)
|
||||
username = managementServer.ConnectionRequestUsername._value;
|
||||
if (managementServer.ConnectionRequestPassword)
|
||||
password = managementServer.ConnectionRequestPassword._value;
|
||||
|
||||
const conReq = () => {
|
||||
const udpSent = udpConReq(udpConnectionRequestAddress, username, password, (err) => {
|
||||
if (err)
|
||||
throw err;
|
||||
});
|
||||
|
||||
httpConReq(connectionRequestUrl, username, password, CONNECTION_REQUEST_ALLOW_BASIC_AUTH, CONNECTION_REQUEST_TIMEOUT, (err) => {
|
||||
if (udpSent)
|
||||
return callback();
|
||||
callback(err);
|
||||
});
|
||||
};
|
||||
|
||||
if (config.auth && config.auth.connectionRequest) {
|
||||
// Callback is optional for backward compatibility
|
||||
if (config.auth.connectionRequest.length > 4)
|
||||
return config.auth.connectionRequest(deviceId, connectionRequestUrl, username, password, (u, p) => {
|
||||
username = u;
|
||||
password = p;
|
||||
conReq();
|
||||
});
|
||||
[username, password] = config.auth.connectionRequest(deviceId, connectionRequestUrl, username, password);
|
||||
}
|
||||
conReq();
|
||||
});
|
||||
}
|
||||
|
||||
function watchTask(deviceId, taskId, timeout, callback) {
|
||||
setTimeout(() => {
|
||||
db.tasksCollection.findOne({_id: taskId}, {_id: 1}, (err, task) => {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!task)
|
||||
return callback(null, "completed");
|
||||
|
||||
const q = {_id: `${deviceId}:task_${taskId}`};
|
||||
db.faultsCollection.findOne(q, {_id: 1}, (err, fault) => {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (fault)
|
||||
return callback(null, "fault");
|
||||
|
||||
if ((timeout -= 500) <= 0)
|
||||
return callback(null, "timeout");
|
||||
|
||||
watchTask(deviceId, taskId, timeout, callback);
|
||||
});
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function sanitizeTask(task, callback) {
|
||||
task.timestamp = new Date(task.timestamp || Date.now());
|
||||
if (task.expiry) {
|
||||
if (common.typeOf(task.expiry) === common.DATE_TYPE || isNaN(task.expiry))
|
||||
task.expiry = new Date(task.expiry);
|
||||
else
|
||||
task.expiry = new Date(task.timestamp.getTime() + +task.expiry * 1000);
|
||||
}
|
||||
callback(task);
|
||||
}
|
||||
|
||||
function insertTasks(tasks, callback) {
|
||||
if (tasks && common.typeOf(tasks) !== common.ARRAY_TYPE)
|
||||
tasks = [tasks];
|
||||
else if (!tasks || tasks.length === 0)
|
||||
return callback(null, tasks || []);
|
||||
|
||||
let counter = tasks.length;
|
||||
for (let task of tasks)
|
||||
sanitizeTask(task, (t) => {
|
||||
if (t.uniqueKey)
|
||||
db.tasksCollection.remove({device: t.device, uniqueKey: t.uniqueKey}, () => {});
|
||||
|
||||
if (--counter === 0)
|
||||
db.tasksCollection.insert(tasks, callback);
|
||||
});
|
||||
}
|
||||
|
||||
function deleteDevice(deviceId, callback) {
|
||||
db.tasksCollection.remove({"device": deviceId}, (err) => {
|
||||
if (err)
|
||||
return callback(err);
|
||||
db.devicesCollection.remove({"_id": deviceId}, (err) => {
|
||||
if (err)
|
||||
return callback(err);
|
||||
db.faultsCollection.remove({
|
||||
"_id": {
|
||||
"$regex": `^${common.escapeRegExp(deviceId)}\\:`
|
||||
}
|
||||
}, (err) => {
|
||||
if (err)
|
||||
return callback(err);
|
||||
db.operationsCollection.remove({
|
||||
"_id": {
|
||||
"$regex": `^${common.escapeRegExp(deviceId)}\\:`
|
||||
}
|
||||
}, (err) => {
|
||||
if (err)
|
||||
return callback(err);
|
||||
cache.del(`${deviceId}_tasks_faults_operations`, callback);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.connectionRequest = connectionRequest;
|
||||
exports.watchTask = watchTask;
|
||||
exports.insertTasks = insertTasks;
|
||||
exports.deleteDevice = deleteDevice;
|
||||
Reference in new issue
Block a user