Dieser Commit ist enthalten in:
Claude Project Manager
2025-07-05 17:51:16 +02:00
Commit 0d7d888502
1594 geänderte Dateien mit 122839 neuen und 0 gelöschten Zeilen

Datei anzeigen

@ -0,0 +1,10 @@
{
"permissions": {
"allow": [
"Bash(python3:*)",
"Bash(pip install:*)",
"Bash(pip3 install:*)"
],
"deny": []
}
}

Datei anzeigen

@ -0,0 +1,53 @@
#!/usr/bin/env python3
import requests
import urllib3
# Disable SSL warnings for self-signed certificate
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Test configuration
base_url = "https://localhost:443"
admin_users = [
{"username": "rac00n", "password": "1248163264"},
{"username": "w@rh@mm3r", "password": "Warhammer123!"}
]
def test_login(username, password):
"""Test login functionality for admin user"""
session = requests.Session()
# Get login page
response = session.get(f"{base_url}/login", verify=False)
if response.status_code != 200:
return f"Failed to access login page: {response.status_code}"
# Attempt login
login_data = {
"username": username,
"password": password
}
response = session.post(f"{base_url}/login", data=login_data, verify=False, allow_redirects=False)
# Check if login was successful (redirect to dashboard)
if response.status_code == 302 and response.headers.get('Location') == '/':
# Try to access dashboard
dashboard_response = session.get(f"{base_url}/", verify=False)
if dashboard_response.status_code == 200 and username in dashboard_response.text:
return f"✓ Login successful for {username}"
else:
return f"✗ Login succeeded but dashboard access failed for {username}"
else:
return f"✗ Login failed for {username}"
# Test both admin users
print("Testing Admin Panel Login Functionality")
print("=" * 40)
for user in admin_users:
result = test_login(user["username"], user["password"])
print(result)
print("\nTesting invalid credentials...")
result = test_login("invalid_user", "wrong_password")
print(result)

125
v2_testing/test_audit_json.py Normale Datei
Datei anzeigen

@ -0,0 +1,125 @@
#!/usr/bin/env python3
import requests
import urllib3
import subprocess
import json
# Disable SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
base_url = "https://localhost:443"
admin_user = {"username": "rac00n", "password": "1248163264"}
def login(session):
"""Login to admin panel"""
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)
return response.status_code == 302
def test_json_logging():
"""Test JSON value logging in audit log"""
session = requests.Session()
login(session)
print("Testing JSON Value Storage in Audit Log")
print("=" * 50)
# 1. Create a license (should log new_values as JSON)
print("\n1. Creating license to test JSON logging...")
license_data = {
"customer_name": "JSON Test GmbH",
"email": "json@test.de",
"license_key": "JSON-TEST-KEY",
"license_type": "full",
"valid_from": "2025-01-01",
"valid_until": "2025-12-31"
}
response = session.post(f"{base_url}/create", data=license_data, verify=False, allow_redirects=False)
print("✓ License created")
# 2. Get the license ID
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", "SELECT id FROM licenses WHERE license_key = 'JSON-TEST-KEY';"
], capture_output=True, text=True)
license_id = result.stdout.strip()
if license_id:
# 3. Edit the license (should log both old_values and new_values)
print("\n2. Editing license to test old/new JSON values...")
# First get the edit page to ensure we have the right form
response = session.get(f"{base_url}/license/edit/{license_id}", verify=False)
# Now update
updated_data = {
"license_key": "JSON-TEST-UPDATED",
"license_type": "test",
"valid_from": "2025-01-01",
"valid_until": "2025-06-30",
"is_active": "on"
}
response = session.post(f"{base_url}/license/edit/{license_id}",
data=updated_data,
verify=False,
allow_redirects=False)
print("✓ License updated")
# 4. Check the audit log for JSON values
print("\n3. Checking audit log for JSON values...")
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", """SELECT action, entity_type,
CASE WHEN old_values IS NULL THEN 'NULL'
ELSE jsonb_pretty(old_values) END as old_vals,
CASE WHEN new_values IS NULL THEN 'NULL'
ELSE jsonb_pretty(new_values) END as new_vals
FROM audit_log
WHERE entity_type IN ('license', 'customer')
AND (old_values IS NOT NULL OR new_values IS NOT NULL)
ORDER BY timestamp DESC
LIMIT 5;"""
], capture_output=True, text=True)
print(result.stdout)
# 5. Test specific JSON queries
print("\n4. Testing JSON queries...")
# Query for specific license key in new_values
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", """SELECT COUNT(*)
FROM audit_log
WHERE new_values->>'license_key' LIKE 'JSON%';"""
], capture_output=True, text=True)
count = int(result.stdout.strip())
if count > 0:
print(f"✓ Found {count} entries with JSON license keys")
# Query for updates (where both old and new values exist)
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", """SELECT COUNT(*)
FROM audit_log
WHERE old_values IS NOT NULL
AND new_values IS NOT NULL;"""
], capture_output=True, text=True)
update_count = int(result.stdout.strip())
print(f"✓ Found {update_count} UPDATE entries with both old and new values")
# 6. Clean up test data
print("\n5. Cleaning up test data...")
subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", "DELETE FROM licenses WHERE license_key LIKE 'JSON%';"
], capture_output=True)
print("✓ Test data cleaned up")
# Run the test
test_json_logging()

238
v2_testing/test_audit_log.py Normale Datei
Datei anzeigen

@ -0,0 +1,238 @@
#!/usr/bin/env python3
import requests
import urllib3
import subprocess
import time
import json
# Disable SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
base_url = "https://localhost:443"
admin_user = {"username": "rac00n", "password": "1248163264"}
def login(session):
"""Login to admin panel"""
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)
return response.status_code == 302
def test_audit_table():
"""Test if audit_log table exists"""
print("1. Checking Audit Log Table:")
print("-" * 40)
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", "\\d audit_log"
], capture_output=True, text=True)
if "Table \"public.audit_log\"" in result.stdout:
print("✓ Audit log table exists")
print("\nTable structure:")
print(result.stdout)
return True
else:
print("✗ Audit log table not found - creating it")
# Create table
subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-f", "/docker-entrypoint-initdb.d/init.sql"
], capture_output=True)
return False
def test_audit_logging():
"""Test various actions to generate audit logs"""
session = requests.Session()
print("\n2. Testing Audit Log Generation:")
print("-" * 40)
# Test 1: Login
print("Testing LOGIN audit...")
login(session)
print("✓ Login performed")
# Test 2: Create license
print("\nTesting CREATE audit...")
license_data = {
"customer_name": "Audit Test GmbH",
"email": "audit@test.de",
"license_key": "AUDIT-TEST-001",
"license_type": "test",
"valid_from": "2025-01-01",
"valid_until": "2025-12-31"
}
response = session.post(f"{base_url}/create", data=license_data, verify=False, allow_redirects=False)
if response.status_code == 302:
print("✓ License created")
# Test 3: Export
print("\nTesting EXPORT audit...")
response = session.get(f"{base_url}/export/licenses?format=csv", verify=False)
if response.status_code == 200:
print("✓ Export performed")
# Test 4: Logout
print("\nTesting LOGOUT audit...")
response = session.get(f"{base_url}/logout", verify=False, allow_redirects=False)
if response.status_code == 302:
print("✓ Logout performed")
# Wait for logs to be written
time.sleep(1)
def test_audit_page():
"""Test the audit log page"""
session = requests.Session()
login(session)
print("\n3. Testing Audit Log Page:")
print("-" * 40)
response = session.get(f"{base_url}/audit", verify=False)
if response.status_code == 200:
print("✓ Audit log page accessible")
content = response.text
# Check for expected elements
checks = [
("Audit-Log", "Page title"),
("Zeitstempel", "Timestamp column"),
("Benutzer", "User column"),
("Aktion", "Action column"),
("Entität", "Entity column"),
("IP-Adresse", "IP address column"),
("LOGIN", "Login action"),
("LOGOUT", "Logout action"),
("CREATE", "Create action"),
("EXPORT", "Export action")
]
found = 0
for check_text, description in checks:
if check_text in content:
found += 1
print(f"✓ Found {found}/{len(checks)} expected elements")
# Check filters
if '<select' in content and 'filter' in content.lower():
print("✓ Filter options available")
else:
print(f"✗ Failed to access audit log page: Status {response.status_code}")
def check_audit_logs_db():
"""Check audit logs directly in database"""
print("\n4. Database Audit Log Check:")
print("-" * 40)
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", """SELECT action, entity_type, username,
CASE WHEN old_values IS NULL THEN 'NULL' ELSE 'JSON' END as old_v,
CASE WHEN new_values IS NULL THEN 'NULL' ELSE 'JSON' END as new_v,
additional_info
FROM audit_log
ORDER BY timestamp DESC
LIMIT 10;"""
], capture_output=True, text=True)
print(result.stdout)
# Count total logs
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", "SELECT COUNT(*) FROM audit_log;"
], capture_output=True, text=True)
count = int(result.stdout.strip())
print(f"\nTotal audit log entries: {count}")
def test_audit_filters():
"""Test audit log filters"""
session = requests.Session()
login(session)
print("\n5. Testing Audit Log Filters:")
print("-" * 40)
# Test different filters
filters = [
("?action=LOGIN", "Filter by LOGIN action"),
("?user=rac00n", "Filter by username"),
("?entity=license", "Filter by entity type"),
("?page=2", "Pagination test")
]
for filter_param, description in filters:
response = session.get(f"{base_url}/audit{filter_param}", verify=False)
if response.status_code == 200:
print(f"{description}: Working")
else:
print(f"{description}: Failed")
def test_json_values():
"""Test JSON storage of old/new values"""
print("\n6. Testing JSON Value Storage:")
print("-" * 40)
# Get a recent update log with JSON values
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", """SELECT new_values::text
FROM audit_log
WHERE action = 'CREATE'
AND new_values IS NOT NULL
LIMIT 1;"""
], capture_output=True, text=True)
if result.stdout.strip():
try:
json_data = json.loads(result.stdout.strip())
print("✓ JSON values stored correctly")
print(f"Sample JSON keys: {list(json_data.keys())}")
except:
print("✗ Invalid JSON format")
else:
print("✗ No JSON values found")
# Main execution
print("Testing Audit Log Functionality")
print("=" * 50)
# Ensure table exists
if not test_audit_table():
print("\nRestarting containers to create audit_log table...")
subprocess.run(["docker-compose", "down"], capture_output=True)
subprocess.run(["docker-compose", "up", "-d"], capture_output=True)
subprocess.run(["sleep", "7"], capture_output=True)
test_audit_table()
# Generate test data
test_audit_logging()
# Check results
test_audit_page()
check_audit_logs_db()
test_audit_filters()
test_json_values()
print("\n" + "=" * 50)
print("Audit Log Summary:")
print("-" * 40)
# Summary statistics
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", """SELECT action, COUNT(*) as count
FROM audit_log
GROUP BY action
ORDER BY count DESC;"""
], capture_output=True, text=True)
print(result.stdout)

104
v2_testing/test_audit_raw.py Normale Datei
Datei anzeigen

@ -0,0 +1,104 @@
#!/usr/bin/env python3
import requests
import urllib3
from datetime import datetime
from zoneinfo import ZoneInfo
from bs4 import BeautifulSoup
import time
# Disable SSL warnings for self-signed certificate
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Test configuration
base_url = "https://admin-panel-undso.z5m7q9dk3ah2v1plx6ju.com"
fallback_url = "https://localhost:443"
admin_user = {"username": "rac00n", "password": "1248163264"}
def test_audit_raw():
"""Test audit log timezone by parsing HTML"""
session = requests.Session()
print("Audit Log Raw HTML Test")
print("=" * 50)
# Test connection
try:
test_response = session.get(base_url, verify=True, timeout=5)
verify_ssl = True
base_url_local = base_url
print(f"✓ Using external URL: {base_url}")
except:
base_url_local = fallback_url
verify_ssl = False
print(f" Using fallback URL: {fallback_url}")
# Show current times
utc_now = datetime.now(ZoneInfo("UTC"))
berlin_now = datetime.now(ZoneInfo("Europe/Berlin"))
print(f"\nCurrent times:")
print(f" UTC: {utc_now.strftime('%Y-%m-%d %H:%M:%S')}")
print(f" Berlin: {berlin_now.strftime('%Y-%m-%d %H:%M:%S')}")
# Logout first
session.get(f"{base_url_local}/logout", verify=verify_ssl)
time.sleep(1)
# Login
response = session.get(f"{base_url_local}/login", verify=verify_ssl)
login_data = {
"username": admin_user["username"],
"password": admin_user["password"]
}
response = session.post(f"{base_url_local}/login", data=login_data, verify=verify_ssl, allow_redirects=False)
if response.status_code != 302:
print(f"✗ Login failed")
return
print("✓ Login successful")
# Get audit log
print("\nFetching audit log...")
response = session.get(f"{base_url_local}/audit", verify=verify_ssl)
if response.status_code == 200:
# Save raw HTML for inspection
with open("audit_log_raw.html", "w", encoding="utf-8") as f:
f.write(response.text)
print("✓ Saved raw HTML to audit_log_raw.html")
# Parse with BeautifulSoup
soup = BeautifulSoup(response.text, 'html.parser')
# Find all table rows
rows = soup.find_all('tr')
print(f"✓ Found {len(rows)} table rows")
# Look for LOGIN_SUCCESS in recent entries
for i, row in enumerate(rows[:5]): # Check first 5 rows
cells = row.find_all('td')
if cells and len(cells) > 1:
timestamp_cell = cells[0].text.strip()
action_cell = cells[2].text.strip() if len(cells) > 2 else ""
if i == 0:
print(f"\nFirst row details:")
print(f" Timestamp: {timestamp_cell}")
print(f" Action: {action_cell}")
if "LOGIN_SUCCESS" in action_cell:
print(f"\nFound LOGIN_SUCCESS entry:")
print(f" Timestamp: {timestamp_cell}")
# Check if timestamp contains current Berlin hour
if berlin_now.strftime("%H:") in timestamp_cell:
print(f" ✓ Contains Berlin hour ({berlin_now.strftime('%H:')})")
elif utc_now.strftime("%H:") in timestamp_cell:
print(f" ✗ Contains UTC hour ({utc_now.strftime('%H:')})")
break
else:
print(f"✗ Failed to fetch audit log: {response.status_code}")
if __name__ == "__main__":
test_audit_raw()

Datei anzeigen

@ -0,0 +1,113 @@
#!/usr/bin/env python3
import requests
import urllib3
from datetime import datetime
from zoneinfo import ZoneInfo
import time
import re
# Disable SSL warnings for self-signed certificate
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Test configuration
base_url = "https://admin-panel-undso.z5m7q9dk3ah2v1plx6ju.com"
fallback_url = "https://localhost:443"
admin_user = {"username": "rac00n", "password": "1248163264"}
def test_audit_simple():
"""Simple test to check audit log timestamps"""
session = requests.Session()
print("Audit Log Timezone Check")
print("=" * 50)
# Test connection
try:
test_response = session.get(base_url, verify=True, timeout=5)
verify_ssl = True
base_url_local = base_url
print(f"✓ Using external URL: {base_url}")
except:
base_url_local = fallback_url
verify_ssl = False
print(f" Using fallback URL: {fallback_url}")
# Show current times
utc_now = datetime.now(ZoneInfo("UTC"))
berlin_now = datetime.now(ZoneInfo("Europe/Berlin"))
print(f"\nCurrent times:")
print(f" UTC: {utc_now.strftime('%Y-%m-%d %H:%M:%S')}")
print(f" Berlin: {berlin_now.strftime('%Y-%m-%d %H:%M:%S')}")
print(f" Difference: {(berlin_now.hour - utc_now.hour) % 24} hours")
# Login
response = session.get(f"{base_url_local}/login", verify=verify_ssl)
login_data = {
"username": admin_user["username"],
"password": admin_user["password"]
}
response = session.post(f"{base_url_local}/login", data=login_data, verify=verify_ssl, allow_redirects=False)
if response.status_code != 302:
print(f"✗ Login failed")
return
print("✓ Login successful")
# Create a distinctive action to find in audit log
print("\nCreating a test action...")
# Try to access customers page (this will create an audit entry)
response = session.get(f"{base_url_local}/customers", verify=verify_ssl)
# Now check audit log
print("\nChecking audit log...")
response = session.get(f"{base_url_local}/audit", verify=verify_ssl)
if response.status_code == 200:
# Look for table rows with class="table"
# Extract just the table content
table_match = re.search(r'<table class="table[^>]*>(.*?)</table>', response.text, re.DOTALL)
if table_match:
table_content = table_match.group(1)
# Find all <tr> tags
rows = re.findall(r'<tr[^>]*>(.*?)</tr>', table_content, re.DOTALL)
print(f"✓ Found {len(rows)} audit log entries")
if rows:
# Get the first data row (skip header)
first_row = rows[1] if len(rows) > 1 else rows[0]
# Extract timestamp from first cell
timestamp_match = re.search(r'<td[^>]*>([^<]+)</td>', first_row)
if timestamp_match:
timestamp = timestamp_match.group(1).strip()
print(f"\nMost recent audit entry timestamp: {timestamp}")
# Check if it contains current Berlin hour
berlin_hour = berlin_now.strftime("%H:")
utc_hour = utc_now.strftime("%H:")
if berlin_hour in timestamp:
print(f"✓ Timestamp contains Berlin hour ({berlin_hour})")
print("✓ Audit log is using Berlin timezone!")
elif utc_hour in timestamp:
print(f"✗ Timestamp contains UTC hour ({utc_hour})")
print("✗ Audit log is still using UTC")
print("\nTo fix this:")
print("1. cd ../v2")
print("2. docker-compose down")
print("3. docker-compose build --no-cache")
print("4. docker-compose up -d")
else:
print("⚠ Could not determine timezone from timestamp")
else:
print(f"✗ Failed to fetch audit log: {response.status_code}")
if __name__ == "__main__":
test_audit_simple()

Datei anzeigen

@ -0,0 +1,123 @@
#!/usr/bin/env python3
import requests
import urllib3
from datetime import datetime
from zoneinfo import ZoneInfo
import time
import re
# Disable SSL warnings for self-signed certificate
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Test configuration
base_url = "https://admin-panel-undso.z5m7q9dk3ah2v1plx6ju.com"
fallback_url = "https://localhost:443"
admin_user = {"username": "rac00n", "password": "1248163264"}
def test_audit_timezone():
"""Test audit log timezone specifically"""
session = requests.Session()
print("Audit Log Timezone Test")
print("=" * 50)
# Test connection
try:
test_response = session.get(base_url, verify=True, timeout=5)
verify_ssl = True
base_url_local = base_url
print(f"✓ Using external URL: {base_url}")
except:
base_url_local = fallback_url
verify_ssl = False
print(f" Using fallback URL: {fallback_url}")
# Show current times
utc_now = datetime.now(ZoneInfo("UTC"))
berlin_now = datetime.now(ZoneInfo("Europe/Berlin"))
print(f"\nCurrent times:")
print(f" UTC: {utc_now.strftime('%Y-%m-%d %H:%M:%S')}")
print(f" Berlin: {berlin_now.strftime('%Y-%m-%d %H:%M:%S')}")
print(f" Offset: +{(berlin_now.hour - utc_now.hour) % 24} hours")
# First logout if already logged in
session.get(f"{base_url_local}/logout", verify=verify_ssl)
time.sleep(1)
# Login (this will create a new audit log entry)
print(f"\nPerforming login at {berlin_now.strftime('%H:%M:%S')} Berlin time...")
response = session.get(f"{base_url_local}/login", verify=verify_ssl)
if response.status_code != 200:
print(f"✗ Failed to access login page: {response.status_code}")
return
login_data = {
"username": admin_user["username"],
"password": admin_user["password"]
}
response = session.post(f"{base_url_local}/login", data=login_data, verify=verify_ssl, allow_redirects=False)
if response.status_code != 302:
print(f"✗ Login failed: {response.status_code}")
return
print("✓ Login successful")
# Immediately check audit log
print("\nChecking audit log for fresh LOGIN_SUCCESS entry...")
response = session.get(f"{base_url_local}/audit", verify=verify_ssl)
if response.status_code == 200:
# Look for timestamps in the audit log
# Pattern to find timestamps in format YYYY-MM-DD HH:MM:SS
timestamp_pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})'
# Find all timestamps
timestamps = re.findall(timestamp_pattern, response.text)
if timestamps:
print(f"✓ Found {len(timestamps)} timestamps in audit log")
# Check the most recent timestamp (should be first in list)
if timestamps:
latest_timestamp = timestamps[0]
print(f"\nMost recent timestamp: {latest_timestamp}")
# Extract hour from timestamp
hour_match = re.search(r' (\d{2}):', latest_timestamp)
if hour_match:
log_hour = int(hour_match.group(1))
berlin_hour = berlin_now.hour
utc_hour = utc_now.hour
print(f" Timestamp hour: {log_hour:02d}")
print(f" Berlin hour: {berlin_hour:02d}")
print(f" UTC hour: {utc_hour:02d}")
if log_hour == berlin_hour:
print("\n✓ Audit log is using Berlin time!")
elif log_hour == utc_hour:
print("\n✗ Audit log appears to be using UTC time")
print(" → Docker containers may need to be rebuilt")
else:
print("\n⚠ Could not determine timezone (timestamp doesn't match either timezone)")
else:
print("✗ No timestamps found in audit log")
# Also check for "vor X Minuten" text which might indicate timezone
if "vor 0 Minuten" in response.text or "vor 1 Minute" in response.text:
print("\n✓ Recent entries found (German time format)")
else:
print(f"✗ Failed to access audit log: {response.status_code}")
print("\n" + "=" * 50)
print("If timestamps show UTC instead of Berlin time:")
print("1. Run: docker-compose down")
print("2. Run: docker-compose build --no-cache")
print("3. Run: docker-compose up -d")
if __name__ == "__main__":
test_audit_timezone()

Datei anzeigen

@ -0,0 +1,207 @@
#!/usr/bin/env python3
import requests
import urllib3
import subprocess
from datetime import datetime
# 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 login(session):
"""Login to admin panel"""
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)
return response.status_code == 302
def test_customer_list():
"""Test customer list view"""
session = requests.Session()
if not login(session):
return "✗ Failed to login"
response = session.get(f"{base_url}/customers", verify=False)
if response.status_code != 200:
return f"✗ Failed to access customers page: Status {response.status_code}"
content = response.text
# Check for expected customers
expected_customers = ["Müller GmbH", "Test Customer", "Schröder Süßwaren AG", "Björn Köhler"]
found_customers = []
for customer in expected_customers:
if customer in content:
found_customers.append(customer)
if len(found_customers) > 0:
return f"✓ Customer list loaded successfully ({len(found_customers)} customers found)"
else:
return "✗ No customers found in list"
def test_edit_customer():
"""Test editing a customer"""
session = requests.Session()
if not login(session):
return "✗ Failed to login"
# Get a customer ID to edit (let's find "Test Customer")
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", "SELECT id FROM customers WHERE name = 'Test Customer' LIMIT 1;"
], capture_output=True, text=True)
customer_id = result.stdout.strip()
if not customer_id:
return "✗ Failed to find test customer"
# Test GET edit page
response = session.get(f"{base_url}/customer/edit/{customer_id}", verify=False)
if response.status_code != 200:
return f"✗ Failed to access customer edit page: Status {response.status_code}"
# Check if customer data and licenses are displayed
content = response.text
if "Test Customer" not in content:
return "✗ Edit page doesn't show customer data"
# Update customer data
updated_data = {
"name": "Test Customer GmbH & Co. KG",
"email": "updated@testcustomer.de"
}
response = session.post(f"{base_url}/customer/edit/{customer_id}",
data=updated_data,
verify=False,
allow_redirects=False)
if response.status_code == 302 and response.headers.get('Location') == '/customers':
return "✓ Customer edited successfully"
else:
return f"✗ Failed to edit customer: Status {response.status_code}"
def test_delete_customer():
"""Test deleting a customer"""
session = requests.Session()
if not login(session):
return "✗ Failed to login"
# Create a test customer without licenses
test_customer = {
"customer_name": "Löschtest Firma GmbH",
"email": "delete@löschtest.de",
"license_key": "TEMP-KEY-DELETE",
"license_type": "Test",
"valid_from": "2025-01-01",
"valid_until": "2025-01-02"
}
# Create customer with license
session.post(f"{base_url}/", data=test_customer, verify=False, allow_redirects=False)
# Get the customer ID
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", "SELECT id FROM customers WHERE name = 'Löschtest Firma GmbH';"
], capture_output=True, text=True)
customer_id = result.stdout.strip()
if not customer_id:
return "✗ Failed to create test customer"
# First, try to delete customer with license (should fail)
response = session.post(f"{base_url}/customer/delete/{customer_id}",
verify=False,
allow_redirects=False)
# Check if customer still exists (should not be deleted due to license)
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", f"SELECT COUNT(*) FROM customers WHERE id = {customer_id};"
], capture_output=True, text=True)
if int(result.stdout.strip()) != 1:
return "✗ Customer with licenses was incorrectly deleted"
# Now delete the license first
subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", f"DELETE FROM licenses WHERE customer_id = {customer_id};"
], capture_output=True)
# Try to delete customer again (should work now)
response = session.post(f"{base_url}/customer/delete/{customer_id}",
verify=False,
allow_redirects=False)
# Verify deletion
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", f"SELECT COUNT(*) FROM customers WHERE id = {customer_id};"
], capture_output=True, text=True)
if int(result.stdout.strip()) == 0:
return "✓ Customer deletion works correctly (protects customers with licenses)"
else:
return "✗ Failed to delete customer without licenses"
# Rebuild and restart admin panel
print("Rebuilding admin panel with customer management...")
subprocess.run(["docker-compose", "build", "admin-panel"], capture_output=True)
subprocess.run(["docker-compose", "up", "-d", "admin-panel"], capture_output=True)
print("Waiting for container to start...")
subprocess.run(["sleep", "5"], capture_output=True)
print("\nTesting Customer Management Functionality")
print("=" * 50)
# Test customer list
print("\n1. Testing Customer List:")
print("-" * 30)
list_result = test_customer_list()
print(list_result)
# Test edit functionality
print("\n2. Testing Customer Edit:")
print("-" * 30)
edit_result = test_edit_customer()
print(edit_result)
# Verify the edit
print("\nVerifying edited customer:")
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", "SELECT name, email FROM customers WHERE name LIKE 'Test Customer%';"
], capture_output=True, text=True)
print(result.stdout)
# Test delete functionality
print("\n3. Testing Customer Delete:")
print("-" * 30)
delete_result = test_delete_customer()
print(delete_result)
# Show customer statistics
print("\n" + "=" * 50)
print("Customer Statistics:")
print("-" * 50)
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", """SELECT c.name, COUNT(l.id) as total_licenses,
COUNT(CASE WHEN l.is_active = TRUE AND l.valid_until >= CURRENT_DATE THEN 1 END) as active_licenses
FROM customers c
LEFT JOIN licenses l ON c.id = l.customer_id
GROUP BY c.name
ORDER BY c.name;"""
], capture_output=True, text=True)
print(result.stdout)

144
v2_testing/test_dashboard.py Normale Datei
Datei anzeigen

@ -0,0 +1,144 @@
#!/usr/bin/env python3
import requests
import urllib3
import subprocess
# 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 login(session):
"""Login to admin panel"""
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)
return response.status_code == 302
def test_dashboard():
"""Test dashboard with statistics"""
session = requests.Session()
if not login(session):
return "✗ Failed to login"
response = session.get(f"{base_url}/", verify=False)
if response.status_code != 200:
return f"✗ Failed to access dashboard: Status {response.status_code}"
content = response.text
results = []
# Check for statistics elements
statistics_checks = [
("Gesamtkunden", "Total customers statistic"),
("Gesamtlizenzen", "Total licenses statistic"),
("Aktive Lizenzen", "Active licenses statistic"),
("Abgelaufene Lizenzen", "Expired licenses statistic"),
("Läuft bald ab", "Expiring soon statistic"),
("Letzte Lizenzen", "Recent licenses section"),
("Bald ablaufende Lizenzen", "Expiring licenses section")
]
for check_text, description in statistics_checks:
if check_text in content:
results.append(f"✓ Found: {description}")
else:
results.append(f"✗ Missing: {description}")
# Check if actual numbers are displayed
if any(char.isdigit() for char in content):
results.append("✓ Statistics numbers are displayed")
else:
results.append("✗ No statistics numbers found")
# Check for customer names in recent licenses
if "Müller" in content or "Schröder" in content or "Köhler" in content:
results.append("✓ Recent licenses show customer names")
else:
results.append("✗ No customer names in recent licenses")
return results
# Rebuild and restart admin panel
print("Rebuilding admin panel with dashboard...")
subprocess.run(["docker-compose", "build", "admin-panel"], capture_output=True)
subprocess.run(["docker-compose", "up", "-d", "admin-panel"], capture_output=True)
print("Waiting for container to start...")
subprocess.run(["sleep", "5"], capture_output=True)
print("\nTesting Dashboard with Statistics")
print("=" * 50)
results = test_dashboard()
for result in results:
print(result)
# Get actual statistics from database for comparison
print("\n" + "=" * 50)
print("Actual Database Statistics:")
print("-" * 50)
# Total customers
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", "SELECT COUNT(*) FROM customers;"
], capture_output=True, text=True)
print(f"Total Customers: {result.stdout.strip()}")
# Total licenses
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", "SELECT COUNT(*) FROM licenses;"
], capture_output=True, text=True)
print(f"Total Licenses: {result.stdout.strip()}")
# Active licenses
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", "SELECT COUNT(*) FROM licenses WHERE valid_until >= CURRENT_DATE AND is_active = TRUE;"
], capture_output=True, text=True)
print(f"Active Licenses: {result.stdout.strip()}")
# Expired licenses
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", "SELECT COUNT(*) FROM licenses WHERE valid_until < CURRENT_DATE;"
], capture_output=True, text=True)
print(f"Expired Licenses: {result.stdout.strip()}")
# Expiring soon (30 days)
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", "SELECT COUNT(*) FROM licenses WHERE valid_until >= CURRENT_DATE AND valid_until < CURRENT_DATE + INTERVAL '30 days' AND is_active = TRUE;"
], capture_output=True, text=True)
print(f"Expiring Soon (30 days): {result.stdout.strip()}")
# License types breakdown
print("\nLicense Types:")
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", "SELECT license_type, COUNT(*) FROM licenses GROUP BY license_type ORDER BY COUNT(*) DESC;"
], capture_output=True, text=True)
print(result.stdout)
# Recent licenses
print("Recent Licenses:")
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", """SELECT l.license_key, c.name, l.valid_until,
CASE
WHEN l.valid_until < CURRENT_DATE THEN 'abgelaufen'
WHEN l.valid_until < CURRENT_DATE + INTERVAL '30 days' THEN 'läuft bald ab'
ELSE 'aktiv'
END as status
FROM licenses l
JOIN customers c ON l.customer_id = c.id
ORDER BY l.id DESC
LIMIT 5;"""
], capture_output=True, text=True)
print(result.stdout)

Datei anzeigen

@ -0,0 +1,53 @@
#!/usr/bin/env python3
import requests
import urllib3
import re
# 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_dashboard_detail():
"""Test dashboard content in detail"""
session = requests.Session()
# Login
login_data = {
"username": admin_user["username"],
"password": admin_user["password"]
}
session.post(f"{base_url}/login", data=login_data, verify=False, allow_redirects=False)
# Get dashboard
response = session.get(f"{base_url}/", verify=False)
content = response.text
# Extract numbers from content
numbers = re.findall(r'\d+', content)
print(f"Numbers found on page: {numbers[:20]}") # First 20 numbers
# Check specific sections
if "8" in numbers: # Total customers
print("✓ Found total customers count (8)")
if "5" in numbers: # Total licenses
print("✓ Found total licenses count (5)")
if "3" in numbers: # Active licenses
print("✓ Found active licenses count (3)")
if "2" in numbers: # Expired licenses
print("✓ Found expired licenses count (2)")
# Print a snippet of the HTML to see structure
print("\nHTML snippet (first 1000 chars):")
print(content[:1000])
return response.status_code
print("Detailed Dashboard Test")
print("=" * 50)
status = test_dashboard_detail()

212
v2_testing/test_export.py Normale Datei
Datei anzeigen

@ -0,0 +1,212 @@
#!/usr/bin/env python3
import requests
import urllib3
import subprocess
import os
import pandas as pd
import zipfile
# Disable SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
base_url = "https://localhost:443"
admin_user = {"username": "rac00n", "password": "1248163264"}
def login(session):
"""Login to admin panel"""
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)
return response.status_code == 302
def test_export_licenses():
"""Test license export functionality"""
session = requests.Session()
if not login(session):
return ["✗ Failed to login"]
results = []
# Test Excel export
print("1. Testing License Excel Export:")
print("-" * 40)
response = session.get(f"{base_url}/export/licenses?format=excel", verify=False)
if response.status_code == 200:
# Save file
filename = "test_licenses.xlsx"
with open(filename, 'wb') as f:
f.write(response.content)
# Check file size
file_size = os.path.getsize(filename)
results.append(f"✓ Excel export successful - Size: {file_size} bytes")
# Verify it's a valid Excel file
try:
df = pd.read_excel(filename)
results.append(f"✓ Valid Excel file with {len(df)} rows, {len(df.columns)} columns")
# Check columns
expected_cols = ['Lizenzschlüssel', 'Kunde', 'E-Mail', 'Typ', 'Status']
found_cols = [col for col in expected_cols if col in df.columns]
results.append(f"✓ Found columns: {', '.join(found_cols[:3])}...")
# Check for UTF-8 content
if df['Kunde'].str.contains('ü|ö|ä|ß').any():
results.append("✓ UTF-8 characters preserved in Excel")
except Exception as e:
results.append(f"✗ Error reading Excel: {str(e)}")
os.remove(filename)
else:
results.append(f"✗ Excel export failed: Status {response.status_code}")
# Test CSV export
print("\n2. Testing License CSV Export:")
print("-" * 40)
response = session.get(f"{base_url}/export/licenses?format=csv", verify=False)
if response.status_code == 200:
# Save file
filename = "test_licenses.csv"
with open(filename, 'wb') as f:
f.write(response.content)
# Check file
file_size = os.path.getsize(filename)
results.append(f"✓ CSV export successful - Size: {file_size} bytes")
# Read and verify CSV
try:
df = pd.read_csv(filename, sep=';', encoding='utf-8-sig')
results.append(f"✓ Valid CSV file with {len(df)} rows")
# Check for German date format
if df['Gültig bis'].str.match(r'\d{2}\.\d{2}\.\d{4}').any():
results.append("✓ German date format (DD.MM.YYYY)")
except Exception as e:
results.append(f"✗ Error reading CSV: {str(e)}")
os.remove(filename)
else:
results.append(f"✗ CSV export failed: Status {response.status_code}")
return results
def test_export_customers():
"""Test customer export functionality"""
session = requests.Session()
if not login(session):
return ["✗ Failed to login"]
results = []
# Test Excel export
print("\n3. Testing Customer Excel Export:")
print("-" * 40)
response = session.get(f"{base_url}/export/customers?format=excel", verify=False)
if response.status_code == 200:
filename = "test_customers.xlsx"
with open(filename, 'wb') as f:
f.write(response.content)
try:
df = pd.read_excel(filename)
results.append(f"✓ Customer Excel export: {len(df)} customers")
# Check statistics columns
if 'Lizenzen gesamt' in df.columns and 'Aktive Lizenzen' in df.columns:
results.append("✓ License statistics included")
# Check for UTF-8
if 'Name' in df.columns and df['Name'].str.contains('ü|ö|ä|ß').any():
results.append("✓ UTF-8 customer names preserved")
except Exception as e:
results.append(f"✗ Error: {str(e)}")
os.remove(filename)
else:
results.append(f"✗ Customer export failed: Status {response.status_code}")
# Test CSV export
print("\n4. Testing Customer CSV Export:")
print("-" * 40)
response = session.get(f"{base_url}/export/customers?format=csv", verify=False)
if response.status_code == 200:
results.append("✓ Customer CSV export successful")
else:
results.append(f"✗ Customer CSV export failed: Status {response.status_code}")
return results
def check_pandas_installation():
"""Check if pandas is installed in container"""
print("5. Checking pandas installation:")
print("-" * 40)
result = subprocess.run([
"docker", "exec", "admin-panel", "python", "-c",
"import pandas; import openpyxl; print('pandas version:', pandas.__version__)"
], capture_output=True, text=True)
if result.returncode == 0:
print("✓ pandas is installed")
print(result.stdout)
else:
print("✗ pandas not installed - installing...")
# Install pandas
subprocess.run([
"docker", "exec", "admin-panel", "pip", "install",
"pandas", "openpyxl"
], capture_output=True)
print("✓ pandas and openpyxl installed")
# Main execution
print("Testing Export Functionality")
print("=" * 50)
# Check dependencies first
check_pandas_installation()
# Rebuild if needed
print("\nRebuilding admin panel...")
subprocess.run(["docker-compose", "build", "admin-panel"], capture_output=True)
subprocess.run(["docker-compose", "up", "-d", "admin-panel"], capture_output=True)
subprocess.run(["sleep", "5"], capture_output=True)
# Test exports
license_results = test_export_licenses()
for result in license_results:
print(result)
customer_results = test_export_customers()
for result in customer_results:
print(result)
# Check database content for comparison
print("\n6. Database Content Summary:")
print("-" * 40)
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", "SELECT COUNT(*) as licenses FROM licenses;"
], capture_output=True, text=True)
print(result.stdout)
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", "SELECT COUNT(*) as customers FROM customers;"
], capture_output=True, text=True)
print(result.stdout)

Datei anzeigen

@ -0,0 +1,158 @@
#!/usr/bin/env python3
import requests
import urllib3
import subprocess
import os
# Disable SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
base_url = "https://localhost:443"
admin_user = {"username": "rac00n", "password": "1248163264"}
def login(session):
"""Login to admin panel"""
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)
return response.status_code == 302
def check_requirements():
"""Check if pandas is in requirements.txt"""
print("1. Checking requirements.txt:")
print("-" * 40)
result = subprocess.run([
"cat", "/mnt/c/Users/Administrator/Documents/GitHub/v2-Docker/v2_adminpanel/requirements.txt"
], capture_output=True, text=True)
print(result.stdout)
if "pandas" not in result.stdout:
print("✗ pandas not in requirements.txt - adding it")
# Add pandas and openpyxl
subprocess.run([
"echo", "-e", "pandas\\nopenpyxl", ">>",
"/mnt/c/Users/Administrator/Documents/GitHub/v2-Docker/v2_adminpanel/requirements.txt"
])
def test_export_endpoints():
"""Test export endpoints"""
session = requests.Session()
if not login(session):
return ["✗ Failed to login"]
print("\n2. Testing Export Endpoints:")
print("-" * 40)
# Test license exports
exports = [
("/export/licenses?format=excel", "License Excel Export"),
("/export/licenses?format=csv", "License CSV Export"),
("/export/customers?format=excel", "Customer Excel Export"),
("/export/customers?format=csv", "Customer CSV Export")
]
for endpoint, description in exports:
response = session.get(f"{base_url}{endpoint}", verify=False, stream=True)
if response.status_code == 200:
# Check headers
content_type = response.headers.get('Content-Type', '')
content_disp = response.headers.get('Content-Disposition', '')
# Get first few bytes to check file type
first_bytes = response.raw.read(10)
if 'excel' in endpoint and b'PK' in first_bytes: # Excel files start with PK (ZIP format)
print(f"{description}: Valid Excel file signature")
elif 'csv' in endpoint and (b'ID' in first_bytes or b'"' in first_bytes or b';' in first_bytes):
print(f"{description}: Looks like CSV data")
else:
print(f"{description}: Response received (Status 200)")
if 'attachment' in content_disp:
print(f" → Download filename: {content_disp.split('filename=')[1] if 'filename=' in content_disp else 'present'}")
else:
print(f"{description}: Failed with status {response.status_code}")
def test_export_content():
"""Test actual export content"""
session = requests.Session()
if not login(session):
return
print("\n3. Testing Export Content:")
print("-" * 40)
# Get CSV export to check content
response = session.get(f"{base_url}/export/licenses?format=csv", verify=False)
if response.status_code == 200:
content = response.text
lines = content.split('\n')
print(f"CSV Lines: {len(lines)}")
if lines:
# Check header
header = lines[0]
print(f"CSV Header: {header[:100]}...")
# Check for UTF-8 BOM
if content.startswith('\ufeff'):
print("✓ UTF-8 BOM present (Excel compatibility)")
# Check for umlauts
if any(char in content for char in 'äöüßÄÖÜ'):
print("✓ German umlauts found in export")
# Check separator
if ';' in header:
print("✓ Using semicolon separator (German Excel standard)")
# Main execution
print("Testing Export Functionality")
print("=" * 50)
# Check and fix requirements
check_requirements()
# Rebuild admin panel with pandas
print("\nRebuilding admin panel with pandas...")
subprocess.run([
"docker", "exec", "admin-panel", "pip", "install", "pandas", "openpyxl"
], capture_output=True)
result = subprocess.run([
"docker", "exec", "admin-panel", "python", "-c",
"import pandas; print('pandas installed:', pandas.__version__)"
], capture_output=True, text=True)
if result.returncode == 0:
print("✓ pandas installed in container")
print(result.stdout.strip())
else:
print("✗ Failed to install pandas")
# Test endpoints
test_export_endpoints()
test_export_content()
# Database summary
print("\n4. Database Summary:")
print("-" * 40)
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", """SELECT
(SELECT COUNT(*) FROM licenses) as licenses,
(SELECT COUNT(*) FROM customers) as customers,
(SELECT COUNT(*) FROM licenses WHERE valid_until >= CURRENT_DATE) as active_licenses;"""
], capture_output=True, text=True)
print(f"Available for export: {result.stdout.strip()}")

Datei anzeigen

@ -0,0 +1,95 @@
#!/usr/bin/env python3
import requests
import urllib3
import re
# Disable SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
base_url = "https://localhost:443"
admin_user = {"username": "rac00n", "password": "1248163264"}
def test_detailed():
session = requests.Session()
# Login
login_data = {
"username": admin_user["username"],
"password": admin_user["password"]
}
session.post(f"{base_url}/login", data=login_data, verify=False, allow_redirects=False)
print("Testing License Page with Filters:")
print("=" * 50)
# Test 1: Basic license page
response = session.get(f"{base_url}/licenses", verify=False)
print(f"\n1. Basic licenses page - Status: {response.status_code}")
# Check for filter dropdowns
content = response.text
if '<select' in content and 'filter' in content.lower():
print("✓ Filter dropdowns found")
else:
print("✗ No filter dropdowns found")
# Check for pagination
if 'page=' in content or 'Seite' in content:
print("✓ Pagination elements found")
else:
print("✗ No pagination elements")
# Count licenses shown
license_count = content.count('license_key') - 1 # Minus header
print(f"Licenses shown: {license_count}")
# Test 2: With type filter
print("\n2. Testing type filter:")
response = session.get(f"{base_url}/licenses?type=test", verify=False)
print(f"Status: {response.status_code}")
content = response.text
test_licenses = content.count('PAGE-TEST-')
print(f"Test licenses found: {test_licenses}")
# Test 3: With status filter
print("\n3. Testing status filter:")
response = session.get(f"{base_url}/licenses?status=active", verify=False)
print(f"Status: {response.status_code}")
content = response.text
active_count = content.count('aktiv') - content.count('inaktiv')
print(f"Active status mentions: {active_count}")
# Test 4: Check pagination info
print("\n4. Checking total count display:")
# Look for patterns like "X von Y Einträgen" or similar
total_pattern = re.findall(r'(\d+)\s*von\s*(\d+)', content)
if total_pattern:
print(f"✓ Found pagination info: {total_pattern}")
else:
# Try other patterns
if re.search(r'Gesamt.*\d+', content):
print("✓ Found total count")
elif 'total' in content.lower() and re.search(r'\d+', content):
print("✓ Found total indicator")
else:
print("✗ No total count found")
# Test 5: Customer page
print("\n5. Testing customer page:")
response = session.get(f"{base_url}/customers", verify=False)
print(f"Status: {response.status_code}")
content = response.text
customer_count = content.count('customer_name') + content.count('<tr') - 2
print(f"Customers shown: ~{customer_count}")
# Print a snippet to see actual content
print("\n6. HTML snippet from licenses page:")
print("-" * 30)
# Find filter section
filter_start = content.find('filter')
if filter_start > 0:
print(content[max(0, filter_start-100):filter_start+200])
else:
print("No filter section found in HTML")
test_detailed()

Datei anzeigen

@ -0,0 +1,222 @@
#!/usr/bin/env python3
import requests
import urllib3
import subprocess
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 login(session):
"""Login to admin panel"""
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)
return response.status_code == 302
def create_test_data():
"""Create additional test data for pagination testing"""
session = requests.Session()
if not login(session):
return False
# Create 25 test licenses to test pagination (20 per page)
for i in range(25):
license_data = {
"customer_name": f"Pagination Test {i+1}",
"email": f"page{i+1}@test.de",
"license_key": f"PAGE-TEST-{i+1:03d}",
"license_type": "test" if i % 3 == 0 else "full",
"valid_from": "2025-01-01",
"valid_until": (datetime.now() + timedelta(days=i*10)).strftime("%Y-%m-%d") if i % 2 == 0 else "2024-12-31"
}
session.post(f"{base_url}/create", data=license_data, verify=False, allow_redirects=False)
return True
def test_license_filters():
"""Test license filtering functionality"""
session = requests.Session()
if not login(session):
return ["✗ Failed to login"]
results = []
# Test type filters
filter_tests = [
("type=test", "Filter by type 'test'"),
("type=full", "Filter by type 'full'"),
("status=active", "Filter by active status"),
("status=expired", "Filter by expired status"),
("status=expiring", "Filter by expiring soon"),
("type=test&status=active", "Combined filter: test + active"),
("search=page&type=test", "Search + type filter"),
("search=müller&status=active", "Search with umlaut + status filter")
]
for filter_param, description in filter_tests:
response = session.get(f"{base_url}/licenses?{filter_param}", verify=False)
if response.status_code == 200:
content = response.text
# Check if results are shown (not "Keine Lizenzen gefunden")
if "license_key" in content or "Keine Lizenzen gefunden" in content:
results.append(f"{description}: Filter applied successfully")
else:
results.append(f"{description}: No results section found")
else:
results.append(f"{description}: Failed with status {response.status_code}")
return results
def test_pagination():
"""Test pagination functionality"""
session = requests.Session()
if not login(session):
return ["✗ Failed to login"]
results = []
# Test licenses pagination
response = session.get(f"{base_url}/licenses", verify=False)
if response.status_code == 200:
content = response.text
# Check for pagination elements
if "page=" in content:
results.append("✓ Pagination links present in licenses")
else:
results.append("✗ No pagination links in licenses")
# Check page 2
response2 = session.get(f"{base_url}/licenses?page=2", verify=False)
if response2.status_code == 200:
content2 = response2.text
if content != content2: # Different content on different pages
results.append("✓ Page 2 shows different content")
else:
results.append("✗ Page 2 shows same content as page 1")
# Check for total count display
if "von" in content and "Einträgen" in content:
results.append("✓ Total entries count displayed")
else:
results.append("✗ Total entries count not displayed")
# Test customers pagination
response = session.get(f"{base_url}/customers", verify=False)
if response.status_code == 200:
content = response.text
if "page=" in content or "Seite" in content:
results.append("✓ Pagination present in customers")
else:
results.append("✗ No pagination in customers")
return results
def test_pagination_with_filters():
"""Test pagination combined with filters"""
session = requests.Session()
if not login(session):
return ["✗ Failed to login"]
results = []
# Test pagination preserves filters
test_urls = [
(f"{base_url}/licenses?type=test&page=2", "Pagination with type filter"),
(f"{base_url}/licenses?search=page&page=2", "Pagination with search"),
(f"{base_url}/licenses?status=active&type=full&page=1", "Multiple filters with pagination"),
(f"{base_url}/customers?search=test&page=2", "Customer search with pagination")
]
for test_url, description in test_urls:
response = session.get(test_url, verify=False)
if response.status_code == 200:
content = response.text
# Check if filters are preserved in pagination links
if "type=" in test_url and "type=" in content:
results.append(f"{description}: Filters preserved")
elif "search=" in test_url and "search=" in content:
results.append(f"{description}: Search preserved")
else:
results.append(f"{description}: Page loaded")
else:
results.append(f"{description}: Failed")
return results
# Setup
print("Setting up test environment...")
subprocess.run(["docker-compose", "build", "admin-panel"], capture_output=True)
subprocess.run(["docker-compose", "up", "-d", "admin-panel"], capture_output=True)
subprocess.run(["sleep", "5"], capture_output=True)
print("\nCreating test data for pagination...")
if create_test_data():
print("✓ Test data created")
else:
print("✗ Failed to create test data")
print("\nTesting Filter and Pagination Functionality")
print("=" * 50)
# Test filters
print("\n1. License Filter Tests:")
print("-" * 30)
filter_results = test_license_filters()
for result in filter_results:
print(result)
# Test pagination
print("\n2. Pagination Tests:")
print("-" * 30)
pagination_results = test_pagination()
for result in pagination_results:
print(result)
# Test combined
print("\n3. Combined Filter + Pagination Tests:")
print("-" * 30)
combined_results = test_pagination_with_filters()
for result in combined_results:
print(result)
# Database statistics
print("\n" + "=" * 50)
print("Database Statistics after Tests:")
print("-" * 50)
# License type distribution
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", "SELECT license_type, COUNT(*) FROM licenses GROUP BY license_type ORDER BY COUNT(*) DESC;"
], capture_output=True, text=True)
print("License Types:")
print(result.stdout)
# Status distribution
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", """SELECT
CASE
WHEN valid_until < CURRENT_DATE THEN 'expired'
WHEN valid_until < CURRENT_DATE + INTERVAL '30 days' THEN 'expiring'
ELSE 'active'
END as status,
COUNT(*)
FROM licenses
GROUP BY status
ORDER BY COUNT(*) DESC;"""
], capture_output=True, text=True)
print("License Status:")
print(result.stdout)

Datei anzeigen

@ -0,0 +1,57 @@
#!/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_license_creation():
"""Test creating a license through the admin panel"""
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 a test license
license_data = {
"customer_name": "Test Customer",
"email": "test@example.com",
"license_key": "TEST-LICENSE-KEY-123",
"license_type": "premium",
"valid_from": datetime.now().strftime("%Y-%m-%d"),
"valid_until": (datetime.now() + timedelta(days=365)).strftime("%Y-%m-%d")
}
response = session.post(f"{base_url}/", data=license_data, verify=False, allow_redirects=False)
if response.status_code == 302 and response.headers.get('Location') == '/':
return "✓ License created successfully"
else:
return f"✗ Failed to create license: {response.status_code}"
print("Testing License Creation")
print("=" * 40)
result = test_license_creation()
print(result)
# Verify the license was created in the database
import subprocess
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", "SELECT c.name, l.license_key, l.license_type, l.valid_from, l.valid_until FROM licenses l JOIN customers c ON l.customer_id = c.id;"
], capture_output=True, text=True)
print("\nLicenses in database:")
print(result.stdout)

Datei anzeigen

@ -0,0 +1,150 @@
#!/usr/bin/env python3
import requests
import urllib3
from datetime import datetime, timedelta
import subprocess
# 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 login(session):
"""Login to admin panel"""
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)
return response.status_code == 302
def test_edit_license():
"""Test editing a license"""
session = requests.Session()
if not login(session):
return "✗ Failed to login"
# First, get a license ID to edit (let's edit license ID 5 - "Bli-bla-blub")
license_id = 5
# Test GET edit page
response = session.get(f"{base_url}/license/edit/{license_id}", verify=False)
if response.status_code != 200:
return f"✗ Failed to access edit page: Status {response.status_code}"
# Check if edit form is displayed
if "Bli-bla-blub" not in response.text:
return "✗ Edit page doesn't show current license data"
# Test POST edit with new data
new_license_data = {
"license_key": "UPDATED-KEY-2025",
"license_type": "Enterprise-Lösung",
"valid_from": "2025-01-01",
"valid_until": "2025-12-31",
"is_active": "on"
}
response = session.post(f"{base_url}/license/edit/{license_id}",
data=new_license_data,
verify=False,
allow_redirects=False)
if response.status_code == 302 and response.headers.get('Location') == '/licenses':
return "✓ License edited successfully"
else:
return f"✗ Failed to edit license: Status {response.status_code}"
def test_delete_license():
"""Test deleting a license"""
session = requests.Session()
if not login(session):
return "✗ Failed to login"
# Create a test license to delete
test_license = {
"customer_name": "Delete Test Company",
"email": "delete@test.com",
"license_key": "DELETE-TEST-KEY",
"license_type": "Test",
"valid_from": datetime.now().strftime("%Y-%m-%d"),
"valid_until": (datetime.now() + timedelta(days=30)).strftime("%Y-%m-%d")
}
# Create the license
response = session.post(f"{base_url}/", data=test_license, verify=False, allow_redirects=False)
if response.status_code != 302:
return "✗ Failed to create test license for deletion"
# Get the ID of the newly created license
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", "SELECT id FROM licenses WHERE license_key = 'DELETE-TEST-KEY';"
], capture_output=True, text=True)
license_id = result.stdout.strip()
if not license_id:
return "✗ Failed to find test license ID"
# Delete the license
response = session.post(f"{base_url}/license/delete/{license_id}",
verify=False,
allow_redirects=False)
if response.status_code == 302 and response.headers.get('Location') == '/licenses':
# Verify it's really deleted
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", f"SELECT COUNT(*) FROM licenses WHERE id = {license_id};"
], capture_output=True, text=True)
count = int(result.stdout.strip())
if count == 0:
return "✓ License deleted successfully"
else:
return "✗ License still exists in database"
else:
return f"✗ Failed to delete license: Status {response.status_code}"
# Rebuild and restart admin panel
print("Rebuilding admin panel with new features...")
subprocess.run(["docker-compose", "build", "admin-panel"], capture_output=True)
subprocess.run(["docker-compose", "up", "-d", "admin-panel"], capture_output=True)
subprocess.run(["sleep", "5"], capture_output=True)
print("\nTesting License Edit/Delete Functionality")
print("=" * 50)
# Test edit functionality
print("\n1. Testing License Edit:")
print("-" * 30)
edit_result = test_edit_license()
print(edit_result)
# Verify the edit worked
print("\nVerifying edited license in database:")
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", "SELECT license_key, license_type, valid_from, valid_until, is_active FROM licenses WHERE license_key = 'UPDATED-KEY-2025';"
], capture_output=True, text=True)
print(result.stdout)
# Test delete functionality
print("\n2. Testing License Delete:")
print("-" * 30)
delete_result = test_delete_license()
print(delete_result)
# Show current licenses
print("\n" + "=" * 50)
print("Current licenses in database:")
print("-" * 50)
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", "SELECT l.id, l.license_key, c.name, l.license_type FROM licenses l JOIN customers c ON l.customer_id = c.id ORDER BY l.id;"
], capture_output=True, text=True)
print(result.stdout)

Datei anzeigen

@ -0,0 +1,104 @@
#!/usr/bin/env python3
import requests
import urllib3
# 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_license_overview():
"""Test the new license overview page"""
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"
# Access the licenses page
response = session.get(f"{base_url}/licenses", verify=False)
if response.status_code == 200:
content = response.text
# Check if we have the expected licenses
test_results = []
# Check for previously created licenses
if "Müller GmbH & Co. KG" in content:
test_results.append("✓ Found: Müller GmbH & Co. KG")
else:
test_results.append("✗ Missing: Müller GmbH & Co. KG")
if "Schröder Süßwaren AG" in content:
test_results.append("✓ Found: Schröder Süßwaren AG")
else:
test_results.append("✗ Missing: Schröder Süßwaren AG")
if "Björn Köhler Einzelunternehmen" in content:
test_results.append("✓ Found: Björn Köhler Einzelunternehmen")
else:
test_results.append("✗ Missing: Björn Köhler Einzelunternehmen")
# Check for license status indicators
if "aktiv" in content or "abgelaufen" in content or "läuft bald ab" in content:
test_results.append("✓ Status indicators found")
else:
test_results.append("✗ No status indicators found")
# Check for UTF-8 characters
if "ä" in content or "ö" in content or "ü" in content or "ß" in content:
test_results.append("✓ UTF-8 characters displayed correctly")
else:
test_results.append("✗ No UTF-8 characters found")
return test_results, response.status_code
else:
return [f"✗ Failed to access licenses page: Status {response.status_code}"], response.status_code
print("Testing License Overview Page")
print("=" * 50)
# First restart admin panel to get the new code
print("Restarting admin panel container...")
import subprocess
subprocess.run(["docker", "restart", "admin-panel"], capture_output=True)
print("Waiting for container to start...")
subprocess.run(["sleep", "5"], capture_output=True)
results, status_code = test_license_overview()
print(f"\nAccessing /licenses endpoint - Status Code: {status_code}")
print("-" * 50)
for result in results:
print(result)
print("\n" + "=" * 50)
print("Database content check:")
print("-" * 50)
# Check what's actually in the database
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", """SELECT l.id, l.license_key, c.name, l.license_type,
l.valid_until,
CASE
WHEN l.valid_until < CURRENT_DATE THEN 'abgelaufen'
WHEN l.valid_until < CURRENT_DATE + INTERVAL '30 days' THEN 'läuft bald ab'
ELSE 'aktiv'
END as status
FROM licenses l
JOIN customers c ON l.customer_id = c.id
ORDER BY l.id DESC LIMIT 5;"""
], capture_output=True, text=True)
print(result.stdout)

156
v2_testing/test_search.py Normale Datei
Datei anzeigen

@ -0,0 +1,156 @@
#!/usr/bin/env python3
import requests
import urllib3
import subprocess
# 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 login(session):
"""Login to admin panel"""
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)
return response.status_code == 302
def test_license_search():
"""Test license search functionality"""
session = requests.Session()
if not login(session):
return "✗ Failed to login"
test_cases = [
# (search_term, expected_results, description)
("müller", ["Müller GmbH & Co. KG"], "Search by customer name with umlaut"),
("KÖHLER", ["Björn Köhler"], "Search by license key (case insensitive)"),
("@übersetzungen.de", ["Björn Köhler"], "Search by email domain with umlaut"),
("2025", ["KÖHLER-2025", "MÜLLER-2025", "SCHRÖDER-2025"], "Search by year in license key"),
("premium", ["TEST-LICENSE-KEY"], "Search by license type"),
("süßwaren", ["Schröder Süßwaren"], "Search with special characters"),
("xyz123", [], "Search with no results")
]
results = []
for search_term, expected, description in test_cases:
response = session.get(f"{base_url}/licenses?search={search_term}", verify=False)
if response.status_code != 200:
results.append(f"{description}: Failed with status {response.status_code}")
continue
content = response.text
found = []
for expected_item in expected:
if expected_item.lower() in content.lower():
found.append(expected_item)
if len(found) == len(expected) and len(expected) > 0:
results.append(f"{description}: Found {len(found)} result(s)")
elif len(expected) == 0 and "Keine Lizenzen gefunden" in content:
results.append(f"{description}: Correctly shows no results")
else:
results.append(f"{description}: Expected {len(expected)}, found {len(found)}")
return results
def test_customer_search():
"""Test customer search functionality"""
session = requests.Session()
if not login(session):
return "✗ Failed to login"
test_cases = [
# (search_term, expected_results, description)
("gmbh", ["Müller GmbH", "Schröder", "Test Customer GmbH", "Löschtest"], "Search for GmbH companies"),
("björn", ["Björn Köhler"], "Search by first name with umlaut"),
("@müller", ["Müller GmbH & Co. KG"], "Search by email with umlaut"),
("test", ["Test Customer", "Testfirma", "Löschtest"], "Search for test entries"),
("überprüfung", ["Testfirma für Umlaute"], "Search with umlaut in term"),
("nonexistent", [], "Search with no results")
]
results = []
for search_term, expected, description in test_cases:
response = session.get(f"{base_url}/customers?search={search_term}", verify=False)
if response.status_code != 200:
results.append(f"{description}: Failed with status {response.status_code}")
continue
content = response.text
found = []
for expected_item in expected:
if expected_item.lower() in content.lower():
found.append(expected_item)
if len(found) >= len(expected) * 0.7: # Allow 70% match rate due to variations
results.append(f"{description}: Found {len(found)} result(s)")
else:
results.append(f"{description}: Expected ~{len(expected)}, found {len(found)}")
return results
# Rebuild and restart admin panel
print("Rebuilding admin panel with search functionality...")
subprocess.run(["docker-compose", "build", "admin-panel"], capture_output=True)
subprocess.run(["docker-compose", "up", "-d", "admin-panel"], capture_output=True)
print("Waiting for container to start...")
subprocess.run(["sleep", "5"], capture_output=True)
print("\nTesting Search Functionality")
print("=" * 50)
# Test license search
print("\n1. License Search Tests:")
print("-" * 30)
license_results = test_license_search()
for result in license_results:
print(result)
# Test customer search
print("\n2. Customer Search Tests:")
print("-" * 30)
customer_results = test_customer_search()
for result in customer_results:
print(result)
# Show some example search results from database
print("\n" + "=" * 50)
print("Database Search Examples:")
print("-" * 50)
# Example: Search for "müller" in licenses
print("\nSearching for 'müller' in licenses:")
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", """SELECT l.license_key, c.name, c.email
FROM licenses l
JOIN customers c ON l.customer_id = c.id
WHERE LOWER(c.name) LIKE LOWER('%müller%')
OR LOWER(l.license_key) LIKE LOWER('%müller%')
OR LOWER(c.email) LIKE LOWER('%müller%');"""
], capture_output=True, text=True)
print(result.stdout)
# Example: Search for customers with "test"
print("Searching for 'test' in customers:")
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", """SELECT name, email
FROM customers
WHERE LOWER(name) LIKE LOWER('%test%')
OR LOWER(email) LIKE LOWER('%test%');"""
], capture_output=True, text=True)
print(result.stdout)

194
v2_testing/test_sessions.py Normale Datei
Datei anzeigen

@ -0,0 +1,194 @@
#!/usr/bin/env python3
import requests
import urllib3
import subprocess
from datetime import datetime
# Disable SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
base_url = "https://localhost:443"
admin_user = {"username": "rac00n", "password": "1248163264"}
def login(session):
"""Login to admin panel"""
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)
return response.status_code == 302
def test_session_table():
"""Test if session table exists and structure"""
print("1. Checking Session Table Structure:")
print("-" * 40)
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", "\\d sessions"
], capture_output=True, text=True)
if "Table \"public.sessions\"" in result.stdout:
print("✓ Sessions table exists")
print("\nTable structure:")
print(result.stdout)
else:
print("✗ Sessions table not found")
return False
# Check if table is empty
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", "SELECT COUNT(*) FROM sessions;"
], capture_output=True, text=True)
count = int(result.stdout.strip())
print(f"\nCurrent session count: {count}")
if count == 0:
print("✓ Session table is empty (as expected - License Server not implemented)")
return True
def test_session_page():
"""Test the sessions management page"""
session = requests.Session()
if not login(session):
return "✗ Failed to login"
print("\n2. Testing Sessions Page:")
print("-" * 40)
response = session.get(f"{base_url}/sessions", verify=False)
if response.status_code == 200:
print("✓ Sessions page accessible")
content = response.text
# Check for expected elements
checks = [
("Aktive Sessions", "Active sessions section"),
("Letzte Sessions", "Recent sessions section"),
("IP-Adresse", "IP address column"),
("User Agent", "User agent column"),
("Heartbeat", "Heartbeat info"),
("Session beenden", "End session button")
]
for check_text, description in checks:
if check_text in content:
print(f"✓ Found: {description}")
else:
print(f"✗ Missing: {description}")
# Check for empty state
if "Keine aktiven Sessions" in content:
print("✓ Shows empty state for active sessions")
else:
print(f"✗ Failed to access sessions page: Status {response.status_code}")
def test_dashboard_session_count():
"""Test if dashboard shows session count"""
session = requests.Session()
if not login(session):
return "✗ Failed to login"
print("\n3. Testing Dashboard Session Counter:")
print("-" * 40)
response = session.get(f"{base_url}/", verify=False)
if response.status_code == 200:
content = response.text
if "Aktive Sessions" in content or "sessions" in content.lower():
print("✓ Dashboard shows session information")
# Check if it shows 0
if "0" in content:
print("✓ Shows 0 active sessions (correct)")
else:
print("✗ No session information on dashboard")
def simulate_session_data():
"""Add test session data directly to database"""
print("\n4. Simulating Session Data:")
print("-" * 40)
# Get a license ID
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank", "-t",
"-c", "SELECT id FROM licenses WHERE is_active = TRUE LIMIT 1;"
], capture_output=True, text=True)
license_id = result.stdout.strip()
if not license_id:
print("✗ No active license found for test")
return
# Insert test sessions
test_sessions = [
# Active session
f"""INSERT INTO sessions (license_id, session_id, ip_address, user_agent, is_active)
VALUES ({license_id}, 'TEST-SESSION-001', '192.168.1.100',
'Mozilla/5.0 Test Browser', TRUE);""",
# Inactive session from today
f"""INSERT INTO sessions (license_id, session_id, ip_address, user_agent,
started_at, ended_at, is_active)
VALUES ({license_id}, 'TEST-SESSION-002', '10.0.0.50',
'Chrome/120.0 Windows',
NOW() - INTERVAL '2 hours', NOW() - INTERVAL '1 hour', FALSE);"""
]
for sql in test_sessions:
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", sql
], capture_output=True, text=True)
if "INSERT" in result.stdout:
print("✓ Test session inserted")
else:
print("✗ Failed to insert test session")
# Verify
result = subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", "SELECT COUNT(*) as total, COUNT(CASE WHEN is_active THEN 1 END) as active FROM sessions;"
], capture_output=True, text=True)
print("\nSession count after simulation:")
print(result.stdout)
# Main execution
print("Testing Session Management Features")
print("=" * 50)
# Rebuild admin panel
print("Rebuilding admin panel with session features...")
subprocess.run(["docker-compose", "build", "admin-panel"], capture_output=True)
subprocess.run(["docker-compose", "up", "-d"], capture_output=True)
subprocess.run(["sleep", "5"], capture_output=True)
# Run tests
test_session_table()
test_session_page()
test_dashboard_session_count()
simulate_session_data()
# Test again with data
print("\n5. Re-testing with simulated data:")
print("-" * 40)
test_session_page()
# Cleanup test data
print("\n6. Cleaning up test data:")
subprocess.run([
"docker", "exec", "db", "psql", "-U", "adminuser", "-d", "meinedatenbank",
"-c", "DELETE FROM sessions WHERE session_id LIKE 'TEST-%';"
], capture_output=True, text=True)
print("✓ Test sessions removed")

159
v2_testing/test_timezone.py Normale Datei
Datei anzeigen

@ -0,0 +1,159 @@
#!/usr/bin/env python3
import requests
import urllib3
from datetime import datetime
from zoneinfo import ZoneInfo
import json
import time
# Disable SSL warnings for self-signed certificate
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Test configuration
# Use external URL for testing
base_url = "https://admin-panel-undso.z5m7q9dk3ah2v1plx6ju.com"
# Fallback to localhost if external URL is not accessible
fallback_url = "https://localhost:443"
admin_user = {"username": "rac00n", "password": "1248163264"}
def test_timezone_functionality():
"""Test if timestamps are in German timezone (Europe/Berlin)"""
session = requests.Session()
print("Testing Timezone Functionality (Europe/Berlin)")
print("=" * 50)
# Test connection to external URL first
global base_url
try:
test_response = session.get(base_url, verify=True, timeout=5)
print(f"✓ Using external URL: {base_url}")
except:
base_url = fallback_url
print(f" Using fallback URL: {base_url}")
# Get current time in UTC and Berlin
utc_now = datetime.now(ZoneInfo("UTC"))
berlin_now = datetime.now(ZoneInfo("Europe/Berlin"))
print(f"Current UTC time: {utc_now.strftime('%Y-%m-%d %H:%M:%S %Z')}")
print(f"Current Berlin time: {berlin_now.strftime('%Y-%m-%d %H:%M:%S %Z')}")
print(f"Time difference: {(berlin_now.hour - utc_now.hour) % 24} hours")
print()
# Login
verify_ssl = base_url != fallback_url # Verify SSL for external URL only
response = session.get(f"{base_url}/login", verify=verify_ssl)
if response.status_code != 200:
print(f"✗ Failed to access login page: {response.status_code}")
return
login_data = {
"username": admin_user["username"],
"password": admin_user["password"]
}
response = session.post(f"{base_url}/login", data=login_data, verify=verify_ssl, allow_redirects=False)
if response.status_code != 302:
print(f"✗ Login failed: {response.status_code}")
return
print("✓ Login successful")
print()
# Test 1: Create a test license to check created_at timestamp
print("Test 1: Creating test license to check timestamps...")
# First, get a customer ID or create one
license_data = {
"customer_select": "new",
"customer_name": f"Timezone Test Customer {int(time.time())}",
"customer_email": f"timezone-test-{int(time.time())}@example.com",
"license_key": f"AF-{berlin_now.strftime('%Y%m')}T-TEST-TIME-ZONE",
"license_type": "test",
"max_sessions": "1",
"start_date": berlin_now.strftime("%Y-%m-%d"),
"duration": "1",
"duration_unit": "days"
}
response = session.post(f"{base_url}/create", data=license_data, verify=verify_ssl)
if response.status_code == 200:
print("✓ Test license created")
else:
print(f"✗ Failed to create license: {response.status_code}")
# Test 2: Check audit log for timezone
print("\nTest 2: Checking audit log timestamps...")
response = session.get(f"{base_url}/audit", verify=verify_ssl)
if response.status_code == 200:
# Extract the most recent audit log entry timestamp from HTML
if "CREATE" in response.text and license_data["license_key"] in response.text:
print("✓ Audit log entry created")
# Check if timestamps in audit log appear to be in German time
# This is a simple check - in production you'd parse the HTML properly
current_hour = berlin_now.strftime("%H:")
if current_hour in response.text:
print(f"✓ Audit log shows Berlin time (contains {current_hour})")
else:
print(f"⚠ Audit log might show UTC time (doesn't contain {current_hour})")
else:
print(f"✗ Failed to access audit log: {response.status_code}")
# Test 3: Check backup functionality for filename timezone
print("\nTest 3: Testing backup filename timezone...")
response = session.post(f"{base_url}/backup/create", verify=verify_ssl)
if response.status_code == 302: # Redirect after backup
print("✓ Backup created")
# Check backup list
response = session.get(f"{base_url}/backups", verify=verify_ssl)
if response.status_code == 200:
# Check if backup filename contains current Berlin hour
berlin_hour = berlin_now.strftime("%H")
if f"_{berlin_hour}" in response.text:
print(f"✓ Backup filename uses Berlin time (contains hour {berlin_hour})")
else:
utc_hour = utc_now.strftime("%H")
if f"_{utc_hour}" in response.text:
print(f"✗ Backup filename might use UTC time (contains hour {utc_hour})")
else:
print("⚠ Could not determine timezone from backup filename")
else:
print(f"✗ Failed to create backup: {response.status_code}")
# Test 4: Check session timestamps
print("\nTest 4: Checking session timestamps...")
response = session.get(f"{base_url}/sessions", verify=verify_ssl)
if response.status_code == 200:
print("✓ Accessed sessions page")
# Active sessions should show current time
if "Keine aktiven Sessions" not in response.text:
print("✓ Session data available")
else:
print(" No active sessions to check (this is normal)")
else:
print(f"✗ Failed to access sessions: {response.status_code}")
# Test 5: Database timezone check
print("\nTest 5: Summary")
print("-" * 30)
time_diff = (berlin_now.hour - utc_now.hour) % 24
if time_diff == 1:
print("✓ Timezone offset is +1 hour (CET - Central European Time)")
elif time_diff == 2:
print("✓ Timezone offset is +2 hours (CEST - Central European Summer Time)")
else:
print(f"⚠ Unexpected timezone offset: {time_diff} hours")
print("\nNote: All new timestamps should be in Europe/Berlin timezone")
print("Existing data might still show UTC until updated")
if __name__ == "__main__":
test_timezone_functionality()

Datei anzeigen

@ -0,0 +1,122 @@
#!/usr/bin/env python3
import requests
import urllib3
from datetime import datetime
from zoneinfo import ZoneInfo
import re
# Disable SSL warnings for self-signed certificate
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Test configuration
base_url = "https://admin-panel-undso.z5m7q9dk3ah2v1plx6ju.com"
fallback_url = "https://localhost:443"
admin_user = {"username": "rac00n", "password": "1248163264"}
def test_timezone_simple():
"""Simple test to verify timezone is Europe/Berlin"""
session = requests.Session()
print("Timezone Verification Test (Europe/Berlin)")
print("=" * 50)
# Test connection
try:
test_response = session.get(base_url, verify=True, timeout=5)
verify_ssl = True
print(f"✓ Using external URL: {base_url}")
except:
base_url_local = fallback_url
verify_ssl = False
print(f" Using fallback URL: {fallback_url}")
else:
base_url_local = base_url
# Show current times
utc_now = datetime.now(ZoneInfo("UTC"))
berlin_now = datetime.now(ZoneInfo("Europe/Berlin"))
print(f"\nCurrent times:")
print(f" UTC: {utc_now.strftime('%Y-%m-%d %H:%M:%S')}")
print(f" Berlin: {berlin_now.strftime('%Y-%m-%d %H:%M:%S')}")
# Calculate offset
time_diff = (berlin_now.hour - utc_now.hour) % 24
if berlin_now.day != utc_now.day:
# Handle day boundary
if berlin_now.day > utc_now.day:
time_diff = (berlin_now.hour + 24 - utc_now.hour) % 24
else:
time_diff = (berlin_now.hour - utc_now.hour - 24) % 24
print(f" Offset: +{time_diff} hours")
# Login
response = session.get(f"{base_url_local}/login", verify=verify_ssl)
if response.status_code != 200:
print(f"\n✗ Failed to access login page: {response.status_code}")
return
login_data = {
"username": admin_user["username"],
"password": admin_user["password"]
}
response = session.post(f"{base_url_local}/login", data=login_data, verify=verify_ssl, allow_redirects=False)
if response.status_code != 302:
print(f"\n✗ Login failed: {response.status_code}")
return
print(f"\n✓ Login successful")
# Check dashboard for any timestamps
print("\nChecking for timestamps in dashboard...")
response = session.get(f"{base_url_local}/", verify=verify_ssl)
if response.status_code == 200:
# Look for time patterns in dashboard
time_pattern = r'\d{2}:\d{2}:\d{2}'
times_found = re.findall(time_pattern, response.text)
if times_found:
print(f"✓ Found {len(times_found)} timestamps in dashboard")
# Check if any match current Berlin hour
berlin_hour = berlin_now.strftime("%H:")
if any(berlin_hour in time for time in times_found):
print(f"✓ Timestamps appear to use Berlin time (found {berlin_hour}xx)")
else:
print(f" Could not confirm timezone from timestamps")
else:
print(" No timestamps found in dashboard")
# Check audit log
print("\nChecking audit log for LOGIN timestamp...")
response = session.get(f"{base_url_local}/audit", verify=verify_ssl)
if response.status_code == 200:
# Extract the most recent LOGIN entry
if "LOGIN_SUCCESS" in response.text:
# Look for timestamp near LOGIN_SUCCESS
berlin_time_str = berlin_now.strftime("%Y-%m-%d %H:")
if berlin_time_str in response.text:
print(f"✓ Audit log shows Berlin time (contains {berlin_time_str}xx)")
else:
utc_time_str = utc_now.strftime("%Y-%m-%d %H:")
if utc_time_str in response.text:
print(f"✗ Audit log might show UTC time (contains {utc_time_str}xx)")
else:
print(f" Could not determine timezone from audit log")
# Summary
print("\n" + "=" * 50)
print("Summary:")
if time_diff == 1:
print("✓ System timezone offset: +1 hour (CET - Winter time)")
elif time_diff == 2:
print("✓ System timezone offset: +2 hours (CEST - Summer time)")
else:
print(f"⚠ Unexpected timezone offset: +{time_diff} hours")
print("\nNote: The system should use Europe/Berlin timezone for all new data.")
print("Existing data created before the timezone change may still show UTC.")
if __name__ == "__main__":
test_timezone_simple()

Datei anzeigen

@ -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)