diff --git a/APIDOCS.md b/APIDOCS.md index a499cd9..56c04e9 100644 --- a/APIDOCS.md +++ b/APIDOCS.md @@ -13,7 +13,7 @@ You need this headers for send request to API: ``` But in front end, the API will works with session. -## Limits: +## Default Limits: - 3 - 25 char for username, password and category name - 256 char for user about and desp of category - 5 - 128 char for thread titles. diff --git a/config.json b/config.json index 5eecc31..7d1d9ea 100644 --- a/config.json +++ b/config.json @@ -1,5 +1,16 @@ { "def_theme": "default", "forum_name": "akf", - "description": "Akf-forum!" + "description": "Akf-forum!", + "limits": { + "title": 128, + "message": 1024, + "names": 25, + "desp": 256 + }, + "global_ratelimit":{ + "enabled": true, + "max": 25, + "windowMs": 60000 + } } \ No newline at end of file diff --git a/index.js b/index.js index 0f92cca..c386ab5 100644 --- a/index.js +++ b/index.js @@ -4,7 +4,7 @@ const { urlencoded: BP } = require('body-parser'), SES = require('express-session'); const - { def_theme, forum_name, description } = require("./config.json"), + { def_theme, forum_name, description, limits, global_ratelimit: RLS } = require("./config.json"), { UserModel, BanModel } = require("./models"), port = process.env.PORT || 3000, mongoose = require("mongoose"), @@ -19,8 +19,9 @@ mongoose.connect(process.env.MONGO_DB_URL, async () => console.log("Database is connected with", (app.ips = await BanModel.find({})).length, "banned IPs")); app.set("view engine", "ejs"); +app.set("limits", limits); -app.use(express.static("public"), express.json(), IP(), +app.use(express.static("public"), express.json(), IP(), SES({ secret: 'secret', resave: true, saveUninitialized: true }), async (req, res, next) => { if (app.ips.includes(req.clientIp)) return res.status(403).send("You are banned from this forum."); @@ -38,12 +39,12 @@ app.use(express.static("public"), express.json(), IP(), return res.error(403, "Your account has been deleted."); } next(); - }, RL({ - windowMs: 60_000, max: 20, - handler: (req, res, next, opts) => !req.user?.admin ? res.error(opts.statusCode, "You are begin ratelimited") : next() - }), BP({ extended: true }) + }, BP({ extended: true }) ); +if (RLS.enabled) + app.use(RL({ ...RLS, handler: (req, res, next, opts) => !req.user?.admin ? res.error(opts.statusCode, "You are begin ratelimited") : next() })); + for (const file of fs.readdirSync("./routes")) app.use("/" + file.replace(".js", ""), require(`./routes/${file}`)); diff --git a/routes/api/routes/messages.js b/routes/api/routes/messages.js index 345be88..b119dfc 100644 --- a/routes/api/routes/messages.js +++ b/routes/api/routes/messages.js @@ -27,7 +27,9 @@ app.patch("/:id/", async (req, res) => { if (user.id !== message.authorID && !user.admin) return res.error(403, "You have not got permission for this."); const { content = null } = req.body; if (!content) return res.error(400, "Missing message content in request body."); - if (content.length < 5 || content.length > 1024) return res.error(400, "content must be between 5 - 1024 characters"); + + const limits = req.app.get("limits"); + if (content.length < 5 || content.length > limits.message) return res.error(400, "content must be between 5 - 1024 characters"); message.content = content; message.edited = true; @@ -45,7 +47,9 @@ app.post("/", rateLimit({ const { threadID, content } = req.body; if (!content) return res.error(400, "Missing message content in request body."); - if (content.length < 5 || content.length > 1024) return res.error(400, "content must be between 5 - 1024 characters"); + const limits = req.app.get("limits"); + + if (content.length < 5 || content.length > limits.message) return res.error(400, "content must be between 5 - 1024 characters"); const thread = await ThreadModel.get(threadID); diff --git a/routes/api/routes/threads.js b/routes/api/routes/threads.js index d0a5f1c..c668c24 100644 --- a/routes/api/routes/threads.js +++ b/routes/api/routes/threads.js @@ -41,8 +41,10 @@ app.post("/", async (req, res) => { const { title, content, category } = req.body; if (!content || !title) return res.error(400, "Missing content/title in request body."); - if (title.length < 5 || title.length > 128) return res.error(400, "title must be between 5 - 128 characters"); - if (content.length < 5 || content.length > 1024) return res.error(400, "content must be between 5 - 1024 characters"); + const limits = req.app.get("limits"); + + if (title.length < 5 || title.length > limits.title) return res.error(400, "title must be between 5 - 128 characters"); + if (content.length < 5 || content.length > limits.message) return res.error(400, "content must be between 5 - 1024 characters"); const { user } = req; const thread = await new ThreadModel({ title, author: user }).takeId() if (category) @@ -61,7 +63,9 @@ app.patch("/:id/", async (req, res) => { if (user.id !== thread.authorID && !user.admin) return res.error(403, "You have not got permission for this."); const { title } = req.body; if (!title) return res.error(400, "Missing thread title in request body."); - if (title.length < 5 || title.length > 128) return res.error(400, "title must be between 5 - 128 characters"); + const limits = req.app.get("limits"); + + if (title.length < 5 || title.length > limits.title) return res.error(400, "title must be between 5 - 128 characters"); thread.title = title; await thread.save(); diff --git a/routes/api/routes/users.js b/routes/api/routes/users.js index 40bcf04..d015d02 100644 --- a/routes/api/routes/users.js +++ b/routes/api/routes/users.js @@ -42,7 +42,6 @@ app.post("/:id/undelete/", async (req, res) => { if (!member.deleted) return res.error(404, "This user is not deleted, first, delete it."); member.deleted = false; - ; res.complate(await member.save()); @@ -57,17 +56,17 @@ app.patch("/:id/", async (req, res) => { const { name, about, theme, admin, deleted } = req.body; if ((admin?.length || "deleted" in req.body) && !req.user.admin) return res.error(403, "You have not got permission for edit 'admin' and 'deleted' information, or bad request."); - + const { names, desp } = req.app.get("limits"); if (name) { - if (name.length < 3 || name.length > 25) return res.error(400, "Username must be between 3 - 25 characters"); + if (name.length < 3 || names > 25) return res.error(400, "Username must be between 3 - 25 characters"); await SecretModel.updateOne({ id: member.id }, { username: name }); member.name = name; } if (about) { - if (about.length > 256) return res.error(400, "About must be under 256 characters"); + if (about.length > desp) return res.error(400, "About must be under 256 characters"); member.about = about; } if (theme || ["default", "black"].includes(theme)) member.theme = theme; diff --git a/routes/register.js b/routes/register.js index 1a40ef9..ec5c50d 100644 --- a/routes/register.js +++ b/routes/register.js @@ -16,8 +16,9 @@ app.post("/", rateLimit({ let { username, password: body_pass, about } = req.body; if (!username || !body_pass) return res.error(400, "You forgot entering some values"); - if (username.length < 3 || username.length > 25) return res.error(400, "Username must be between 3 - 25 characters"); - if (body_pass.length < 3 || body_pass.length > 25) return res.error(400, "Password must be between 3 - 25 characters"); + const {names} = req.app.get("limits"); + if (username.length < 3 || names > 25) return res.error(400, "Username must be between 3 - 25 characters"); + if (body_pass.length < 3 || names > 25) return res.error(400, "Password must be between 3 - 25 characters"); const user = await SecretModel.findOne({ username });