mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-02-02 12:00:10 +08:00
Add initial report quote endpoint (#2367) by Bruception
* Add initial report quote endpoint * Tune rate limiter for report quote * Tune rate limiter * Increase max comment size * Add supported languages to schema validation * Fix naming
This commit is contained in:
parent
e7a41c52b4
commit
7ce9146c7d
6 changed files with 151 additions and 0 deletions
|
@ -1,8 +1,11 @@
|
|||
const joi = require("joi");
|
||||
const { authenticateRequest } = require("../../middlewares/auth");
|
||||
const { Router } = require("express");
|
||||
const NewQuotesController = require("../controllers/new-quotes");
|
||||
const QuoteRatingsController = require("../controllers/quote-ratings");
|
||||
const RateLimit = require("../../middlewares/rate-limit");
|
||||
const { requestValidation } = require("../../middlewares/apiUtils");
|
||||
const SUPPORTED_QUOTE_LANGUAGES = require("../../constants/quoteLanguages");
|
||||
|
||||
const quotesRouter = Router();
|
||||
|
||||
|
@ -48,4 +51,31 @@ quotesRouter.post(
|
|||
QuoteRatingsController.submitRating
|
||||
);
|
||||
|
||||
quotesRouter.post(
|
||||
"/report",
|
||||
RateLimit.quoteReportSubmit,
|
||||
authenticateRequest,
|
||||
requestValidation({
|
||||
body: {
|
||||
quoteId: joi.string().required(),
|
||||
quoteLanguage: joi
|
||||
.string()
|
||||
.valid(...SUPPORTED_QUOTE_LANGUAGES)
|
||||
.required(),
|
||||
reason: joi
|
||||
.string()
|
||||
.valid(
|
||||
"Grammatical error",
|
||||
"Inappropriate content",
|
||||
"Low quality content"
|
||||
)
|
||||
.required(),
|
||||
comment: joi.string().allow("").max(250).required(),
|
||||
},
|
||||
}),
|
||||
(req, res) => {
|
||||
res.sendStatus(200);
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = quotesRouter;
|
||||
|
|
37
backend/constants/quoteLanguages.js
Normal file
37
backend/constants/quoteLanguages.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
const SUPPORTED_QUOTE_LANGUAGES = [
|
||||
"albanian",
|
||||
"arabic",
|
||||
"code_c++",
|
||||
"code_c",
|
||||
"code_java",
|
||||
"code_javascript",
|
||||
"code_python",
|
||||
"code_rust",
|
||||
"czech",
|
||||
"danish",
|
||||
"dutch",
|
||||
"english",
|
||||
"filipino",
|
||||
"french",
|
||||
"german",
|
||||
"hindi",
|
||||
"icelandic",
|
||||
"indonesian",
|
||||
"irish",
|
||||
"italian",
|
||||
"lithuanian",
|
||||
"malagasy",
|
||||
"polish",
|
||||
"portuguese",
|
||||
"russian",
|
||||
"serbian",
|
||||
"slovak",
|
||||
"spanish",
|
||||
"swedish",
|
||||
"thai",
|
||||
"toki_pona",
|
||||
"turkish",
|
||||
"vietnamese",
|
||||
];
|
||||
|
||||
module.exports = SUPPORTED_QUOTE_LANGUAGES;
|
32
backend/middlewares/apiUtils.js
Normal file
32
backend/middlewares/apiUtils.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
const joi = require("joi");
|
||||
const MonkeyError = require("../handlers/error");
|
||||
|
||||
function requestValidation(validationSchema) {
|
||||
return (req, res, next) => {
|
||||
// In dev environments, as an alternative to token authentication,
|
||||
// you can pass the authentication middleware by having a user id in the body.
|
||||
// Inject the user id into the schema so that validation will not fail.
|
||||
if (process.env.MODE === "dev") {
|
||||
validationSchema.body = {
|
||||
uid: joi.any(),
|
||||
...(validationSchema.body ?? {}),
|
||||
};
|
||||
}
|
||||
|
||||
Object.keys(validationSchema).forEach((key) => {
|
||||
const schema = validationSchema[key];
|
||||
const joiSchema = joi.object().keys(schema);
|
||||
const { error } = joiSchema.validate(req[key] ?? {});
|
||||
if (error) {
|
||||
const errorMessage = error.details[0].message;
|
||||
throw new MonkeyError(400, `Invalid request: ${errorMessage}`);
|
||||
}
|
||||
});
|
||||
|
||||
next();
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
requestValidation,
|
||||
};
|
|
@ -68,6 +68,14 @@ exports.quoteRatingsSubmit = rateLimit({
|
|||
keyGenerator: getAddress,
|
||||
});
|
||||
|
||||
// Quote reporting
|
||||
exports.quoteReportSubmit = rateLimit({
|
||||
windowMs: 30 * 60 * 1000, // 30 min
|
||||
max: 50 * multiplier,
|
||||
message,
|
||||
keyGenerator: getAddress,
|
||||
});
|
||||
|
||||
// Presets Routing
|
||||
exports.presetsGet = rateLimit({
|
||||
windowMs: 60 * 60 * 1000, // 60 min
|
||||
|
|
43
package-lock.json
generated
43
package-lock.json
generated
|
@ -1735,6 +1735,19 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"@hapi/hoek": {
|
||||
"version": "9.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz",
|
||||
"integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw=="
|
||||
},
|
||||
"@hapi/topo": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz",
|
||||
"integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==",
|
||||
"requires": {
|
||||
"@hapi/hoek": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"@humanwhocodes/config-array": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
|
||||
|
@ -2005,6 +2018,24 @@
|
|||
"integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=",
|
||||
"optional": true
|
||||
},
|
||||
"@sideway/address": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.3.tgz",
|
||||
"integrity": "sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ==",
|
||||
"requires": {
|
||||
"@hapi/hoek": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"@sideway/formula": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz",
|
||||
"integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg=="
|
||||
},
|
||||
"@sideway/pinpoint": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz",
|
||||
"integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ=="
|
||||
},
|
||||
"@sindresorhus/is": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
|
||||
|
@ -7813,6 +7844,18 @@
|
|||
"integrity": "sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==",
|
||||
"dev": true
|
||||
},
|
||||
"joi": {
|
||||
"version": "17.6.0",
|
||||
"resolved": "https://registry.npmjs.org/joi/-/joi-17.6.0.tgz",
|
||||
"integrity": "sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==",
|
||||
"requires": {
|
||||
"@hapi/hoek": "^9.0.0",
|
||||
"@hapi/topo": "^5.0.0",
|
||||
"@sideway/address": "^4.1.3",
|
||||
"@sideway/formula": "^3.0.0",
|
||||
"@sideway/pinpoint": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"jose": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/jose/-/jose-2.0.5.tgz",
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
"gulp-replace": "^1.1.3",
|
||||
"helmet": "^4.6.0",
|
||||
"howler": "^2.2.1",
|
||||
"joi": "^17.6.0",
|
||||
"moment-timezone": "^0.5.33",
|
||||
"mongodb": "^3.6.9",
|
||||
"node-fetch": "^2.6.7",
|
||||
|
|
Loading…
Reference in a new issue