Adding new query handler

This commit is contained in:
Fabian 2019-11-04 14:17:04 +01:00
parent 68011e3866
commit 9f944549b6
5 changed files with 91 additions and 63 deletions

3
.editorconfig Normal file
View File

@ -0,0 +1,3 @@
charset = utf-8
indent_size = 3
indent_style = space

6
package-lock.json generated
View File

@ -122,12 +122,6 @@
"integrity": "sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ==", "integrity": "sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ==",
"dev": true "dev": true
}, },
"@types/ini": {
"version": "1.3.30",
"resolved": "https://registry.npmjs.org/@types/ini/-/ini-1.3.30.tgz",
"integrity": "sha512-2+iF8zPSbpU83UKE+PNd4r/MhwNAdyGpk3H+VMgEH3EhjFZq1kouLgRoZrmIcmoGX97xFvqdS44DkICR5Nz3tQ==",
"dev": true
},
"@types/jsonwebtoken": { "@types/jsonwebtoken": {
"version": "8.3.5", "version": "8.3.5",
"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.3.5.tgz", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.3.5.tgz",

View File

@ -19,6 +19,21 @@ async function verifyJWT(token: string, publicKey: string) {
}) })
} }
const StoreSym = Symbol("store");
function StoreQuery(result?: any) {
return {
[StoreSym]: true,
result
}
}
function DeleteQuery(result?: any) {
return {
[StoreSym]: false,
result
}
}
import { URLSearchParams } from "url"; import { URLSearchParams } from "url";
type QueryTypes = "keys" | "get" | "set" | "update" | "delete" | "push" | "subscribe" | "unsubscribe"; type QueryTypes = "keys" | "get" | "set" | "update" | "delete" | "push" | "subscribe" | "unsubscribe";
@ -84,68 +99,85 @@ export class ConnectionManager {
const handler = new Map<string, ((data: any) => void)>(); const handler = new Map<string, ((data: any) => void)>();
type QueryData = { id: string, type: QueryTypes, path: string[], data: any, options: any }; type QueryData = { id: string, type: QueryTypes, path: string[], data: any, options: any };
const queryHandler = new Map<string, (query: Query, permissions: { read: boolean, write: boolean }, data?: any) => Promise<any>>();
const noperm = new Error("No permisison!");
queryHandler.set("keys", (query, perm, data) => {
if (!perm.read)
throw noperm;
return query.keys();
})
queryHandler.set("get", (query, perm, data) => {
if (!perm.read)
throw noperm;
return query.get();
})
queryHandler.set("set", (query, perm, data) => {
if (!perm.write)
throw noperm;
return query.set(data, {});
})
queryHandler.set("update", (query, perm, data) => {
if (!perm.write)
throw noperm;
return query.update(data);
})
queryHandler.set("delete", (query, perm, data) => {
if (!perm.write)
throw noperm;
return query.delete();
})
queryHandler.set("subscribe", async (query, perm, data) => {
if (!perm.read)
throw noperm;
let subscriptionID = shortid.generate();
query.subscribe((data) => {
socket.send(JSON.stringify({ ns: "event", data: { id: subscriptionID, data } }));
}, data.types, data.options);
return StoreQuery(subscriptionID);
})
queryHandler.set("unsubscribe", async (query, perm, data) => {
query.unsubscribe();
return DeleteQuery(true);
})
handler.set("query", async ({ id, type, path, data }: QueryData) => { handler.set("query", async ({ id, type, path, data }: QueryData) => {
//TODO: Handle case with no id, type, path //TODO: Handle case with no id, type, path
Logging.debug(`Request with id '${id}' from type '${type}' and path '${path}' with data`, data) Logging.debug(`Request with id '${id}' from type '${type}' and path '${path}' with data`, data)
try { try {
const perms = db.rules.hasPermission(path, session);
const noperm = new Error("No permisison!");
if (!db) if (!db)
answer(id, "Database not found!", true); throw new Error("Database not found!");
else { else {
const query = stored.get(id) || db.getQuery(path, session.sessionid); let handler = queryHandler.get(type);
if (!handler) {
throw new Error("Invalid Request!");
} else {
const query = stored.get(id) || db.getQuery(path || [], session.sessionid);
const perms = db.rules.hasPermission(path, session);
switch (type) { let res = await handler(query, perms, data);
case "keys": if (res[StoreSym] !== undefined) {
if (!perms.read) if (res[StoreSym])
throw noperm; stored.set(id, query);
answer(id, await query.keys()); else
return; stored.delete(id);
case "get": }
if (!perms.read) answer(id, res);
throw noperm;
answer(id, await query.get());
return;
case "set":
if (!perms.write)
throw noperm;
answer(id, await query.set(data, {}));
return;
case "update":
if (!perms.write)
throw noperm;
answer(id, await query.update(data));
return;
case "delete":
if (!perms.write)
throw noperm;
answer(id, await query.delete());
return;
case "push":
if (!perms.write)
throw noperm;
answer(id, await query.push(data));
return;
case "subscribe":
if (!perms.read)
throw noperm;
let subscriptionID = shortid.generate();
query.subscribe((data) => {
socket.send(JSON.stringify({ ns: "event", data: { id: subscriptionID, data } }));
}, data.types, data.options);
stored.set(id, query);
answer(id, subscriptionID);
return;
case "unsubscribe":
query.unsubscribe();
stored.delete(id);
answer(id, true);
return;
} }
answer(id, "Invalid request!", true);
} }
} catch (err) { } catch (err) {
Logging.error(err); Logging.error(err);

View File

@ -1,6 +1,5 @@
import { Database, Change, ChangeTypes } from "./database"; import { Database, Change, ChangeTypes } from "./database";
import { resNull, LevelDB } from "../storage"; import { resNull } from "../storage";
import { LevelUpChain } from "levelup";
import shortid = require("shortid"); import shortid = require("shortid");
import Logging from "@hibas123/nodelogging"; import Logging from "@hibas123/nodelogging";
import * as MSGPack from "what-the-pack"; import * as MSGPack from "what-the-pack";