From e002a8716e032fef16b3fd6e1b6cb83a3d1a6f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Klaas=20B=C3=B6rgmann?= Date: Thu, 12 Sep 2024 10:46:14 +0200 Subject: [PATCH] =?UTF-8?q?Jahr=20als=20Parameter=20f=C3=BCr=20Trainingsau?= =?UTF-8?q?swahl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env_default | 2 + app.js | 818 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 488 insertions(+), 332 deletions(-) diff --git a/.env_default b/.env_default index 4912b34..ba41e86 100644 --- a/.env_default +++ b/.env_default @@ -5,3 +5,5 @@ MAILUSER= MAILFROM= MAILPASS= PORT=2000 +TELEBOT= +TELECHAT= \ No newline at end of file diff --git a/app.js b/app.js index 98abbb1..9749d4e 100644 --- a/app.js +++ b/app.js @@ -1,13 +1,13 @@ -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'); -const moment = require('moment'); -require('dotenv').config(); -const log = require('node-file-logger'); +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"); +const moment = require("moment"); +require("dotenv").config(); +const log = require("node-file-logger"); const app = express(); const port = process.env.PORT; @@ -28,42 +28,43 @@ bot.on('text', (msg) => { bot.start(); */ const options = { - timeZone: 'europe/Berlin', - folderPath: './logs/', + timeZone: "europe/Berlin", + folderPath: "./logs/", dateBasedFileNaming: true, - fileNamePrefix: 'DailyLogs_', - fileNameExtension: '.log', - dateFormat: 'YYYY_MM_D', - timeFormat: 'H:mm:ss', -} + fileNamePrefix: "DailyLogs_", + fileNameExtension: ".log", + dateFormat: "YYYY_MM_D", + timeFormat: "H:mm:ss", +}; log.SetUserOptions(options); - // Middleware -app.use(express.static(path.join(__dirname, 'public'))); +app.use(express.static(path.join(__dirname, "public"))); app.use(express.json()); -app.set('view engine', 'ejs'); +app.set("view engine", "ejs"); app.use(express.urlencoded({ extended: false })); // Session-Konfiguration -app.use(session({ - secret: process.env.SESSIONSECRET, - resave: false, - saveUninitialized: true, - cookie: { maxAge: 1000 * 60 * 60 * 24 * 2 } -})); +app.use( + session({ + secret: process.env.SESSIONSECRET, + resave: false, + saveUninitialized: true, + cookie: { maxAge: 1000 * 60 * 60 * 24 * 2 }, + }) +); // Authentifizierungs-Middleware const requireAuth = (req, res, next) => { if (!req.session.userId) { - return res.redirect('/login'); + return res.redirect("/login"); } next(); }; const requireAdmin = (req, res, next) => { - if (req.session.role !== 'admin') { - return res.status(403).send('Access denied'); + if (req.session.role !== "admin") { + return res.status(403).send("Access denied"); } next(); }; @@ -75,13 +76,13 @@ const transporter = nodemailer.createTransport({ secure: true, auth: { user: process.env.MAILUSER, - pass: process.env.MAILPASS - } + pass: process.env.MAILPASS, + }, }); // Datenbankverbindung const pool = new Pool({ - connectionString: process.env.DATABASE_URL + connectionString: process.env.DATABASE_URL, }); // Altersberechnung @@ -99,15 +100,16 @@ const calculateAge = (birthdate) => { // Datumsformatierung const formatDate = (date) => { const d = new Date(date); - const day = String(d.getDate()).padStart(2, '0'); - const month = String(d.getMonth() + 1).padStart(2, '0'); + const day = String(d.getDate()).padStart(2, "0"); + const month = String(d.getMonth() + 1).padStart(2, "0"); const year = d.getFullYear(); return `${day}.${month}.${year}`; }; // Funktion zum Laden des aktuellen oder letzten Trainings -const getTraining = async (kw) => { - const result = await pool.query(` +const getTraining = async (kw, jahr) => { + const result = await pool.query( + ` SELECT tr.*, g1.name AS geraet_riege_1_name, g2.name AS geraet_riege_2_name, g3.name AS geraet_riege_3_name, g4.name AS geraet_riege_4_name, g5.name AS geraet_riege_5_name, @@ -123,10 +125,12 @@ const getTraining = async (kw) => { LEFT JOIN teilnehmende t2 ON tr.spielleiter = t2.id LEFT JOIN spiele sp1 ON tr.aufwaermen = sp1.id LEFT JOIN spiele sp2 ON tr.spiel = sp2.id - WHERE tr.kw <= $1 + WHERE tr.kw <= $1 AND tr.jahr = $2 ORDER BY tr.kw DESC LIMIT 1 - `, [kw]); + `, + [kw, jahr] + ); return result.rows[0]; }; @@ -142,19 +146,22 @@ const getAllSpiele = async () => { // Funktion zum Hinzufügen eines neuen Spiels, falls es noch nicht existiert const addNewSpiel = async (spielName) => { try { - const result = await pool.query('INSERT INTO spiele (name) VALUES ($1) RETURNING id', [spielName]); + const result = await pool.query( + "INSERT INTO spiele (name) VALUES ($1) RETURNING id", + [spielName] + ); return result.rows[0].id; } catch (error) { - console.error('Error adding new spiel:', error); + console.error("Error adding new spiel:", error); throw error; } }; function getThursdayOfWeek(week, year) { - const firstDayOfYear = new Date(year, 0, 1); const dayOfWeek = firstDayOfYear.getDay(); - const daysUntilFirstThursday = (dayOfWeek <= 4) ? (4 - dayOfWeek) : (11 - dayOfWeek); + const daysUntilFirstThursday = + dayOfWeek <= 4 ? 4 - dayOfWeek : 11 - dayOfWeek; const daysUntilThursdayOfWeek = (week - 1) * 7 + daysUntilFirstThursday; const thursdayOfWeek = new Date(year, 0, 1 + daysUntilThursdayOfWeek); return thursdayOfWeek; @@ -177,19 +184,34 @@ ORDER BY weeks_since_last DESC; const putInRiege = async (riege, teilnehmerID) => { try { if (riege == 0) { - const resultRiege = await pool.query('DELETE FROM riegen WHERE fremdid_teilnehmende = $1;', [teilnehmerID]); + const resultRiege = await pool.query( + "DELETE FROM riegen WHERE fremdid_teilnehmende = $1;", + [teilnehmerID] + ); } else { - const resultRiege = await pool.query('SELECT * FROM riegen WHERE fremdid_teilnehmende = $1;', [teilnehmerID]); + const resultRiege = await pool.query( + "SELECT * FROM riegen WHERE fremdid_teilnehmende = $1;", + [teilnehmerID] + ); - if (resultRiege.rows.length > 0) { - const resultRiege = await pool.query('UPDATE riegen SET riegennummer = $1 WHERE fremdid_teilnehmende = $2', [riege, teilnehmerID]); - log.Info("Mitglied " + teilnehmerID + " ist jetzt in Riege " + riege); - } else { - const resultRiege = await pool.query('INSERT INTO riegen (fremdid_teilnehmende, riegennummer) VALUES ($1, $2)', [teilnehmerID, riege]); - log.Info("Mitglied " + teilnehmerID + " neu in Riege " + riege + " eingefügt."); - }} + if (resultRiege.rows.length > 0) { + const resultRiege = await pool.query( + "UPDATE riegen SET riegennummer = $1 WHERE fremdid_teilnehmende = $2", + [riege, teilnehmerID] + ); + log.Info("Mitglied " + teilnehmerID + " ist jetzt in Riege " + riege); + } else { + const resultRiege = await pool.query( + "INSERT INTO riegen (fremdid_teilnehmende, riegennummer) VALUES ($1, $2)", + [teilnehmerID, riege] + ); + log.Info( + "Mitglied " + teilnehmerID + " neu in Riege " + riege + " eingefügt." + ); + } + } } catch (error) { - console.error('Error adding new spiel:', error); + console.error("Error adding new spiel:", error); throw error; } }; @@ -229,42 +251,48 @@ const getAnwesenheit = function (id, anwesend) { }; // Registrierung -app.post('/register', async (req, res) => { +app.post("/register", async (req, res) => { const { username, email, password } = req.body; try { const hashedPassword = await bcrypt.hash(password, 10); - await pool.query('INSERT INTO users (username, email, password) VALUES ($1, $2, $3)', [username, email, hashedPassword]); - const message = 'Registrierung erfolgreich. Ein Admin wird dich in kürze freischalten'; + await pool.query( + "INSERT INTO users (username, email, password) VALUES ($1, $2, $3)", + [username, email, hashedPassword] + ); + const message = + "Registrierung erfolgreich. Ein Admin wird dich in kürze freischalten"; const mailOptions = { - to: 'admin@boergmann.it', - from: 'admin@boergmann.it', - subject: 'Neue Registrierung', - text: `${username} hat sich registriert` + to: "admin@boergmann.it", + from: "admin@boergmann.it", + subject: "Neue Registrierung", + text: `${username} hat sich registriert`, }; transporter.sendMail(mailOptions, (error) => { if (error) { - console.error('Error sending email:', error); - const message = 'Error sending Mail:' + error; - res.render('error', { session: req.session, message }); + console.error("Error sending email:", error); + const message = "Error sending Mail:" + error; + res.render("error", { session: req.session, message }); } }); - res.render('error', { session: req.session, message }); - + res.render("error", { session: req.session, message }); } catch (error) { - console.error('Error registering user:', error); - const message = 'Error registering user:' + error; - res.render('error', { session: req.session, message }); + console.error("Error registering user:", error); + const message = "Error registering user:" + error; + res.render("error", { session: req.session, message }); } }); // Login -app.post('/login', async (req, res) => { +app.post("/login", async (req, res) => { const { username, password } = req.body; try { - const userResult = await pool.query("SELECT *, CASE WHEN admin_temp IS NOT NULL AND (now() - admin_temp) > interval '22 hours' THEN 'expired' ELSE 'valid' END AS admin_status FROM users WHERE username = $1", [username]); + const userResult = await pool.query( + "SELECT *, CASE WHEN admin_temp IS NOT NULL AND (now() - admin_temp) > interval '22 hours' THEN 'expired' ELSE 'valid' END AS admin_status FROM users WHERE username = $1", + [username] + ); if (userResult.rows.length > 0) { const user = userResult.rows[0]; const match = await bcrypt.compare(password, user.password); @@ -273,268 +301,326 @@ app.post('/login', async (req, res) => { req.session.userId = user.id; req.session.userName = user.username; req.session.activeRiege = 1; - req.session.activeTab = 'geraete'; - req.session.message = [title = '', message = '', type = 'none']; - if (user.admin_status === 'expired') { - await pool.query('UPDATE users SET role = $1, admin_temp = NULL WHERE id = $2', ['user', user.id]); - req.session.role = 'user'; + req.session.activeTab = "geraete"; + req.session.message = [(title = ""), (message = ""), (type = "none")]; + if (user.admin_status === "expired") { + await pool.query( + "UPDATE users SET role = $1, admin_temp = NULL WHERE id = $2", + ["user", user.id] + ); + req.session.role = "user"; } else { req.session.role = user.role; } - res.redirect('/training'); + res.redirect("/training"); } else { - res.redirect('/freischaltung') + res.redirect("/freischaltung"); } } else { - const message = 'Falsches Passwort'; - res.render('login', { session: req.session, username, message }); + const message = "Falsches Passwort"; + res.render("login", { session: req.session, username, message }); } } else { - const message = 'Unbekannter Benutzer'; - res.render('login', { session: req.session, username, message }); + const message = "Unbekannter Benutzer"; + res.render("login", { session: req.session, username, message }); } } catch (error) { - console.error('Error logging in:', error); - const message = 'Error logging in:' + error; - res.render('error', { session: req.session, message }); + console.error("Error logging in:", error); + const message = "Error logging in:" + error; + res.render("error", { session: req.session, message }); } }); //Wird angezeigt, wenn ein nicht freigeschalteter User sich anmelden will. -app.get('/freischaltung', async (req, res) => { - res.render('freischaltung', { session: req.session }); -}) +app.get("/freischaltung", async (req, res) => { + res.render("freischaltung", { session: req.session }); +}); // Logout -app.get('/logout', (req, res) => { - req.session.destroy(err => { +app.get("/logout", (req, res) => { + req.session.destroy((err) => { if (err) { - return res.status(500).send('Internal Server Error'); + return res.status(500).send("Internal Server Error"); } - res.redirect('/'); + res.redirect("/"); }); }); // Benutzer freischalten (nur Admin) -app.post('/userrights', requireAuth, requireAdmin, async (req, res) => { +app.post("/userrights", requireAuth, requireAdmin, async (req, res) => { const { userId, type } = req.body; try { - if (type === 'activate') { - await pool.query('UPDATE users SET is_active = TRUE WHERE id = $1', [userId]); - const userResult = await pool.query('SELECT * FROM users WHERE id = $1', [userId]); + if (type === "activate") { + await pool.query("UPDATE users SET is_active = TRUE WHERE id = $1", [ + userId, + ]); + const userResult = await pool.query("SELECT * FROM users WHERE id = $1", [ + userId, + ]); if (userResult.rows.length > 0) { if (userResult.rows[0].email) { const mailOptions = { to: userResult.rows[0].email, - from: 'admin@boergmann.it', - subject: 'Freischaltung', - text: `Hallo ${userResult.rows[0].username}, du wurdest soeben freigeschaltet.` + from: "admin@boergmann.it", + subject: "Freischaltung", + text: `Hallo ${userResult.rows[0].username}, du wurdest soeben freigeschaltet.`, }; transporter.sendMail(mailOptions, (error) => { if (error) { - console.error('Error sending email:', error); - const message = 'Error sending Mail:' + error; - res.render('error', { session: req.session, message }); + console.error("Error sending email:", error); + const message = "Error sending Mail:" + error; + res.render("error", { session: req.session, message }); } - }) + }); } } - } else if (type === 'admin') { - await pool.query('UPDATE users SET role = $1 WHERE id = $2', ['admin', userId]); + } else if (type === "admin") { + await pool.query("UPDATE users SET role = $1 WHERE id = $2", [ + "admin", + userId, + ]); + } else if (type === "admint") { + await pool.query( + "UPDATE users SET role = $1, admin_temp = $2 WHERE id = $3", + ["admin", moment().toDate(), userId] + ); + } else if (type === "delete") { + await pool.query("DELETE FROM users WHERE id = $1", [userId]); } - else if (type === 'admint') { - await pool.query('UPDATE users SET role = $1, admin_temp = $2 WHERE id = $3', ['admin', moment().toDate(), userId]); - } else if (type === 'delete') { - await pool.query('DELETE FROM users WHERE id = $1', [userId]); - } - res.redirect('/admin'); + res.redirect("/admin"); } catch (error) { - console.error('Error activating user:', error); - const message = 'Error activating user:' + error; - res.render('error', { session: req.session, message }); + console.error("Error activating user:", error); + const message = "Error activating user:" + error; + res.render("error", { session: req.session, message }); } }); // Passwort-Zurücksetzung anfordern -app.post('/send-password', async (req, res) => { +app.post("/send-password", async (req, res) => { const { email } = req.body; try { - const userResult = await pool.query('SELECT * FROM users WHERE email = $1', [email]); + 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 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, selectedDate = moment().add(1, 'd').toDate(), user.id]); + await pool.query( + "UPDATE users SET reset_password_token = $1, reset_password_expires = $2 WHERE id = $3", + [token, (selectedDate = moment().add(1, "d").toDate()), user.id] + ); const mailOptions = { to: user.email, - from: 'admin@boergmann.it', - subject: 'Password Reset', - text: `Click the following link to reset your password: ${resetLink}` + 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); - const message = 'Error sending Mail:' + error; - res.render('error', { session: req.session, message }); + console.error("Error sending email:", err); + const message = "Error sending Mail:" + error; + res.render("error", { session: req.session, message }); } else { - const message = 'Password reset link sent'; - res.render('error', { session: req.session, message }); + const message = "Password reset link sent"; + res.render("error", { session: req.session, message }); } }); } else { - const message = 'Email not found'; - res.render('error', { session: req.session, message }); + const message = "Email not found"; + res.render("error", { session: req.session, message }); } } catch (error) { - console.error('Error in forgot-password:', error); - const message = 'Error in forgot-password'; - res.render('error', { session: req.session, message }); + console.error("Error in forgot-password:", error); + const message = "Error in forgot-password"; + res.render("error", { session: req.session, message }); } }); -app.get('/forgot-password', async (req, res) => { - res.render('forgot-password', { session: req.session }) -}) +app.get("/forgot-password", async (req, res) => { + res.render("forgot-password", { session: req.session }); +}); // Passwort zurücksetzen -app.get('/reset-password/:token', async (req, res) => { +app.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()]); - const userResult = await pool.query("SELECT *, CASE WHEN reset_password_token IS NOT NULL AND (now() - reset_password_expires) > interval '22 hours' THEN 'expired' ELSE 'valid' END AS reset_status FROM users WHERE reset_password_token = $1", [token]); + const userResult = await pool.query( + "SELECT *, CASE WHEN reset_password_token IS NOT NULL AND (now() - reset_password_expires) > interval '22 hours' THEN 'expired' ELSE 'valid' END AS reset_status FROM users WHERE reset_password_token = $1", + [token] + ); if (userResult.rows.length > 0) { - res.render('reset-password', { session: req.session, token }); // Stelle sicher, dass es eine reset-password.ejs gibt + res.render("reset-password", { session: req.session, token }); // Stelle sicher, dass es eine reset-password.ejs gibt } else { - const message = 'Token ungültig oder abgelaufen'; - res.render('error', { session: req.session, message }); + const message = "Token ungültig oder abgelaufen"; + res.render("error", { session: req.session, message }); } } catch (error) { - console.error('Error in reset-password:', error); - const message = 'Error in reset-password'; - res.render('error', { session: req.session, message }); + console.error("Error in reset-password:", error); + const message = "Error in reset-password"; + res.render("error", { session: req.session, message }); } }); -app.post('/reset-password/:token', async (req, res) => { +app.post("/reset-password/:token", async (req, res) => { const { token } = req.params; const { password } = req.body; try { - const userResult = await pool.query("SELECT *, CASE WHEN reset_password_token IS NOT NULL AND (now() - reset_password_expires) > interval '22 hours' THEN 'expired' ELSE 'valid' END AS reset_status FROM users WHERE reset_password_token = $1", [token]); + const userResult = await pool.query( + "SELECT *, CASE WHEN reset_password_token IS NOT NULL AND (now() - reset_password_expires) > interval '22 hours' THEN 'expired' ELSE 'valid' END AS reset_status FROM users WHERE reset_password_token = $1", + [token] + ); 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'); + 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 { - const message = 'Token ungültig oder abgelaufen'; - res.render('error', { session: req.session, message }); + const message = "Token ungültig oder abgelaufen"; + res.render("error", { session: req.session, message }); } } catch (error) { - console.error('Error in reset-password:', error); - const message = 'Error in reset-password'; - res.render('error', { session: req.session, message }); + console.error("Error in reset-password:", error); + const message = "Error in reset-password"; + res.render("error", { session: req.session, message }); } }); // Profilseite -app.get('/profile', requireAuth, (req, res) => { - res.render('profile', { session: req.session }); // Stelle sicher, dass es eine profile.ejs gibt +app.get("/profile", requireAuth, (req, res) => { + res.render("profile", { session: req.session }); // Stelle sicher, dass es eine profile.ejs gibt }); -app.post('/profile', requireAuth, async (req, res) => { +app.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]); + 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]); + await pool.query("UPDATE users SET password = $1 WHERE id = $2", [ + hashedPassword, + req.session.userId, + ]); } - res.redirect('/profile'); + res.redirect("/profile"); } catch (error) { - console.error('Error updating profile:', error); - const message = 'Error updating profile:' + error; - res.render('error', { session: req.session, message }); + console.error("Error updating profile:", error); + const message = "Error updating profile:" + error; + res.render("error", { session: req.session, message }); } }); -app.post('/update-training', requireAuth, async (req, res) => { +app.post("/update-training", requireAuth, async (req, res) => { const { trainingId, type, spielName } = req.body; - req.session.activeTab = 'spiel'; + req.session.activeTab = "spiel"; let spielId; - const spiel = await pool.query(`SELECT * FROM spiele WHERE name = $1`, [spielName]); + const spiel = await pool.query(`SELECT * FROM spiele WHERE name = $1`, [ + spielName, + ]); if (spiel.rows.length > 0) { spielId = spiel.rows[0].id; } else { - const newSpiel = await pool.query('INSERT INTO spiele (name) VALUES ($1) RETURNING id', [spielName]); + const newSpiel = await pool.query( + "INSERT INTO spiele (name) VALUES ($1) RETURNING id", + [spielName] + ); spielId = newSpiel.rows[0].id; - req.session.message = [title = 'Neues Spiel', body = 'Das Spiel ${ spielName } wurde angelegt.']; + req.session.message = [ + (title = "Neues Spiel"), + (body = "Das Spiel ${ spielName } wurde angelegt."), + ]; } try { - if (type === 'spiel') { - await pool.query('UPDATE trainings SET spiel = $1 WHERE id = $2', [spielId, trainingId]); - } else if (type === 'aufwaermen') { - await pool.query('UPDATE trainings SET aufwaermen = $1 WHERE id = $2', [spielId, trainingId]); + if (type === "spiel") { + await pool.query("UPDATE trainings SET spiel = $1 WHERE id = $2", [ + spielId, + trainingId, + ]); + } else if (type === "aufwaermen") { + await pool.query("UPDATE trainings SET aufwaermen = $1 WHERE id = $2", [ + spielId, + trainingId, + ]); } - res.redirect('/training'); + res.redirect("/training"); } catch (error) { console.error(error); - const message = 'Error:' + error; - res.render('error', { session: req.session, message }); + const message = "Error:" + error; + res.render("error", { session: req.session, message }); } }); -app.post('/update-leader', requireAuth, async (req, res) => { +app.post("/update-leader", requireAuth, async (req, res) => { const { trainingId, type, leaderId } = req.body; - req.session.activeTab = 'spiel'; + req.session.activeTab = "spiel"; 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]); + 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('/training'); + res.redirect("/training"); } catch (error) { console.error(error); - const message = 'Error:' + error; - res.render('error', { session: req.session, message }); + const message = "Error:" + error; + res.render("error", { session: req.session, message }); } }); // Admin-Seite -app.get('/admin', requireAuth, requireAdmin, async (req, res) => { - const usersResult = await pool.query('SELECT * FROM users'); - res.render('admin', { users: usersResult.rows, session: req.session }); // Stelle sicher, dass es eine admin.ejs gibt +app.get("/admin", requireAuth, requireAdmin, async (req, res) => { + const usersResult = await pool.query("SELECT * FROM users"); + res.render("admin", { users: usersResult.rows, session: req.session }); // Stelle sicher, dass es eine admin.ejs gibt }); -app.post('/new-member', requireAuth, requireAdmin, async (req, res) => { - const { vorname, nachname, geburt, riege, adresse, probe} = req.body; +app.post("/new-member", requireAuth, requireAdmin, async (req, res) => { + const { vorname, nachname, geburt, riege, adresse, probe } = req.body; var geb = "01.01.2024"; - const name = vorname + ' ' + nachname; + const name = vorname + " " + nachname; try { - if(geburt){ + if (geburt) { geb = geburt; } - const teilnehmerID = await pool.query('INSERT INTO teilnehmende (name, geburtsdatum, adresse, vorname, nachname, probe) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id', [name, geb, adresse, vorname, nachname, probe ? true : false]); - log.Info("Mitglied " + name + " durch " + req.session.userName + " angelegt" ); + const teilnehmerID = await pool.query( + "INSERT INTO teilnehmende (name, geburtsdatum, adresse, vorname, nachname, probe) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id", + [name, geb, adresse, vorname, nachname, probe ? true : false] + ); + log.Info( + "Mitglied " + name + " durch " + req.session.userName + " angelegt" + ); putInRiege(riege, teilnehmerID.rows[0].id); - res.redirect('/riege'); + res.redirect("/riege"); } catch (error) { - const message = 'Error:' + error; - res.render('error', { session: req.session, message }); + const message = "Error:" + error; + res.render("error", { session: req.session, message }); } -}) +}); // Teilnehmer_innen -app.get('/training', requireAuth, async (req, res) => { +app.get("/training", requireAuth, async (req, res) => { try { let dateParam = req.query.date; let kwParam = req.query.kw; @@ -543,35 +629,49 @@ app.get('/training', requireAuth, async (req, res) => { let selectedKW; let selectetYear; + if (kwParam) { + selectedKW = kwParam; + } else { + selectedKW = moment().isoWeek(); + } - if (kwParam) { - selectedKW = kwParam; - } else { - selectedKW = moment().isoWeek(); - } + if (jahrParam) { + selectedYear = jahrParam; + } else { + selectedYear = moment().year(); + } - if (jahrParam) { - selectedYear = jahrParam; - } else { - selectedYear = moment().year(); - } + const training = await getTraining(selectedKW, selectedYear); - const training = await getTraining(selectedKW); - - const anwesendResult = await pool.query('SELECT * FROM anwesend WHERE fid_training = $1', [training.id]); + const anwesendResult = await pool.query( + "SELECT * FROM anwesend WHERE fid_training = $1", + [training.id] + ); anwesend = anwesendResult.rows; - const trainingsResult = await pool.query('SELECT kw, jahr FROM trainings ORDER BY kw ASC'); - const trainingsDates = trainingsResult.rows.map(tr => ({ + const trainingsResult = await pool.query( + "SELECT kw, jahr FROM trainings ORDER BY kw ASC" + ); + const trainingsDates = trainingsResult.rows.map((tr) => ({ kw: tr.kw, - datum: formatDate(getThursdayOfWeek(tr.kw, tr.jahr)) + datum: formatDate(getThursdayOfWeek(tr.kw, tr.jahr)), })); // Vorheriges Training ermitteln - const previousTrainingResult = await pool.query('SELECT * FROM trainings WHERE kw < $1 ORDER BY kw DESC LIMIT 1', [selectedKW]); - const nextTrainingResult = await pool.query('SELECT * FROM trainings WHERE kw > $1 ORDER BY kw ASC LIMIT 1', [selectedKW]); - const previousTraining = previousTrainingResult.rows.length > 0 ? previousTrainingResult.rows[0] : null; - const nextTraining = nextTrainingResult.rows.length > 0 ? nextTrainingResult.rows[0] : null; + const previousTrainingResult = await pool.query( + "SELECT * FROM trainings WHERE kw < $1 ORDER BY kw DESC LIMIT 1", + [selectedKW] + ); + const nextTrainingResult = await pool.query( + "SELECT * FROM trainings WHERE kw > $1 ORDER BY kw ASC LIMIT 1", + [selectedKW] + ); + const previousTraining = + previousTrainingResult.rows.length > 0 + ? previousTrainingResult.rows[0] + : null; + const nextTraining = + nextTrainingResult.rows.length > 0 ? nextTrainingResult.rows[0] : null; // Abrufen der Riegendaten einschließlich der Teilnehmer und deren Altersberechnung const result = await pool.query(` @@ -583,7 +683,7 @@ app.get('/training', requireAuth, async (req, res) => { // Gruppieren der Riegenteilnehmer nach Riegennummer const riegen = {}; - result.rows.forEach(row => { + result.rows.forEach((row) => { const age = calculateAge(row.geburtsdatum); const tnAnwesend = getAnwesenheit(row.id, anwesend); if (!riegen[row.riegennummer]) { @@ -596,7 +696,7 @@ app.get('/training', requireAuth, async (req, res) => { nachname: row.nachname, age: age, helfer: row.helfer, - anwesend: tnAnwesend + anwesend: tnAnwesend, }); }); @@ -609,7 +709,7 @@ app.get('/training', requireAuth, async (req, res) => { const spielCandidates = await getAllSpiele(); const aufwaermenCandidates = await getAllSpiele(); - res.render('trainings', { + res.render("trainings", { training, trainingsDates, selectedKW: training.kw, @@ -623,16 +723,16 @@ app.get('/training', requireAuth, async (req, res) => { riegen, activeRiege: req.session.activeRiege, activeTab: req.session.activeTab, - moment + moment, }); } catch (error) { console.error(error); - const message = 'Error:' + error; - res.render('error', { session: req.session, message }); + const message = "Error:" + error; + res.render("error", { session: req.session, message }); } }); -app.get('/riege', requireAuth, async (req, res) => { +app.get("/riege", requireAuth, async (req, res) => { try { // Abrufen der Riegendaten einschließlich der Teilnehmer und deren Altersberechnung const result = await pool.query(` @@ -644,7 +744,7 @@ app.get('/riege', requireAuth, async (req, res) => { // Gruppieren der Riegenteilnehmer nach Riegennummer const riegen = {}; - result.rows.forEach(row => { + result.rows.forEach((row) => { const age = calculateAge(row.geburtsdatum); if (!riegen[row.riegennummer]) { riegen[row.riegennummer] = []; @@ -659,227 +759,281 @@ app.get('/riege', requireAuth, async (req, res) => { }); }); - res.render('riegen', { riegen: riegen, session: req.session }); + res.render("riegen", { riegen: riegen, session: req.session }); } catch (error) { - console.error('Error fetching riegen:', error); - req.session.message = ['Error', error, 'error']; - res.render('error', { session: req.session }); + console.error("Error fetching riegen:", error); + req.session.message = ["Error", error, "error"]; + res.render("error", { session: req.session }); } }); -app.get('/teilnehmer', requireAuth, requireAdmin, async (req, res) => { +app.get("/teilnehmer", requireAuth, requireAdmin, async (req, res) => { try { - const teilnehmendeResult = await pool.query('SELECT * FROM teilnehmende ORDER BY helfer DESC, vorname ASC'); + const teilnehmendeResult = await pool.query( + "SELECT * FROM teilnehmende ORDER BY helfer DESC, vorname ASC" + ); - const teilnehmende = teilnehmendeResult.rows.map(t => ({ + const teilnehmende = teilnehmendeResult.rows.map((t) => ({ ...t, - age: calculateAge(t.geburtsdatum) + age: calculateAge(t.geburtsdatum), })); - res.render('teilnehmer', { teilnehmende, session: req.session }); + res.render("teilnehmer", { teilnehmende, session: req.session }); } catch (error) { console.error(error); - req.session.message = ['Error', error, 'error']; - res.render('error', { session: req.session }); + req.session.message = ["Error", error, "error"]; + res.render("error", { session: req.session }); } }); -app.get('/mitglied/:id', requireAuth, requireAdmin, async (req, res) => { +app.get("/mitglied/:id", requireAuth, requireAdmin, async (req, res) => { const { id } = req.params; try { var riege = 0; - const userResult = await pool.query('SELECT * FROM teilnehmende WHERE id = $1', [id]); - const riegeResult = await pool.query('SELECT * FROM riegen WHERE fremdid_teilnehmende = $1', [id]); - if (riegeResult.rows.length > 0 ) { + const userResult = await pool.query( + "SELECT * FROM teilnehmende WHERE id = $1", + [id] + ); + const riegeResult = await pool.query( + "SELECT * FROM riegen WHERE fremdid_teilnehmende = $1", + [id] + ); + if (riegeResult.rows.length > 0) { riege = riegeResult.rows[0].riegennummer; } req.session.activeRiege = riege; - const anwesendResult = await pool.query('SELECT * FROM anwesend WHERE fid_teilnehmer = $1', [id]); + const anwesendResult = await pool.query( + "SELECT * FROM anwesend WHERE fid_teilnehmer = $1", + [id] + ); const anwesend = anwesendResult.rows.length; - const numberResult = await pool.query('SELECT telefonnummern.*, telverbindung.bezeichnung FROM telefonnummern JOIN telverbindung ON telefonnummern.verbindung = telverbindung.id WHERE telefonnummern.fid_teilnehmer = $1', [id]); - const numbers = numberResult.rows + const numberResult = await pool.query( + "SELECT telefonnummern.*, telverbindung.bezeichnung FROM telefonnummern JOIN telverbindung ON telefonnummern.verbindung = telverbindung.id WHERE telefonnummern.fid_teilnehmer = $1", + [id] + ); + const numbers = numberResult.rows; if (userResult.rows.length > 0) { - const mitglied = userResult.rows.map(t => ({ + const mitglied = userResult.rows.map((t) => ({ ...t, - age: calculateAge(t.geburtsdatum) - })) - res.render('mitglied', { + age: calculateAge(t.geburtsdatum), + })); + res.render("mitglied", { id, mitglied: mitglied[0], numbers, riege, anwesend, - session: req.session + session: req.session, }); } else { - req.session.message = ['Error', 'Mitglied existiert nicht', 'error']; - res.redirect('/teilnehmer') + req.session.message = ["Error", "Mitglied existiert nicht", "error"]; + res.redirect("/teilnehmer"); } } catch (error) { - console.error('Error in Mitglied:', error); - req.session.message = ['Error', 'Mitglied existiert nicht', 'error']; - res.redirect('/teilnehmer'); + console.error("Error in Mitglied:", error); + req.session.message = ["Error", "Mitglied existiert nicht", "error"]; + res.redirect("/teilnehmer"); } }); -app.post('/set-riege', requireAuth, async (req, res) => { +app.post("/set-riege", requireAuth, async (req, res) => { const { riege, id } = req.body; putInRiege(riege, id); - res.redirect('/riege'); -}) + res.redirect("/riege"); +}); -app.post('/update-mitglied', requireAdmin, async (req, res) => { - const { type, id, geburt, telid, adresse, name, verbindung, nummer, probe } = req.body; +app.post("/update-mitglied", requireAdmin, async (req, res) => { + const { type, id, geburt, telid, adresse, name, verbindung, nummer, probe } = + req.body; try { if (type == "tel") { - console.log('INSERT INTO telefonnummern (fid_teilnehmer, name, verbindung, nummer, stand) VALUES ($1, $2, $3, $4, $5)', [id, name, verbindung, nummer, moment().toDate()]); - await pool.query('INSERT INTO telefonnummern (fid_teilnehmer, name, verbindung, nummer, stand) VALUES ($1, $2, $3, $4, $5)', [id, name, verbindung, nummer, moment().toDate()]); + console.log( + "INSERT INTO telefonnummern (fid_teilnehmer, name, verbindung, nummer, stand) VALUES ($1, $2, $3, $4, $5)", + [id, name, verbindung, nummer, moment().toDate()] + ); + await pool.query( + "INSERT INTO telefonnummern (fid_teilnehmer, name, verbindung, nummer, stand) VALUES ($1, $2, $3, $4, $5)", + [id, name, verbindung, nummer, moment().toDate()] + ); } else if (type == "tel-delete") { - await pool.query('DELETE FROM telefonnummern WHERE id = $1', [telid]); - console.log('delete numer $1', [telid]); + await pool.query("DELETE FROM telefonnummern WHERE id = $1", [telid]); + console.log("delete numer $1", [telid]); } else if (type == "adresse") { - await pool.query('UPDATE teilnehmende SET geburtsdatum = $1, adresse = $2, probe = $3 WHERE id = $4', [geburt, adresse, probe ? true : false, id]); + await pool.query( + "UPDATE teilnehmende SET geburtsdatum = $1, adresse = $2, probe = $3 WHERE id = $4", + [geburt, adresse, probe ? true : false, id] + ); } - res.redirect('/mitglied/' + id); + res.redirect("/mitglied/" + id); } catch (error) { console.error(error); - req.session.message = ['Error', error, 'error']; - res.redirect('/mitglied/' + id); + req.session.message = ["Error", error, "error"]; + res.redirect("/mitglied/" + id); } }); // Login und Registrierung anzeigen -app.get('/login', (req, res) => { - req.session.message = ['', '', 'none']; - res.render('login', { session: req.session }); // Stelle sicher, dass es eine login.ejs gibt +app.get("/login", (req, res) => { + req.session.message = ["", "", "none"]; + res.render("login", { session: req.session }); // Stelle sicher, dass es eine login.ejs gibt }); // Registrierung -app.get('/register', (req, res) => { - res.render('register', { session: req.session }); // Stelle sicher, dass es eine register.ejs gibt +app.get("/register", (req, res) => { + res.render("register", { session: req.session }); // Stelle sicher, dass es eine register.ejs gibt }); // Spieleliste -app.get('/spiele', async (req, res) => { +app.get("/spiele", async (req, res) => { try { - const spieleResult = await pool.query('SELECT * FROM spiele ORDER BY name ASC;'); + const spieleResult = await pool.query( + "SELECT * FROM spiele ORDER BY name ASC;" + ); const spiele = spieleResult.rows; - res.render('spiele', { spiele, session: req.session }); + res.render("spiele", { spiele, session: req.session }); } catch (error) { - console.error('Error in Mitglied:', error); - req.session.message = ['Error', error, 'error']; - res.render('spiele', { spiele, session: req.session }); + console.error("Error in Mitglied:", error); + req.session.message = ["Error", error, "error"]; + res.render("spiele", { spiele, session: req.session }); } -}) +}); -app.post('/delete-spiel', requireAdmin, async (req, res) => { +app.post("/delete-spiel", requireAdmin, async (req, res) => { const { spielId } = req.body; console.log(spielId); - await pool.query('DELETE FROM spiele WHERE id = $1', [spielId]); - res.redirect('/spiele'); -}) + await pool.query("DELETE FROM spiele WHERE id = $1", [spielId]); + res.redirect("/spiele"); +}); // Gerenderte Seite für gewähltes Spiel -app.get('/spiel/:id', async (req, res) => { +app.get("/spiel/:id", async (req, res) => { const { id } = req.params; try { - const spieleResult = await pool.query('SELECT * FROM spiele WHERE id = $1', [id]); + const spieleResult = await pool.query( + "SELECT * FROM spiele WHERE id = $1", + [id] + ); if (spieleResult.rows.length > 0) { const spiel = spieleResult.rows[0]; - res.render('spiel', { spiel, session: req.session }); + res.render("spiel", { spiel, session: req.session }); } else { - req.session.message = ['Error', 'Spiel existiert nicht', 'error']; - res.redirect('/spiele'); + req.session.message = ["Error", "Spiel existiert nicht", "error"]; + res.redirect("/spiele"); } } catch (error) { - console.error('Error in Spiele:', error); - req.session.message = ['Error', 'Spiel existiert nicht', 'error']; - res.redirect('/spiele'); + console.error("Error in Spiele:", error); + req.session.message = ["Error", "Spiel existiert nicht", "error"]; + res.redirect("/spiele"); } -}) +}); // Postseite für Änderungen -app.post('/edit-spiel', requireAuth, async (req, res) => { +app.post("/edit-spiel", requireAuth, async (req, res) => { const { material, dauer, regeln, variationen, type, id } = req.body; try { - const queryResult = await pool.query('UPDATE spiele set material = $1, regeln = $2, dauer = $3, variationen = $4, type = $5 Where id = $6 ', [material, regeln, dauer, variationen, type, id]); - req.session.message = ['Erfolg', 'Das Spiel wurde gespeichert', 'success']; - res.redirect('/spiel/' + id); + const queryResult = await pool.query( + "UPDATE spiele set material = $1, regeln = $2, dauer = $3, variationen = $4, type = $5 Where id = $6 ", + [material, regeln, dauer, variationen, type, id] + ); + req.session.message = ["Erfolg", "Das Spiel wurde gespeichert", "success"]; + res.redirect("/spiel/" + id); } catch (error) { - console.error('Error in edit Spiel:', error); - req.session.message = ['Error', error, 'error']; - res.redirect('/spiel/' + id); + console.error("Error in edit Spiel:", error); + req.session.message = ["Error", error, "error"]; + res.redirect("/spiel/" + id); } - -}) +}); // Startseite -app.get('/', (req, res) => { - req.session.message = ['', '', 'none'] - res.render('index', { session: req.session }); +app.get("/", (req, res) => { + req.session.message = ["", "", "none"]; + res.render("index", { session: req.session }); }); // Changelog -app.get('/changelog', async (req, res) => { +app.get("/changelog", async (req, res) => { try { - const changeResult = await pool.query('SELECT * FROM changelog ORDER BY datetime DESC;'); + const changeResult = await pool.query( + "SELECT * FROM changelog ORDER BY datetime DESC;" + ); const changes = changeResult.rows; - req.session.message = ['Erfolg', 'Log gespeichert', 'success']; - res.render('changelog', { changes, session: req.session }); + req.session.message = ["Erfolg", "Log gespeichert", "success"]; + res.render("changelog", { changes, session: req.session }); } catch (error) { - console.error('Error:', error); - req.session.message = ['Error', error, 'error']; - res.redirect('/changelog'); + console.error("Error:", error); + req.session.message = ["Error", error, "error"]; + res.redirect("/changelog"); } -}) +}); -app.post('/changelog', requireAdmin, async (req, res) => { +app.post("/changelog", requireAdmin, async (req, res) => { const { title, body } = req.body; try { - await pool.query('INSERT INTO changelog (title, body) VALUES ($1, $2);', [title, body]); + await pool.query("INSERT INTO changelog (title, body) VALUES ($1, $2);", [ + title, + body, + ]); - const changeResult = await pool.query('SELECT * FROM changelog ORDER BY datetime DESC;'); + const changeResult = await pool.query( + "SELECT * FROM changelog ORDER BY datetime DESC;" + ); const changes = changeResult.rows; - res.render('changelog', { changes, session: req.session }); + res.render("changelog", { changes, session: req.session }); } catch (error) { - console.error('Error:', error); - req.session.message = ['Error', error, 'error']; - res.render('changelog', { changes, session: req.session }); + console.error("Error:", error); + req.session.message = ["Error", error, "error"]; + res.render("changelog", { changes, session: req.session }); } -}) +}); -app.post('/anwesend', requireAuth, async (req, res) => { - const { anw, inriege , trainingId, riege } = req.body; - req.session.activeTab = 'anwesend'; +app.post("/anwesend", requireAuth, async (req, res) => { + const { anw, inriege, trainingId, riege } = req.body; + req.session.activeTab = "anwesend"; try { - for (const mitgliedId of inriege){ - const Idresult = await pool.query('SELECT *From anwesend WHERE fid_teilnehmer = $1 AND fid_training=$2', [mitgliedId, trainingId]) + for (const mitgliedId of inriege) { + const Idresult = await pool.query( + "SELECT *From anwesend WHERE fid_teilnehmer = $1 AND fid_training=$2", + [mitgliedId, trainingId] + ); console.log(anw); console.log(inriege); if (Idresult.rows.length > 0) { - if (!anw.includes(mitgliedId)){ - await pool.query('Delete FROM anwesend WHERE fid_teilnehmer = $1 AND fid_training=$2', [mitgliedId, trainingId]) + if (!anw.includes(mitgliedId)) { + await pool.query( + "Delete FROM anwesend WHERE fid_teilnehmer = $1 AND fid_training=$2", + [mitgliedId, trainingId] + ); } } } for (const teilnehmer of anw) { - const Tnresult = await pool.query('SELECT *From anwesend WHERE fid_teilnehmer = $1 AND fid_training=$2', [teilnehmer, trainingId]) + const Tnresult = await pool.query( + "SELECT *From anwesend WHERE fid_teilnehmer = $1 AND fid_training=$2", + [teilnehmer, trainingId] + ); if (Tnresult.rows.length === 0) { - await pool.query('INSERT INTO anwesend (fid_teilnehmer, fid_training) VALUES ($1, $2)', [teilnehmer, trainingId]); + await pool.query( + "INSERT INTO anwesend (fid_teilnehmer, fid_training) VALUES ($1, $2)", + [teilnehmer, trainingId] + ); } } req.session.activeRiege = riege; - req.session.activeTab = 'anwesend'; - req.session.message = [title = 'Erfolg', body = 'Die Anwesenheit wurde gespeichert', type = 'success']; - res.redirect('/training'); + req.session.activeTab = "anwesend"; + req.session.message = [ + (title = "Erfolg"), + (body = "Die Anwesenheit wurde gespeichert"), + (type = "success"), + ]; + res.redirect("/training"); } catch (error) { - console.error('Error:', error); - req.session.message = ['Error', error, 'error']; - res.redirect('/training'); + console.error("Error:", error); + req.session.message = ["Error", error, "error"]; + res.redirect("/training"); } -}) +}); -const server = app.listen(port, '0.0.0.0', () => { +const server = app.listen(port, "0.0.0.0", () => { log.Info(`Server is running on ${process.env.HOST}:${port}/`); });