diff --git a/.gitignore b/.gitignore index 6854423..4d2b33e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,5 @@ node_modules/ # env .env -# Test files: -a.js -db.js \ No newline at end of file +# Test files +test.js \ No newline at end of file diff --git a/README.md b/README.md index 76c83ef..1866ee6 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ A Node.js based forum software. ### Extra Run `node util/reset` to **reset the database**, and run `node util/admin` for give admin perms to first member. +Edit `config.json` for default themes of users... ## API Akf-forum has got an API for AJAX, other clients etc. And, you can learn about API in `util/APIDOCS.md`. @@ -43,6 +44,7 @@ Akf-forum has got an API for AJAX, other clients etc. And, you can learn about A | Message count | 🟢 | MEDIUM | | Delete user | 🟢 | HIGH | | Undelete | 🟢 | MEDIUM | +| PM | 🔴 | MEDIUM | | About me | 🔴 | LOW | | Edit user | 🔴 | HIGH | | IP ban | 🔴 | MEDIUM | @@ -81,13 +83,13 @@ Akf-forum has got an API for AJAX, other clients etc. And, you can learn about A ### Other | To do | Is done? | Priority | | ----- | -------- | -------- | -| Footer | 🔴 | LOW | +| from form to AJAX | 🟢 | HIGH | | auto-scroll | 🟢 | LOW | | Multi-theme support, black theme | 🟡 | LOW | | Search | 🔴 | MEDIUM | | Page support, support message limit correct | 🔴 | MEDIUM | -| from form to AJAX | 🟢 | HIGH | - +| Locales | 🔴 | MEDIUM | +| Footer | 🔴 | LOW | ## Major Version History - V3: New Theme - V2: Backend fix, mongoose is fixed. Really big fix. diff --git a/config.json b/config.json new file mode 100644 index 0000000..426dadc --- /dev/null +++ b/config.json @@ -0,0 +1,3 @@ +{ + "def_theme": "default" +} \ No newline at end of file diff --git a/index.js b/index.js index 1106a40..689aec9 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,6 @@ -const { UserModel } = require("./models"), +const { def_theme } = require("./config.json"), session = require('express-session'), + { UserModel } = require("./models"), bodyParser = require('body-parser'), port = process.env.PORT || 3000, mongoose = require("mongoose"), @@ -17,7 +18,11 @@ app.set("view engine", "ejs"); app.use(express.json()); app.use(async (req, res, next) => { req.user = await UserModel.get(req.session.userid); - res.error = (type, error) => res.status(type).render("error", {user: req.user, type, error }); + res.reply = (page, options = {}, status = 200) => res.status(status) + .render(page, { user: req.user, theme: req.user?.theme || def_theme, ...options }); + + res.error = (type, error) => res.reply("error", { type, error }, type); + if (req.user?.deleted) { req.session.destroy(); return res.error(403, "Your account has been deleted."); diff --git a/models/User.js b/models/User.js index 662dd57..d1b3426 100644 --- a/models/User.js +++ b/models/User.js @@ -1,5 +1,5 @@ const mongoose = require("mongoose") - +const { def_theme } = require("../config.json"); const schema = new mongoose.Schema({ id: { type: String }, @@ -7,7 +7,8 @@ const schema = new mongoose.Schema({ avatar: { type: String, default: "/images/guest.png" }, time: { type: Date, default: Date.now }, deleted: { type: Boolean, default: false }, - admin: { type: Boolean, default: false } + admin: { type: Boolean, default: false }, + theme: { type: String, default: def_theme } }); diff --git a/routes/.js b/routes/.js index 81dcdc8..1c96c6e 100644 --- a/routes/.js +++ b/routes/.js @@ -12,7 +12,7 @@ app.get("/", async (req, res) => { messages = await MessageModel.count({deleted:false}), user = req.user; - res.render("index", { mem, user, users, threads, messages }) + res.reply("index", { mem, users, threads, messages }) }) diff --git a/routes/admin.js b/routes/admin.js index f0bda0e..d662bef 100644 --- a/routes/admin.js +++ b/routes/admin.js @@ -9,7 +9,7 @@ app.get("/", async (req, res) => { if (!user?.admin) return res.error( 403, "You have not got permissions for view to this page."); - res.render("admin", { user, user2: false }) + res.reply("admin", { user2: false }) }); diff --git a/routes/login.js b/routes/login.js index bb3732b..93d1ad1 100644 --- a/routes/login.js +++ b/routes/login.js @@ -3,7 +3,7 @@ const { Router } = require("express"); const app = Router(); const bcrypt = require("bcrypt"); -app.get("/", (req, res) => res.render("login",{redirect: req.query.redirect,user:null})); +app.get("/", (req, res) => res.reply("login",{redirect: req.query.redirect,user:null})); app.post("/", async (req, res) => { req.session.userid = null; diff --git a/routes/register.js b/routes/register.js index 31b9c15..0ec89f4 100644 --- a/routes/register.js +++ b/routes/register.js @@ -5,42 +5,35 @@ const rateLimit = require('express-rate-limit') const app = Router(); -app.get("/", (req, res) => res.render("register",{user:null})); +app.get("/", (req, res) => res.reply("register", { user: null })); app.post("/", rateLimit({ - windowMs: 24*60*60_000, max: 1, standardHeaders: true, legacyHeaders: false, - handler: (request, response, next, options) => - response.error(options.statusCode, "You are begin ratelimited") - + windowMs: 24 * 60 * 60_000, max: 1, standardHeaders: true, legacyHeaders: false, + handler: (_r, response, _n, options) => response.error(options.statusCode, "You are begin ratelimited") }), async (req, res) => { req.session.userid = null; - let { username = null, password = null, avatar } = req.body; + let { username = null, password: body_pass = null, avatar } = req.body; - if (username && password) { - const user = await SecretModel.findOne({ username }); + if (!username || !body_pass) return res.error(res, 400, "You forgot entering some values"); + const user = await SecretModel.findOne({ username }); - if (user) - res.error(res, 400, `We have got an user named ${username}!`) - - else { + if (user) return res.error(res, 400, `We have got an user named ${username}!`) - const user2 = new UserModel({ name: req.body.username, avatar }) - await user2.takeId() - await user2.save(); + const user2 = new UserModel({ name: req.body.username }) + if (avatar) user2.avatar = 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; + const salt = await bcrypt.genSalt(10); + const password = await bcrypt.hash(body_pass, salt); + await SecretModel.create({ username, password, id: user2.id }) + req.session.userid = user2.id; - res.redirect('/'); - } + res.redirect('/'); - } else - res.error(res, 400, "You forgot entering some values") }) diff --git a/routes/threads.js b/routes/threads.js index ca5aa6f..29668f5 100644 --- a/routes/threads.js +++ b/routes/threads.js @@ -6,19 +6,14 @@ const { ThreadModel, MessageModel } = require("../models") app.get("/", async (req, res) => { - const user = req.user; + const threads = await ThreadModel.find(req.user?.admin ? {} : { deleted: false }).limit(10); - const threads = await ThreadModel.find(user?.admin ? {} : { deleted: false }).limit(10); - - return res.render("threads", { threads, user }); + return res.reply("threads", { threads }); }); app.get("/create*", async (req, res) => { - - const user = req.user - res.render("create_thread", { user }) - + res.reply("create_thread") }); app.get("/:id", async (req, res) => { @@ -31,13 +26,13 @@ app.get("/:id", async (req, res) => { if (thread && (user?.admin || !thread.deleted)) { const messages = await Promise.all(thread.messages.map(async id => { - const message = await MessageModel.get(id) + const message = await MessageModel.get(id) return user?.admin || !message?.deleted ? message.toObject({ virtuals: true }) : null; })); - res.render("thread", { thread, messages, user,scroll:req.query.scroll || false }); + res.reply("thread", { thread, messages, scroll: req.query.scroll || false }); } else - res.error( 404, "We have not got this thread."); + res.error(404, "We have not got this thread."); }); diff --git a/routes/users.js b/routes/users.js index 32e301c..2bcda13 100644 --- a/routes/users.js +++ b/routes/users.js @@ -5,7 +5,7 @@ const { UserModel, MessageModel, ThreadModel } = require("../models"); app.get("/", async ({ user }, res) => { const users = await UserModel.find(user?.admin ? {} : { deleted: false }); - return res.render("users", { users, user }) + return res.reply("users", { users }) }); @@ -19,7 +19,7 @@ app.get("/:id", async (req, res) => { const message = await MessageModel.count({ "author.id": id });// this place was having problem. fixed const thread = await ThreadModel.count({ "author.id": id }); - res.render("user", { user, member, counts: { message, thread } }) + res.reply("user", { member, counts: { message, thread } }) } else res.error(404, "We have not got this user."); diff --git a/views/create_thread.ejs b/views/create_thread.ejs index f53edb8..743f81d 100644 --- a/views/create_thread.ejs +++ b/views/create_thread.ejs @@ -3,10 +3,11 @@ <%- include("extra/meta", {title: "Create thread!" }) %> - + + <%- include("extra/navbar") %> diff --git a/views/thread.ejs b/views/thread.ejs index 10da760..310b4ce 100644 --- a/views/thread.ejs +++ b/views/thread.ejs @@ -15,8 +15,8 @@ <%= thread.title %> -

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

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

<% if (user && !thread.deleted){ %> diff --git a/views/user.ejs b/views/user.ejs index 369c458..3dabfba 100644 --- a/views/user.ejs +++ b/views/user.ejs @@ -10,7 +10,7 @@