Socket connection now works
- Pairing a new device works (I did a lot since the last commit)
This commit is contained in:
63
backend/.idea/workspace.xml
generated
63
backend/.idea/workspace.xml
generated
@@ -1,63 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="19050b14-6aa3-4201-be2a-b6c9fb417ff6" name="Default Changelist" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/../android/app/src/main/java/de/nicolasklier/livebeat/MainActivity.kt" beforeDir="false" afterPath="$PROJECT_DIR$/../android/app/src/main/java/de/nicolasklier/livebeat/MainActivity.kt" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app.ts" beforeDir="false" afterPath="$PROJECT_DIR$/app.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/config.ts" beforeDir="false" afterPath="$PROJECT_DIR$/config.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/endpoints/beat.ts" beforeDir="false" afterPath="$PROJECT_DIR$/endpoints/beat.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/endpoints/phone.ts" beforeDir="false" afterPath="$PROJECT_DIR$/endpoints/phone.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/lib/rabbit.ts" beforeDir="false" afterPath="$PROJECT_DIR$/lib/rabbit.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/src/app/api.service.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/api.service.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/src/app/map.worker.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/map.worker.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/src/app/map/map.component.html" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/map/map.component.html" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../package-lock.json" beforeDir="false" afterPath="$PROJECT_DIR$/../package-lock.json" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
|
||||
</component>
|
||||
<component name="ProjectId" id="1qRNQeCqRVVNuS6QKJoYRrUYOnM" />
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
|
||||
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
|
||||
<property name="WebServerToolWindowFactoryState" value="false" />
|
||||
</component>
|
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="19050b14-6aa3-4201-be2a-b6c9fb417ff6" name="Default Changelist" comment="" />
|
||||
<created>1617038467045</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1617038467045</updated>
|
||||
<workItem from="1617038468601" duration="1438000" />
|
||||
<workItem from="1617121449363" duration="83000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
<component name="Vcs.Log.Tabs.Properties">
|
||||
<option name="TAB_STATES">
|
||||
<map>
|
||||
<entry key="MAIN">
|
||||
<value>
|
||||
<State />
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
<option name="oldMeFiltersMigrated" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -7,14 +7,15 @@ import * as figlet from 'figlet';
|
||||
import * as mongoose from 'mongoose';
|
||||
import { exit } from 'process';
|
||||
import * as winston from 'winston';
|
||||
import { createServer } from 'http';
|
||||
|
||||
import { config } from './config';
|
||||
import { GetBeat, GetBeatStats } from './endpoints/beat';
|
||||
import { getNotification } from './endpoints/notification';
|
||||
import { GetPhone, PostPhone } from './endpoints/phone';
|
||||
import { DeleteUser, GetUser, LoginRabbitUser, LoginUser, MW_User, PatchUser, PostUser, Resource, Topic, VHost } from './endpoints/user';
|
||||
import { DeleteUser, GetUser, LoginUser, MW_User, PatchUser, PostUser } from './endpoints/user';
|
||||
import { hashPassword, randomPepper, randomString } from './lib/crypto';
|
||||
import { RabbitMQ } from './lib/rabbit';
|
||||
import { SocketManager } from './lib/socketio';
|
||||
import { UserType } from './models/user/user.interface';
|
||||
import { User } from './models/user/user.model';
|
||||
|
||||
@@ -27,7 +28,6 @@ export const JWT_SECRET = process.env.JWT_SECRET || "";
|
||||
export const IS_DEBUG = process.env.DEBUG == 'true';
|
||||
|
||||
export let logger: winston.Logger;
|
||||
export let rabbitmq: RabbitMQ;
|
||||
|
||||
async function run() {
|
||||
const { combine, timestamp, label, printf, prettyPrint } = winston.format;
|
||||
@@ -108,10 +108,8 @@ async function run() {
|
||||
await User.create({
|
||||
name: 'admin',
|
||||
password: await hashPassword(randomPassword + salt + randomPepper()),
|
||||
brokerToken: randomString(16),
|
||||
salt,
|
||||
createdAt: Date.now(),
|
||||
lastLogin: 0,
|
||||
lastLogin: new Date(0),
|
||||
type: UserType.ADMIN
|
||||
});
|
||||
logger.info("===================================================");
|
||||
@@ -124,14 +122,23 @@ async function run() {
|
||||
/**
|
||||
* HTTP server
|
||||
*/
|
||||
logger.debug("Preparing HTTP server ...")
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
const server = createServer(app);
|
||||
|
||||
app.use(cors());
|
||||
app.options('*', cors());
|
||||
|
||||
app.use(express.json());
|
||||
app.use(bodyParser.json({ limit: '5kb' }));
|
||||
|
||||
app.use((req, res, next) => {
|
||||
res.on('finish', () => {
|
||||
const done = Date.now();
|
||||
// Censor any user passwords
|
||||
if (req.body.password != null) {
|
||||
req.body.password = "***********";
|
||||
}
|
||||
|
||||
logger.debug(`${req.method} - ${req.url} ${JSON.stringify(req.body)} -> ${res.statusCode}`);
|
||||
});
|
||||
next();
|
||||
@@ -141,10 +148,6 @@ async function run() {
|
||||
|
||||
// User authentication
|
||||
app.post('/user/login', (req, res) => LoginUser(req, res));
|
||||
app.get('/user/rabbitlogin', (req, res) => LoginRabbitUser(req, res));
|
||||
app.get('/user/vhost', (req, res) => VHost(req, res));
|
||||
app.get('/user/resource', (req, res) => Resource(req, res));
|
||||
app.get('/user/topic', (req, res) => Topic(req, res));
|
||||
|
||||
// CRUD user
|
||||
app.get('/user/notification', MW_User, (req, res) => getNotification(req, res)); // Notifications
|
||||
@@ -163,16 +166,11 @@ async function run() {
|
||||
app.get('/beat/', MW_User, (req, res) => GetBeat(req, res));
|
||||
app.get('/beat/stats', MW_User, (req, res) => GetBeatStats(req, res));
|
||||
|
||||
app.listen(config.http.port, config.http.host, () => {
|
||||
const socketManager = new SocketManager(server);
|
||||
|
||||
server.listen(config.http.port, config.http.host, () => {
|
||||
logger.info(`HTTP server is running at ${config.http.host}:${config.http.port}`);
|
||||
});
|
||||
|
||||
/**
|
||||
* Message broker
|
||||
*/
|
||||
rabbitmq = new RabbitMQ();
|
||||
await rabbitmq.init();
|
||||
logger.info("Connected with message broker.");
|
||||
}
|
||||
|
||||
run();
|
||||
@@ -5,12 +5,16 @@ import { Beat } from "../models/beat/beat.model.";
|
||||
import { Phone } from "../models/phone/phone.model";
|
||||
|
||||
export async function GetBeatStats(req: LivebeatRequest, res: Response) {
|
||||
const phones = await Phone.find({ user: req.user?._id });
|
||||
const phones = await Phone.find({ user: req.user?._id }).exec();
|
||||
const perPhone: any = {};
|
||||
let totalBeats = 0;
|
||||
|
||||
if (phones[0] == undefined) return;
|
||||
|
||||
const phone = phones[0];
|
||||
|
||||
for (let i = 0; i < phones.length; i++) {
|
||||
const beatCount = await Beat.countDocuments({ phone: phones[i] });
|
||||
const beatCount = await Beat.countDocuments({ [phone.id]: phone.id });
|
||||
perPhone[phones[i]._id] = {};
|
||||
perPhone[phones[i]._id] = beatCount;
|
||||
totalBeats += beatCount;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Response } from "express";
|
||||
import { logger, rabbitmq } from "../app";
|
||||
import { logger } from "../app";
|
||||
import { LivebeatRequest } from "../lib/request";
|
||||
import { Beat } from "../models/beat/beat.model.";
|
||||
import { Phone } from "../models/phone/phone.model";
|
||||
@@ -66,7 +66,7 @@ export async function PostPhone(req: LivebeatRequest, res: Response) {
|
||||
});
|
||||
|
||||
logger.info(`New device (${displayName}) registered for ${req.user?.name}.`);
|
||||
rabbitmq.publish(req.user?.id, newPhone.toJSON(), 'phone_register')
|
||||
//rabbitmq.publish(req.user?.id, newPhone.toJSON(), 'phone_register')
|
||||
|
||||
res.status(200).send();
|
||||
}
|
||||
@@ -111,7 +111,7 @@ export async function LoginUser(req: Request, res: Response) {
|
||||
}
|
||||
|
||||
// We're good. Create JWT token.
|
||||
const token = sign({ user: user._id }, JWT_SECRET, { expiresIn: '30d' });
|
||||
const token = sign({ user: user._id, type: 'frontend' }, JWT_SECRET, { expiresIn: '30d' });
|
||||
|
||||
user.lastLogin = new Date(Date.now());
|
||||
await user.save();
|
||||
@@ -120,159 +120,6 @@ export async function LoginUser(req: Request, res: Response) {
|
||||
res.status(200).send({ token });
|
||||
}
|
||||
|
||||
/**
|
||||
* This function handles all logins to RabbitMQ since they need a differnt type of response
|
||||
* then requests from frontends (web and phone).
|
||||
*/
|
||||
export async function LoginRabbitUser(req: Request, res: Response) {
|
||||
const username = req.query.username;
|
||||
const password = req.query.password;
|
||||
res.status(200);
|
||||
|
||||
if (username === undefined || password === undefined) {
|
||||
res.send('deny');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if request comes from backend. Basicly, we permitting ourself to connect with RabbitMQ.
|
||||
if (username === "backend" && password === RABBITMQ_URI.split(':')[2].split('@')[0]) {
|
||||
res.send('allow administrator');
|
||||
return;
|
||||
}
|
||||
|
||||
// Get user from database
|
||||
const user = await User.findOne({ name: username.toString() });
|
||||
|
||||
// If we are here, it means we have a non-admin user.
|
||||
if (user === null) {
|
||||
res.send('deny');
|
||||
return;
|
||||
}
|
||||
|
||||
// Auth token for message broker is stored in plain text since it's randomly generated and only grants access to the broker.
|
||||
if (user.brokerToken === password.toString()) {
|
||||
if (user.type === UserType.ADMIN) {
|
||||
res.send('allow administrator');
|
||||
} else {
|
||||
// Not an admin, grant user privilieges
|
||||
res.send('allow user')
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
res.send('deny');
|
||||
}
|
||||
|
||||
/**
|
||||
* This function basicly allows access to the root vhost if the user is known.
|
||||
*/
|
||||
export async function VHost(req: Request, res: Response) {
|
||||
const vhost = req.query.vhost;
|
||||
const username = req.query.username;
|
||||
|
||||
if (vhost === undefined || username === undefined) {
|
||||
res.status(200).send('deny');
|
||||
return;
|
||||
}
|
||||
|
||||
if (vhost != '/') {
|
||||
res.status(200).send('deny');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if user is us
|
||||
if (username === 'backend') {
|
||||
res.status(200).send('allow');
|
||||
return;
|
||||
}
|
||||
|
||||
const user = await User.findOne({ name: username.toString() });
|
||||
if (user === null) {
|
||||
// Deny if user doesn't exist.
|
||||
res.status(200).send('deny');
|
||||
} else {
|
||||
res.status(200).send('allow');
|
||||
}
|
||||
}
|
||||
|
||||
export async function Resource(req: Request, res: Response) {
|
||||
const username = req.query.username;
|
||||
const vhost = req.query.vhost;
|
||||
const resource = req.query.resource;
|
||||
const name = req.query.name;
|
||||
const permission = req.query.permission;
|
||||
const tags = req.query.tags;
|
||||
|
||||
if (username === undefined || vhost === undefined || resource === undefined || name === undefined || permission === undefined || tags === undefined) {
|
||||
res.status(200).send('deny');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if it's us
|
||||
if (username.toString() == 'backend') {
|
||||
res.status(200).send('allow');
|
||||
return;
|
||||
}
|
||||
|
||||
// Deny if not root vhost
|
||||
if (vhost.toString() != '/') {
|
||||
res.status(200).send('deny');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if user exists
|
||||
const user = await User.findOne({ name: username.toString() });
|
||||
if (user == null) {
|
||||
res.status(200).send('deny');
|
||||
return;
|
||||
}
|
||||
|
||||
if (tags.toString() == "administrator" && user.type != UserType.ADMIN) {
|
||||
res.status(200).send('deny');
|
||||
return;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
res.status(200).send('allow');
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
/**
|
||||
* This middleware validates any tokens that are required to access most of the endpoints.
|
||||
* Note: This validation doesn't contain any permission checking.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { hash, verify } from 'argon2';
|
||||
import { verify as jwtVerify } from 'jsonwebtoken';
|
||||
import { config } from '../config';
|
||||
import { IS_DEBUG, logger } from '../app';
|
||||
import { IS_DEBUG, JWT_SECRET, logger } from '../app';
|
||||
|
||||
export async function hashPassword(input: string): Promise<string> {
|
||||
const start = Date.now();
|
||||
@@ -64,9 +65,19 @@ export async function verifyPassword(password: string, hashInput: string): Promi
|
||||
});
|
||||
}
|
||||
|
||||
export function randomString(length: number): string {
|
||||
export async function verifyJWT(token: string): Promise<boolean> {
|
||||
return new Promise<boolean>(async (resolve, reject) => {
|
||||
try {
|
||||
jwtVerify(token, JWT_SECRET, { algorithms: ['HS256'] });
|
||||
resolve(true);
|
||||
} catch {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function randomString(length: number, characters: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'): string {
|
||||
let result = '';
|
||||
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
||||
const charactersLength = characters.length;
|
||||
for ( let i = 0; i < length; i++ ) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
|
||||
@@ -1,23 +1,165 @@
|
||||
import * as socketio from "socket.io";
|
||||
import { Server } from 'http';
|
||||
import { JWT_SECRET, logger } from "../app";
|
||||
import { randomString, verifyJWT } from "./crypto";
|
||||
import { decode, sign } from "jsonwebtoken";
|
||||
import { User } from "../models/user/user.model";
|
||||
import { IPhone } from "../models/phone/phone.interface";
|
||||
import { IUser } from "../models/user/user.interface";
|
||||
import { Phone } from "../models/phone/phone.model";
|
||||
|
||||
/**
|
||||
* This class handles all SocketIO connections.
|
||||
*
|
||||
* *SocketIO is another layer ontop of WebSockets*
|
||||
*/
|
||||
class SocketManager {
|
||||
export class SocketManager {
|
||||
|
||||
io: socketio.Server;
|
||||
express: Express.Application;
|
||||
|
||||
constructor (express: Express.Application) {
|
||||
this.io = new socketio.Server(express);
|
||||
this.express = express;
|
||||
/**
|
||||
* Frontends have limited access to socket.io features. They just sit in connection and wait for any events.
|
||||
*/
|
||||
frontends: Array<string>;
|
||||
|
||||
/**
|
||||
* A phone has some more privileges. They activly send new data and thus have write access.
|
||||
*/
|
||||
phones: Array<string>;
|
||||
|
||||
constructor(httpServer: Server) {
|
||||
logger.debug("Preparing real-time communication ...");
|
||||
|
||||
this.frontends = [];
|
||||
this.phones = [];
|
||||
|
||||
this.io = new socketio.Server();
|
||||
this.io.listen(httpServer);
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
getUserRoom(user: IUser) {
|
||||
return `user-${user.id}`;
|
||||
}
|
||||
|
||||
getUserFrontendRoom(user: IUser) {
|
||||
return `user-${user.id}-frontend`;
|
||||
}
|
||||
|
||||
getUserPhoneRoom(user: IUser) {
|
||||
return `user-${user.id}-phone`;
|
||||
}
|
||||
|
||||
init() {
|
||||
this.io.on('connect', data => {
|
||||
console.log('New connection')
|
||||
this.io.on('connection', socket => {
|
||||
socket.on('requestAccess', async data => {
|
||||
data = JSON.parse(data);
|
||||
|
||||
let token: string = data.token;
|
||||
let phone: IPhone = data.phone;
|
||||
|
||||
// If request is faulty or token invalid -> return.
|
||||
if (data === undefined || phone === undefined) return;
|
||||
if (await !verifyJWT(token)) return;
|
||||
|
||||
const id = decode(token, { json: true })!.user;
|
||||
const user = await User.findById(id);
|
||||
|
||||
// If user doesn't exist -> return.
|
||||
if (user === null) return;
|
||||
|
||||
const approvalCode = randomString(6, '0123456789');
|
||||
|
||||
// Create phone
|
||||
const newPhone = await Phone.create({
|
||||
...phone,
|
||||
user,
|
||||
approval: {
|
||||
code: approvalCode
|
||||
}
|
||||
});
|
||||
|
||||
this.io.to(this.getUserRoom(user)).emit('approvePhone', newPhone);
|
||||
|
||||
// Respond with id so device can later submit correct code.
|
||||
socket.emit('requestAccess', { phoneId: newPhone.id });
|
||||
|
||||
logger.info(`User ${user?.name} requests to connect new phone ${phone.displayName}`);
|
||||
});
|
||||
|
||||
socket.on('submitPairCode', async data => {
|
||||
const { phoneId, code } = JSON.parse(data);
|
||||
|
||||
console.log("Entry:", data, phoneId, code);
|
||||
|
||||
if (phoneId === undefined || code === undefined) return;
|
||||
|
||||
const phone = await Phone.findById(phoneId);
|
||||
if (phone === null) return;
|
||||
|
||||
console.log(data, phoneId, code);
|
||||
|
||||
// If provided code isn't equal with actual code -> Emit event again.
|
||||
if (phone.approval.code !== code) {
|
||||
console.log(data, phoneId, code);
|
||||
socket.emit('submitPairCode', '');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
phone.approval.approvedOn = new Date();
|
||||
await phone.save();
|
||||
|
||||
// We're good. Create JWT token.
|
||||
const token = sign({ user: phone.user._id, type: 'phone' }, JWT_SECRET, { expiresIn: '30d' });
|
||||
|
||||
socket.emit('submitPairCode', token);
|
||||
});
|
||||
|
||||
socket.on('loginFrontend', async (token: string) => {
|
||||
if (await verifyJWT(token)) {
|
||||
const tokenDecoded = decode(token, { json: true });
|
||||
const id = tokenDecoded!.user;
|
||||
const type = tokenDecoded!.type;
|
||||
const user = await User.findById(id);
|
||||
|
||||
if (user == null) return;
|
||||
if (type != 'frontend') return;
|
||||
|
||||
|
||||
if (this.frontends.indexOf(socket.id) != -1)
|
||||
this.frontends.push(socket.id);
|
||||
|
||||
socket.join(this.getUserRoom(user));
|
||||
socket.join(this.getUserFrontendRoom(user));
|
||||
|
||||
logger.info(`Socket ${socket.id} became a frontend socket.`);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('loginPhone', async (token: string) => {
|
||||
if (await verifyJWT(token)) {
|
||||
const tokenDecoded = decode(token, { json: true });
|
||||
const id = tokenDecoded!.user;
|
||||
const type = tokenDecoded!.type;
|
||||
const user = await User.findById(id);
|
||||
|
||||
if (user == null) return;
|
||||
if (type != 'phone') return;
|
||||
|
||||
if (this.frontends.indexOf(socket.id) != -1)
|
||||
this.frontends.push(socket.id);
|
||||
|
||||
socket.join(this.getUserRoom(user));
|
||||
socket.join(this.getUserPhoneRoom(user));
|
||||
|
||||
logger.info(`Socket ${socket.id} became a phone socket.`);
|
||||
}
|
||||
});
|
||||
|
||||
logger.info(`New socket connection from ${socket.handshake.address} with id ${socket.id} (total connections: ${this.io.sockets.sockets.size})`);
|
||||
socket.emit('test', 'Yay, it works.');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,14 @@ import { IUser } from '../user/user.interface';
|
||||
export interface IPhone extends Document {
|
||||
androidId: String,
|
||||
displayName: String,
|
||||
modelName: String,
|
||||
modelName: string,
|
||||
operatingSystem: String,
|
||||
architecture: String,
|
||||
user: IUser,
|
||||
active: Boolean,
|
||||
approval: {
|
||||
approvedOn?: Date,
|
||||
code: String
|
||||
},
|
||||
updatedAt?: Date,
|
||||
createdAt?: Date
|
||||
}
|
||||
@@ -8,7 +8,10 @@ const schemaPhone = new Schema({
|
||||
operatingSystem: { type: String, required: false },
|
||||
architecture: { type: String, required: false },
|
||||
user: { type: SchemaTypes.ObjectId, required: true },
|
||||
active: { type: Boolean, required: true }
|
||||
approval: {
|
||||
approvedOn: { type: Date, required: false },
|
||||
code: { type: String, required: true }
|
||||
}
|
||||
}, {
|
||||
timestamps: {
|
||||
createdAt: true,
|
||||
|
||||
@@ -12,7 +12,5 @@ export interface IUser extends Document {
|
||||
salt: string,
|
||||
type: UserType,
|
||||
lastLogin: Date,
|
||||
twoFASecret?: string,
|
||||
brokerToken: string,
|
||||
createdAt?: Date
|
||||
twoFASecret?: string
|
||||
}
|
||||
@@ -6,7 +6,6 @@ const schemaUser = new Schema({
|
||||
salt: { type: String, required: true },
|
||||
type: { type: String, required: true, default: 'user' }, // This could be user, admin, guest
|
||||
twoFASecret: { type: String, required: false },
|
||||
brokerToken: { type: String, required: true },
|
||||
lastLogin: { type: Date, required: true, default: Date.now },
|
||||
}, {
|
||||
timestamps: {
|
||||
|
||||
3810
backend/package-lock.json
generated
3810
backend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -17,10 +17,7 @@
|
||||
"author": "Mondei1",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@types/node": "^14.14.9",
|
||||
"@types/socket.io": "^2.1.13",
|
||||
"amqplib": "^0.6.0",
|
||||
"argon2": "^0.27.0",
|
||||
"argon2": "^0.28.2",
|
||||
"body-parser": "^1.19.0",
|
||||
"chalk": "^4.1.0",
|
||||
"cors": "^2.8.5",
|
||||
@@ -29,14 +26,13 @@
|
||||
"figlet": "^1.5.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"moment": "^2.29.1",
|
||||
"mongoose": "^5.10.9",
|
||||
"socket.io": "^4.0.1",
|
||||
"mongoose": "^5.13.7",
|
||||
"socket.io": "^4.3.2",
|
||||
"ts-node": "^9.0.0",
|
||||
"typescript": "^4.0.3",
|
||||
"winston": "^3.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/amqplib": "0.5.14",
|
||||
"@types/argon2": "0.15.0",
|
||||
"@types/body-parser": "1.19.0",
|
||||
"@types/chalk": "2.2.0",
|
||||
@@ -47,6 +43,8 @@
|
||||
"@types/jsonwebtoken": "8.5.0",
|
||||
"@types/moment": "2.13.0",
|
||||
"@types/mongoose": "5.7.36",
|
||||
"@types/node": "^14.14.9",
|
||||
"@types/socket.io": "^2.1.13",
|
||||
"@types/typescript": "2.0.0",
|
||||
"@types/winston": "2.4.4",
|
||||
"concurrently": "^5.3.0",
|
||||
|
||||
Reference in New Issue
Block a user