ratelimit & crypto & .ejs fix

added ratelimit to post threads and messages.
Added encryption to passwords.
Thread.ejs is fixed
This commit is contained in:
Akif9748 2022-08-10 00:22:12 +03:00
parent 086f2b5713
commit 11965e8de9
9 changed files with 44 additions and 12 deletions

View File

@ -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 |

View File

@ -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" },

18
package-lock.json generated
View File

@ -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",

View File

@ -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"
}

View File

@ -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!')

View File

@ -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) => {

View File

@ -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;

View File

@ -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;

View File

@ -12,7 +12,7 @@
<%= thread.title %>
</h1>
<h2>By <a style="color: #bcbcbc;" href=<%="/users/" + thread.author.id %>> <%= thread.author.name %></a>
<h2>By <a href=<%="/users/" + thread.author.id %>> <%= thread.author.name %></a>
<img class="yuvarlak" src=<%= thread.author.avatar %> alt=<%= thread.author.name %>>
</h2>
<hr>
@ -27,7 +27,7 @@
<h2>
<img class="yuvarlak" src=<%=message.author.avatar %> alt=<%= message.author.name %>>
<a style="color: #bcbcbc;" href=<%="/users/" + message.author.id %>> <%= message.author.name %></a>:
<a href=<%="/users/" + message.author.id %>> <%= message.author.name %></a>:
</h2>
<h2>