const express = require('express'); const { Client } = require('pg'); const session = require('express-session'); const dotenv = require('dotenv'); const MemoryStore = require('memorystore')(session); const fs = require('fs'); const bcrypt = require('bcryptjs'); // const fileupload = require('express-fileupload'); const app = express(); dotenv.config({ path: './web.env' }); const default_board_settings = require('../default_board_settings.json'); const db = new Client({ user: process.env.DB_USER, host: process.env.DB_HOST, database: process.env.DB_NAME, password: process.env.DB_PASS, port: 5432 }); db.connect((error) => { if (error) console.log(error); else console.log("Database connected"); db.query('SELECT to_regclass(\'admins\');', (err, res) => { if(res.rows[0].to_regclass != "admins") init(); }) }) const init = async () => { let initSQL = fs.readFileSync("./database_schematic.pgsql").toString(); console.log("No tables found, assuming first run, creating database scheme"); db.query(initSQL, (err, res) => { if (err) console.log(err); }); 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]) } let tokens = {}; app.set('views','./public'); app.use(express.static('public')); app.set('view engine', 'ejs'); app.use(express.urlencoded({ extended: true })) app.use(express.json()) app.use(session({ secret: process.env.SESSION_SECRET, store: new MemoryStore({ checkPeriod: 86400000 }), resave: false, saveUninitialized: false, cookie: { maxAge: 1000*60*60*24 } })); app.get('/', (req, res) => { res.render('index'); }); app.post('/api/uploadMedia', async (req, res) => { }); app.post('/api/post', async (req, res) => { const { content, } = req.body; }); app.post('/api/createThread', async (req, res) => { let login, token const { boardId, threadName, isLocked, isPinned, content, options} = req.body; try { let currentSession = req.session; token = currentSession.token; login = currentSession.login; } catch (err) { console.log(err); } if (token != tokens[login]) return res.status(403).send("Невалидный токен"); // if () }); app.get('/api/getBoards', async (req, res) => { let queryRes = await db.query('SELECT * FROM boards'); res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify(queryRes.rows)); }); app.post('/api/login', async (req, res) => { const { login, password } = req.body; if (!(login && password)) return res.status(401).send("Не указан логин или пароль"); queryRes = await db.query('SELECT * FROM admins WHERE login = $1', [login]) if (queryRes.rowCount == 0) return res.status(401).send("Такого лоигна нет"); let hashedPassword = queryRes.rows[0].password_hash; bcrypt.compare(password, hashedPassword, (err, result) => { if (!result) return res.status(403).send("Пароли не совпадают"); 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; 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("Неверно сформирован запрос"); 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 (!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("Борда успешно создана"); }); app.listen(process.env.APP_PORT, () => { console.log("App started"); });