mirror of
https://github.com/Akif9748/akf-forum.git
synced 2024-11-22 20:10:40 +03:00
Added char limits
This commit is contained in:
parent
171f83f4cf
commit
1cbcd16954
15 changed files with 55 additions and 38 deletions
|
@ -13,6 +13,12 @@ You need this headers for send request to API:
|
||||||
```
|
```
|
||||||
But in front end, the API will works with session.
|
But in front end, the API will works with session.
|
||||||
|
|
||||||
|
## Limits:
|
||||||
|
- 3 - 25 char for username, password and category name
|
||||||
|
- 256 char for user about and desp of category
|
||||||
|
- 5 - 128 char for thread titles.
|
||||||
|
- 5 - 1024 char for messages.
|
||||||
|
|
||||||
## How to request?
|
## How to request?
|
||||||
|
|
||||||
### Request types:
|
### Request types:
|
||||||
|
|
|
@ -43,7 +43,6 @@ Akf-forum has got an API for AJAX (fetch), other clients etc. And, you can learn
|
||||||
- upload other photos, model for it
|
- upload other photos, model for it
|
||||||
- categories page is need a update.
|
- categories page is need a update.
|
||||||
- preview for send messages in markdown format.
|
- preview for send messages in markdown format.
|
||||||
- Limits for thread title, message content, username, user about
|
|
||||||
- desp => description
|
- desp => description
|
||||||
|
|
||||||
## Major Version History
|
## Major Version History
|
||||||
|
|
|
@ -5,7 +5,7 @@ const schema = new mongoose.Schema({
|
||||||
author: Object,
|
author: Object,
|
||||||
threadID: String,
|
threadID: String,
|
||||||
authorID: String,
|
authorID: String,
|
||||||
content: String,
|
content: { type: String, maxlength: 1024 },
|
||||||
time: { type: Date, default: Date.now },
|
time: { type: Date, default: Date.now },
|
||||||
deleted: { type: Boolean, default: false },
|
deleted: { type: Boolean, default: false },
|
||||||
edited: { type: Boolean, default: false },
|
edited: { type: Boolean, default: false },
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const mongoose = require("mongoose")
|
const mongoose = require("mongoose")
|
||||||
|
|
||||||
const schema = new mongoose.Schema({
|
const schema = new mongoose.Schema({
|
||||||
username: { type: String, unique: true },
|
username: { type: String, unique: true, maxlength: 25 },
|
||||||
password: String,
|
password: String,
|
||||||
id: { type: String, unique: true }
|
id: { type: String, unique: true }
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,7 @@ const schema = new mongoose.Schema({
|
||||||
authorID: String,
|
authorID: String,
|
||||||
author: Object,
|
author: Object,
|
||||||
|
|
||||||
title: String,
|
title: { type: String, maxlength: 128 },
|
||||||
time: { type: Date, default: Date.now },
|
time: { type: Date, default: Date.now },
|
||||||
deleted: { type: Boolean, default: false },
|
deleted: { type: Boolean, default: false },
|
||||||
edited: { type: Boolean, default: false },
|
edited: { type: Boolean, default: false },
|
||||||
|
@ -21,7 +21,7 @@ const schema = new mongoose.Schema({
|
||||||
|
|
||||||
schema.methods.get_author = cache.getAuthor;
|
schema.methods.get_author = cache.getAuthor;
|
||||||
schema.methods.get_category = () => async function () {
|
schema.methods.get_category = () => async function () {
|
||||||
return await require("./Category").findOne({ id: this.categoryID }) || {id: this.categoryID, name: "Unknown"} ;
|
return await require("./Category").findOne({ id: this.categoryID }) || { id: this.categoryID, name: "Unknown" };
|
||||||
}
|
}
|
||||||
schema.methods.messageCount = async function (admin = false) {
|
schema.methods.messageCount = async function (admin = false) {
|
||||||
const query = { threadID: this.id };
|
const query = { threadID: this.id };
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
const mongoose = require("mongoose")
|
const mongoose = require("mongoose")
|
||||||
const { def_theme } = require("../config.json");
|
const { def_theme } = require("../config.json");
|
||||||
const schema = new mongoose.Schema({
|
const schema = new mongoose.Schema({
|
||||||
id: { type: String },
|
id: { type: String, unique: true },
|
||||||
|
name: { type: String, maxlength: 25 },
|
||||||
name: String,
|
|
||||||
avatar: { type: String, default: "/images/avatars/default.jpg" },
|
avatar: { type: String, default: "/images/avatars/default.jpg" },
|
||||||
time: { type: Date, default: Date.now },
|
time: { type: Date, default: Date.now },
|
||||||
deleted: { type: Boolean, default: false },
|
deleted: { type: Boolean, default: false },
|
||||||
edited: { type: Boolean, default: false },
|
edited: { type: Boolean, default: false },
|
||||||
about: { type: String, default: "" },
|
about: { type: String, default: "", maxlength: 256 },
|
||||||
admin: { type: Boolean, default: false },
|
admin: { type: Boolean, default: false },
|
||||||
theme: { type: String, default: def_theme },
|
theme: { type: String, default: def_theme },
|
||||||
lastSeen: { type: Date, default: Date.now, select: false },
|
lastSeen: { type: Date, default: Date.now, select: false },
|
||||||
|
|
|
@ -27,6 +27,8 @@ app.patch("/:id/", async (req, res) => {
|
||||||
if (user.id !== message.authorID && !user.admin) return res.error(403, "You have not got permission for this.");
|
if (user.id !== message.authorID && !user.admin) return res.error(403, "You have not got permission for this.");
|
||||||
const { content = null } = req.body;
|
const { content = null } = req.body;
|
||||||
if (!content) return res.error(400, "Missing message content in request body.");
|
if (!content) return res.error(400, "Missing message content in request body.");
|
||||||
|
if (content.length < 5 || content.length > 1024) return res.error(400, "content must be between 5 - 1024 characters");
|
||||||
|
|
||||||
message.content = content;
|
message.content = content;
|
||||||
message.edited = true;
|
message.edited = true;
|
||||||
|
|
||||||
|
@ -43,6 +45,7 @@ app.post("/", rateLimit({
|
||||||
|
|
||||||
const { threadID, content } = req.body;
|
const { threadID, content } = req.body;
|
||||||
if (!content) return res.error(400, "Missing message content in request body.");
|
if (!content) return res.error(400, "Missing message content in request body.");
|
||||||
|
if (content.length < 5 || content.length > 1024) return res.error(400, "content must be between 5 - 1024 characters");
|
||||||
|
|
||||||
const thread = await ThreadModel.get(threadID);
|
const thread = await ThreadModel.get(threadID);
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,8 @@ app.post("/", async (req, res) => {
|
||||||
const { title, content, category } = req.body;
|
const { title, content, category } = req.body;
|
||||||
|
|
||||||
if (!content || !title) return res.error(400, "Missing content/title in request body.");
|
if (!content || !title) return res.error(400, "Missing content/title in request body.");
|
||||||
|
if (title.length < 5 || title.length > 128) return res.error(400, "title must be between 5 - 128 characters");
|
||||||
|
if (content.length < 5 || content.length > 1024) return res.error(400, "content must be between 5 - 1024 characters");
|
||||||
const { user } = req;
|
const { user } = req;
|
||||||
const thread = await new ThreadModel({ title, author: user }).takeId()
|
const thread = await new ThreadModel({ title, author: user }).takeId()
|
||||||
if (category)
|
if (category)
|
||||||
|
@ -60,6 +61,8 @@ app.patch("/:id/", async (req, res) => {
|
||||||
if (user.id !== thread.authorID && !user.admin) return res.error(403, "You have not got permission for this.");
|
if (user.id !== thread.authorID && !user.admin) return res.error(403, "You have not got permission for this.");
|
||||||
const { title } = req.body;
|
const { title } = req.body;
|
||||||
if (!title) return res.error(400, "Missing thread title in request body.");
|
if (!title) return res.error(400, "Missing thread title in request body.");
|
||||||
|
if (title.length < 5 || title.length > 128) return res.error(400, "title must be between 5 - 128 characters");
|
||||||
|
|
||||||
thread.title = title;
|
thread.title = title;
|
||||||
await thread.save();
|
await thread.save();
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ const multer = require("multer");
|
||||||
const app = Router();
|
const app = Router();
|
||||||
|
|
||||||
app.param("id", async (req, res, next, id) => {
|
app.param("id", async (req, res, next, id) => {
|
||||||
req.member = await UserModel.get(id, req.user.admin ? "+lastSeen": "");
|
req.member = await UserModel.get(id, req.user.admin ? "+lastSeen" : "");
|
||||||
|
|
||||||
if (!req.member) return res.error(404, `We don't have any user with id ${id}.`);
|
if (!req.member) return res.error(404, `We don't have any user with id ${id}.`);
|
||||||
|
|
||||||
|
@ -58,12 +58,18 @@ app.patch("/:id/", async (req, res) => {
|
||||||
|
|
||||||
if ((admin?.length || "deleted" in req.body) && !req.user.admin) return res.error(403, "You have not got permission for edit 'admin' and 'deleted' information, or bad request.");
|
if ((admin?.length || "deleted" in req.body) && !req.user.admin) return res.error(403, "You have not got permission for edit 'admin' and 'deleted' information, or bad request.");
|
||||||
|
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
|
|
||||||
|
if (name.length < 3 || name.length > 25) return res.error(400, "Username must be between 3 - 25 characters");
|
||||||
await SecretModel.updateOne({ id: member.id }, { username: name });
|
await SecretModel.updateOne({ id: member.id }, { username: name });
|
||||||
member.name = name;
|
member.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (about) member.about = about;
|
if (about) {
|
||||||
|
if (about.length > 256) return res.error(400, "About must be under 256 characters");
|
||||||
|
member.about = about;
|
||||||
|
}
|
||||||
if (theme || ["default", "black"].includes(theme)) member.theme = theme;
|
if (theme || ["default", "black"].includes(theme)) member.theme = theme;
|
||||||
|
|
||||||
if (typeof admin === "boolean" || ["false", "true"].includes(admin)) member.admin = admin;
|
if (typeof admin === "boolean" || ["false", "true"].includes(admin)) member.admin = admin;
|
||||||
|
|
|
@ -11,18 +11,24 @@ app.post("/", rateLimit({
|
||||||
handler: (_r, response, _n, options) => response.error(options.statusCode, "You are begin ratelimited")
|
handler: (_r, response, _n, options) => response.error(options.statusCode, "You are begin ratelimited")
|
||||||
}), async (req, res) => {
|
}), async (req, res) => {
|
||||||
|
|
||||||
req.session.userID=null;
|
req.session.userID = null;
|
||||||
|
|
||||||
let { username = null, password: body_pass = null, about } = req.body;
|
let { username = null, password: body_pass = null, about } = req.body;
|
||||||
|
|
||||||
if (!username || !body_pass) return res.error(res, 400, "You forgot entering some values");
|
if (!username || !body_pass) return res.error(400, "You forgot entering some values");
|
||||||
|
if (username.length < 3 || username.length > 25) return res.error(400, "Username must be between 3 - 25 characters");
|
||||||
|
if (body_pass.length < 3 || body_pass.length > 25) return res.error(400, "Password must be between 3 - 25 characters");
|
||||||
|
|
||||||
const user = await SecretModel.findOne({ username });
|
const user = await SecretModel.findOne({ username });
|
||||||
|
|
||||||
if (user) return res.error(res, 400, `We have got an user named ${username}!`)
|
if (user) return res.error(400, `We have got an user named ${username}!`)
|
||||||
|
|
||||||
const user2 = new UserModel({ name: req.body.username })
|
const user2 = new UserModel({ name: username })
|
||||||
|
|
||||||
if (about) user2.about = about;
|
if (about) {
|
||||||
|
if (about.length > 256) return res.error(400, "about must be under 256 characters");
|
||||||
|
user2.about = about;
|
||||||
|
}
|
||||||
|
|
||||||
await user2.takeId()
|
await user2.takeId()
|
||||||
await user2.save();
|
await user2.save();
|
||||||
|
|
|
@ -9,9 +9,9 @@
|
||||||
|
|
||||||
<form>
|
<form>
|
||||||
<h2 class="title" style="align-self: baseline;">Name:</h2>
|
<h2 class="title" style="align-self: baseline;">Name:</h2>
|
||||||
<input name="name" class="input"></input>
|
<input name="name" class="input" required maxlength="25" ></input>
|
||||||
<h2 class="title" style="align-self: baseline;">Description:</h2>
|
<h2 class="title" style="align-self: baseline;">Description:</h2>
|
||||||
<textarea rows="4" cols="50" name="desp" class="input"></textarea>
|
<textarea rows="4" cols="50" name="desp" maxlength="256" class="input" required></textarea>
|
||||||
<button class="btn-primary" style="width:100%" type="submit">Create Category!</button>
|
<button class="btn-primary" style="width:100%" type="submit">Create Category!</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
|
|
||||||
|
|
||||||
<form>
|
<form>
|
||||||
<h2 class="title" style="align-self: baseline;">Title:</h2>
|
<h2 class="title"style="align-self: baseline;">Title:</h2>
|
||||||
<input name="title" class="input"></input>
|
<input name="title" maxlength="128" class="input" required></input>
|
||||||
<h2 class="title" style="align-self: baseline;">Content:</h2>
|
<h2 class="title" style="align-self: baseline;">Content:</h2>
|
||||||
<textarea rows="4" cols="50" name="content" class="input"></textarea>
|
<textarea rows="4" cols="50" maxlength="1024" name="content" class="input" required></textarea>
|
||||||
<h2 class="title" style="align-self: baseline;">Category:</h2>
|
<h2 class="title" style="align-self: baseline;">Category:</h2>
|
||||||
|
|
||||||
<select name="category">
|
<select name="category">
|
||||||
|
|
|
@ -12,13 +12,9 @@
|
||||||
<h1 class="title">Register</h1>
|
<h1 class="title">Register</h1>
|
||||||
|
|
||||||
<form action="/register" method="post">
|
<form action="/register" method="post">
|
||||||
|
<input type="text" name="username" maxlength="25" placeholder="Username" class="input" required>
|
||||||
|
<input type="password" name="password" maxlength="25" placeholder="Password" class="input" required>
|
||||||
<input type="text" name="username" placeholder="Username" class="input" required>
|
<textarea class="input" name="about" rows="4" maxlength="256" placeholder="About you... You can use markdown"></textarea>
|
||||||
|
|
||||||
<input type="password" name="password" placeholder="Password" class="input" required>
|
|
||||||
|
|
||||||
<textarea class="input" name="about" rows="4" placeholder="About you... Not required"></textarea>
|
|
||||||
<input type="submit" class="btn-primary" style="width:100%;" value="Register">
|
<input type="submit" class="btn-primary" style="width:100%;" value="Register">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
|
@ -109,11 +109,10 @@
|
||||||
|
|
||||||
<div class="message" id="send-div">
|
<div class="message" id="send-div">
|
||||||
<form id="send" style="width:100%">
|
<form id="send" style="width:100%">
|
||||||
<textarea rows="4" name="content"></textarea>
|
<textarea rows="4" maxlength="1024" name="content" required></textarea>
|
||||||
<input name="threadID" type="hidden" value="<%= thread.id %>"></input>
|
<input name="threadID" type="hidden" value="<%= thread.id %>"></input>
|
||||||
<input name="page" type="hidden" value="<%= page %>"></input>
|
<input name="page" type="hidden" value="<%= page %>"></input>
|
||||||
<button class="btn-primary">Send!</button>
|
<button class="btn-primary">Send!</button>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -28,9 +28,9 @@
|
||||||
<h1 class="title" style="text-align:center;">Edit <a class="see" href="/users/<%= member.id %>"><%= member.name %></a></h1>
|
<h1 class="title" style="text-align:center;">Edit <a class="see" href="/users/<%= member.id %>"><%= member.name %></a></h1>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<form id="form" class="see" style="box-shadow:none">
|
<form id="form" class="see" style="box-shadow:none">
|
||||||
<input type="text" name="name" placeholder="<%=member.name%>" class="input">
|
<input type="text" name="name" minlength="3" maxlength="25" placeholder="<%=member.name%>" class="input" required>
|
||||||
|
|
||||||
<textarea class="input" name="about" rows="4" cols="60" name="content" placeholder="<%=member.about%>"></textarea>
|
<textarea class="input" name="about" maxlength="256" required rows="4" cols="60" name="content" placeholder="<%=member.about%>"></textarea>
|
||||||
<% if (user?.admin){ %>
|
<% if (user?.admin){ %>
|
||||||
Is Admin? <input id='admin' type='checkbox' value='true' name='admin' <%=member.admin ? "checked": ""%>>
|
Is Admin? <input id='admin' type='checkbox' value='true' name='admin' <%=member.admin ? "checked": ""%>>
|
||||||
<input id='adminHidden' type='hidden' value='false' name='admin'>
|
<input id='adminHidden' type='hidden' value='false' name='admin'>
|
||||||
|
|
Loading…
Reference in a new issue