diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..99cd0f5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,3 @@ +charset = utf-8 +indent_size = 3 +indent_style = space \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 29eb7b2..13f48dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -122,12 +122,6 @@ "integrity": "sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ==", "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": { "version": "8.3.5", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.3.5.tgz", diff --git a/package.json b/package.json index 7e3e8f3..6d98c2a 100644 --- a/package.json +++ b/package.json @@ -44,4 +44,4 @@ "what-the-pack": "^2.0.3", "ws": "^7.2.0" } -} \ No newline at end of file +} diff --git a/src/connection.ts b/src/connection.ts index ce30c2c..15e0de4 100644 --- a/src/connection.ts +++ b/src/connection.ts @@ -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"; type QueryTypes = "keys" | "get" | "set" | "update" | "delete" | "push" | "subscribe" | "unsubscribe"; @@ -84,68 +99,85 @@ export class ConnectionManager { const handler = new Map void)>(); type QueryData = { id: string, type: QueryTypes, path: string[], data: any, options: any }; + + const queryHandler = new Map Promise>(); + + 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) => { //TODO: Handle case with no id, type, path Logging.debug(`Request with id '${id}' from type '${type}' and path '${path}' with data`, data) + + + try { - const perms = db.rules.hasPermission(path, session); - const noperm = new Error("No permisison!"); if (!db) - answer(id, "Database not found!", true); + throw new Error("Database not found!"); 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) { - case "keys": - if (!perms.read) - throw noperm; - answer(id, await query.keys()); - return; - case "get": - if (!perms.read) - 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; + let res = await handler(query, perms, data); + if (res[StoreSym] !== undefined) { + if (res[StoreSym]) + stored.set(id, query); + else + stored.delete(id); + } + answer(id, res); } - - answer(id, "Invalid request!", true); } } catch (err) { Logging.error(err); diff --git a/src/database/query.ts b/src/database/query.ts index fb32ed5..62c9825 100644 --- a/src/database/query.ts +++ b/src/database/query.ts @@ -1,6 +1,5 @@ import { Database, Change, ChangeTypes } from "./database"; -import { resNull, LevelDB } from "../storage"; -import { LevelUpChain } from "levelup"; +import { resNull } from "../storage"; import shortid = require("shortid"); import Logging from "@hibas123/nodelogging"; import * as MSGPack from "what-the-pack";