mirror of
https://github.com/Akif9748/akf-forum.git
synced 2024-12-22 07:39:08 +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.
|
||||
|
||||
## 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?
|
||||
|
||||
### 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
|
||||
- categories page is need a update.
|
||||
- preview for send messages in markdown format.
|
||||
- Limits for thread title, message content, username, user about
|
||||
- desp => description
|
||||
|
||||
## Major Version History
|
||||
|
|
|
@ -5,7 +5,7 @@ const schema = new mongoose.Schema({
|
|||
author: Object,
|
||||
threadID: String,
|
||||
authorID: String,
|
||||
content: String,
|
||||
content: { type: String, maxlength: 1024 },
|
||||
time: { type: Date, default: Date.now },
|
||||
deleted: { type: Boolean, default: false },
|
||||
edited: { type: Boolean, default: false },
|
||||
|
@ -30,7 +30,7 @@ const model = mongoose.model('message', schema);
|
|||
|
||||
model.get = async id => {
|
||||
const message = await model.findOne({ id })
|
||||
return await message.get_author();
|
||||
return await message.get_author();
|
||||
};
|
||||
|
||||
module.exports = model;
|
|
@ -1,7 +1,7 @@
|
|||
const mongoose = require("mongoose")
|
||||
|
||||
const schema = new mongoose.Schema({
|
||||
username: { type: String, unique: true },
|
||||
username: { type: String, unique: true, maxlength: 25 },
|
||||
password: String,
|
||||
id: { type: String, unique: true }
|
||||
});
|
||||
|
|
|
@ -8,7 +8,7 @@ const schema = new mongoose.Schema({
|
|||
authorID: String,
|
||||
author: Object,
|
||||
|
||||
title: String,
|
||||
title: { type: String, maxlength: 128 },
|
||||
time: { type: Date, default: Date.now },
|
||||
deleted: { type: Boolean, default: false },
|
||||
edited: { type: Boolean, default: false },
|
||||
|
@ -21,10 +21,10 @@ const schema = new mongoose.Schema({
|
|||
|
||||
schema.methods.get_author = cache.getAuthor;
|
||||
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) {
|
||||
const query = { threadID: this.id };
|
||||
const query = { threadID: this.id };
|
||||
if (!admin) query.deleted = false;
|
||||
return await MessageModel.count(query) || 0;
|
||||
};
|
||||
|
@ -47,7 +47,7 @@ const model = mongoose.model('thread', schema);
|
|||
|
||||
model.get = async id => {
|
||||
const thread = await model.findOne({ id })
|
||||
return await thread.get_author();
|
||||
return await thread.get_author();
|
||||
};
|
||||
|
||||
module.exports = model;
|
|
@ -1,14 +1,13 @@
|
|||
const mongoose = require("mongoose")
|
||||
const { def_theme } = require("../config.json");
|
||||
const schema = new mongoose.Schema({
|
||||
id: { type: String },
|
||||
|
||||
name: String,
|
||||
id: { type: String, unique: true },
|
||||
name: { type: String, maxlength: 25 },
|
||||
avatar: { type: String, default: "/images/avatars/default.jpg" },
|
||||
time: { type: Date, default: Date.now },
|
||||
deleted: { type: Boolean, default: false },
|
||||
edited: { type: Boolean, default: false },
|
||||
about: { type: String, default: "" },
|
||||
about: { type: String, default: "", maxlength: 256 },
|
||||
admin: { type: Boolean, default: false },
|
||||
theme: { type: String, default: def_theme },
|
||||
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.");
|
||||
const { content = null } = req.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.edited = true;
|
||||
|
||||
|
@ -43,6 +45,7 @@ app.post("/", rateLimit({
|
|||
|
||||
const { threadID, content } = req.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);
|
||||
|
||||
|
|
|
@ -41,7 +41,8 @@ app.post("/", async (req, res) => {
|
|||
const { title, content, category } = req.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 thread = await new ThreadModel({ title, author: user }).takeId()
|
||||
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.");
|
||||
const { title } = req.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;
|
||||
await thread.save();
|
||||
|
||||
|
|
|
@ -5,10 +5,10 @@ const multer = require("multer");
|
|||
const app = Router();
|
||||
|
||||
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.deleted && !req.user?.admin)
|
||||
return res.error(404, `You do not have permissions to view this 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 (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 });
|
||||
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 (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")
|
||||
}), async (req, res) => {
|
||||
|
||||
req.session.userID=null;
|
||||
req.session.userID = null;
|
||||
|
||||
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 });
|
||||
|
||||
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.save();
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
|
||||
<form>
|
||||
<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>
|
||||
<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>
|
||||
</form>
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
|||
document.addEventListener("submit", async e => {
|
||||
e.preventDefault();
|
||||
const data = new FormData(e.target);
|
||||
|
||||
|
||||
const response = await request("/api/categories/", "POST", {
|
||||
name: data.get("name"),
|
||||
desp: data.get("desp")
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
|
||||
|
||||
<form>
|
||||
<h2 class="title" style="align-self: baseline;">Title:</h2>
|
||||
<input name="title" class="input"></input>
|
||||
<h2 class="title"style="align-self: baseline;">Title:</h2>
|
||||
<input name="title" maxlength="128" class="input" required></input>
|
||||
<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>
|
||||
|
||||
<select name="category">
|
||||
|
|
|
@ -12,13 +12,9 @@
|
|||
<h1 class="title">Register</h1>
|
||||
|
||||
<form action="/register" method="post">
|
||||
|
||||
|
||||
<input type="text" name="username" placeholder="Username" class="input" required>
|
||||
|
||||
<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="text" name="username" maxlength="25" placeholder="Username" class="input" required>
|
||||
<input type="password" name="password" maxlength="25" placeholder="Password" class="input" required>
|
||||
<textarea class="input" name="about" rows="4" maxlength="256" placeholder="About you... You can use markdown"></textarea>
|
||||
<input type="submit" class="btn-primary" style="width:100%;" value="Register">
|
||||
</form>
|
||||
|
||||
|
|
|
@ -109,11 +109,10 @@
|
|||
|
||||
<div class="message" id="send-div">
|
||||
<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="page" type="hidden" value="<%= page %>"></input>
|
||||
<button class="btn-primary">Send!</button>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -28,9 +28,9 @@
|
|||
<h1 class="title" style="text-align:center;">Edit <a class="see" href="/users/<%= member.id %>"><%= member.name %></a></h1>
|
||||
<div class="content">
|
||||
<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){ %>
|
||||
Is Admin? <input id='admin' type='checkbox' value='true' name='admin' <%=member.admin ? "checked": ""%>>
|
||||
<input id='adminHidden' type='hidden' value='false' name='admin'>
|
||||
|
|
Loading…
Reference in a new issue