Devices can now subscribe to specific topics.
- Device can now become (in)active - Error alert makes sound - Alerts now execute function on click
This commit is contained in:
@@ -92,7 +92,7 @@ async function run() {
|
||||
/**
|
||||
* Database connection
|
||||
*/
|
||||
mongoose.set('debug', true);
|
||||
//mongoose.set('debug', true);
|
||||
const connection = await mongoose.connect(MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true }).catch((err) => {
|
||||
logger.crit("Database connection could not be made: ", err);
|
||||
exit(1);
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { Response } from "express";
|
||||
import { logger } from "../app";
|
||||
import { logger, rabbitmq } from "../app";
|
||||
import { LivebeatRequest } from "../lib/request";
|
||||
import { Beat } from "../models/beat/beat.model.";
|
||||
import { Phone } from "../models/phone/phone.model";
|
||||
|
||||
|
||||
|
||||
export async function GetPhone(req: LivebeatRequest, res: Response) {
|
||||
const phoneId: String = req.params['id'];
|
||||
|
||||
@@ -16,7 +18,7 @@ export async function GetPhone(req: LivebeatRequest, res: Response) {
|
||||
|
||||
// Check database for phone
|
||||
const phone = await Phone.findOne({ androidId: phoneId, user: req.user?._id });
|
||||
if (phone === undefined) {
|
||||
if (phone === null) {
|
||||
res.status(404).send();
|
||||
return;
|
||||
}
|
||||
@@ -53,7 +55,7 @@ export async function PostPhone(req: LivebeatRequest, res: Response) {
|
||||
}
|
||||
|
||||
// Create phone
|
||||
await Phone.create({
|
||||
const newPhone = await Phone.create({
|
||||
androidId,
|
||||
displayName,
|
||||
modelName,
|
||||
@@ -63,7 +65,8 @@ export async function PostPhone(req: LivebeatRequest, res: Response) {
|
||||
active: false
|
||||
});
|
||||
|
||||
logger.info(`New device (${displayName}) registered for ${req.user?.name}.`)
|
||||
logger.info(`New device (${displayName}) registered for ${req.user?.name}.`);
|
||||
rabbitmq.publish(req.user?.id, newPhone.toJSON(), 'phone_register')
|
||||
|
||||
res.status(200).send();
|
||||
}
|
||||
@@ -232,7 +232,7 @@ export async function Resource(req: Request, res: Response) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: This has to change if we want to allow users to see the realtime movement of others.
|
||||
// TODO: This has to change if we want to allow users to see the realtime movement of others.
|
||||
if (resource.toString().startsWith('tracker-') && resource != 'tracker-' + username) {
|
||||
res.status(200).send('deny');
|
||||
return;
|
||||
@@ -242,6 +242,34 @@ export async function Resource(req: Request, res: Response) {
|
||||
}
|
||||
|
||||
export async function Topic(req: Request, res: Response) {
|
||||
res.status(200);
|
||||
|
||||
const username = req.query.username;
|
||||
const routingKey = req.query.routing_key;
|
||||
|
||||
if (routingKey === undefined || username === undefined) {
|
||||
res.send('deny');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if it's us
|
||||
if (username.toString() == 'backend') {
|
||||
res.status(200).send('allow');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if user exists
|
||||
const user = await User.findOne({ name: username.toString() });
|
||||
if (user === null) {
|
||||
res.send('deny');
|
||||
return;
|
||||
}
|
||||
|
||||
if (routingKey !== user.id) {
|
||||
res.send('deny');
|
||||
return;
|
||||
}
|
||||
|
||||
res.status(200).send('allow');
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ export class RabbitMQ {
|
||||
connection: amqp.Connection | null = null;
|
||||
channel: amqp.Channel | null = null;
|
||||
|
||||
timeouts: Map<string, Timeout> = new Map<string, Timeout>();
|
||||
|
||||
async init() {
|
||||
this.connection = await amqp.connect(RABBITMQ_URI);
|
||||
this.channel = await this.connection.createChannel();
|
||||
@@ -26,7 +28,7 @@ export class RabbitMQ {
|
||||
// Get phone
|
||||
const phone = await Phone.findOne({ androidId: msg.token });
|
||||
if (phone == undefined) {
|
||||
logger.info(`Received beat from unknown device with id ${msg.token}`);
|
||||
logger.warning(`Received beat from unknown device with id ${msg.token}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -41,13 +43,33 @@ export class RabbitMQ {
|
||||
battery: msg.battery,
|
||||
createdAt: msg.timestamp
|
||||
});
|
||||
|
||||
// Broadcast if device became active
|
||||
if (this.timeouts.has(phone.id)) {
|
||||
clearTimeout(this.timeouts.get(phone.id));
|
||||
} else {
|
||||
logger.debug('Set phone active');
|
||||
phone.active = true;
|
||||
await phone.save();
|
||||
this.publish(phone.user.toString(), phone.toJSON(), 'phone_alive');
|
||||
}
|
||||
|
||||
const timeoutTimer = setTimeout(async () => {
|
||||
this.publish(phone.user.toString(), phone.toJSON(), 'phone_dead');
|
||||
this.timeouts.delete(phone.id);
|
||||
phone.active = false;
|
||||
await phone.save();
|
||||
}, 30_000);
|
||||
this.timeouts.set(phone.id, timeoutTimer);
|
||||
|
||||
this.channel!.publish('amq.topic', '.', Buffer.from(JSON.stringify(newBeat.toJSON())));
|
||||
this.publish(phone.user.toString(), newBeat.toJSON(), 'beat');
|
||||
}, { noAck: true });
|
||||
}
|
||||
|
||||
async publish(queueName = 'tracker', data: any) {
|
||||
async publish(userId: string, data: any, type: 'beat' | 'phone_alive' | 'phone_dead' | 'phone_register' | 'panic' = 'beat') {
|
||||
if (this.connection == undefined) await this.init()
|
||||
this.channel?.sendToQueue(queueName, Buffer.from(data));
|
||||
|
||||
data = { type, ...data };
|
||||
this.channel?.publish('amq.topic', userId, Buffer.from(JSON.stringify(data)));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user