diff --git a/src/auth.js b/src/auth.js new file mode 100644 index 0000000..3a28574 --- /dev/null +++ b/src/auth.js @@ -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 \ No newline at end of file diff --git a/src/index.js b/src/index.js index 0ebb962..02f45c9 100644 --- a/src/index.js +++ b/src/index.js @@ -7,6 +7,7 @@ const fs = require('fs'); const bcrypt = require('bcryptjs'); // const fileupload = require('express-fileupload'); const cors = require('cors'); +const { authorize, authenticate, tokens } = require('./auth.js'); const app = express(); @@ -43,11 +44,10 @@ const init = async () => { let adminPassword = Math.random().toString(36).slice(-8); let passwordHash = await bcrypt.hash(adminPassword, 8); 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 admins (login, password_hash, privelege_name) VALUES ('admin', $1, 'admin')", [passwordHash]) + db.query("INSERT INTO privileges (privilege_name, access_level) VALUES ('admin', 100)"); + 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.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) => { + 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 = []; (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)) @@ -77,45 +88,31 @@ app.get('/api/getPosts/:boardId/:threadId', async (req, res) => { res.end(JSON.stringify(posts)); }); -app.post('/api/post', async (req, res) => { - let login = req.session.login, - token = req.session.token, - isAdmin = false; +app.post('/api/post', authorize, async (req, res) => { 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 (authorize(login, token)) isAdmin = true; - else res.status(403).send("Невалидный токен"); - } + if (!threadId || !boardId) return res.status(400).send("Thread ID or board ID is not specified"); 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('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) => { - let login = req.session.login, - token = req.session.token, - isLocked, - isPinned, - isAdmin = false; +app.post('/api/createThread', authorize, async (req, res) => { + let isLocked, + isPinned 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 - isPinned = isPinned? isPinned : false; + isLocked = isLocked || false; // if undefined then false + isPinned = isPinned || false; 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; @@ -129,7 +126,7 @@ app.post('/api/createThread', async (req, res) => { let validateResults = validateThread(threadTitle, isLocked, isPinned, content, options, - boardOptions, isAdmin); + boardOptions, req.isAdmin); 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]); @@ -139,8 +136,8 @@ app.post('/api/createThread', async (req, res) => { app.get('/api/getThreads/:boardId', async (req, res) => { threads = []; - (await db.query('SELECT thread_id FROM threads WHERE board_id = $1', [req.params.boardId])).rows - .forEach((thread) => threads.push(thread.thread_id)) + (await db.query('SELECT * FROM threads WHERE board_id = $1', [req.params.boardId])).rows + .forEach((thread) => threads.push(thread)) res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify(threads)); @@ -151,58 +148,47 @@ app.get('/api/getBoards', async (req, res) => { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify(queryRes.rows)); - // res.json(JSON.stringify(queryRes.rows)); }); app.post('/api/login', async (req, res) => { 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]) - 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; 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; currentSession.login = login; if (!tokens[login]) { let token = Math.random().toString(26).slice(2); // ONLY IN DEV MODE tokens[login] = token; currentSession.token = token; - console.log(token); } res.redirect("/"); }); }); -app.post('/api/createBoard', async (req, res) => { - let login, token; +app.post('/api/createBoard', authenticate, async (req, res) => { + let login = req.session.login; let { boardId, boardTitle, options} = req.body; - try { - 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("Неверно сформирован запрос"); + if (!boardId || !boardTitle) return res.status(400).send("Board ID or board title is not specified"); console.log(`Admin ${login} is creating new board: ${boardId}, ${boardTitle}`); 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 (boardTitle.length == 0 || boardTitle.length > 32) return res.status(401).send("Неверный размер имени борды"); - if (queryRes.rowCount > 0) return res.status(401).send("Такая борда уже существует."); + 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("Invalid size of the name of board"); + if (queryRes.rowCount > 0) return res.status(401).send("Such board already exists"); if (!options) options = default_board_settings; 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, () => { @@ -210,13 +196,15 @@ app.listen(process.env.APP_PORT, () => { }); const validateThread = (threadName, isLocked, isPinned, content, options, boardOptions, isAdmin) => { - if ((isPinned || isLocked) && !isAdmin) return "Нет прав на выставление админских флагов"; - if (!content && boardOptions.requireContentForThreadCreation) return "Нельзя создать тред без текста"; + if ((isPinned || isLocked) && !isAdmin) return "Insuffucuent permissions for flags"; + if (!content && boardOptions.requireContentForThreadCreation) return "You cannot create thread without text"; //TODO: check if image is required return 'ok' }; -const authorize = (login, token) => { - return tokens[login] == token? true : false; -}; \ No newline at end of file +app.post('/api/test', authorize, (req, res) => { + console.log("test") + console.log(authorize) + return res.status(200).send("Здаров заебал") +}); \ No newline at end of file