forked from dachan/dach
moved authorization and authetication to separate middleware
This commit is contained in:
parent
95efd1c332
commit
4d13d11f60
|
@ -0,0 +1,29 @@
|
||||||
|
let tokens = {};
|
||||||
|
|
||||||
|
function credentialsLog (req, res) {
|
||||||
|
console.log(`Login: ${req.session.login}`);
|
||||||
|
console.log(`Token: ${req.session.token}`);
|
||||||
|
console.log(`Tokens[login]: ${tokens[req.session.login]}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
function authenticate (req, res, next) {
|
||||||
|
credentialsLog(req, res)
|
||||||
|
if (!req.session.login || !req.session.token)
|
||||||
|
return res.status(403).send("Either login or token was not specified")
|
||||||
|
if (tokens[req.session.login] != req.session.token)
|
||||||
|
return res.status(403).send("Invalid credentials");
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
function authorize (req, res, next) {
|
||||||
|
credentialsLog(req, res)
|
||||||
|
// if (!req.session.login || !req.session.token)
|
||||||
|
// next();
|
||||||
|
req.isAdmin = (req.session.token && req.session.login) &&
|
||||||
|
tokens[req.session.login] != req.session.token || false
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.authorize = authorize
|
||||||
|
module.exports.authenticate = authenticate
|
||||||
|
module.exports.tokens = tokens
|
100
src/index.js
100
src/index.js
|
@ -7,6 +7,7 @@ const fs = require('fs');
|
||||||
const bcrypt = require('bcryptjs');
|
const bcrypt = require('bcryptjs');
|
||||||
// const fileupload = require('express-fileupload');
|
// const fileupload = require('express-fileupload');
|
||||||
const cors = require('cors');
|
const cors = require('cors');
|
||||||
|
const { authorize, authenticate, tokens } = require('./auth.js');
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
|
@ -43,11 +44,10 @@ const init = async () => {
|
||||||
let adminPassword = Math.random().toString(36).slice(-8);
|
let adminPassword = Math.random().toString(36).slice(-8);
|
||||||
let passwordHash = await bcrypt.hash(adminPassword, 8);
|
let passwordHash = await bcrypt.hash(adminPassword, 8);
|
||||||
console.log(`Creating admin account with credentials: admin:${adminPassword}`);
|
console.log(`Creating admin account with credentials: admin:${adminPassword}`);
|
||||||
db.query("INSERT INTO priveleges (privelege_name, access_level) VALUES ('admin', 100)");
|
db.query("INSERT INTO privileges (privilege_name, access_level) VALUES ('admin', 100)");
|
||||||
db.query("INSERT INTO admins (login, password_hash, privelege_name) VALUES ('admin', $1, 'admin')", [passwordHash])
|
db.query("INSERT INTO admins (login, password_hash, privilege_name) VALUES ('admin', $1, 'admin')", [passwordHash])
|
||||||
}
|
}
|
||||||
|
|
||||||
let tokens = {};
|
|
||||||
|
|
||||||
app.use(express.urlencoded({ extended: true }))
|
app.use(express.urlencoded({ extended: true }))
|
||||||
app.use(express.json())
|
app.use(express.json())
|
||||||
|
@ -68,7 +68,18 @@ app.post('/api/uploadMedia', async (req, res) => {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.get('/api/getThreadIdByPostId/:postId', async (req, res) => {
|
||||||
|
if (!req.params.postId) {
|
||||||
|
return res.status(400).send("Didn't provide post id.");
|
||||||
|
}
|
||||||
|
threadId = (await db.query(`SELECT thread_id FROM threads WHERE $1 = ANY(posts_ids)`, [req.params.postId]));
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
|
res.end(JSON.stringify(threadId.rows[0].thread_id));
|
||||||
|
})
|
||||||
|
|
||||||
app.get('/api/getPosts/:boardId/:threadId', async (req, res) => {
|
app.get('/api/getPosts/:boardId/:threadId', async (req, res) => {
|
||||||
|
if (!req.params.boardId) return res.status(400).send("Didn't provide board id.");
|
||||||
|
if (req.params.threadId == undefined) return res.status(400).send("Didn't provide thread id.");
|
||||||
posts = [];
|
posts = [];
|
||||||
(await db.query('SELECT post_id, content, timestamp, options FROM posts WHERE board_id = $1 AND thread_id = $2', [req.params.boardId, req.params.threadId])).rows
|
(await db.query('SELECT post_id, content, timestamp, options FROM posts WHERE board_id = $1 AND thread_id = $2', [req.params.boardId, req.params.threadId])).rows
|
||||||
.forEach((post) => posts.push(post))
|
.forEach((post) => posts.push(post))
|
||||||
|
@ -77,46 +88,32 @@ app.get('/api/getPosts/:boardId/:threadId', async (req, res) => {
|
||||||
res.end(JSON.stringify(posts));
|
res.end(JSON.stringify(posts));
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/api/post', async (req, res) => {
|
app.post('/api/post', authorize, async (req, res) => {
|
||||||
let login = req.session.login,
|
|
||||||
token = req.session.token,
|
|
||||||
isAdmin = false;
|
|
||||||
const {options, content, threadId, boardId} = req.body;
|
const {options, content, threadId, boardId} = req.body;
|
||||||
|
|
||||||
if (!threadId || !boardId) return res.status(400).send("Не указано ID треда или доски");
|
console.log(`${options} ${content} ${threadId} ${boardId}`)
|
||||||
|
|
||||||
if (login && token) {
|
if (!threadId || !boardId) return res.status(400).send("Thread ID or board ID is not specified");
|
||||||
if (authorize(login, token)) isAdmin = true;
|
|
||||||
else res.status(403).send("Невалидный токен");
|
|
||||||
}
|
|
||||||
|
|
||||||
let postId = Number((await db.query('SELECT post_id FROM posts WHERE board_id = $1 ORDER BY post_id DESC LIMIT 1', [boardId])).rows[0].post_id) + 1
|
let postId = Number((await db.query('SELECT post_id FROM posts WHERE board_id = $1 ORDER BY post_id DESC LIMIT 1', [boardId])).rows[0].post_id) + 1
|
||||||
await db.query('INSERT INTO posts(board_id, thread_id, post_id, options, content, media_ids, is_root, timestamp, user_ip) VALUES ($1, $2, $3, $4, $5, \'{}\', false, NOW(), $6)', [boardId, threadId, postId, options, content, req.socket.remoteAddress]);
|
await db.query('INSERT INTO posts(board_id, thread_id, post_id, options, content, media_ids, is_root, timestamp, user_ip) VALUES ($1, $2, $3, $4, $5, \'{}\', false, NOW(), $6)', [boardId, threadId, postId, options, content, req.socket.remoteAddress]);
|
||||||
await db.query('UPDATE threads SET posts_ids = ARRAY_APPEND(posts_ids, $1) WHERE thread_id = $2 AND board_id = $3', [postId, threadId, boardId]);
|
await db.query('UPDATE threads SET posts_ids = ARRAY_APPEND(posts_ids, $1) WHERE thread_id = $2 AND board_id = $3', [postId, threadId, boardId]);
|
||||||
|
|
||||||
res.status(200).send("Пост отправлен");
|
res.status(200).send("Post sent");
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/api/createThread', async (req, res) => {
|
app.post('/api/createThread', authorize, async (req, res) => {
|
||||||
let login = req.session.login,
|
let isLocked,
|
||||||
token = req.session.token,
|
isPinned
|
||||||
isLocked,
|
|
||||||
isPinned,
|
|
||||||
isAdmin = false;
|
|
||||||
const { boardId, threadTitle, content, options} = req.body;
|
const { boardId, threadTitle, content, options} = req.body;
|
||||||
|
|
||||||
if (!boardId) return res.status(400).send("Не указано имя доски");
|
if (!boardId) return res.status(400).send("Board name is not specified");
|
||||||
|
|
||||||
isLocked = isLocked? isLocked : false; // if undefined then false
|
isLocked = isLocked || false; // if undefined then false
|
||||||
isPinned = isPinned? isPinned : false;
|
isPinned = isPinned || false;
|
||||||
|
|
||||||
console.log(`Board id: ${boardId}\nThread name: ${threadTitle}\nIs locked: ${isLocked}\nIs pinned: ${isPinned}\nContent: ${content}\nOptions: ${options}`);
|
console.log(`Board id: ${boardId}\nThread name: ${threadTitle}\nIs locked: ${isLocked}\nIs pinned: ${isPinned}\nContent: ${content}\nOptions: ${options}`);
|
||||||
|
|
||||||
if (login && token) {
|
|
||||||
if (authorize(login, token)) isAdmin = true;
|
|
||||||
else res.status(403).send("Невалидный токен");
|
|
||||||
}
|
|
||||||
|
|
||||||
const boardOptions = (await db.query('SELECT options FROM boards WHERE board_id = $1', [boardId])).rows[0].options;
|
const boardOptions = (await db.query('SELECT options FROM boards WHERE board_id = $1', [boardId])).rows[0].options;
|
||||||
|
|
||||||
let threadId = (await db.query('SELECT EXISTS(SELECT FROM threads WHERE board_id = $1)', [boardId])).rows[0].exists?
|
let threadId = (await db.query('SELECT EXISTS(SELECT FROM threads WHERE board_id = $1)', [boardId])).rows[0].exists?
|
||||||
|
@ -129,7 +126,7 @@ app.post('/api/createThread', async (req, res) => {
|
||||||
|
|
||||||
let validateResults = validateThread(threadTitle, isLocked,
|
let validateResults = validateThread(threadTitle, isLocked,
|
||||||
isPinned, content, options,
|
isPinned, content, options,
|
||||||
boardOptions, isAdmin);
|
boardOptions, req.isAdmin);
|
||||||
if (validateResults != "ok") return res.status(400).send(validateResults);
|
if (validateResults != "ok") return res.status(400).send(validateResults);
|
||||||
|
|
||||||
await db.query('INSERT INTO posts (board_id, thread_id, post_id, content, is_root, timestamp, user_ip) VALUES($1, $2, $3, $4, $5, NOW(), $6)', [boardId, threadId, postId, content, true, req.socket.remoteAddress]);
|
await db.query('INSERT INTO posts (board_id, thread_id, post_id, content, is_root, timestamp, user_ip) VALUES($1, $2, $3, $4, $5, NOW(), $6)', [boardId, threadId, postId, content, true, req.socket.remoteAddress]);
|
||||||
|
@ -139,8 +136,8 @@ app.post('/api/createThread', async (req, res) => {
|
||||||
|
|
||||||
app.get('/api/getThreads/:boardId', async (req, res) => {
|
app.get('/api/getThreads/:boardId', async (req, res) => {
|
||||||
threads = [];
|
threads = [];
|
||||||
(await db.query('SELECT thread_id FROM threads WHERE board_id = $1', [req.params.boardId])).rows
|
(await db.query('SELECT * FROM threads WHERE board_id = $1', [req.params.boardId])).rows
|
||||||
.forEach((thread) => threads.push(thread.thread_id))
|
.forEach((thread) => threads.push(thread))
|
||||||
|
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.setHeader('Content-Type', 'application/json');
|
||||||
res.end(JSON.stringify(threads));
|
res.end(JSON.stringify(threads));
|
||||||
|
@ -151,58 +148,47 @@ app.get('/api/getBoards', async (req, res) => {
|
||||||
|
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.setHeader('Content-Type', 'application/json');
|
||||||
res.end(JSON.stringify(queryRes.rows));
|
res.end(JSON.stringify(queryRes.rows));
|
||||||
// res.json(JSON.stringify(queryRes.rows));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/api/login', async (req, res) => {
|
app.post('/api/login', async (req, res) => {
|
||||||
const { login, password } = req.body;
|
const { login, password } = req.body;
|
||||||
|
|
||||||
if (!(login && password)) return res.status(401).send("Не указан логин или пароль");
|
if (!(login && password)) return res.status(401).send("Login or password is not specified");
|
||||||
|
|
||||||
queryRes = await db.query('SELECT * FROM admins WHERE login = $1', [login])
|
queryRes = await db.query('SELECT * FROM admins WHERE login = $1', [login])
|
||||||
if (queryRes.rowCount == 0) return res.status(401).send("Такого лоигна нет");
|
if (queryRes.rowCount == 0) return res.status(401).send("No such login");
|
||||||
|
|
||||||
let hashedPassword = queryRes.rows[0].password_hash;
|
let hashedPassword = queryRes.rows[0].password_hash;
|
||||||
bcrypt.compare(password, hashedPassword, (err, result) => {
|
bcrypt.compare(password, hashedPassword, (err, result) => {
|
||||||
if (!result) return res.status(403).send("Пароли не совпадают");
|
if (!result) return res.status(403).send("Incorrect password");
|
||||||
let currentSession = req.session;
|
let currentSession = req.session;
|
||||||
currentSession.login = login;
|
currentSession.login = login;
|
||||||
if (!tokens[login]) {
|
if (!tokens[login]) {
|
||||||
let token = Math.random().toString(26).slice(2); // ONLY IN DEV MODE
|
let token = Math.random().toString(26).slice(2); // ONLY IN DEV MODE
|
||||||
tokens[login] = token;
|
tokens[login] = token;
|
||||||
currentSession.token = token;
|
currentSession.token = token;
|
||||||
console.log(token);
|
|
||||||
}
|
}
|
||||||
res.redirect("/");
|
res.redirect("/");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/api/createBoard', async (req, res) => {
|
app.post('/api/createBoard', authenticate, async (req, res) => {
|
||||||
let login, token;
|
let login = req.session.login;
|
||||||
let { boardId, boardTitle, options} = req.body;
|
let { boardId, boardTitle, options} = req.body;
|
||||||
|
|
||||||
try {
|
if (!boardId || !boardTitle) return res.status(400).send("Board ID or board title is not specified");
|
||||||
let currentSession = req.session;
|
|
||||||
token = currentSession.token;
|
|
||||||
login = currentSession.login;
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token != tokens[login] || !token) return res.status(403).send("Невалидный токен");
|
|
||||||
if (!boardId || !boardTitle) return res.status(400).send("Неверно сформирован запрос");
|
|
||||||
|
|
||||||
console.log(`Admin ${login} is creating new board: ${boardId}, ${boardTitle}`);
|
console.log(`Admin ${login} is creating new board: ${boardId}, ${boardTitle}`);
|
||||||
|
|
||||||
let queryRes = await db.query('SELECT * FROM boards WHERE board_id = $1::text', [boardId]);
|
let queryRes = await db.query('SELECT * FROM boards WHERE board_id = $1::text', [boardId]);
|
||||||
if (boardId.length == 0 || boardId.length > 5) return res.status(401).send("Неверный размер URI борды");
|
if (boardId.length == 0 || boardId.length > 5) return res.status(401).send("Invalid size of the URI of board");
|
||||||
if (boardTitle.length == 0 || boardTitle.length > 32) return res.status(401).send("Неверный размер имени борды");
|
if (boardTitle.length == 0 || boardTitle.length > 32) return res.status(401).send("Invalid size of the name of board");
|
||||||
if (queryRes.rowCount > 0) return res.status(401).send("Такая борда уже существует.");
|
if (queryRes.rowCount > 0) return res.status(401).send("Such board already exists");
|
||||||
|
|
||||||
if (!options) options = default_board_settings;
|
if (!options) options = default_board_settings;
|
||||||
|
|
||||||
await db.query('INSERT INTO boards (board_id, board_name, options) VALUES ($1, $2, $3)', [boardId, boardTitle, options]);
|
await db.query('INSERT INTO boards (board_id, board_name, options) VALUES ($1, $2, $3)', [boardId, boardTitle, options]);
|
||||||
return res.status(200).send("Борда успешно создана");
|
return res.status(200).send("The board was created succsessfully");
|
||||||
});
|
});
|
||||||
|
|
||||||
app.listen(process.env.APP_PORT, () => {
|
app.listen(process.env.APP_PORT, () => {
|
||||||
|
@ -210,13 +196,15 @@ app.listen(process.env.APP_PORT, () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const validateThread = (threadName, isLocked, isPinned, content, options, boardOptions, isAdmin) => {
|
const validateThread = (threadName, isLocked, isPinned, content, options, boardOptions, isAdmin) => {
|
||||||
if ((isPinned || isLocked) && !isAdmin) return "Нет прав на выставление админских флагов";
|
if ((isPinned || isLocked) && !isAdmin) return "Insuffucuent permissions for flags";
|
||||||
if (!content && boardOptions.requireContentForThreadCreation) return "Нельзя создать тред без текста";
|
if (!content && boardOptions.requireContentForThreadCreation) return "You cannot create thread without text";
|
||||||
|
|
||||||
//TODO: check if image is required
|
//TODO: check if image is required
|
||||||
return 'ok'
|
return 'ok'
|
||||||
};
|
};
|
||||||
|
|
||||||
const authorize = (login, token) => {
|
app.post('/api/test', authorize, (req, res) => {
|
||||||
return tokens[login] == token? true : false;
|
console.log("test")
|
||||||
};
|
console.log(authorize)
|
||||||
|
return res.status(200).send("Здаров заебал")
|
||||||
|
});
|
Loading…
Reference in New Issue