Implement 301 redirects for www to non-www and enhance canonical tag handling
This commit adds 301 redirects in the Apache configuration to redirect traffic from www.tt-tagebuch.de to tt-tagebuch.de for both HTTP and HTTPS. Additionally, it introduces middleware in the backend to dynamically set canonical tags based on the request URL, ensuring proper SEO practices. The request logging middleware has been disabled, and sensitive data handling has been improved in the MyTischtennis model and API logging service, ensuring compliance with data protection regulations. Frontend updates include enhanced descriptions and features in the application, improving user experience and clarity.
This commit is contained in:
169
backend/scripts/migrateMyTischtennisEncryption.js
Normal file
169
backend/scripts/migrateMyTischtennisEncryption.js
Normal file
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* Migration Script: Verschlüsselung für bestehende MyTischtennis-Daten
|
||||
*
|
||||
* WICHTIG: Dieses Script verschlüsselt bestehende unverschlüsselte MyTischtennis-Daten.
|
||||
* Es sollte NUR EINMAL ausgeführt werden, nachdem das Model aktualisiert wurde.
|
||||
*
|
||||
* Vorsicht: Wenn Daten bereits verschlüsselt sind, wird dieses Script sie doppelt verschlüsseln!
|
||||
*
|
||||
* Usage: node backend/scripts/migrateMyTischtennisEncryption.js
|
||||
*/
|
||||
|
||||
import sequelize from '../database.js';
|
||||
import MyTischtennis from '../models/MyTischtennis.js';
|
||||
import { encryptData } from '../utils/encrypt.js';
|
||||
|
||||
async function migrateMyTischtennisEncryption() {
|
||||
console.log('🔄 Starte Migration: Verschlüsselung für MyTischtennis-Daten\n');
|
||||
|
||||
try {
|
||||
// Hole alle MyTischtennis-Einträge mit raw: true, um unverschlüsselte Daten zu bekommen
|
||||
const accounts = await MyTischtennis.findAll({
|
||||
raw: true,
|
||||
attributes: ['id', 'email', 'access_token', 'refresh_token', 'cookie', 'user_data', 'club_id', 'club_name', 'fed_nickname']
|
||||
});
|
||||
|
||||
console.log(`📊 Gefundene Einträge: ${accounts.length}\n`);
|
||||
|
||||
if (accounts.length === 0) {
|
||||
console.log('✅ Keine Einträge gefunden. Migration nicht erforderlich.');
|
||||
return;
|
||||
}
|
||||
|
||||
let migrated = 0;
|
||||
let skipped = 0;
|
||||
let errors = 0;
|
||||
|
||||
for (const account of accounts) {
|
||||
try {
|
||||
// Prüfe, ob Daten bereits verschlüsselt sind
|
||||
// Verschlüsselte Daten sind hex-Strings und haben eine bestimmte Länge
|
||||
// Unverschlüsselte E-Mail-Adressen enthalten normalerweise @
|
||||
const emailIsEncrypted = !account.email.includes('@') && account.email.length > 32;
|
||||
|
||||
if (emailIsEncrypted) {
|
||||
console.log(`⏭️ Eintrag ${account.id}: Bereits verschlüsselt, überspringe...`);
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
console.log(`🔐 Verschlüssele Eintrag ${account.id}...`);
|
||||
|
||||
// Verschlüssele alle Felder direkt in der Datenbank
|
||||
const updateData = {};
|
||||
|
||||
if (account.email && account.email.includes('@')) {
|
||||
updateData.email = encryptData(account.email);
|
||||
}
|
||||
|
||||
if (account.access_token && !account.access_token.startsWith('encrypted_')) {
|
||||
// Prüfe, ob es bereits verschlüsselt aussieht (hex-String)
|
||||
const looksEncrypted = /^[0-9a-f]+$/i.test(account.access_token) && account.access_token.length > 32;
|
||||
if (!looksEncrypted) {
|
||||
updateData.access_token = encryptData(account.access_token);
|
||||
}
|
||||
}
|
||||
|
||||
if (account.refresh_token && !account.refresh_token.startsWith('encrypted_')) {
|
||||
const looksEncrypted = /^[0-9a-f]+$/i.test(account.refresh_token) && account.refresh_token.length > 32;
|
||||
if (!looksEncrypted) {
|
||||
updateData.refresh_token = encryptData(account.refresh_token);
|
||||
}
|
||||
}
|
||||
|
||||
if (account.cookie && !account.cookie.startsWith('encrypted_')) {
|
||||
const looksEncrypted = /^[0-9a-f]+$/i.test(account.cookie) && account.cookie.length > 32;
|
||||
if (!looksEncrypted) {
|
||||
updateData.cookie = encryptData(account.cookie);
|
||||
}
|
||||
}
|
||||
|
||||
if (account.user_data) {
|
||||
// user_data ist JSON, muss zuerst zu String konvertiert werden
|
||||
try {
|
||||
const userDataStr = typeof account.user_data === 'string'
|
||||
? account.user_data
|
||||
: JSON.stringify(account.user_data);
|
||||
// Prüfe, ob bereits verschlüsselt
|
||||
const looksEncrypted = /^[0-9a-f]+$/i.test(userDataStr) && userDataStr.length > 32;
|
||||
if (!looksEncrypted) {
|
||||
updateData.user_data = encryptData(userDataStr);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(` ⚠️ Fehler bei user_data für Eintrag ${account.id}:`, e.message);
|
||||
}
|
||||
}
|
||||
|
||||
if (account.club_id && account.club_id.length > 0 && !account.club_id.startsWith('encrypted_')) {
|
||||
const looksEncrypted = /^[0-9a-f]+$/i.test(account.club_id) && account.club_id.length > 32;
|
||||
if (!looksEncrypted) {
|
||||
updateData.club_id = encryptData(account.club_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (account.club_name && account.club_name.length > 0 && !account.club_name.startsWith('encrypted_')) {
|
||||
const looksEncrypted = /^[0-9a-f]+$/i.test(account.club_name) && account.club_name.length > 32;
|
||||
if (!looksEncrypted) {
|
||||
updateData.club_name = encryptData(account.club_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (account.fed_nickname && account.fed_nickname.length > 0 && !account.fed_nickname.startsWith('encrypted_')) {
|
||||
const looksEncrypted = /^[0-9a-f]+$/i.test(account.fed_nickname) && account.fed_nickname.length > 32;
|
||||
if (!looksEncrypted) {
|
||||
updateData.fed_nickname = encryptData(account.fed_nickname);
|
||||
}
|
||||
}
|
||||
|
||||
// Update nur, wenn es etwas zu aktualisieren gibt
|
||||
if (Object.keys(updateData).length > 0) {
|
||||
await sequelize.query(
|
||||
`UPDATE my_tischtennis SET ${Object.keys(updateData).map(key => `\`${key}\` = :${key}`).join(', ')} WHERE id = :id`,
|
||||
{
|
||||
replacements: { ...updateData, id: account.id },
|
||||
type: sequelize.QueryTypes.UPDATE
|
||||
}
|
||||
);
|
||||
migrated++;
|
||||
console.log(` ✅ Eintrag ${account.id} erfolgreich verschlüsselt`);
|
||||
} else {
|
||||
skipped++;
|
||||
console.log(` ⏭️ Eintrag ${account.id}: Keine unverschlüsselten Daten gefunden`);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
errors++;
|
||||
console.error(` ❌ Fehler bei Eintrag ${account.id}:`, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\n📊 Migrations-Zusammenfassung:');
|
||||
console.log(` ✅ Migriert: ${migrated}`);
|
||||
console.log(` ⏭️ Übersprungen: ${skipped}`);
|
||||
console.log(` ❌ Fehler: ${errors}`);
|
||||
|
||||
if (errors === 0) {
|
||||
console.log('\n✅ Migration erfolgreich abgeschlossen!');
|
||||
} else {
|
||||
console.log('\n⚠️ Migration abgeschlossen, aber es gab Fehler. Bitte prüfen Sie die Logs.');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Kritischer Fehler bei Migration:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
await sequelize.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Script ausführen
|
||||
migrateMyTischtennisEncryption()
|
||||
.then(() => {
|
||||
console.log('\n✅ Script beendet.');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('\n❌ Script fehlgeschlagen:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user