From dc29ed59069db78ebfb8f1c05cbe2fe486c383ce Mon Sep 17 00:00:00 2001 From: Akif9748 Date: Wed, 10 Aug 2022 02:08:18 +0300 Subject: [PATCH] API is optimized, and better ratelimit --- README.md | 2 +- public/js/navbar.js | 0 routes/api/ApiResponse.js | 7 ------- routes/api/index.js | 34 +++++++++++++++++-------------- routes/api/routes/message.js | 39 +++++++++++++++++++----------------- routes/api/routes/threads.js | 32 ++++++++++++----------------- routes/api/routes/user.js | 15 +++++--------- routes/message.js | 6 +++++- routes/threads.js | 10 ++++++--- 9 files changed, 71 insertions(+), 74 deletions(-) delete mode 100644 public/js/navbar.js delete mode 100644 routes/api/ApiResponse.js diff --git a/README.md b/README.md index d9dcd27..795ea53 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ And, you can learn about API in `util/APIDOCS.md`. - `/errors/error` will change, better error page. - Redirect query. - Will fix API - +- message.js/12, so, admin perms,(req.user?.admin || !thread.deleted), and api in message ## Roadmap ### User | To do | Is done? | Priority | diff --git a/public/js/navbar.js b/public/js/navbar.js deleted file mode 100644 index e69de29..0000000 diff --git a/routes/api/ApiResponse.js b/routes/api/ApiResponse.js deleted file mode 100644 index 39b9280..0000000 --- a/routes/api/ApiResponse.js +++ /dev/null @@ -1,7 +0,0 @@ -class ApiResponse { - constructor(status, result) { - this.status = status; - this.result = result; - } -} -module.exports = ApiResponse; \ No newline at end of file diff --git a/routes/api/index.js b/routes/api/index.js index b25aa6a..0f1afdf 100644 --- a/routes/api/index.js +++ b/routes/api/index.js @@ -1,13 +1,10 @@ const { Router } = require("express") const app = Router(); +const bcrypt = require("bcrypt"); -/** - * @deprecated - * for less time - */ const { request, response } = require("express"); -const { SecretModel } = require("../../models") -const ApiResponse = require("./ApiResponse") +const { SecretModel, UserModel } = require("../../models") + /** * AUTH TYPE: @@ -34,30 +31,37 @@ const ApiResponse = require("./ApiResponse") * @param {request} req * @param {response} res */ -/* + app.use(async (req, res, next) => { - const error = (status, error) => - res.status(status).json(new ApiResponse(status, { error })) + res.error = (status, error) => + res.status(status).json({ status, result: { error } }) + + res.complate = result => res.status(200).json({ status: 200, result }); const { username = null, password = null } = req.headers; if (!username || !password) - return error(401, "Authorise headers are missing") + return res.error(401, "Authorise headers are missing") const user = await SecretModel.findOne({ username }); if (!user) - return error(401, "We have not got any user has got this name") + return res.error(401, "We have not got any user has got this name") + + const validPassword = await bcrypt.compare(password, user.password); + + if (!validPassword) + return res.error(401, 'Incorrect Password!') + req.user = await UserModel.findOne({ name: req.headers.username }); - if (user.password !== password) - return error(401, 'Incorrect Password!') next(); }); +/* will add for loop */ app.use("/messages", require("./routes/message")) app.use("/users", require("./routes/user")) app.use("/threads", require("./routes/threads")) -*/ -app.all("*", (req, res) => res.status(400).json(new ApiResponse(400, { error: "Bad request" }))); + +app.all("*", (req, res) => res.error(400, "Bad request")); module.exports = app; \ No newline at end of file diff --git a/routes/api/routes/message.js b/routes/api/routes/message.js index 007e0d0..7608850 100644 --- a/routes/api/routes/message.js +++ b/routes/api/routes/message.js @@ -1,5 +1,5 @@ -const { User, Message, Thread } = require("../../../classes"); -const ApiResponse = require("../ApiResponse"); +const { UserModel, MessageModel, ThreadModel } = require("../../../models"); +const rateLimit = require('express-rate-limit') const { Router } = require("express") @@ -7,34 +7,37 @@ const app = Router(); app.get("/:id", async (req, res) => { - const error = (status, error) => - res.status(status).json(new ApiResponse(status, { error })); const { id = null } = req.params; - if (!id) return error(400, "Missing id in query") - const message = await new Message().getById(id); + if (!id) return res.error(400, "Missing id in query") + const message = await MessageModel.get(id); - if (!message || message.deleted) return error(404, "We have not got any message declared as this id."); + if (!message || message.deleted) return res.error(404, "We have not got any message declared as this id."); - res.status(200).json(new ApiResponse(200, message)); + res.complate(message); }) -app.post("/", async (req, res) => { - const error = (status, error) => - res.status(status).json(new ApiResponse(status, { error })); +app.post("/", rateLimit({ + windowMs: 60_000, max: 1, standardHeaders: true, legacyHeaders: false, + handler: (request, response, next, options) => + !request.user.admin ? + response.error(options.statusCode, "You are begin ratelimited") + : next() +}), async (req, res) => { + const { threadID = null, content = null } = req.body; - const thread = await new Thread().getById(threadID); + if (!content) return res.error(400, "Missing message content in request body."); - if (!content) return error(400, "Missing message content in request body."); - if (!thread) return error(404, "We have not got this thread."); + const thread = await ThreadModel.get(threadID); + if (!thread) return res.error(404, "We have not got this thread."); - const message = await new Message(content, await new User().getByName(req.headers.username), thread.id).takeId() - message.save(); - thread.push(message.id).save(); + const message = await new MessageModel({ content, author: req.user, threadID: thread.id }).takeId(); + await message.save(); + await thread.push(message.id).save(); - res.status(200).json(new ApiResponse(200, message)); + res.complate(message); }) diff --git a/routes/api/routes/threads.js b/routes/api/routes/threads.js index efc66da..363e566 100644 --- a/routes/api/routes/threads.js +++ b/routes/api/routes/threads.js @@ -1,42 +1,36 @@ -const { Thread, User, Message } = require("../../../classes"); -const ApiResponse = require("../ApiResponse"); +const { UserModel, MessageModel, ThreadModel } = require("../../../models"); const { Router } = require("express") const app = Router(); app.get("/:id", async (req, res) => { - const error = (status, error) => - res.status(status).json(new ApiResponse(status, { error })) - - const { id = null } = req.params; - if (!id) return error(400, "Missing id in query") + if (!id) return res.error(400, "Missing id in query") - const thread = await new Thread().getById(id); - if (!thread || thread.deleted) return error(404, "We have not got any thread declared as this id."); + const thread = await ThreadModel.get(id); + if (thread && (req.user?.admin || !thread.deleted)) + res.complate( thread); + else + return res.error(404, "We have not got any thread declared as this id."); - res.status(200).json(new ApiResponse(200, thread)); }); app.post("/", async (req, res) => { - const error = (status, error) => - res.status(status).json(new ApiResponse(status, { error })); - const { title = null, content = null } = req.body; - if (!content || !title) return error(400, "Missing content/title in request body."); + if (!content || !title) return res.error(400, "Missing content/title in request body."); - const user = await new User().getByName(req.headers.username) - const thread = await new Thread(title, user).takeId() - const message = await new Message(content, user, thread.id).takeId() - thread.push(message.id).save(); + const user = req.user; + const thread = await new ThreadModel({ title, author: user }).takeId() + const message = await new MessageModel({ content, author: user, threadID: thread.id }).takeId() + await thread.push(message.id).save(); await message.save(); - res.status(200).json(new ApiResponse(200, thread)); + res.complate(thread); }); diff --git a/routes/api/routes/user.js b/routes/api/routes/user.js index 4669a21..2e28bf8 100644 --- a/routes/api/routes/user.js +++ b/routes/api/routes/user.js @@ -1,21 +1,16 @@ -const { User } = require("../../../classes"); -const ApiResponse = require("../ApiResponse"); +const { UserModel, MessageModel, ThreadModel } = require("../../../models"); const { Router } = require("express") const app = Router(); app.get("/:id", async (req, res) => { - const error = (status, error) => - res.status(status).json(new ApiResponse(status, { error })) - - const { id = null } = req.params; - if (!id) return error(400, "Missing id in query") - const member = await new User().getById(id); - if (!member || member.deleted) return error(404, "We have not got any user declared as this id."); + if (!id) return res.error(400, "Missing id in query") + const member = await UserModel.get(id); + if (!member || member.deleted) return res.error(404, "We have not got any user declared as this id."); - res.status(200).json(new ApiResponse(200, member)); + res.complate(member); }); diff --git a/routes/message.js b/routes/message.js index 9143156..4ebe937 100644 --- a/routes/message.js +++ b/routes/message.js @@ -17,7 +17,11 @@ app.get("/:id", async (req, res) => { app.use(require("../middlewares/login")); app.post("/", rateLimit({ - windowMs: 60_000, max: 1, standardHeaders: true, legacyHeaders: false + windowMs: 60_000, max: 1, standardHeaders: true, legacyHeaders: false, + handler: (request, response, next, options) => + !request.user.admin ? + error(response, options.statusCode, "You are begin ratelimited") + : next() }), async (req, res) => { const thread = await ThreadModel.get(req.body.threadID); diff --git a/routes/threads.js b/routes/threads.js index 694795f..41785fe 100644 --- a/routes/threads.js +++ b/routes/threads.js @@ -28,9 +28,9 @@ app.get("/:id", async (req, res) => { const { id } = req.params; const thread = await ThreadModel.get(id); + const user = req.user; - if (thread && !thread.deleted) { - const user = req.user; + if (thread && (user?.admin || !thread.deleted)) { const messages = await Promise.all(thread.messages.map(async id => { const message = await MessageModel.get(id) @@ -49,7 +49,11 @@ app.use(require("../middlewares/login")); app.post("/", rateLimit({ - windowMs: 10 * 60_000, max: 1, standardHeaders: true, legacyHeaders: false + windowMs: 10 * 60_000, max: 1, standardHeaders: true, legacyHeaders: false, + handler: (request, response, next, options) => + !request.user.admin ? + error(response, options.statusCode, "You are begin ratelimited") + : next() }), async (req, res) => { const { title = null, content = null } = req.body;