better folder system
|
@ -6,14 +6,14 @@ A Node.js based forum software.
|
|||
- Run `npm i` to install **dependencies**.
|
||||
- Enter your database credentials in `.env`.
|
||||
- Run `npm start` for run it.
|
||||
- Go /setup page for setup your forum.
|
||||
- Go `/setup` page for setup your forum.
|
||||
|
||||
### Extra (If you are not use `setup` page)
|
||||
Run `node util/reset` to **reset the database** for duplicate key errors, and run `node util/admin` for give admin perms to first member.
|
||||
Edit `config.json` for default theme color (`black` or `white`) of users, and forum name, meta description, character limits, discord auth enabler, global ratelimit.
|
||||
Edit `config.json` for default theme for users, forum name, meta description, character limits, discord auth enabler, global ratelimit etc.
|
||||
|
||||
### How to install theme:
|
||||
- Copy your theme to `themes` folder.
|
||||
- Copy your theme to `src/themes` folder.
|
||||
Additional note for themes: If a theme has not got any .ejs file, it will use default theme's .ejs files. default theme is in themes folder, named as `common`.
|
||||
|
||||
### DISCORD AUTH:
|
||||
|
@ -62,7 +62,8 @@ Akf-forum has got an API for AJAX (fetch), other clients etc. And, you can learn
|
|||
- add support for transition around gravatar
|
||||
- BETTER SETUP PAGE
|
||||
- add used open source libraries to README.md
|
||||
- better folder system
|
||||
- send public to common/public
|
||||
- new screenshoots
|
||||
### front-end
|
||||
- text alling center body
|
||||
- add a css file for CodeMirror in threads / send message ok
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "akf-forum",
|
||||
"version": "5.2.2",
|
||||
"description": "A Node.js based forum software",
|
||||
"main": "index.js",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"start": "node .",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
require("dotenv").config();
|
||||
const
|
||||
{ def_theme, forum_name, description, limits, global_ratelimit: RLS, discord_auth, host } = require("./config.json"),
|
||||
{ def_theme, forum_name, description, limits, global_ratelimit: RLS, discord_auth, host } = require("../config.json"),
|
||||
{ UserModel, BanModel } = require("./models"),
|
||||
port = process.env.PORT || 3000,
|
||||
mongoose = require("mongoose"),
|
||||
|
@ -25,11 +25,11 @@ app.set("limits", limits);
|
|||
|
||||
if (RLS.enabled) app.use(RL(RLS.windowMs, RLS.max));
|
||||
|
||||
for (const theme of fs.readdirSync("./themes"))
|
||||
app.use(`/themes/${theme}`, express.static(`./themes/${theme}/public/`));
|
||||
for (const theme of fs.readdirSync(join(__dirname, "themes")))
|
||||
app.use(`/themes/${theme}`, express.static(join(__dirname, "themes", theme, "public")));
|
||||
|
||||
|
||||
app.use(express.static("public"), express.json(), express.urlencoded({ extended: true }), IP(),
|
||||
app.use(express.static(join(__dirname, "public")), express.json(), express.urlencoded({ extended: true }), IP(),
|
||||
SES({ secret: process.env.SECRET, store: MS.create({ clientPromise: DB, stringify: false }), resave: false, saveUninitialized: false }),
|
||||
async (req, res, next) => {
|
||||
if (app.ips.includes(req.clientIp)) return res.status(403).send("You are banned from this forum.");
|
||||
|
@ -73,7 +73,7 @@ app.use(express.static("public"), express.json(), express.urlencoded({ extended:
|
|||
if (discord_auth)
|
||||
app.set("discord_auth", `https://discord.com/api/oauth2/authorize?client_id=${discord_auth}&redirect_uri=${host}%2Fauth%2Fdiscord&response_type=code&scope=identify`);
|
||||
|
||||
for (const file of fs.readdirSync("./routes"))
|
||||
for (const file of fs.readdirSync(join(__dirname, "routes")))
|
||||
app.use("/" + file.replace(".js", ""), require(`./routes/${file}`));
|
||||
|
||||
app.all("*", (req, res) => res.error(404, "This page does not exist on this forum."));
|
|
@ -1,12 +1,12 @@
|
|||
const RL = require('express-rate-limit');
|
||||
const nodemailer = require("nodemailer");
|
||||
const config = require("./config.json");
|
||||
const config = require("../config.json");
|
||||
const crypto = require("crypto");
|
||||
const { readdirSync } = require('fs');
|
||||
|
||||
const { join } = require('path');
|
||||
require("dotenv").config();
|
||||
module.exports = {
|
||||
themes: readdirSync("./themes").filter(f => f !== "common").map(f => require(`./themes/${f}`)),
|
||||
themes: readdirSync(join(__dirname, "themes")).filter(f => f !== "common").map(f => require(`./themes/${f}`)),
|
||||
threadEnum: ["OPEN", "APPROVAL", "DELETED"],
|
||||
userEnum: ["ACTIVE", "APPROVAL", "DELETED", "BANNED"],
|
||||
RL(windowMs = 60_000, max = 1) {
|
|
@ -1,6 +1,6 @@
|
|||
const mongoose = require("mongoose");
|
||||
const cache = require("./cache");
|
||||
const { limits } = require("../config.json");
|
||||
const { limits } = require("../../config.json");
|
||||
|
||||
const schema = new mongoose.Schema({
|
||||
id: { type: String, unique: true },
|
|
@ -1,7 +1,7 @@
|
|||
const mongoose = require("mongoose");
|
||||
const cache = require("./cache")
|
||||
const MessageModel = require("./Message");
|
||||
const { limits, default_thread_state } = require("../config.json");
|
||||
const { limits, default_thread_state } = require("../../config.json");
|
||||
const { threadEnum } = require("../lib");
|
||||
const schema = new mongoose.Schema({
|
||||
id: { type: String, unique: true },
|
|
@ -1,5 +1,5 @@
|
|||
const mongoose = require("mongoose")
|
||||
const { def_theme, limits, default_user_state } = require("../config.json");
|
||||
const { def_theme, limits, default_user_state } = require("../../config.json");
|
||||
const { userEnum } = require("../lib");
|
||||
|
||||
const schema = new mongoose.Schema({
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
BIN
src/public/images/avatars/0.jpg
Normal file
After Width: | Height: | Size: 704 KiB |
BIN
src/public/images/avatars/1.jpg
Normal file
After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
@ -3,7 +3,7 @@ const app = Router();
|
|||
const fs = require("fs");
|
||||
const bcrypt = require("bcrypt");
|
||||
const { UserModel } = require("../../models");
|
||||
|
||||
const{join}=require("path");
|
||||
|
||||
app.use(async (req, res, next) => {
|
||||
res.error = (status, error) => res.status(status).json({ error });
|
||||
|
@ -31,7 +31,7 @@ app.use(async (req, res, next) => {
|
|||
|
||||
app.get("/me", (req, res) => res.complate(req.user))
|
||||
|
||||
for (const file of fs.readdirSync("./routes/api/routes"))
|
||||
for (const file of fs.readdirSync(join(__dirname, "routes")))
|
||||
app.use("/" + file.replace(".js", ""), require(`./routes/${file}`));
|
||||
|
||||
app.all("*", (req, res) => res.error(400, "Bad request"));
|
|
@ -16,10 +16,10 @@ app.get("/", (req, res) => {
|
|||
}
|
||||
});
|
||||
app.put("/", (req, res) => {
|
||||
const write= req.query.text ? req.body : JSON.stringify(req.body, null, 4)
|
||||
fs.writeFileSync("./config.json",write );
|
||||
require.cache[require.resolve("../../../config.json")] = require("../../../config.json");
|
||||
res.complate(require("../../../config.json"));
|
||||
const write = req.query.text ? req.body : JSON.stringify(req.body, null, 4)
|
||||
fs.writeFileSync("./config.json", write);
|
||||
require.cache[require.resolve("../../../../config.json")] = require("../../../../config.json");
|
||||
res.complate(require("../../../../config.json"));
|
||||
});
|
||||
|
||||
module.exports = app;
|
|
@ -3,7 +3,7 @@ const { Router } = require("express");
|
|||
const multer = require("multer");
|
||||
const { themes } = require("../../../lib")
|
||||
const app = Router();
|
||||
|
||||
const { join } = require("path");
|
||||
app.param("id", async (req, res, next, id) => {
|
||||
req.member = await UserModel.get(id, req.user.admin ? "+lastSeen +ips" : "");
|
||||
|
||||
|
@ -80,7 +80,7 @@ app.post("/:id/ban", async (req, res) => {
|
|||
});
|
||||
|
||||
const storage = multer.diskStorage({
|
||||
destination:'./public/images/avatars',
|
||||
destination: join(__dirname, "..", "..", "..", "public", "images", "avatars"),
|
||||
filename: function (req, _file, cb) {
|
||||
cb(null, req.member.id + ".jpg")
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ const storage = multer.diskStorage({
|
|||
const upload = multer({ storage })
|
||||
|
||||
app.post("/:id/avatar", upload.single('avatar'), async (req, res) => {
|
||||
|
||||
|
||||
const { member } = req;
|
||||
|
||||
if (req.user.id !== member.id && !req.user.admin) return res.error(403, "You have not got permission for this.");
|
|
@ -2,7 +2,7 @@ const { Router } = require("express")
|
|||
const { UserModel } = require("../models");
|
||||
const fetch = require("node-fetch");
|
||||
const app = Router();
|
||||
const { host, discord_auth, email_auth } = require("../config.json")
|
||||
const { host, discord_auth, email_auth } = require("../../config.json")
|
||||
|
||||
app.get("/discord", async (req, res) => {
|
||||
const client_id = discord_auth;
|
|
@ -3,7 +3,7 @@ const { Router } = require("express")
|
|||
const bcrypt = require("bcrypt");
|
||||
const { RL, transporter, emailRegEx, getGravatar } = require('../lib');
|
||||
const app = Router();
|
||||
const { email_auth, forum_name, host } = require("../config.json");
|
||||
const { email_auth, forum_name, host } = require("../../config.json");
|
||||
app.get("/", (req, res) => res.reply("register", { user: null, discord: req.app.get("discord_auth"), mail: email_auth }));
|
||||
|
||||
app.post("/", RL(24 * 60 * 60_000, 5), async (req, res) => {
|
|
@ -27,7 +27,7 @@ app.post("/", async (req, res) => {
|
|||
original[key] = content[key];
|
||||
|
||||
fs.writeFileSync("./config.json", JSON.stringify(original, null, 4));
|
||||
require.cache[require.resolve("../config.json")] = require("../config.json");
|
||||
require.cache[require.resolve("../../config.json")] = require("../../config.json");
|
||||
res.redirect("/register");
|
||||
})
|
||||
|
|
@ -3,7 +3,7 @@ require("dotenv").config();
|
|||
|
||||
mongoose.connect(process.env.MONGO_DB_URL, () => console.log("Database is connected"));
|
||||
|
||||
const { UserModel } = require("../models");
|
||||
const { UserModel } = require("../src/models");
|
||||
(async () => {
|
||||
|
||||
const member = await UserModel.get("0");
|
||||
|
|
|
@ -3,6 +3,6 @@ require("dotenv").config();
|
|||
|
||||
mongoose.connect(process.env.MONGO_DB_URL, () => console.log("Database is connected"));
|
||||
|
||||
const Models = require("../models");
|
||||
const Models = require("../src/models");
|
||||
|
||||
Object.values(Models).forEach(model => model.collection.drop().then(console.log));
|
||||
|
|