diff --git a/README.md b/README.md index 54c92ee..1a6a4e4 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,10 @@ A forum software written in Node.js. ## Installation - Clone or download this repo. - Run `npm i` to install **dependencies**. -- Run `node util/reset` to **reset the database**, and `npm start` for run it. +- Run `npm start` for run it. -**Note:** Reseting the database is important! +### Extra +Run `node util/reset` to **reset the database**, and run `node util/admin` for give admin perms for first member. ## API Akf-forum has got an API for other clients etc. You can test api with run apitest.py. @@ -21,7 +22,6 @@ And, you can learn about API in `util/APIDOCS.md`. ## To do (Backend, bug fixes) - `/errors/error` will change, better error page. - Redirect query. -- middleware for timeouts - Will fix API ## Roadmap @@ -42,7 +42,7 @@ And, you can learn about API in `util/APIDOCS.md`. ### Messages | To do | Is done? | Priority | | ----- | -------- | -------- | -| Ratelimit | 🔴 | HIGH | +| Ratelimit | 🟢 | HIGH | | Send | 🟢 | HIGH | | Delete | 🟢 | HIGH | | Edit | 🔴 | HIGH | diff --git a/models/User.js b/models/User.js index df2016c..662dd57 100644 --- a/models/User.js +++ b/models/User.js @@ -1,7 +1,7 @@ const mongoose = require("mongoose") const schema = new mongoose.Schema({ - id: { type: String, unique: true }, + id: { type: String }, name: String, avatar: { type: String, default: "/images/guest.png" }, diff --git a/package-lock.json b/package-lock.json index 77dda69..993372d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "dotenv": "^16.0.1", "ejs": "^3.1.6", "express": "^4.17.3", + "express-rate-limit": "^6.5.1", "express-session": "^1.17.2", "mongoose": "^6.5.1" } @@ -486,6 +487,17 @@ "node": ">= 0.10.0" } }, + "node_modules/express-rate-limit": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.5.1.tgz", + "integrity": "sha512-pxO6ioBLd3i8IHL+RmJtL4noYzte5fugoMdaDabtU4hcg53+x0QkTwfPtM7vWD0YUaXQgNj9NRdzmps+CHEHlA==", + "engines": { + "node": ">= 12.9.0" + }, + "peerDependencies": { + "express": "^4 || ^5" + } + }, "node_modules/express-session": { "version": "1.17.2", "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", @@ -1904,6 +1916,12 @@ "vary": "~1.1.2" } }, + "express-rate-limit": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.5.1.tgz", + "integrity": "sha512-pxO6ioBLd3i8IHL+RmJtL4noYzte5fugoMdaDabtU4hcg53+x0QkTwfPtM7vWD0YUaXQgNj9NRdzmps+CHEHlA==", + "requires": {} + }, "express-session": { "version": "1.17.2", "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", diff --git a/package.json b/package.json index 8583ef5..ae661db 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "dotenv": "^16.0.1", "ejs": "^3.1.6", "express": "^4.17.3", + "express-rate-limit": "^6.5.1", "express-session": "^1.17.2", "mongoose": "^6.5.1" } diff --git a/routes/login.js b/routes/login.js index 59f6d77..f352204 100644 --- a/routes/login.js +++ b/routes/login.js @@ -2,6 +2,7 @@ const { UserModel, SecretModel } = require("../models"); const { Router } = require("express"); const error = require("../errors/error"); const app = Router(); +const bcrypt = require("bcrypt"); app.get("/", (req, res) => res.render("login")); @@ -13,7 +14,10 @@ app.post("/", async (req, res) => { if (username && password) { const user = await SecretModel.findOne({ username }); if (user) { - if (user.password !== password) return error(res, 403, 'Incorrect Password!') + + const validPassword = await bcrypt.compare(password, user.password); + + if (!validPassword) return error(res, 403, 'Incorrect Password!') const member = await UserModel.findOne({ name: username }); if (!member || member.deleted) return error(res, 403, 'Incorrect Username and/or Password!') diff --git a/routes/message.js b/routes/message.js index 7db2aa6..9143156 100644 --- a/routes/message.js +++ b/routes/message.js @@ -1,5 +1,6 @@ const { ThreadModel, MessageModel } = require("../models"); const error = require("../errors/error") +const rateLimit = require('express-rate-limit') const { Router } = require("express"); @@ -15,8 +16,9 @@ app.get("/:id", async (req, res) => { app.use(require("../middlewares/login")); - -app.post("/", async (req, res) => { +app.post("/", rateLimit({ + windowMs: 60_000, max: 1, standardHeaders: true, legacyHeaders: false +}), async (req, res) => { const thread = await ThreadModel.get(req.body.threadID); if (thread) { @@ -42,7 +44,7 @@ app.post("/:id/delete", async (req, res) => { await message.save(); - res.status(200).redirect( "/threads/" + message.threadID); + res.status(200).redirect("/threads/" + message.threadID); }) app.post("/:id/react", async (req, res) => { diff --git a/routes/register.js b/routes/register.js index 35e5336..231dad3 100644 --- a/routes/register.js +++ b/routes/register.js @@ -1,6 +1,7 @@ const { UserModel, SecretModel } = require("../models"); const { Router } = require("express") const error = require("../errors/error") +const bcrypt = require("bcrypt"); const app = Router(); @@ -24,6 +25,9 @@ app.post("/", async (req, res) => { const user2 = new UserModel({ name: req.body.username, avatar }) await user2.takeId() await user2.save(); + + const salt = await bcrypt.genSalt(10); + password = await bcrypt.hash(password, salt); await SecretModel.create({ username, password, id: user2.id }) req.session.userid = user2.id; diff --git a/routes/threads.js b/routes/threads.js index 2b6179f..bf2d9b7 100644 --- a/routes/threads.js +++ b/routes/threads.js @@ -1,5 +1,6 @@ const { Router } = require("express"); const app = Router(); +const rateLimit = require('express-rate-limit') const error = require("../errors/error") const { ThreadModel, MessageModel } = require("../models") @@ -47,7 +48,9 @@ app.get("/:id", async (req, res) => { app.use(require("../middlewares/login")); -app.post("/", async (req, res) => { +app.post("/", rateLimit({ + windowMs: 10*60_000, max: 1, standardHeaders: true, legacyHeaders: false +}), async (req, res) => { const { title = null, content = null } = req.body; diff --git a/views/thread.ejs b/views/thread.ejs index e82d697..0c1d80c 100644 --- a/views/thread.ejs +++ b/views/thread.ejs @@ -12,7 +12,7 @@ <%= thread.title %> -

By > <%= thread.author.name %> +

By > <%= thread.author.name %> alt=<%= thread.author.name %>>


@@ -27,7 +27,7 @@

alt=<%= message.author.name %>> - > <%= message.author.name %>: + > <%= message.author.name %>: