mirror of
https://github.com/Akif9748/akf-forum.git
synced 2024-11-26 05:10:41 +03:00
ratelimit & crypto & .ejs fix
added ratelimit to post threads and messages. Added encryption to passwords. Thread.ejs is fixed
This commit is contained in:
parent
086f2b5713
commit
11965e8de9
9 changed files with 44 additions and 12 deletions
|
@ -6,9 +6,10 @@ A forum software written in Node.js.
|
||||||
## Installation
|
## Installation
|
||||||
- Clone or download this repo.
|
- Clone or download this repo.
|
||||||
- Run `npm i` to install **dependencies**.
|
- 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
|
## API
|
||||||
Akf-forum has got an API for other clients etc. You can test api with run apitest.py.
|
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)
|
## To do (Backend, bug fixes)
|
||||||
- `/errors/error` will change, better error page.
|
- `/errors/error` will change, better error page.
|
||||||
- Redirect query.
|
- Redirect query.
|
||||||
- middleware for timeouts
|
|
||||||
- Will fix API
|
- Will fix API
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
@ -42,7 +42,7 @@ And, you can learn about API in `util/APIDOCS.md`.
|
||||||
### Messages
|
### Messages
|
||||||
| To do | Is done? | Priority |
|
| To do | Is done? | Priority |
|
||||||
| ----- | -------- | -------- |
|
| ----- | -------- | -------- |
|
||||||
| Ratelimit | 🔴 | HIGH |
|
| Ratelimit | 🟢 | HIGH |
|
||||||
| Send | 🟢 | HIGH |
|
| Send | 🟢 | HIGH |
|
||||||
| Delete | 🟢 | HIGH |
|
| Delete | 🟢 | HIGH |
|
||||||
| Edit | 🔴 | HIGH |
|
| Edit | 🔴 | HIGH |
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const mongoose = require("mongoose")
|
const mongoose = require("mongoose")
|
||||||
|
|
||||||
const schema = new mongoose.Schema({
|
const schema = new mongoose.Schema({
|
||||||
id: { type: String, unique: true },
|
id: { type: String },
|
||||||
|
|
||||||
name: String,
|
name: String,
|
||||||
avatar: { type: String, default: "/images/guest.png" },
|
avatar: { type: String, default: "/images/guest.png" },
|
||||||
|
|
18
package-lock.json
generated
18
package-lock.json
generated
|
@ -14,6 +14,7 @@
|
||||||
"dotenv": "^16.0.1",
|
"dotenv": "^16.0.1",
|
||||||
"ejs": "^3.1.6",
|
"ejs": "^3.1.6",
|
||||||
"express": "^4.17.3",
|
"express": "^4.17.3",
|
||||||
|
"express-rate-limit": "^6.5.1",
|
||||||
"express-session": "^1.17.2",
|
"express-session": "^1.17.2",
|
||||||
"mongoose": "^6.5.1"
|
"mongoose": "^6.5.1"
|
||||||
}
|
}
|
||||||
|
@ -486,6 +487,17 @@
|
||||||
"node": ">= 0.10.0"
|
"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": {
|
"node_modules/express-session": {
|
||||||
"version": "1.17.2",
|
"version": "1.17.2",
|
||||||
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz",
|
||||||
|
@ -1904,6 +1916,12 @@
|
||||||
"vary": "~1.1.2"
|
"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": {
|
"express-session": {
|
||||||
"version": "1.17.2",
|
"version": "1.17.2",
|
||||||
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz",
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
"dotenv": "^16.0.1",
|
"dotenv": "^16.0.1",
|
||||||
"ejs": "^3.1.6",
|
"ejs": "^3.1.6",
|
||||||
"express": "^4.17.3",
|
"express": "^4.17.3",
|
||||||
|
"express-rate-limit": "^6.5.1",
|
||||||
"express-session": "^1.17.2",
|
"express-session": "^1.17.2",
|
||||||
"mongoose": "^6.5.1"
|
"mongoose": "^6.5.1"
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ const { UserModel, SecretModel } = require("../models");
|
||||||
const { Router } = require("express");
|
const { Router } = require("express");
|
||||||
const error = require("../errors/error");
|
const error = require("../errors/error");
|
||||||
const app = Router();
|
const app = Router();
|
||||||
|
const bcrypt = require("bcrypt");
|
||||||
|
|
||||||
app.get("/", (req, res) => res.render("login"));
|
app.get("/", (req, res) => res.render("login"));
|
||||||
|
|
||||||
|
@ -13,7 +14,10 @@ app.post("/", async (req, res) => {
|
||||||
if (username && password) {
|
if (username && password) {
|
||||||
const user = await SecretModel.findOne({ username });
|
const user = await SecretModel.findOne({ username });
|
||||||
if (user) {
|
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 });
|
const member = await UserModel.findOne({ name: username });
|
||||||
if (!member || member.deleted) return error(res, 403, 'Incorrect Username and/or Password!')
|
if (!member || member.deleted) return error(res, 403, 'Incorrect Username and/or Password!')
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const { ThreadModel, MessageModel } = require("../models");
|
const { ThreadModel, MessageModel } = require("../models");
|
||||||
const error = require("../errors/error")
|
const error = require("../errors/error")
|
||||||
|
const rateLimit = require('express-rate-limit')
|
||||||
|
|
||||||
const { Router } = require("express");
|
const { Router } = require("express");
|
||||||
|
|
||||||
|
@ -15,8 +16,9 @@ app.get("/:id", async (req, res) => {
|
||||||
|
|
||||||
app.use(require("../middlewares/login"));
|
app.use(require("../middlewares/login"));
|
||||||
|
|
||||||
|
app.post("/", rateLimit({
|
||||||
app.post("/", async (req, res) => {
|
windowMs: 60_000, max: 1, standardHeaders: true, legacyHeaders: false
|
||||||
|
}), async (req, res) => {
|
||||||
|
|
||||||
const thread = await ThreadModel.get(req.body.threadID);
|
const thread = await ThreadModel.get(req.body.threadID);
|
||||||
if (thread) {
|
if (thread) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const { UserModel, SecretModel } = require("../models");
|
const { UserModel, SecretModel } = require("../models");
|
||||||
const { Router } = require("express")
|
const { Router } = require("express")
|
||||||
const error = require("../errors/error")
|
const error = require("../errors/error")
|
||||||
|
const bcrypt = require("bcrypt");
|
||||||
|
|
||||||
const app = Router();
|
const app = Router();
|
||||||
|
|
||||||
|
@ -24,6 +25,9 @@ app.post("/", async (req, res) => {
|
||||||
const user2 = new UserModel({ name: req.body.username, avatar })
|
const user2 = new UserModel({ name: req.body.username, avatar })
|
||||||
await user2.takeId()
|
await user2.takeId()
|
||||||
await user2.save();
|
await user2.save();
|
||||||
|
|
||||||
|
const salt = await bcrypt.genSalt(10);
|
||||||
|
password = await bcrypt.hash(password, salt);
|
||||||
await SecretModel.create({ username, password, id: user2.id })
|
await SecretModel.create({ username, password, id: user2.id })
|
||||||
req.session.userid = user2.id;
|
req.session.userid = user2.id;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const { Router } = require("express");
|
const { Router } = require("express");
|
||||||
const app = Router();
|
const app = Router();
|
||||||
|
const rateLimit = require('express-rate-limit')
|
||||||
|
|
||||||
const error = require("../errors/error")
|
const error = require("../errors/error")
|
||||||
const { ThreadModel, MessageModel } = require("../models")
|
const { ThreadModel, MessageModel } = require("../models")
|
||||||
|
@ -47,7 +48,9 @@ app.get("/:id", async (req, res) => {
|
||||||
app.use(require("../middlewares/login"));
|
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;
|
const { title = null, content = null } = req.body;
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<%= thread.title %>
|
<%= thread.title %>
|
||||||
</h1>
|
</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 %>>
|
<img class="yuvarlak" src=<%= thread.author.avatar %> alt=<%= thread.author.name %>>
|
||||||
</h2>
|
</h2>
|
||||||
<hr>
|
<hr>
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
<h2>
|
<h2>
|
||||||
<img class="yuvarlak" src=<%=message.author.avatar %> alt=<%= message.author.name %>>
|
<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>
|
||||||
|
|
||||||
<h2>
|
<h2>
|
||||||
|
|
Loading…
Reference in a new issue