Adding new query handler
This commit is contained in:
		
							
								
								
									
										3
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
charset = utf-8
 | 
			
		||||
indent_size = 3
 | 
			
		||||
indent_style = space
 | 
			
		||||
							
								
								
									
										6
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -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",
 | 
			
		||||
 | 
			
		||||
@ -44,4 +44,4 @@
 | 
			
		||||
    "what-the-pack": "^2.0.3",
 | 
			
		||||
    "ws": "^7.2.0"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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<string, ((data: any) => void)>();
 | 
			
		||||
      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) => {
 | 
			
		||||
         //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);
 | 
			
		||||
 | 
			
		||||
@ -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";
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user