From a503edb22052cfc63b86827f92dc1a05136cbd88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=B6rdle=20Bot?= Date: Mon, 1 Dec 2025 17:06:07 +0100 Subject: [PATCH] fix: enhance database script with improved permission handling and error checks - Added permission setting for backup and temporary database files to ensure proper access. - Implemented checks for file readability and ownership adjustments to enhance robustness. - Included detailed SQL commands to fix internationalization data in the database, improving data integrity. --- FIX_I18N.md | 83 +++++++++++++++++++++++++++++++++++++ scripts/fix-i18n-easy.sh | 87 +++++++++++++++++++++++++++++++++++++++ scripts/fix-i18n-local.sh | 59 ++++++++++++++++++++++++-- 3 files changed, 226 insertions(+), 3 deletions(-) create mode 100644 FIX_I18N.md create mode 100755 scripts/fix-i18n-easy.sh diff --git a/FIX_I18N.md b/FIX_I18N.md new file mode 100644 index 0000000..d4edf92 --- /dev/null +++ b/FIX_I18N.md @@ -0,0 +1,83 @@ +# Fix für i18n-Daten (String → JSON Konvertierung) + +## Problem +Die Datenbank hat Genre-/Special-/News-Namen als einfache Strings (`"Rock"`) statt JSON (`{"de": "Rock", "en": "Rock"}`) gespeichert, was zu `SyntaxError: "Rock" is not valid JSON` führt. + +## Lösung: Manuell ausführen + +Führe diese Befehle **direkt auf dem Server** aus: + +```bash +cd ~/hoerdle + +# 1. Backup erstellen +docker cp hoerdle:/app/data/prod.db ./data/prod.db.backup.$(date +%Y%m%d_%H%M%S) + +# 2. Kopiere DB lokal +docker cp hoerdle:/app/data/prod.db ./data/prod.db.tmp + +# 3. Setze Berechtigungen +sudo chmod 666 ./data/prod.db.tmp +sudo chmod 775 ./data + +# 4. Prüfe ob sqlite3 installiert ist +which sqlite3 || sudo apt-get install -y sqlite3 + +# 5. Fixe die Datenbank (kopiere diesen Block komplett) +sqlite3 ./data/prod.db.tmp << 'EOF' +UPDATE Genre SET name = json_object('de', name, 'en', name) WHERE typeof(name) = 'text' AND name NOT LIKE '{%'; +UPDATE Genre SET subtitle = json_object('de', subtitle, 'en', subtitle) WHERE subtitle IS NOT NULL AND typeof(subtitle) = 'text' AND subtitle NOT LIKE '{%'; +UPDATE Special SET name = json_object('de', name, 'en', name) WHERE typeof(name) = 'text' AND name NOT LIKE '{%'; +UPDATE Special SET subtitle = json_object('de', subtitle, 'en', subtitle) WHERE subtitle IS NOT NULL AND typeof(subtitle) = 'text' AND subtitle NOT LIKE '{%'; +UPDATE News SET title = json_object('de', title, 'en', title) WHERE typeof(title) = 'text' AND title NOT LIKE '{%'; +UPDATE News SET content = json_object('de', content, 'en', content) WHERE typeof(content) = 'text' AND content NOT LIKE '{%'; +SELECT '✅ Fertig!' as status; +EOF + +# 6. Kopiere zurück +docker cp ./data/prod.db.tmp hoerdle:/app/data/prod.db + +# 7. Aufräumen +rm ./data/prod.db.tmp + +# 8. Container neu starten +docker compose restart hoerdle + +# 9. Logs prüfen +docker logs hoerdle --tail=50 +``` + +Falls Schritt 5 mit "permission denied" fehlschlägt, verwende `sudo`: + +```bash +sudo sqlite3 ./data/prod.db.tmp << 'EOF' +[... SQL-Befehle wie oben ...] +EOF +``` + +## Automatisiertes Skript + +Alternativ kannst du das automatische Skript verwenden: + +```bash +./scripts/fix-i18n-easy.sh +``` + +Oder das lokale Skript: + +```bash +./scripts/fix-i18n-local.sh +``` + +## Prüfen ob es funktioniert hat + +Nach dem Neustart sollte die Seite wieder funktionieren: + +```bash +# Prüfe Logs (sollte keine JSON-Fehler mehr zeigen) +docker logs hoerdle --tail=100 | grep -i "json\|error" || echo "✅ Keine JSON-Fehler gefunden" + +# Teste die Seite +curl -s https://hoerdle.de/de | head -20 +``` + diff --git a/scripts/fix-i18n-easy.sh b/scripts/fix-i18n-easy.sh new file mode 100755 index 0000000..67a4557 --- /dev/null +++ b/scripts/fix-i18n-easy.sh @@ -0,0 +1,87 @@ +#!/bin/bash +# Einfaches Fix-Skript für i18n-Daten + +set -e + +echo "🔧 Fixe i18n-Daten..." +echo "" + +# Prüfe ob Container läuft +if ! docker ps | grep -q hoerdle; then + echo "❌ Container 'hoerdle' läuft nicht!" + exit 1 +fi + +# Backup +BACKUP_FILE="./data/prod.db.backup.$(date +%Y%m%d_%H%M%S)" +echo "💾 Erstelle Backup..." +docker cp hoerdle:/app/data/prod.db "$BACKUP_FILE" || { + echo "❌ Backup fehlgeschlagen!" + exit 1 +} +echo "✅ Backup: $BACKUP_FILE" +echo "" + +# Kopiere DB +echo "📥 Kopiere Datenbank lokal..." +DB_TMP="./data/prod.db.tmp" +docker cp hoerdle:/app/data/prod.db "$DB_TMP" +echo "✅ Datenbank kopiert" +echo "" + +# Setze Berechtigungen +echo "🔐 Setze Berechtigungen..." +sudo chmod 666 "$DB_TMP" 2>/dev/null || chmod 666 "$DB_TMP" || { + echo "⚠️ Konnte Berechtigungen nicht setzen" +} +sudo chmod 775 ./data 2>/dev/null || chmod 775 ./data || true +echo "" + +# Prüfe sqlite3 +if ! command -v sqlite3 &> /dev/null; then + echo "❌ sqlite3 nicht gefunden! Installiere es:" + echo " sudo apt-get update && sudo apt-get install -y sqlite3" + exit 1 +fi + +# Fixe DB +echo "🔧 Führe SQL-Updates aus..." +sqlite3 "$DB_TMP" << 'SQL' || { + echo "⚠️ Normale Ausführung fehlgeschlagen, versuche mit sudo..." + sudo sqlite3 "$DB_TMP" << 'SQL2' +UPDATE Genre SET name = json_object('de', name, 'en', name) WHERE typeof(name) = 'text' AND name NOT LIKE '{%'; +UPDATE Genre SET subtitle = json_object('de', subtitle, 'en', subtitle) WHERE subtitle IS NOT NULL AND typeof(subtitle) = 'text' AND subtitle NOT LIKE '{%'; +UPDATE Special SET name = json_object('de', name, 'en', name) WHERE typeof(name) = 'text' AND name NOT LIKE '{%'; +UPDATE Special SET subtitle = json_object('de', subtitle, 'en', subtitle) WHERE subtitle IS NOT NULL AND typeof(subtitle) = 'text' AND subtitle NOT LIKE '{%'; +UPDATE News SET title = json_object('de', title, 'en', title) WHERE typeof(title) = 'text' AND title NOT LIKE '{%'; +UPDATE News SET content = json_object('de', content, 'en', content) WHERE typeof(content) = 'text' AND content NOT LIKE '{%'; +SQL2 +} +UPDATE Genre SET name = json_object('de', name, 'en', name) WHERE typeof(name) = 'text' AND name NOT LIKE '{%'; +UPDATE Genre SET subtitle = json_object('de', subtitle, 'en', subtitle) WHERE subtitle IS NOT NULL AND typeof(subtitle) = 'text' AND subtitle NOT LIKE '{%'; +UPDATE Special SET name = json_object('de', name, 'en', name) WHERE typeof(name) = 'text' AND name NOT LIKE '{%'; +UPDATE Special SET subtitle = json_object('de', subtitle, 'en', subtitle) WHERE subtitle IS NOT NULL AND typeof(subtitle) = 'text' AND subtitle NOT LIKE '{%'; +UPDATE News SET title = json_object('de', title, 'en', title) WHERE typeof(title) = 'text' AND title NOT LIKE '{%'; +UPDATE News SET content = json_object('de', content, 'en', content) WHERE typeof(content) = 'text' AND content NOT LIKE '{%'; +SELECT '✅ Fertig!' as status; +SQL + +echo "" +echo "✅ Datenbank gefixt" +echo "" + +# Kopiere zurück +echo "📤 Kopiere Datenbank zurück..." +docker cp "$DB_TMP" hoerdle:/app/data/prod.db +echo "✅ Zurück kopiert" +echo "" + +# Aufräumen +rm -f "$DB_TMP" + +echo "🔄 Starte Container neu..." +docker compose restart hoerdle +echo "" + +echo "✅ Fertig! Prüfe Logs: docker logs hoerdle --tail=50" + diff --git a/scripts/fix-i18n-local.sh b/scripts/fix-i18n-local.sh index 2bd201b..30a4be0 100755 --- a/scripts/fix-i18n-local.sh +++ b/scripts/fix-i18n-local.sh @@ -16,12 +16,20 @@ fi BACKUP_FILE="./data/prod.db.backup.$(date +%Y%m%d_%H%M%S)" echo "💾 Erstelle Backup..." docker cp hoerdle:/app/data/prod.db "$BACKUP_FILE" +# Setze Berechtigungen (kann root gehören) +sudo chmod 666 "$BACKUP_FILE" 2>/dev/null || chmod 666 "$BACKUP_FILE" 2>/dev/null || true echo "✅ Backup erstellt: $BACKUP_FILE" echo "" # Kopiere DB lokal echo "📥 Kopiere Datenbank lokal..." docker cp hoerdle:/app/data/prod.db ./data/prod.db.tmp +# Setze Berechtigungen (Datei kann root gehören) +sudo chmod 666 ./data/prod.db.tmp 2>/dev/null || chmod 666 ./data/prod.db.tmp 2>/dev/null || { + echo "⚠️ Konnte Berechtigungen nicht setzen. Versuche mit sudo..." + sudo chmod 666 ./data/prod.db.tmp +} +chmod 775 ./data 2>/dev/null || sudo chmod 775 ./data 2>/dev/null || true echo "✅ Datenbank kopiert" echo "" @@ -34,10 +42,18 @@ fi # Fixe die Datenbank echo "🔧 Fixe i18n-Daten..." -sqlite3 ./data/prod.db.tmp << 'SQL' --- Backup innerhalb der DB -.backup ./data/prod.db.tmp.backup +# Stelle sicher, dass wir Schreibrechte haben (auch für WAL-Dateien) +chmod 666 ./data/prod.db.tmp 2>/dev/null || sudo chmod 666 ./data/prod.db.tmp +chmod 775 ./data 2>/dev/null || sudo chmod 775 ./data +# Prüfe ob wir die Datei lesen können +if [ ! -r "./data/prod.db.tmp" ]; then + echo "❌ Kann Datenbankdatei nicht lesen. Setze Besitzer..." + sudo chown $(whoami):$(whoami) ./data/prod.db.tmp || true +fi +# Führe SQL-Befehle aus (mit sudo falls nötig) +if [ -r "./data/prod.db.tmp" ] && [ -w "./data" ]; then + sqlite3 ./data/prod.db.tmp << 'SQL' -- Fix Genre.name UPDATE Genre SET name = json_object('de', name, 'en', name) @@ -70,6 +86,43 @@ WHERE typeof(content) = 'text' AND content NOT LIKE '{%'; SELECT '✅ Alle i18n-Daten wurden gefixt!' as status; SQL +else + echo "❌ Kann Datenbankdatei nicht lesen oder schreiben!" + echo " Versuche mit sudo..." + sudo sqlite3 ./data/prod.db.tmp << 'SQL' +-- Fix Genre.name +UPDATE Genre +SET name = json_object('de', name, 'en', name) +WHERE typeof(name) = 'text' AND name NOT LIKE '{%'; + +-- Fix Genre.subtitle +UPDATE Genre +SET subtitle = json_object('de', subtitle, 'en', subtitle) +WHERE subtitle IS NOT NULL AND typeof(subtitle) = 'text' AND subtitle NOT LIKE '{%'; + +-- Fix Special.name +UPDATE Special +SET name = json_object('de', name, 'en', name) +WHERE typeof(name) = 'text' AND name NOT LIKE '{%'; + +-- Fix Special.subtitle +UPDATE Special +SET subtitle = json_object('de', subtitle, 'en', subtitle) +WHERE subtitle IS NOT NULL AND typeof(subtitle) = 'text' AND subtitle NOT LIKE '{%'; + +-- Fix News.title +UPDATE News +SET title = json_object('de', title, 'en', title) +WHERE typeof(title) = 'text' AND title NOT LIKE '{%'; + +-- Fix News.content +UPDATE News +SET content = json_object('de', content, 'en', content) +WHERE typeof(content) = 'text' AND content NOT LIKE '{%'; + +SELECT '✅ Alle i18n-Daten wurden gefixt!' as status; +SQL +fi if [ $? -ne 0 ]; then echo "❌ Fehler beim Fixen der Datenbank!"