Grundlage für KW
This commit is contained in:
parent
3d41bf7ad8
commit
e84b543fb0
34
app.js
34
app.js
|
@ -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,8 +506,12 @@ 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) {
|
||||||
selectedDate = moment(dateParam, 'DD.MM.YYYY').toDate();
|
selectedDate = moment(dateParam, 'DD.MM.YYYY').toDate();
|
||||||
|
@ -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 {
|
||||||
|
@ -827,7 +842,4 @@ 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}/`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
302
routes.js
302
routes.js
|
@ -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
|
|
||||||
});
|
|
|
@ -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();
|
Loading…
Reference in New Issue