Database changed to MongoDB

This commit is contained in:
Akif9748 2022-04-06 21:14:46 +03:00
parent 9c1b9997b6
commit 8024891de2
36 changed files with 807 additions and 1210 deletions

View File

@ -19,8 +19,6 @@ And, you can learn informations about API in `APIDOCS.md`.
## To Do (Backend, bug fixes)
- Better error codes, example 400 for bad request
- Database change. (To MongoDB)
- Better DB writing. Example, not `message.author.id`, `messsage.authorID`
- `/errors/error` will change, better error page.
## Roadmap
@ -48,12 +46,12 @@ And, you can learn informations about API in `APIDOCS.md`.
- [ ] Multiple theme support
- [ ] Search
- [x] New Thread theme, better render for messages
- [ ] sending message etc. Will turn api model
- [ ] Sending message etc. Will turn api model
- [ ] API
- [x] Other client for forum via API
- [ ] Deleting message
- [x] Sending message
- [ ] Open thread
- [x] Open thread
- [x] Get Thread info
## Image:
![image](https://user-images.githubusercontent.com/70021050/160255959-ef216cba-1348-4d4b-9347-fe67e21348e7.png)

View File

@ -1,9 +1,8 @@
const Message = require("./message");
const Thread = require("./thread");
const User = require("./user");
const React = require("./react");
/**
* Classes for akf-forum;
*/
module.exports = { Message, Thread, User, React };
module.exports = { Message, Thread, User };

View File

@ -1,44 +1,52 @@
const { MessageModel } = require("../models");
const User = require("./user");
const User = require("./user")
const Thread = require("./thread")
const db = require("quick.db");
module.exports = class Message {
constructor(content, author = new User(), thread = new Thread(), time = new Date().getTime(), deleted = false, edited = false, react = {}) {
constructor(content, author = User, threadID = null, time = Date.now(), deleted = false, edited = false, react = {}) {
this.authorID = author?.id;
this.content = content;
this.author = author;
this.time = time;
this.thread = thread;
this.threadID = threadID;
this.deleted = deleted;
this.edited = edited;
this.react = react;
}
getId(id = this.id) {
const message = db.get("messages").find(msg => msg.id == id);
async getById(id = this.id) {
this.id = Number(id);
const message = await MessageModel.findOne({ id });
if (!message) return null;
this.id = Number(id);
const { content, author, thread = new Thread(), time = new Date().getTime(), deleted = false, edited = false, react = {} } = message;
const { content, authorID, author = null, threadID = null, time = Date.now(), deleted = false, edited = false, react = {} } = message;
this.content = content;
this.thread = thread;
this.threadID = threadID;
this.author = author;
this.authorID = authorID;
this.time = time;
this.deleted = deleted;
this.edited = edited;
this.react = react;
return this
}
takeId() {
this.id = db.get("messages").length || 0;
return this;
}
write(id = this.id) {
db.set("messages." + id, this)
async takeId() {
this.id = await MessageModel.count({}) || 0;
return this;
}
async write(id = this.id) {
const writing = await MessageModel.findOneAndUpdate({ id }, this);
if (!writing)
await MessageModel.create(this);
return this;
}
getLink(id = this.id) {
return "/messages/" + id;
}

8
classes/react.js vendored
View File

@ -1,8 +0,0 @@
const User = require("./user")
module.exports = class Message {
constructor(like = true, author = new User()) {
this.like = like;
this.author= author;
}
}

View File

@ -1,14 +1,14 @@
const db = require("quick.db")
const User = require("./user")
const { ThreadModel } = require("../models");
module.exports = class Thread {
constructor(title, author = new User(), messages = [], time = new Date().getTime(),deleted = false) {
constructor(title, author = User, messages = [], time = Date.now(), deleted = false) {
this.author = author;
this.authorID = author?.id;
this.title = title;
this.messages = messages;
this.time = time;
@ -16,38 +16,44 @@ module.exports = class Thread {
}
getId(id = this.id) {
const thread = db.get("threads").find(t => t.id == id);
if (!thread) return null;
async getById(id = this.id) {
this.id = Number(id);
const { title, author, messages = [], time = new Date().getTime(), deleted = false } = thread;
const thread = await ThreadModel.findOne({ id });
if (!thread) return null;
const { title, authorID, author, messages = [], time = Date.now(), deleted = false } = thread;
this.title = title
this.author = author
this.author = author;
this.authorID = authorID;
this.messages = messages;
this.time = time;
this.deleted = deleted;
return this;
}
takeId(){
this.id = db.get("threads").length;
return this
}
push(message){
this.messages.push(message)
push(messageID) {
this.messages.push(messageID)
return this;
}
write(id = this.id) {
db.set("threads."+id, this)
async takeId() {
this.id = await ThreadModel.count({}) || 0;
return this;
}
async write(id = this.id) {
const writing = await ThreadModel.findOneAndUpdate({ id }, this);
if (!writing)
await ThreadModel.create(this);
return this;
}
getLink(id = this.id) {
return "/threads/" + id;
}
}

View File

@ -1,9 +1,9 @@
const db = require("quick.db")
const { UserModel } = require("../models");
module.exports = class User {
constructor(name = "guest", avatar = "/images/guest.png", time = new Date().getTime(), admin = false, deleted = false) {
constructor(name = "guest", avatar = "/images/guest.png", time = Date.now(), admin = false, deleted = false) {
this.name = name;
this.avatar = avatar;
@ -13,26 +13,12 @@ module.exports = class User {
}
getId(id = this.id) {
const user = db.get("users").find(u => u.id == id);
if (!user) return null;
async getById(id = this.id) {
this.id = Number(id);
const { name = "guest", avatar = "/images/guest.png", time = new Date().getTime(), admin = false, deleted = false } = user;
this.name = name;
this.avatar = avatar;
this.time = time;
this.admin = admin;
this.deleted = deleted;
return this ;
}
getName(name1 = this.name) {
const user = db.get("users").find(u => u.name == name1);
const user = await UserModel.findOne({ id });
if (!user) return null;
this.id = Number(user.id);
const { name = "guest", avatar = "/images/guest.png", time = new Date().getTime(), admin = false, deleted = false } = user;
const { name = "guest", avatar = "/images/guest.png", time = Date.now(), admin = false, deleted = false } = user;
this.name = name;
this.avatar = avatar;
this.time = time;
@ -41,16 +27,36 @@ module.exports = class User {
return this;
}
takeId() {
let id = db.get("users");
this.id = id ? id.length : 0;
return this
async getByName(Name = this.name) {
const user = await UserModel.findOne({ name: Name });
if (!user) return null;
const { name = "guest", avatar = "/images/guest.png", time = Date.now(), admin = false, deleted = false } = user;
this.name = name;
this.avatar = avatar;
this.time = time;
this.admin = admin;
this.deleted = deleted;
return this;
}
write(id = this.id) {
db.set("users." + id, this)
async takeId() {
this.id = await UserModel.count({}) || 0;
return this;
}
async write(id = this.id) {
const writing = await UserModel.findOneAndUpdate({ id }, this);
if (!writing)
await UserModel.create(this);
return this;
}
getLink(id = this.id) {
return "/users/" + id;
}

View File

@ -2,18 +2,23 @@ const error = require("./errors/error.js"),
session = require('express-session'),
bodyParser = require('body-parser'),
port = process.env.PORT ?? 3000,
mongoose = require("mongoose"),
express = require('express'),
fs = require("fs"),
app = express();
mongoose.connect('mongodb://localhost:27017/akf-forum', () =>console.log("Database is connected"));
app.use(session({ secret: 'secret', resave: true, saveUninitialized: true }));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static("public"));
app.set("view engine", "ejs");
app.use(express.json());
app.use(require("./middlewares/user"));
app.use(require("./middlewares/timeout"));
for (const file of fs.readdirSync("./routes"))
app.use("/" + file.replace(".js",""), require(`./routes/${file}`));
app.use("/" + file.replace(".js", ""), require(`./routes/${file}`));
app.all("*", (req, res) => error(res, 404, "We have not got this page."));

View File

@ -1,4 +1,4 @@
module.exports = (req, res,next) => {
if (!req.session.loggedin) return res.redirect('/login');
module.exports = (req, res, next) => {
if (!req.session.userid?.toString()) return res.redirect('/login');
next();
}

15
middlewares/timeout.js Normal file
View File

@ -0,0 +1,15 @@
const { TimeoutModel } = require("../models");
module.exports = async (req, res, next) => {
if (!req.user || req.user.admin) return next();
const timeout = await TimeoutModel.findOne({ id: req.user.id }) || new TimeoutModel({ until: Date.now() - 1000, id: req.user.id });
req.timeout = timeout;
if (timeout.until > Date.now())
req.ratelimit = true;
next();
}

6
middlewares/user.js Normal file
View File

@ -0,0 +1,6 @@
const { User } = require("../classes");
module.exports = async (req, res, next) => {
req.user = await new User().getById(req.session.userid);
next();
}

17
models/Message.js Normal file
View File

@ -0,0 +1,17 @@
const { Schema, model } = require("mongoose")
module.exports = model('message', new Schema({
id: { type: Number, unique: true },
authorID: Number,
threadID: Number,
author: Object,
content: String,
time: Number,
deleted: { type: Boolean, default: false },
edited: { type: Boolean, default: false },
messages: [Number],
react: Object
}))

10
models/Secret.js Normal file
View File

@ -0,0 +1,10 @@
const { Schema, model } = require("mongoose")
module.exports = model('secret', new Schema({
username: { type: String, unique: true },
password: String,
id: { type: Number, unique: true }
}))

15
models/Thread.js Normal file
View File

@ -0,0 +1,15 @@
const { Schema, model } = require("mongoose")
module.exports = model('thread', new Schema({
id: { type: Number, unique: true },
authorID: Number,
author: Object,
title: String,
time: Number,
deleted: { type: Boolean, default: false },
messages: [Number]
}))

8
models/Timeout.js Normal file
View File

@ -0,0 +1,8 @@
const { Schema, model } = require("mongoose")
module.exports = model('timeout', new Schema({
id: { type: Number, unique: true },
until: Number
}))

12
models/User.js Normal file
View File

@ -0,0 +1,12 @@
const { Schema, model } = require("mongoose")
module.exports = model('user', new Schema({
id: { type: Number, unique: true },
name: String,
avatar: String,
time: Number,
deleted: { type: Boolean, default: false },
admin: { type: Boolean, default: false }
}))

7
models/index.js Normal file
View File

@ -0,0 +1,7 @@
const UserModel = require("./User"),
MessageModel = require("./Message"),
ThreadModel = require("./Thread"),
SecretModel = require("./Secret"),
TimeoutModel = require("./Timeout");
module.exports = { UserModel, MessageModel, ThreadModel, SecretModel, TimeoutModel };

1324
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
{
"name": "akf-lang",
"name": "akf-forum",
"version": "2.1.2",
"description": "A forum script written in Node.js",
"main": "index.js",
@ -9,7 +9,7 @@
},
"repository": {
"type": "git",
"url": "git+https://github.com/Akif9748/akf-lang.git"
"url": "git+https://github.com/Akif9748/akf-forum.git"
},
"author": "Akif9748",
"contributors": [
@ -17,7 +17,7 @@
],
"license": "GPL-3.0-or-later",
"bugs": {
"url": "https://github.com/Akif9748/akf-lang/issues"
"url": "https://github.com/Akif9748/akf-forum/issues"
},
"homepage": "https://github.com/Akif9748/akf-lang#readme",
"dependencies": {
@ -25,6 +25,6 @@
"ejs": "^3.1.6",
"express": "^4.17.3",
"express-session": "^1.17.2",
"quick.db": "^7.1.3"
"mongoose": "^6.2.9"
}
}

View File

@ -1,7 +1,14 @@
const { set } = require("quick.db");
set("users", new Array());
set("threads", new Array());
set("secret", new Object());
set("messages", new Array());
set("timeouts", new Array());
const mongoose = require("mongoose");
mongoose.connect('mongodb://localhost:27017/akf-forum', () => console.log("Database is connected"));
const { SecretModel, UserModel, MessageModel, ThreadModel } = require("./models");
(async () => {
await UserModel.deleteMany({});
await ThreadModel.deleteMany({});
await MessageModel.deleteMany({});
await SecretModel.deleteMany({});
console.log("Success")
})();

View File

@ -1,17 +1,14 @@
const { User } = require("../classes");
const { get } = require("quick.db")
const { UserModel, ThreadModel, MessageModel } = require("../models")
const { Router } = require("express");
const app = Router();
app.get("/", (req, res) => {
app.get("/", async (req, res) => {
const
mem = process.memoryUsage().heapUsed / Math.pow(2, 20),
users = get("users").length,
threads = get("threads").length,
messages = get("messages").length,
user = new User().getId(req.session.userid);
users = await UserModel.count({}),
threads = await ThreadModel.count({}),
messages = await MessageModel.count({}),
user = req.user;
res.render("index", { mem, user, users, threads, messages })

View File

@ -7,23 +7,23 @@ const app = Router();
app.use(require("../middlewares/login"));
app.get("/", (req, res) => {
const user = new User().getId(req.session.userid)
app.get("/", async (req, res) => {
const user = req.user;
if (!user.admin) return error(res, 403, "You have not got permissions for view to this page.");
res.render("admin", { user, user2: false })
});
app.post("/", (req, res) => {
app.post("/", async (req, res) => {
const user = new User().getId(req.session.userid)
const user = req.user;
if (!user.admin) return error(res, 403, "You have not got permissions for view to this page.");
const user2 = new User().getId(req.body.userid)
const user2 = await new User().getById(req.body.userid)
if (!user2)
return error(res, 404, "We have not got this user in all of the forum. Vesselam.");
if (!user2)
return error(res, 404, "We have not got this user in all of the forum. Vesselam.");
else {
user2.admin = true;

View File

@ -1,12 +1,10 @@
const { User, Message, Thread } = require("../../classes");
const db = require("quick.db");
const { Router } = require("express")
const app = Router();
const { request, response } = require("express");
const { SecretModel } = require("../../models")
const ApiResponse = require("./ApiResponse")
/**
* AUTH TYPE:
@ -29,29 +27,29 @@ const { request, response } = require("express");
/**
* For intellisense
* Auth checker
* @param {request} req
* @param {response} res
*/
app.use((req, res, next) => {
app.use(async (req, res, next) => {
const error = (status, error) =>
res.status(status).json(new ApiResponse(status, { error }))
const { username = null, password = null } = req.headers;
if (!username || !password)
return error(401, "Headers are missing")
return error(401, "Authorise headers are missing")
const user = db.get("secret." + username);
const user = await SecretModel.findOne({ username });
if (!user)
return error(401, "We have not got any user has got this name")
if (user.key !== password)
if (user.password !== password)
return error(401, 'Incorrect Password!')
next();
})
});
app.use("/messages", require("./routes/message"))
app.use("/users", require("./routes/user"))

View File

@ -5,14 +5,14 @@ const { Router } = require("express")
const app = Router();
app.get("/:id", (req, res) => {
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 = new Message().getId(id);
const message = await new Message().getById(id);
if (!message || message.deleted) return error(404, "We have not got any message declared as this id.");
@ -20,18 +20,18 @@ app.get("/:id", (req, res) => {
})
app.post("/", (req, res) => {
app.post("/", async (req, res) => {
const error = (status, error) =>
res.status(status).json(new ApiResponse(status, { error }));
const { threadID = null, content = null } = req.body;
const thread = new Thread().getId(threadID);
const thread = await new Thread().getById(threadID);
if (!content) return error(400, "Missing message content in request body.");
if (!thread) return error(404, "We have not got this thread.");
const message = new Message(content, new User().getName(req.headers.username), thread).takeId().write();
const message = await new Message(content, await new User().getByName(req.headers.username), thread.id).takeId()
message.write();
thread.push(message.id).write();
res.status(200).json(new ApiResponse(200, message));

View File

@ -1,10 +1,10 @@
const { Thread } = require("../../../classes");
const { Thread, User, Message } = require("../../../classes");
const ApiResponse = require("../ApiResponse");
const { Router } = require("express")
const app = Router();
app.get("/:id", (req, res) => {
app.get("/:id", async (req, res) => {
const error = (status, error) =>
res.status(status).json(new ApiResponse(status, { error }))
@ -13,11 +13,31 @@ app.get("/:id", (req, res) => {
const { id = null } = req.params;
if (!id) return error(400, "Missing id in query")
const thread = new Thread().getId(id);
const thread = await new Thread().getById(id);
if (!thread || thread.deleted) return 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.");
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).write();
await message.write();
res.status(200).json(new ApiResponse(200, thread));
});
module.exports = app;

View File

@ -4,7 +4,7 @@ const { Router } = require("express")
const app = Router();
app.get("/:id", (req, res) => {
app.get("/:id", async (req, res) => {
const error = (status, error) =>
res.status(status).json(new ApiResponse(status, { error }))
@ -12,7 +12,7 @@ app.get("/:id", (req, res) => {
const { id = null } = req.params;
if (!id) return error(400, "Missing id in query")
const member = new User().getId(id);
const member = await new User().getById(id);
if (!member || member.deleted) return error(404, "We have not got any user declared as this id.");
res.status(200).json(new ApiResponse(200, member));

View File

@ -1,27 +1,23 @@
const { User } = require("../classes");
const db = require("quick.db")
const { Router } = require("express")
const error = require("../errors/error")
const { Router } = require("express");
const { SecretModel } = require("../models");
const error = require("../errors/error");
const app = Router();
app.get("/", (req, res) => res.render("login"));
app.post("/", (req, res) => {
req.session.loggedin = false;
req.session.username = null;
app.post("/", async (req, res) => {
req.session.userid = null;
const { username = null, password = null } = req.body;
if (username && password) {
const user = db.get("secret." + username)
const user = await SecretModel.findOne({ username });
if (user) {
// Authenticate the user
if (user.key !== password) return error(res, 403, 'Incorrect Password!')
if (new User().getName(username).deleted) return error(res, 403, 'Incorrect Username and/or Password!')
req.session.loggedin = true;
req.session.username = username;
if (user.password !== password) return error(res, 403, 'Incorrect Password!')
const member = await new User().getByName(username)
if (!member || member.deleted) return error(res, 403, 'Incorrect Username and/or Password!')
req.session.userid = user.id;
res.redirect('/');

View File

@ -5,24 +5,31 @@ const { Router } = require("express");
const app = Router();
app.get("/:id", (req, res) => {
const message = new Message().getId(req.params.id);
app.get("/:id", async (req, res) => {
const message = await new Message().getById(req.params.id);
if (!message || message.deleted) return error(res, 404, "We have not got any message declared as this id.");
res.redirect("/threads/" + message.thread.id);
res.redirect("/threads/" + message.threadID);
});
app.use(require("../middlewares/login"));
app.post("/", (req, res) => {
const thread = new Thread().getId(req.body.threadID);
app.post("/", async (req, res) => {
if (req.ratelimit)
return error(res, 429, "Wait until " + new Date(req.timeout.until).toLocaleTimeString("tr") + ", you are too quick for send.")
const thread = await new Thread().getById(req.body.threadID);
if (thread) {
const message = new Message(req.body.content, new User().getId(req.session.userid), thread).takeId().write();
thread.push(message.id)
const message = await new Message(req.body.content, req.user, thread.id).takeId()
await message.write();
thread.push(message.id);
thread.write();
req.timeout.until += 1000 * 30;
await req.timeout.save()
res.redirect('/threads/' + req.body.threadID);
}
@ -31,24 +38,23 @@ app.post("/", (req, res) => {
});
app.post("/:id/delete", (req, res) => {
const message = new Message().getId(req.params.id)
app.post("/:id/delete", async (req, res) => {
const message = await new Message().getById(req.params.id)
if (!message || message.deleted) return error(res, 404, "We have not got any message declared as this id.");
const user = new User().getId(req.session.userid);
if (user.id != message.author.id && !user.admin)
const user = req.user;
if (user.id != message.authorID && !user.admin)
return error(res, 403, "You have not got permission for this.");
message.deleted = true;
message.write();
res.status(200).redirect("/threads/" + message.thread.id);
res.status(200).redirect("/threads/" + message.threadID);
})
app.post("/:id/react", (req, res) => {
app.post("/:id/react", async (req, res) => {
const { id = null } = req.params;
const info = req.body;
const message = new Message().getId(id);
const message = await new Message().getById(id);
if (message) {
if (!(req.session.userid in message.react))
message.react[req.session.userid] = "like" in info;
@ -56,10 +62,13 @@ app.post("/:id/react", (req, res) => {
delete message.react[req.session.userid];
message.write();
res.redirect("/threads/" + message.thread.id);
res.redirect("/threads/" + message.threadID);
} else error(res, 404, "We have not got this Message for reacting.");
});
module.exports = app;

View File

@ -1,5 +1,5 @@
const { User } = require("../classes");
const db = require("quick.db")
const { SecretModel } = require("../models");
const { Router } = require("express")
const error = require("../errors/error")
@ -8,26 +8,29 @@ const app = Router();
app.get("/", (req, res) => res.render("register"));
app.post("/", (req, res) => {
req.session.loggedin = false;
req.session.username = null;
app.post("/", async (req, res) => {
req.session.userid = null;
const { username = null, password = null } = req.body;
let { username = null, password = null, avatar } = req.body;
if (username && password) {
const user = db.get("secret." + username)
const user = await SecretModel.findOne({ username });
if (user)
error(res, 404, `We have got an user named ${username}!`)
else {
const user2 = new User(req.body.username, req.body.avatar ?? null).takeId()
db.set("secret." + username, { id: user2.id, key: password })
req.session.loggedin = true;
req.session.username = username;
if (!avatar) avatar ="/images/guest.png";
const user2 = await new User(req.body.username, avatar).takeId();
await SecretModel.create({ username, password, id: user2.id })
req.session.userid = user2.id;
user2.write()
user2.write();
res.redirect('/');
}

View File

@ -1,40 +1,43 @@
const { Thread, Message, User } = require("../classes");
const error = require("../errors/error")
const db = require("quick.db")
const { Router } = require("express");
const app = Router();
const { Thread, Message, User } = require("../classes");
const error = require("../errors/error")
const { ThreadModel } = require("../models")
app.get("/", (req, res) => {
const user = new User().getId(req.session.userid);
app.get("/", async (req, res) => {
const threads = db.get("threads").slice(0, 10)
const links = threads.map(thread => "/threads/" + threads.indexOf(thread))
const user = req.user;
return res.render("threads", { threads, links, user })
const threads = await Promise.all((await ThreadModel.find({}).limit(10))
.map(async threads => await new Thread().getById(threads.id)));
return res.render("threads", { threads, user });
});
app.get("/open*", (req, res) => {
app.get("/open*", async (req, res) => {
const user = new User().getId(req.session.userid)
const user = req.user
res.render("openThread", { user })
});
app.get("/:id", (req, res) => {
app.get("/:id", async (req, res) => {
const { id } = req.params;
const thread = new Thread().getId(id);
const thread = await new Thread().getById(id);
if (thread) {
const user = new User().getId(req.session.userid);
const messages = thread.messages.filter(id => !new Message().getId(id).deleted).map(id => new Message().getId(id));
const user = req.user;
const messages = await Promise.all(thread.messages.map(async id => {
const message = await new Message().getById(id)
return (message.deleted || !message) ? null : message;
}));
res.render("thread", { thread, messages, user })
} else
error(res, 404, "We have not got this thread.");
@ -46,22 +49,22 @@ app.get("/:id", (req, res) => {
app.use(require("../middlewares/login"));
app.post("/", (req, res) => {
const user = new User().getId(req.session.userid);
app.post("/", async (req, res) => {
if (req.ratelimit)
return error(res, 429, "Wait until " + new Date(req.timeout.until).toLocaleTimeString("tr") + ", you are too quick for send.")
const { title = null, content = null } = req.body;
if (!title || !content) return error(res, 400, "Title and content is missing");
if (!title || !content) return error(res, 400, "Title and/or content is missing");
const user = req.user
const thread = await new Thread(title, user).takeId()
const message = await new Message(content, user, thread.id).takeId()
const thread = new Thread(title, user).takeId().write();
thread
.push(new Message(content, user, thread).takeId().write().id)
.write();
thread.push(message.id).write();
message.write();
res.redirect('/threads/' + thread.id);
})

View File

@ -1,30 +1,30 @@
const { User } = require("../classes");
const db = require("quick.db")
const { Router } = require("express")
const error = require("../errors/error")
const { Router } = require("express");
const app = Router();
app.get("/", (req, res) => {
const user = new User().getId(req.session.userid)
const users = db.get("users").slice(0);
const error = require("../errors/error");
const { User } = require("../classes");
const { UserModel, MessageModel, ThreadModel } = require("../models");
app.get("/", async (req, res) => {
const user = req.user
const users = await UserModel.find({});
const links = users.filter(user => !user.deleted).map(user => "/users/" + user.id);
return res.render("users", { users, links, user })
});
app.get("/:id", (req, res) => {
const user = new User().getId(req.session.userid)
app.get("/:id", async (req, res) => {
const user = req.user
const { id = null } = req.params;
const member = new User().getId(req.params.id);
const member = await new User().getById(req.params.id);
if (member && (user?.admin || !member.deleted)) {
const message = db.get("messages").filter(message => message.author.id === Number(id)).length
const thread = db.get("threads").filter(thread => thread.author.id === Number(id)).length
const message = await MessageModel.count({ authorID: id });
const thread = await ThreadModel.count({ authorID: id });
const counts = { message, thread }
res.render("user", { user, member, counts })
}
@ -35,18 +35,19 @@ app.get("/:id", (req, res) => {
app.use(require("../middlewares/login"));
app.post("/:id/delete/", (req, res) => {
const user = new User().getId(req.session.userid);
app.post("/:id/delete/", async (req, res) => {
const user = req.user;
if (!user?.admin)
return error(res, 403, "You have not got permission for this.");
const id = req.url.slice(9 + 3)
const member = new User().getId(id);
const { id = null } = req.params;
const member = await new User().getById(id);
if (!member || member.deleted) return error(res, 404, "We have not got any user declared as this id.");
member.deleted = true;
member.write();
res.redirect("/admin");
});

View File

@ -1,6 +1,6 @@
import requests
# Headers for login to Akf-forum
# Headers for login to Akf-forum
headers = {
"username": "testUser",
"password": "testPassword"
@ -12,39 +12,24 @@ r = requests.get("http://localhost:3000/api/messages/1/", headers=headers)
print(r.json())
example_response = {
"status": 200,
"result":
{ # content of message
"content": "a",
# author of message
"author": {
"name": "ForumcuCocuk",
"avatar": "/images/guest.png",
"time": 1647177723873,
"admin": True,
"id": 1
'status': 200,
'result': {
'authorID': 0,
'content': 'a',
'author': {
'name': 'Akif9748',
'avatar': 'https://www.technopat.net/sosyal/data/avatars/o/298/298223.jpg?1644694020',
'time': 1649189944864,
'admin': False,
'deleted': False,
'id': 0
},
# UNIX Timestamp of message
"time": 1647178873587,
# thread information of message
"thread": {
"author": {
"name": "ForumcuCocuk",
"avatar": "/images/guest.png",
"time": 1647177723873,
"admin": True,
"id": 1
},
"title": "My",
"messages": [0], # ids of messages
"time": 1647178870047,
"deleted": False,
"id": 0
},
# Other informations about message
"deleted": False,
"edited": False,
"react": {},
"id": 1
'time': 1649189950166,
'threadID': 0,
'deleted': False,
'edited': False,
# Reactions: {userid: isLike (Bool)}
'react': {'0': True},
'id': 0
}
}

View File

@ -7,7 +7,7 @@ headers = {
}
r = requests.get("http://localhost:3000/api/threads/0", headers=headers)
r = requests.get("http://localhost:3000/api/threads/0/", headers=headers)
print(r.json())

View File

@ -9,7 +9,7 @@ headers = {
# Body for message parameters
body = {
"content": "This message sent via API",
"threadID": 1
"threadID": 0
}
r = requests.post("http://localhost:3000/api/messages/",

50
tests/post_thread.py Normal file
View File

@ -0,0 +1,50 @@
import requests
# Headers for login to Akf-forum
headers = {
"username": "testUser",
"password": "testPassword"
}
# Body for message parameters
body = {
"content": "This message sent via API",
"title": "This thread opened by API"
}
r = requests.post("http://localhost:3000/api/threads/",
headers=headers, data=body)
print(r.json())
example_response = {
'status': 200,
'result': {
'content': 'This message sent via API',
'author': {
'name': 'testUser',
'avatar': '',
'time': 1649009854217,
'admin': False,
'deleted': False,
'id': 2
},
'time': 1649010863471,
'thread': {
'author': {
'name': 'Akif9748',
'avatar': 'https://www.technopat.net/sosyal/data/avatars/o/298/298223.jpg?1644694020',
'time': 1647895891332, 'admin': True, 'deleted': False, 'id': 0
},
'title': 'API TEST',
'messages': [4, 6],
'time': 1649010834064,
'deleted': False,
'id': 1
},
'deleted': False,
'edited': False,
'react': {},
'id': 6
}
}

View File

@ -17,6 +17,7 @@
</h2>
<hr>
<% messages.forEach(message=>{ %>
<% if (message){ %>
<div id="message-<%= message.id %>" style="border: 2px solid #444444; padding: 10px;">
@ -57,7 +58,13 @@
</div>
<br>
<% } else { %>
<div id="deleted-message" style="border: 2px solid #444444; padding: 10px;">
<h1>DELETED MESSAGE</h1>
</div>
<% } %>
<br>
<% }); %>
<hr>

View File

@ -12,9 +12,8 @@
<ul>
<% threads.forEach(thread=>{ %>
<li>
<h1><a href=<%=links[threads.indexOf(thread)] %> > <%= thread.title %> by <%= thread.author.name
%></a>
</h1>
<h1 style="display: inline;"> <a href=<%= thread.getLink() %> ><%= thread.title %></a></h1>
<h3 style="display: inline;"> | By <%= thread.author.name %></h3>
</li>
<% }); %>
</ul>