const express = require('express'); const mysql = require('mysql2/promise'); const bcrypt = require('bcryptjs'); const session = require('express-session'); const path = require('path'); require('dotenv').config({ path: path.join(__dirname, '../.env') }); const app = express(); const FRONTEND_DIR = path.join(__dirname, '../frontend'); const pool = mysql.createPool({ host: process.env.DB_HOST, port: Number(process.env.DB_PORT), user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_NAME, waitForConnections: true, connectionLimit: 10, queueLimit: 0 }); app.use(express.urlencoded({ extended: true })); app.use(express.json()); app.use(session({ secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false })); app.get('/', (req, res) => { if (req.session.user) { return res.redirect('/index.html'); } res.sendFile(path.join(FRONTEND_DIR, 'login.html')); }); app.get('/register', (req, res) => { res.sendFile(path.join(FRONTEND_DIR, 'register.html')); }); app.get('/index.html', (req, res) => { if (!req.session.user) { return res.redirect('/'); } res.sendFile(path.join(FRONTEND_DIR, 'index.html')); }); app.post('/register', async (req, res) => { const { username, password, password2 } = req.body; if (!username || !password || !password2) { return res.redirect('/register.html?error=' + encodeURIComponent('Vyplň všetky polia')); } if (password !== password2) { return res.redirect('/register.html?error=' + encodeURIComponent('Heslá sa nezhodujú')); } try { const hashedPassword = await bcrypt.hash(password, 10); await pool.execute( 'INSERT INTO users (username, password) VALUES (?, ?)', [username, hashedPassword] ); return res.redirect('/'); } catch (err) { console.error(err); return res.redirect('/register.html?error=' + encodeURIComponent('Používateľ už existuje')); } }); app.post('/login', async (req, res) => { const { username, password } = req.body; if (!username || !password) { return res.redirect('/?error=Vyplň%20všetky%20polia'); } try { const [rows] = await pool.execute( 'SELECT * FROM users WHERE username = ?', [username] ); const row = rows[0]; if (!row) { return res.redirect('/?error=Zlé%20meno%20alebo%20heslo'); } const result = await bcrypt.compare(password, row.password); if (!result) { return res.redirect('/?error=Zlé%20meno%20alebo%20heslo'); } req.session.user = { id: row.id, username: row.username }; return res.redirect('/index.html'); } catch (err) { console.error(err); return res.redirect('/?error=Chyba%20databázy'); } }); app.post('/logout', (req, res) => { req.session.destroy(() => { res.redirect('/'); }); }); app.get('/api/me', (req, res) => { if (!req.session.user) { return res.status(401).json({ error: 'Neprihlásený používateľ' }); } res.json(req.session.user); }); app.get('/api/tasks', async (req, res) => { if (!req.session.user) { return res.status(401).json({ error: 'Neprihlásený používateľ' }); } try { const [rows] = await pool.execute( 'SELECT * FROM tasks WHERE user_id = ? ORDER BY deadline ASC', [req.session.user.id] ); res.json(rows); } catch (err) { console.error(err); return res.status(500).json({ error: 'Chyba pri načítaní úloh' }); } }); app.post('/api/tasks', async (req, res) => { if (!req.session.user) { return res.status(401).json({ error: 'Neprihlásený používateľ' }); } const { title, description, deadline } = req.body; if (!title || !description || !deadline) { return res.status(400).json({ error: 'Vyplň všetky polia' }); } try { const [result] = await pool.execute( 'INSERT INTO tasks (user_id, title, description, deadline) VALUES (?, ?, ?, ?)', [req.session.user.id, title, description, deadline] ); const [rows] = await pool.execute( 'SELECT * FROM tasks WHERE id = ?', [result.insertId] ); res.json(rows[0]); } catch (err) { console.error(err); return res.status(500).json({ error: 'Chyba pri ukladaní úlohy' }); } }); app.delete('/api/tasks/:id', async (req, res) => { if (!req.session.user) { return res.status(401).json({ error: 'Neprihlásený používateľ' }); } try { await pool.execute( 'DELETE FROM tasks WHERE id = ? AND user_id = ?', [req.params.id, req.session.user.id] ); res.json({ success: true }); } catch (err) { console.error(err); return res.status(500).json({ error: 'Chyba pri mazaní úlohy' }); } }); app.patch('/api/tasks/:id/toggle', async (req, res) => { if (!req.session.user) { return res.status(401).json({ error: 'Neprihlásený používateľ' }); } const { status } = req.body; try { await pool.execute( 'UPDATE tasks SET status = ? WHERE id = ? AND user_id = ?', [status ? 1 : 0, req.params.id, req.session.user.id] ); res.json({ success: true }); } catch (err) { console.error(err); return res.status(500).json({ error: 'Chyba pri zmene stavu úlohy' }); } }); app.use(express.static(FRONTEND_DIR)); const PORT = process.env.PORT || 3000; app.listen(PORT, async () => { try { const connection = await pool.getConnection(); console.log('Pripojenie na MySQL úspešné.'); connection.release(); } catch (err) { console.error('Nepodarilo sa pripojiť na MySQL:', err.message); } console.log(`Server beží na http://localhost:${PORT}`); });