Open github-actions[bot] opened 4 years ago
Rate limiting of routes to prevent excessive FS access
https://github.com/Gum-Joe/2Keys/blob/d854e718e954180c637e7e7c7406622effb93c89/packages/@twokeys/server/src/routes/api.ts#L46
*/ import { Router } from "express"; import { readFile } from "fs"; import { join } from "path"; import YAML from "yaml"; import { ProjectConfig } from "@twokeys/core/lib/interfaces"; import { loadMainConfig } from "@twokeys/core/lib/config"; import { TWOKEYS_MAIN_CONFIG_DEFAULT_PATH } from "@twokeys/core/lib/constants"; import { AddOnsRegistry } from "@twokeys/addons"; import { loadDetectors } from "../loaders/loadDetectors"; import { loadExecutors } from "../loaders/loadExecutors"; import getTriggerHotkey from "./triggerHotkey"; import { Logger } from "@twokeys/core"; const logger: Logger = new Logger({ name: "api", }); const router = Router(); /** * Needed so we can use async/await */ // TODO: Rate limiting of routes to prevent excessive FS access // TODO: Remove deprecated routes export default async function getAPI(projectConfig: ProjectConfig, projectDir: string): Promise<Router> { logger.info("Preparing server..."); // 1: Load config // TODO: Watch for changes to project and reload everything logger.info("Loading root config..."); const mainConfig = await loadMainConfig(TWOKEYS_MAIN_CONFIG_DEFAULT_PATH); logger.info("Loading add-ons..."); const registry = new AddOnsRegistry(mainConfig.registry_root); // Load add-ons & run startup functions for detectors const detectors = await loadDetectors(projectConfig, projectDir, registry); const executors = await loadExecutors(registry, projectDir); /** * Returns to config for the 2Keys project */ router.get("/get/config/project", (req, res) => { logger.info("Sending a config copy as JSON..."); // We can rely on hot reload to ensure it is accurate res.statusCode = 200; res.json(projectConfig); }); /** * Returns config for a detector */ router.get("/get/config/detectors/:detector", (req, res) => { const detectorToGet = req. params.detector; logger.info(`Requested config for detector ${detectorToGet}`); if (detectors.has(detectorToGet)) { res.statusCode = 200; res.json(detectors.get(detectorToGet)); } else { logger.info(`${detectorToGet} not found!`); res.statusCode = 404; res.json({ message: "Not Found" }); } }); /** * Returns the config for the 2Keys project * @deprecated */ router.get("/get/deprecated/config", (req, res, next) => { logger.debug("Sending a config copy as JSON..."); logger.warn("/get/config is deprecated."); readFile(join(process.cwd(), "config.yml"), (err, data) => { if (err) { return next(err); } const data_to_send = JSON.stringify(YAML.parse(data.toString())); res.setHeader("Content-Type", "application/json"); res.statusCode = 200; res.send(data_to_send); }); }); /** * Trigger a hotkey * * Provide these property: * ```json * { * "hotkey": "^A" // hotkey code to find in keyboard * "event": "up" | "down" | "hold" // OPTIONAL event type * } * ``` */ router.post("/post/trigger/:detector/:keyboard", getTriggerHotkey(detectors, executors)); /** * Trigger a hotkey * Info to send: * - keyboard: The keyboard name that has been pressed * - hotkey: set of keys that have been pressed * @deprecated */ /*router.post("/post/depreacted/trigger", async (req, res, next) => {*/ /** * 1: Get hotkey function from config * 2: Execute C++ bindings with #Include <root of keyboard>; function() */ // Get vars /*const keyboard = req.body.keyboard; const hotkey_code = req.body.hotkey; const value: EvDevValues = Object.prototype.hasOwnProperty.call(req.body, "value") ? req.body.value : EvDevValues.Down; logger.debug(`Got keyboard ${keyboard} and hotkey ${hotkey_code}, with value ${value}`); // Parse config try { const fetched_hotkey = await fetch_hotkey(keyboard, hotkey_code); // Gets hotkey let func_to_run: string; // Use the value arg to select if (typeof fetched_hotkey.func === "object") { // Is an object logger.debug("Got a multi event hotkey."); // Select which function to run if (value === EvDevValues.Down) { func_to_run = fetched_hotkey.func.down; } else if (value === EvDevValues.Up) { func_to_run = fetched_hotkey.func.up; } else { // Stop exec as and error was encountered return next(new TypeError(`The request keyboard event value of ${value} is invalid. Valid event values are: 0 (Up) & 1 (Down)`)); } // Validate a function actually exists if (typeof func_to_run === "undefined") { // Ignore logger.warn(`Ignoring hotkey ${hotkey_code} of value ${value}, as no function to run exists`); res.statusCode = 404; res.send("Hotkey function not found"); return; } } else { func_to_run = fetched_hotkey.func; } // Execute run_hotkey(fetched_hotkey.file, func_to_run); res.statusCode = 200; res.send("OK"); } catch (err) { next(err); // Hand off to error handler } });*/ /** * Handles keyboard path update */ // TODO: Update this route to use whatever new method for config updates we decide on /*router.post("/post/update-keyboard-path", (req, res, next) => { const { keyboard, path } = req.body; logger.info(`Got update for ${keyboard}, path ${path}`); config_loader() .then((config) => { // Make changes config.keyboards[keyboard].path = path; // Write logger.debug("Writing config..."); writeFile(CONFIG_FILE, YAML.stringify(config), (err) => { if (err) { return next(err); } else { res.statusCode = 200; res.send("OK"); } res.end(); }); }); });*/ return router; } ew file mode 100644 ndex 0000000..58072f4 ++ b/packages/@twokeys/server/src/routes/triggerHotkey.ts
7f1bce620b368d6e7c333b8b3092040c1265b84d
Rate limiting of routes to prevent excessive FS access
https://github.com/Gum-Joe/2Keys/blob/d854e718e954180c637e7e7c7406622effb93c89/packages/@twokeys/server/src/routes/api.ts#L46
7f1bce620b368d6e7c333b8b3092040c1265b84d