2019-09-18 19:54:28 +00:00
|
|
|
import * as io from "socket.io";
|
|
|
|
import { Server } from "http";
|
|
|
|
import { DatabaseManager } from "./database/database";
|
|
|
|
import Logging from "@hibas123/logging";
|
2019-09-19 14:24:35 +00:00
|
|
|
import Query from "./database/query";
|
|
|
|
import Session from "./database/session";
|
2019-10-01 16:24:26 +00:00
|
|
|
import shortid = require("shortid");
|
2019-09-18 19:54:28 +00:00
|
|
|
|
|
|
|
type QueryTypes = "get" | "set" | "push" | "subscribe" | "unsubscribe";
|
|
|
|
|
|
|
|
export class ConnectionManager {
|
|
|
|
static server: io.Server;
|
2019-09-19 14:24:35 +00:00
|
|
|
|
2019-09-18 19:54:28 +00:00
|
|
|
static bind(server: Server) {
|
|
|
|
this.server = io(server);
|
|
|
|
this.server.on("connection", this.onConnection.bind(this));
|
|
|
|
}
|
|
|
|
|
|
|
|
private static onConnection(socket: io.Socket) {
|
2019-10-01 16:24:26 +00:00
|
|
|
Logging.debug("New Connection:", socket.id);
|
2019-09-18 19:54:28 +00:00
|
|
|
const reqMap = new Map<string, [number, number]>();
|
2019-09-19 14:24:35 +00:00
|
|
|
const stored = new Map<string, Query>();
|
|
|
|
const session = new Session();
|
|
|
|
|
2019-09-18 19:54:28 +00:00
|
|
|
const answer = (id: string, data: any, err: boolean = false) => {
|
|
|
|
let time = process.hrtime(reqMap.get(id));
|
2019-09-19 14:24:35 +00:00
|
|
|
reqMap.delete(id);
|
|
|
|
// Logging.debug(`Sending answer for ${id} with data`, data, err ? "as error" : "", "Took", time[1] / 1000, "us");
|
2019-09-18 19:54:28 +00:00
|
|
|
socket.emit("message", id, err, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
socket.on("login", (id: string) => {
|
|
|
|
//TODO: implement
|
|
|
|
})
|
|
|
|
|
|
|
|
socket.on("query", async (id: string, type: QueryTypes, database: string, path: string[], data: any) => {
|
2019-09-19 14:24:35 +00:00
|
|
|
Logging.debug(`Request with id '${id}' from type '${type}' for database '${database}' and path '${path}' with data`, data)
|
2019-09-18 19:54:28 +00:00
|
|
|
reqMap.set(id, process.hrtime());
|
|
|
|
try {
|
|
|
|
const db = DatabaseManager.getDatabase(database);
|
2019-09-19 14:24:35 +00:00
|
|
|
const perms = db.rules.hasPermission(path, session);
|
|
|
|
const noperm = new Error("No permisison!");
|
2019-09-18 19:54:28 +00:00
|
|
|
if (!db)
|
|
|
|
answer(id, "Database not found!", true);
|
|
|
|
else {
|
2019-09-19 14:24:35 +00:00
|
|
|
const query = stored.get(id) || db.getQuery(path);
|
2019-09-18 19:54:28 +00:00
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case "get":
|
2019-09-19 14:24:35 +00:00
|
|
|
if (!perms.read)
|
|
|
|
throw noperm;
|
2019-09-18 19:54:28 +00:00
|
|
|
answer(id, await query.get());
|
2019-09-19 14:24:35 +00:00
|
|
|
return;
|
2019-09-18 19:54:28 +00:00
|
|
|
case "set":
|
2019-09-19 14:24:35 +00:00
|
|
|
if (!perms.write)
|
|
|
|
throw noperm;
|
2019-09-18 19:54:28 +00:00
|
|
|
answer(id, await query.set(data));
|
2019-09-19 14:24:35 +00:00
|
|
|
return;
|
2019-09-18 19:54:28 +00:00
|
|
|
case "push":
|
2019-09-19 14:24:35 +00:00
|
|
|
if (!perms.write)
|
|
|
|
throw noperm;
|
2019-09-18 19:54:28 +00:00
|
|
|
answer(id, await query.push(data));
|
2019-09-19 14:24:35 +00:00
|
|
|
return;
|
2019-09-18 19:54:28 +00:00
|
|
|
case "subscribe":
|
2019-09-19 14:24:35 +00:00
|
|
|
if (!perms.read)
|
|
|
|
throw noperm;
|
2019-10-01 16:24:26 +00:00
|
|
|
|
|
|
|
let subscriptionID = shortid.generate();
|
|
|
|
|
2019-09-19 14:24:35 +00:00
|
|
|
query.subscribe(data, (data) => {
|
2019-10-01 16:24:26 +00:00
|
|
|
socket.emit("event", subscriptionID, data);
|
2019-09-19 14:24:35 +00:00
|
|
|
});
|
|
|
|
stored.set(id, query);
|
2019-10-01 16:24:26 +00:00
|
|
|
answer(id, subscriptionID);
|
2019-09-19 14:24:35 +00:00
|
|
|
return;
|
2019-09-18 19:54:28 +00:00
|
|
|
case "unsubscribe":
|
2019-09-19 14:24:35 +00:00
|
|
|
query.unsubscribe();
|
|
|
|
stored.delete(id);
|
2019-10-01 16:24:26 +00:00
|
|
|
answer(id, true);
|
2019-09-19 14:24:35 +00:00
|
|
|
return;
|
2019-09-18 19:54:28 +00:00
|
|
|
}
|
|
|
|
|
2019-09-19 14:24:35 +00:00
|
|
|
answer(id, "Invalid request!", true);
|
2019-09-18 19:54:28 +00:00
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
Logging.error(err);
|
|
|
|
answer(id, err.message, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
socket.on("disconnect", () => {
|
2019-09-19 14:24:35 +00:00
|
|
|
reqMap.clear();
|
|
|
|
stored.clear();
|
|
|
|
socket.removeAllListeners();
|
2019-09-18 19:54:28 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|