diff --git a/.claude/settings.local.json b/.claude/settings.local.json index bbf35b2..28fd183 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -9,7 +9,8 @@ "Bash(docker-compose down:*)", "Bash(docker logs:*)", "Bash(docker exec:*)", - "Bash(python3:*)" + "Bash(python3:*)", + "Bash(docker-compose restart:*)" ], "deny": [] } diff --git a/JOURNAL.md b/JOURNAL.md index cf5bf8a..3f88bf2 100644 --- a/JOURNAL.md +++ b/JOURNAL.md @@ -100,4 +100,24 @@ Lizenzmanagement-System für Social Media Account-Erstellungssoftware mit Docker ### 2025-01-06 - Journal erstellt - Initialer Projektstand dokumentiert - Aufgabenliste priorisiert -- Technische Anforderungen festgehalten \ No newline at end of file +- Technische Anforderungen festgehalten + +### 2025-01-06 - UTF-8 Support implementiert +- Flask App Konfiguration für UTF-8 hinzugefügt (JSON_AS_ASCII=False) +- PostgreSQL Verbindung mit UTF-8 client_encoding +- HTML Forms mit accept-charset="UTF-8" +- Dockerfile mit deutschen Locale-Einstellungen (de_DE.UTF-8) +- PostgreSQL Container mit UTF-8 Initialisierung +- init.sql mit SET client_encoding = 'UTF8' + +**Geänderte Dateien:** +- v2_adminpanel/app.py +- v2_adminpanel/templates/index.html +- v2_adminpanel/init.sql +- v2_adminpanel/Dockerfile +- v2/docker-compose.yaml + +**Nächster Test:** +- Container neu bauen und starten +- Kundennamen mit Umlauten testen (z.B. "Müller GmbH", "Björn Schäfer") +- Email mit Umlauten testen \ No newline at end of file diff --git a/v2/docker-compose.yaml b/v2/docker-compose.yaml index 9535713..7ce4f8e 100644 --- a/v2/docker-compose.yaml +++ b/v2/docker-compose.yaml @@ -8,6 +8,9 @@ services: env_file: .env environment: POSTGRES_HOST: postgres + POSTGRES_INITDB_ARGS: '--encoding=UTF8 --locale=de_DE.UTF-8' + POSTGRES_COLLATE: 'de_DE.UTF-8' + POSTGRES_CTYPE: 'de_DE.UTF-8' volumes: # Persistente Speicherung der Datenbank auf dem Windows-Host - postgres_data:/var/lib/postgresql/data diff --git a/v2_adminpanel/Dockerfile b/v2_adminpanel/Dockerfile index 345ccad..fa620d5 100644 --- a/v2_adminpanel/Dockerfile +++ b/v2_adminpanel/Dockerfile @@ -1,5 +1,10 @@ FROM python:3.11-slim +# Locale für deutsche Sprache und UTF-8 setzen +ENV LANG=de_DE.UTF-8 +ENV LC_ALL=de_DE.UTF-8 +ENV PYTHONIOENCODING=utf-8 + WORKDIR /app COPY requirements.txt . diff --git a/v2_adminpanel/app.py b/v2_adminpanel/app.py index b20d420..f4e801a 100644 --- a/v2_adminpanel/app.py +++ b/v2_adminpanel/app.py @@ -10,6 +10,8 @@ load_dotenv() app = Flask(__name__) app.config['SECRET_KEY'] = os.urandom(24) app.config['SESSION_TYPE'] = 'filesystem' +app.config['JSON_AS_ASCII'] = False # JSON-Ausgabe mit UTF-8 +app.config['JSONIFY_MIMETYPE'] = 'application/json; charset=utf-8' Session(app) # Login decorator @@ -21,15 +23,18 @@ def login_required(f): return f(*args, **kwargs) return decorated_function -# DB-Verbindung +# DB-Verbindung mit UTF-8 Encoding def get_connection(): - return psycopg2.connect( + conn = psycopg2.connect( host=os.getenv("POSTGRES_HOST", "postgres"), port=os.getenv("POSTGRES_PORT", "5432"), dbname=os.getenv("POSTGRES_DB"), user=os.getenv("POSTGRES_USER"), - password=os.getenv("POSTGRES_PASSWORD") + password=os.getenv("POSTGRES_PASSWORD"), + options='-c client_encoding=UTF8' ) + conn.set_client_encoding('UTF8') + return conn @app.route("/login", methods=["GET", "POST"]) def login(): diff --git a/v2_adminpanel/init.sql b/v2_adminpanel/init.sql index 25f8d2c..abf57a1 100644 --- a/v2_adminpanel/init.sql +++ b/v2_adminpanel/init.sql @@ -1,3 +1,6 @@ +-- UTF-8 Encoding für deutsche Sonderzeichen sicherstellen +SET client_encoding = 'UTF8'; + CREATE TABLE IF NOT EXISTS customers ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, diff --git a/v2_adminpanel/templates/index.html b/v2_adminpanel/templates/index.html index 201e429..7727bc2 100644 --- a/v2_adminpanel/templates/index.html +++ b/v2_adminpanel/templates/index.html @@ -19,15 +19,15 @@

Neue Lizenz erstellen

-
+
- +
- +
diff --git a/v2_testing/test_utf8_umlaute.py b/v2_testing/test_utf8_umlaute.py new file mode 100644 index 0000000..5041fd1 --- /dev/null +++ b/v2_testing/test_utf8_umlaute.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +import requests +import urllib3 +from datetime import datetime, timedelta + +# Disable SSL warnings for self-signed certificate +urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) + +# Test configuration +base_url = "https://localhost:443" +admin_user = {"username": "rac00n", "password": "1248163264"} + +def test_umlaut_support(): + """Test UTF-8 support with German umlauts""" + session = requests.Session() + + # Login first + login_data = { + "username": admin_user["username"], + "password": admin_user["password"] + } + + response = session.post(f"{base_url}/login", data=login_data, verify=False, allow_redirects=False) + if response.status_code != 302: + return "Failed to login" + + # Create test data with German umlauts + test_customers = [ + { + "customer_name": "Müller GmbH & Co. KG", + "email": "kontakt@müller-gmbh.de", + "license_key": "MÜLLER-2025-ÄÖÜ", + "license_type": "Premium-Größe", + "valid_from": datetime.now().strftime("%Y-%m-%d"), + "valid_until": (datetime.now() + timedelta(days=365)).strftime("%Y-%m-%d") + }, + { + "customer_name": "Schröder Süßwaren AG", + "email": "info@schröder-süßwaren.de", + "license_key": "SCHRÖDER-2025-ßÄÖÜ", + "license_type": "Geschäftskunden", + "valid_from": datetime.now().strftime("%Y-%m-%d"), + "valid_until": (datetime.now() + timedelta(days=180)).strftime("%Y-%m-%d") + }, + { + "customer_name": "Björn Köhler Einzelunternehmen", + "email": "björn.köhler@übersetzungen.de", + "license_key": "KÖHLER-2025-BJÖRN", + "license_type": "Übersetzungsbüro", + "valid_from": datetime.now().strftime("%Y-%m-%d"), + "valid_until": (datetime.now() + timedelta(days=90)).strftime("%Y-%m-%d") + } + ] + + results = [] + for customer in test_customers: + response = session.post(f"{base_url}/", data=customer, verify=False, allow_redirects=False) + + if response.status_code == 302 and response.headers.get('Location') == '/': + results.append(f"✓ Created: {customer['customer_name']}") + else: + results.append(f"✗ Failed: {customer['customer_name']} - Status: {response.status_code}") + + return results + +print("Testing UTF-8 German Umlaut Support") +print("=" * 50) +print("Creating customers with special characters: ä, ö, ü, ß, Ä, Ö, Ü") +print("-" * 50) + +results = test_umlaut_support() +for result in results: + print(result) + +# Verify the data in the database +print("\n" + "=" * 50) +print("Verifying database entries:") +print("-" * 50) + +import subprocess +result = subprocess.run([ + "docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", + "-c", "SELECT c.name, c.email, l.license_key, l.license_type FROM licenses l JOIN customers c ON l.customer_id = c.id ORDER BY c.id DESC LIMIT 3;" +], capture_output=True, text=True) + +print(result.stdout) + +# Test direct database insertion with umlauts +print("Direct database test with umlauts:") +print("-" * 50) + +test_query = """ +INSERT INTO customers (name, email) VALUES ('Testfirma für Umlaute: äöüßÄÖÜ', 'test@überprüfung.de') RETURNING name, email; +""" + +result = subprocess.run([ + "docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", + "-c", test_query +], capture_output=True, text=True) + +print(result.stdout) \ No newline at end of file