From 83f1253f42a5c895d23788913f3039d903927bdd Mon Sep 17 00:00:00 2001 From: Bruce Berrios <58147810+Bruception@users.noreply.github.com> Date: Thu, 3 Feb 2022 14:26:34 -0500 Subject: [PATCH] Add config schema (#2401) by Bruception * Add config schema * Change schema * Fix custom validator * Relax schema * add result filters schema * Remove result filters * Fix quoteLength schema --- backend/api/routes/config.js | 12 +++- backend/api/schemas/config-schema.js | 103 +++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 backend/api/schemas/config-schema.js diff --git a/backend/api/routes/config.js b/backend/api/routes/config.js index 7608e3d06..235bccdf5 100644 --- a/backend/api/routes/config.js +++ b/backend/api/routes/config.js @@ -1,11 +1,12 @@ -const { authenticateRequest } = require("../../middlewares/auth"); const { Router } = require("express"); -const ConfigController = require("../controllers/config"); -const RateLimit = require("../../middlewares/rate-limit"); +const { authenticateRequest } = require("../../middlewares/auth"); const { asyncHandlerWrapper, requestValidation, } = require("../../middlewares/api-utils"); +const configSchema = require("../schemas/config-schema"); +const ConfigController = require("../controllers/config"); +const RateLimit = require("../../middlewares/rate-limit"); const router = Router(); @@ -20,6 +21,11 @@ router.post( "/save", RateLimit.configUpdate, authenticateRequest, + requestValidation({ + body: { + config: configSchema, + }, + }), asyncHandlerWrapper(ConfigController.saveConfig) ); diff --git a/backend/api/schemas/config-schema.js b/backend/api/schemas/config-schema.js new file mode 100644 index 000000000..464e55d12 --- /dev/null +++ b/backend/api/schemas/config-schema.js @@ -0,0 +1,103 @@ +const _ = require("lodash"); +const joi = require("joi"); + +const CARET_STYLES = [ + "off", + "default", + "underline", + "outline", + "block", + "carrot", + "banana", +]; + +const CONFIG_SCHEMA = joi.object({ + theme: joi.string(), + customTheme: joi.boolean(), + customThemeColors: joi + .array() + .items(joi.string().pattern(/^#[A-Fa-f0-9]{6}$/)) + .length(9), + favThemes: joi.array().items(joi.string()), + showKeyTips: joi.boolean(), + showLiveWpm: joi.boolean(), + showTimerProgress: joi.boolean(), + smoothCaret: joi.boolean(), + quickTab: joi.boolean(), + punctuation: joi.boolean(), + numbers: joi.boolean(), + words: joi.number().min(0), + time: joi.number().min(0), + mode: joi.string().valid("time", "words", "quote", "zen", "custom"), + quoteLength: joi.array().items(joi.number()), + language: joi.string(), + fontSize: joi.number().valid(1, 125, 15, 2, 3, 4), + freedomMode: joi.boolean(), + difficulty: joi.string().valid("normal", "expert", "master"), + blindMode: joi.boolean(), + quickEnd: joi.boolean(), + caretStyle: joi.string().valid(...CARET_STYLES), + paceCaretStyle: joi.string().valid(...CARET_STYLES), + flipTestColors: joi.boolean(), + layout: joi.string(), + funbox: joi.string(), + confidenceMode: joi.string().valid("off", "on", "max"), + indicateTypos: joi.boolean(), + timerStyle: joi.string().valid("bar", "text", "mini"), + colorfulMode: joi.boolean(), + randomTheme: joi.string().valid("off", "on", "favorite", "light", "dark"), + timerColor: joi.string().valid("black", "sub", "text", "main"), + timerOpacity: joi.number().valid(0.25, 0.5, 0.75, 1), + stopOnError: joi.string().valid("off", "word", "letter"), + showAllLines: joi.boolean(), + keymapMode: joi.string().valid("off", "static", "react", "next"), + keymapStyle: joi + .string() + .valid("staggered", "alice", "matrix", "split", "split_matrix"), + keymapLegendStyle: joi.string().valid("lowercase", "uppercase", "blank"), + keymapLayout: joi.string().valid(), + fontFamily: joi.string(), + smoothLineScroll: joi.boolean(), + alwaysShowDecimalPlaces: joi.boolean(), + alwaysShowWordsHistory: joi.boolean(), + singleListCommandLine: joi.string().valid("manual", "on"), + capsLockWarning: joi.boolean(), + playSoundOnError: joi.boolean(), + playSoundOnClick: joi.string().valid("off", ..._.range(1, 8).map(_.toString)), + soundVolume: joi.string().valid("0.1", "0.5", "1.0"), + startGraphsAtZero: joi.boolean(), + swapEscAndTab: joi.boolean(), + showOutOfFocusWarning: joi.boolean(), + paceCaret: joi.string().valid("off", "average", "pb", "custom"), + paceCaretCustomSpeed: joi.number().min(0), + repeatedPace: joi.boolean(), + pageWidth: joi.string().valid("100", "125", "150", "200", "max"), + chartAccuracy: joi.boolean(), + chartStyle: joi.string().valid("line", "scatter"), + minWpm: joi.string().valid("off", "custom"), + minWpmCustomSpeed: joi.number().min(0), + highlightMode: joi.string().valid("off", "letter", "word"), + alwaysShowCPM: joi.boolean(), + enableAds: joi.string().valid("off", "on", "max"), + hideExtraLetters: joi.boolean(), + strictSpace: joi.boolean(), + minAcc: joi.string().valid("off", "custom"), + minAccCustom: joi.number().min(0), + showLiveAcc: joi.boolean(), + showLiveBurst: joi.boolean(), + monkey: joi.boolean(), + repeatQuotes: joi.string().valid("off", "typing"), + oppositeShiftMode: joi.string().valid("off", "on", "keymap"), + customBackground: joi.string().uri().allow(""), + customBackgroundSize: joi.string().valid("cover", "contain", "max"), + customBackgroundFilter: joi.array().items(joi.number()), + customLayoutfluid: joi.string(), + monkeyPowerLevel: joi.string().valid("off", "1", "2", "3", "4"), + minBurst: joi.string().valid("off", "fixed", "flex"), + minBurstCustomSpeed: joi.number().min(0), + burstHeatmap: joi.boolean(), + britishEnglish: joi.boolean(), + lazyMode: joi.boolean(), +}); + +module.exports = CONFIG_SCHEMA;