Grundlage für KW

This commit is contained in:
Klaas 2024-06-01 22:38:25 +02:00
parent 3d41bf7ad8
commit e84b543fb0
5 changed files with 44 additions and 313 deletions

30
app.js
View File

@ -137,8 +137,7 @@ const getAllSpiele = async () => {
} }
}; };
// Funktion zum Laden der vier Leute, die am längsten nicht Aufwärmen bzw. Spiel geleitet haben // Funktion zum Laden der vier Leute, die am längsten nicht Aufwärmen oder Spiel geleitet haben
// Funktion zum Laden der vier Leute, die am längsten nicht Aufwärmen geleitet haben
const getCandidatesForAufwaermleiter = async () => { const getCandidatesForAufwaermleiter = async () => {
const result = await pool.query(` const result = await pool.query(`
SELECT t.id, t.name, SELECT t.id, t.name,
@ -444,11 +443,10 @@ app.post('/update-training', requireAuth, async (req, res) => {
if (spiel.rows.length > 0) { if (spiel.rows.length > 0) {
spielId = spiel.rows[0].id; spielId = spiel.rows[0].id;
console.log('Spiel existiert, die ID ist $1', [ spielId ]);
} else { } 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; spielId = newSpiel.rows[0].id;
console.log('Spiel existiert nicht, wurde mitID $1 angelegt', [ spielId ]); req.session.message = [title = 'Neues Spiel', body = 'Das Spiel ${ spielName } wurde angelegt.', type = 'Success'];
} }
try { try {
@ -457,7 +455,7 @@ app.post('/update-training', requireAuth, async (req, res) => {
} else if (type === 'aufwaermen') { } else if (type === 'aufwaermen') {
await pool.query('UPDATE trainings SET aufwaermen = $1 WHERE id = $2', [ spielId, trainingId ]); await pool.query('UPDATE trainings SET aufwaermen = $1 WHERE id = $2', [ spielId, trainingId ]);
} }
req.session.message = [title = '', body = '', type = 'none'];
res.redirect('/training'); res.redirect('/training');
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@ -508,7 +506,11 @@ res.redirect('/riege');
app.get('/training', requireAuth, async (req, res) => { app.get('/training', requireAuth, async (req, res) => {
try { try {
let dateParam = req.query.date; let dateParam = req.query.date;
let kwParam = req.query.kw;
let jahrParam = req.query.jahr;
let selectedDate; let selectedDate;
let selectedKW;
let selectetYear;
if (dateParam) { if (dateParam) {
@ -517,6 +519,20 @@ app.get('/training', requireAuth, async (req, res) => {
selectedDate = moment().toDate(); selectedDate = moment().toDate();
} }
if (kwParam) {
selectedKW = kwParam;
if (jahrParam) {
selectetYear = jahrParam;
} else {
if (dateParam) {
selectetYear = moment(selectedDate).year();
}
}
} else {
selectedKW = moment(selectedDate).isoWeek();
selectetYear = moment(selectedDate).year();
}
console.log(selectedKW + ' ' + selectetYear);
const training =await getTraining(selectedDate); const training =await getTraining(selectedDate);
const trainingsResult = await pool.query('SELECT datum FROM trainings ORDER BY datum ASC'); const trainingsResult = await pool.query('SELECT datum FROM trainings ORDER BY datum ASC');
@ -777,7 +793,6 @@ app.get('/', (req, res) => {
res.render('index', {session: req.session}); res.render('index', {session: req.session});
}); });
// Changelog // Changelog
app.get('/changelog', async (req, res) => { app.get('/changelog', async (req, res) => {
try { try {
@ -828,6 +843,3 @@ try {
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}/`); log.Info(`Server is running on ${process.env.HOST}:${port}/`);
}); });

View File

View File

302
routes.js
View File

@ -1,302 +0,0 @@
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
});

21
utilities/changetable.js Normal file
View File

@ -0,0 +1,21 @@
const { Pool } = require('pg');
require('dotenv').config();
const moment = require('moment');
// Datenbankverbindung
const pool = new Pool({
connectionString: process.env.DATABASE_URL
});
async function writeKW() {
const resultTrainings = await pool.query('SELECT * FROM trainings');
const trainings = resultTrainings.rows;
for (const training of trainings) {
const jahr = moment(training.datum).year();
const kw = moment(training.datum).isoWeek();
await pool.query('UPDATE trainings SET kw = $1, jahr = $2 WHERE id = $3', [kw, jahr, training.id])
}
}
writeKW();