Files
TempestDataCollection/routes/ping.js

120 lines
4.2 KiB
JavaScript
Raw Normal View History

let _ = require("underscore");
let express = require('express');
let router = express.Router();
const {MongoClient} = require("mongodb");
let localAddresses = process.env.LOCAL_ADDRESSES; //eg: "10.18.,10.17."
// Create an array of local address beginnings. This is matched against the client addresses to determine if they are local. If not provided then all addresses are considered local.
if(localAddresses) localAddresses = localAddresses.split(',');
//const uri = "mongodb://test:1qaz2wsx@mongodb.avpanthers.org:27017/";
let uri = process.env.MONGO_URL; //Read from the nginx sites-available file for this app.
//mongodb://host1:27017,host2:27017,host3:27017/?replicaSet=myRs
if(!uri) {
uri = "mongodb://localhost/avusd_data_collection";
}
const client = new MongoClient(uri);
let collection;
// We are keeping an in-memory set of current/active records for each Chromebook to reduce the number of reads without _id we perform.
// The idea is that each Chromebook pings every 5 minutes when a student is logged in and using the Chromebook.
// We note how long between the first and last use of each chromebook & user, and how many pings were recorded during that time period.
// This gives us an idea of who used it for any given time period, and roughly how much use it got.
// Prepare a database connection for use later.
async function connect() {
try {
await client.connect();
const database = client.db("avusd_data_collection");
collection = database.collection('records');
// console.log("Connected to Mongodb server");
} catch(e) {
console.log("error: caught ping.js:31 in Data Collection.");
console.log(e);
}
}
// Create a new record for a Chromebook & user. Set it in the cache (replace any existing one for that serial).
async function createRecord(record, isInternal) {
record.startTime = record.endTime = new Date().getTime();
record.count = 1;
record.internalCount = isInternal ? 1 : 0;
//Write to db.
let queryResult = await collection.insertOne(record);
//Handle errors.
if(queryResult.writeConcernError && queryResult.writeConcernError.errmsg) {
console.log("error: caught ping.js:61 in Data Collection.");
console.log(queryResult.writeConcernError.errmsg + " ::: " + JSON.stringify(record));
}
}
async function updateRecord(record, isInternal, clientAddress) {
try {
if(!collection) {
await connect();
}
//Read record with given serial.
let existing = await collection.findOne({serial: record.serial, closed: {$exists: false}});
if(!existing) {
await createRecord(record, isInternal);
}
else {
//If the user has changed, then close the record. Create a new record for the new user.
if(existing.email !== record.email) {
await collection.updateOne({_id: existing._id}, {$set: {closed: true}});
await createRecord(record, isInternal);
}
else {
await collection.updateOne({_id: existing._id}, {$set: {endTime: new Date().getTime()}, $inc: {count: 1, internalCount: isInternal ? 1 : 0}});
}
}
} catch(e) {
console.log(e);
}
}
// Handle the client calling Ping.
router.get('/', function(req, res, next) {
//Get the parameters.
const params = req.query;
const email = params.email;
const assetId = params.assetId;
const serial = params.serial;
const deviceId = params.deviceId;
//DEBUG
// console.log("Email: " + params.email);
// console.log("AssetId: " + params.assetId);
// console.log("Serial: " + params.serial);
// console.log("DeviceId: " + params.deviceId);
// Ignore any calls without a serial.
if(params.serial) {
let clientAddress = req.header("X-Real-IP");
if (!clientAddress) clientAddress = req.socket.remoteAddress;
let isLocal = true;
// console.log("Found IP: " + clientAddress);
if (localAddresses) {
isLocal = false;
for (let i = 0; !isLocal && i < localAddresses.length; i++) {
let next = localAddresses[i];
isLocal = clientAddress.startsWith(next);
}
}
//Note: We are not waiting for this to finish. We don't care about the output.
updateRecord({serial, assetId, deviceId, email}, isLocal, clientAddress);
}
//Send response. Nothing for the moment.
res.setHeader("Access-Control-Allow-Origin", "*");
//res.setHeader("Content-Type", "application/json;charset=UTF8");
res.status(200);
res.end('Pong');
});
module.exports = router;