const express = require('express'); const session = require('express-session'); const bcrypt = require('bcrypt'); const crypto = require('crypto'); const nodemailer = require('nodemailer'); const { Pool } = require('pg'); const path = require('path'); require('dotenv').config(); const router = express.Router(); // Session-Konfiguration app.use(session({ secret: 'your_secret_key', resave: false, saveUninitialized: false, cookie: { maxAge: 60000 } })); // Authentifizierungs-Middleware const requireAuth = (req, res, next) => { if (!req.session.userId) { return res.redirect('/login'); } next(); }; const requireAdmin = (req, res, next) => { if (req.session.role !== 'admin') { return res.status(403).send('Access denied'); } next(); }; // Registrierung router.post('/register', async (req, res) => { const { username, password } = req.body; try { const hashedPassword = await bcrypt.hash(password, 10); await pool.query('INSERT INTO users (username, password) VALUES ($1, $2)', [username, hashedPassword]); res.redirect('/login'); } catch (error) { console.error('Error registering user:', error); res.status(500).send('Internal Server Error'); } }); // Login router.post('/login', async (req, res) => { const { username, password } = req.body; try { const userResult = await pool.query('SELECT * FROM users WHERE username = $1', [username]); if (userResult.rows.length > 0) { const user = userResult.rows[0]; const match = await bcrypt.compare(password, user.password); if (match) { req.session.userId = user.id; req.session.role=user.role; res.redirect('/'); } else { res.redirect('/login'); } } else { res.redirect('/login'); } } catch (error) { console.error('Error logging in:', error); res.status(500).send('Internal Server Error'); } }); // Logout router.post('/logout', (req, res) => { req.session.destroy(err => { if (err) { return res.status(500).send('Internal Server Error'); } res.redirect('/login'); }); }); // Benutzer freischalten (nur Admin) router.post('/activate', requireAuth, requireAdmin, async (req, res) => { const { userId } = req.body; try { await pool.query('UPDATE users SET is_active = TRUE WHERE id = $1', [userId]); res.redirect('/admin'); } catch (error) { console.error('Error activating user:', error); res.status(500).send('Internal Server Error'); } }); // Passwort-Zurücksetzung anfordern router.post('/forgot-password', async (req, res) => { const { email } = req.body; try { const userResult = await pool.query('SELECT * FROM users WHERE email = $1', [email]); if (userResult.rows.length > 0) { const user = userResult.rows[0]; const token = crypto.randomBytes(20).toString('hex'); const resetLink = `http://tkd.boergmann.it/reset-password/${token}`; await pool.query('UPDATE users SET reset_password_token = $1, reset_password_expires = $2 WHERE id = $3', [token, Date.now() + 3600000, user.id]); const mailOptions = { to: user.email, from: 'admin@boergmann.it', subject: 'Password Reset', text: `Click the following link to reset your password: ${resetLink}` }; transporter.sendMail(mailOptions, (err) => { if (err) { console.error('Error sending email:', err); res.status(500).send('Error sending email'); } else { res.send('Password reset link sent'); } }); } else { res.status(400).send('Email not found'); } } catch (error) { console.error('Error in forgot-password:', error); res.status(500).send('Internal Server Error'); } }); // Passwort zurücksetzen router.get('/reset-password/:token', async (req, res) => { const { token } = req.params; try { const userResult = await pool.query('SELECT * FROM users WHERE reset_password_token = $1 AND reset_password_expires > $2', [token, Date.now()]); if (userResult.rows.length > 0) { res.render('reset-password', { token }); // Stelle sicher, dass es eine reset-password.ejs gibt } else { res.status(400).send('Password reset token is invalid or has expired'); } } catch (error) { console.error('Error in reset-password:', error); res.status(500).send('Internal Server Error'); } }); router.post('/reset-password/:token', async (req, res) => { const { token } = req.params; const { password } = req.body; try { const userResult = await pool.query('SELECT * FROM users WHERE reset_password_token = $1 AND reset_password_expires > $2', [token, Date.now()]); if (userResult.rows.length > 0) { const user = userResult.rows[0]; const hashedPassword = await bcrypt.hash(password, 10); await pool.query('UPDATE users SET password = $1, reset_password_token = NULL, reset_password_expires = NULL WHERE id = $2', [hashedPassword, user.id]); res.redirect('/login'); } else { res.status(400).send('Password reset token is invalid or has expired'); } } catch (error) { console.error('Error in reset-password:', error); res.status(500).send('Internal Server Error'); } }); // Profilseite router.get('/profile', requireAuth, (req, res) => { res.render('profile', { session: req.session}); // Stelle sicher, dass es eine profile.ejs gibt }); router.post('/profile', requireAuth, async (req, res) => { const { email, password } = req.body; try { if (email) { await pool.query('UPDATE users SET email = $1 WHERE id = $2', [email, req.session.userId]); } if (password) { const hashedPassword = await bcrypt.hash(password, 10); await pool.query('UPDATE users SET password = $1 WHERE id = $2', [hashedPassword, req.session.userId]); } res.redirect('/profile'); } catch (error) { console.error('Error updating profile:', error); res.status(500).send('Internal Server Error'); } }); router.post('/update-leader', async (req, res) => { const { trainingId, type, leaderId } = req.body; try { if (type === 'aufwaermleiter') { await pool.query('UPDATE trainings SET aufwaermleiter = $1 WHERE id = $2', [leaderId, trainingId]); } else if (type === 'spielleiter') { await pool.query('UPDATE trainings SET spielleiter = $1 WHERE id = $2', [leaderId, trainingId]); } res.redirect('/'); } catch (err) { console.error(err); res.send("Error " + err); } }); // Admin-Seite router.get('/admin', requireAuth, requireAdmin, async (req, res) => { const usersResult = await pool.query('SELECT * FROM users WHERE is_active = FALSE'); res.render('admin', { users: usersResult.rows, session: req.session }); // Stelle sicher, dass es eine admin.ejs gibt }); // Teilnehmer_innen router.get('/', requireAuth, async (req, res) => { try { const selectedDate = req.query.date; const training = await getTraining(selectedDate); const trainingsResult = await pool.query('SELECT datum FROM trainings ORDER BY datum ASC'); const trainingsDates = trainingsResult.rows.map(tr => ({ datum: formatDate(tr.datum), rawDatum: tr.datum })); if (training) { training.datum = formatDate(training.datum); } const aufwaermleiterCandidates = await getCandidatesForAufwaermleiter(); const spielleiterCandidates = await getCandidatesForSpielleiter(); const spielCandidates = await getAllSpiele(); const aufwaermenCandidates = await getAllSpiele(); res.render('trainings', { training, trainingsDates, selectedDate: formatDate(selectedDate), aufwaermleiterCandidates, spielleiterCandidates, aufwaermenCandidates, // Übergeben der Kandidaten für Aufwärmleiter spielCandidates, // Übergeben der Spiele session: req.session }); } catch (err) { console.error(err); res.send("Error " + err); } }); router.get('/riege', requireAuth, async (req, res) => { try { // Abrufen der Riegendaten einschließlich der Teilnehmer und deren Altersberechnung const result = await pool.query(` SELECT r.riegennummer, t.id, t.name, t.geburtsdatum, r.helfer FROM riegen r JOIN teilnehmende t ON r.fremdID_Teilnehmende = t.id ORDER BY r.riegennummer, t.geburtsdatum ASC `); // Gruppieren der Riegenteilnehmer nach Riegennummer const riegen = {}; result.rows.forEach(row => { const age = calculateAge(row.geburtsdatum); if (!riegen[row.riegennummer]) { riegen[row.riegennummer] = []; } riegen[row.riegennummer].push({ id: row.id, name: row.name, age: age, helfer: row.helfer, }); }); res.render('riegen', { riegen: riegen, session: req.session }); } catch (error) { console.error('Error fetching riegen:', error); res.status(500).send('Internal Server Error'); } }); router.get('/teilnehmer', requireAuth, async (req, res) => { try { const teilnehmendeResult = await pool.query('SELECT * FROM teilnehmende'); const teilnehmende = teilnehmendeResult.rows.map(t => ({ ...t, age: calculateAge(t.geburtsdatum) })).sort((a, b) => b.age - a.age); res.render('teilnehmer', { teilnehmende, session: req.session }); } catch (err) { console.error(err); res.send("Error " + err); } }); // Login und Registrierung anzeigen router.get('/login', (req, res) => { res.render('login', {session: req.session}); // Stelle sicher, dass es eine login.ejs gibt }); router.get('/register', (req, res) => { res.render('register'); // Stelle sicher, dass es eine register.ejs gibt });