🎉 3 Änderungen an Tools-Modul vorgenommen:

- backend/form_test_automator.py -> backend/tools/analysis/form_test_automator.py
- backend/simple_form_tester.py -> backend/tools/analysis/simple_form_tester.py
- backend/template_analysis_tool.py -> backend/tools/analysis/template_analysis_tool.py
- backend
This commit is contained in:
2025-06-19 20:54:40 +02:00
parent 3f7aa12577
commit b295c2585f
6 changed files with 0 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,635 @@
#!/usr/bin/env python3
"""
Vereinfachter HTML-Formular Tester für MYP System
===============================================
Ein schlanker Formular-Tester ohne externe Dependencies,
der grundlegende Formular-Validierung mit Standard-Python-Libraries testet.
Autor: Till Tomczak
Mercedes-Benz Projektarbeit MYP
"""
import asyncio
import json
import time
import urllib.request
import urllib.parse
import urllib.error
from urllib.parse import urljoin, urlparse
from html.parser import HTMLParser
from dataclasses import dataclass
from typing import Dict, List, Optional
import sys
import re
@dataclass
class FormField:
"""Repräsentiert ein Formular-Feld"""
name: str
field_type: str
required: bool = False
pattern: str = ""
placeholder: str = ""
value: str = ""
@dataclass
class Form:
"""Repräsentiert ein HTML-Formular"""
action: str
method: str
fields: List[FormField]
name: str = ""
class FormParser(HTMLParser):
"""Parst HTML und extrahiert Formular-Informationen"""
def __init__(self):
super().__init__()
self.forms = []
self.current_form = None
self.in_form = False
def handle_starttag(self, tag, attrs):
attrs_dict = dict(attrs)
if tag == 'form':
self.in_form = True
self.current_form = Form(
action=attrs_dict.get('action', ''),
method=attrs_dict.get('method', 'GET').upper(),
fields=[],
name=attrs_dict.get('name', attrs_dict.get('id', f'form_{len(self.forms)}'))
)
elif self.in_form and tag in ['input', 'textarea', 'select']:
field = FormField(
name=attrs_dict.get('name', attrs_dict.get('id', f'field_{len(self.current_form.fields)}')),
field_type=attrs_dict.get('type', tag),
required='required' in attrs_dict,
pattern=attrs_dict.get('pattern', ''),
placeholder=attrs_dict.get('placeholder', ''),
value=attrs_dict.get('value', '')
)
self.current_form.fields.append(field)
def handle_endtag(self, tag):
if tag == 'form' and self.in_form:
self.in_form = False
if self.current_form:
self.forms.append(self.current_form)
self.current_form = None
class SimpleFormTester:
"""
Vereinfachter Formular-Tester ohne Browser-Dependencies.
Führt HTTP-basierte Tests durch.
"""
def __init__(self, base_url: str):
self.base_url = base_url.rstrip('/')
self.session_cookies = {}
def fetch_page(self, path: str) -> str:
"""Lädt eine Seite und gibt den HTML-Inhalt zurück"""
url = urljoin(self.base_url, path)
try:
request = urllib.request.Request(url)
# Cookies hinzufügen
if self.session_cookies:
cookie_header = '; '.join([f'{k}={v}' for k, v in self.session_cookies.items()])
request.add_header('Cookie', cookie_header)
with urllib.request.urlopen(request) as response:
html = response.read().decode('utf-8')
# Cookies aus Response extrahieren
cookie_header = response.getheader('Set-Cookie')
if cookie_header:
self._parse_cookies(cookie_header)
return html
except urllib.error.URLError as e:
print(f"❌ Fehler beim Laden von {url}: {e}")
return ""
def _parse_cookies(self, cookie_header: str):
"""Parst Set-Cookie Header"""
for cookie in cookie_header.split(','):
if '=' in cookie:
name, value = cookie.split('=', 1)
self.session_cookies[name.strip()] = value.split(';')[0].strip()
def find_forms(self, html: str) -> List[Form]:
"""Findet alle Formulare in HTML"""
parser = FormParser()
parser.feed(html)
return parser.forms
def generate_test_data(self, field: FormField) -> str:
"""Generiert Test-Daten für ein Feld"""
if field.field_type == 'email':
return "test@mercedes-benz.com"
elif field.field_type == 'password':
return "TestPassword123!"
elif field.field_type == 'tel':
return "+49 711 17-0"
elif field.field_type == 'url':
return "https://www.mercedes-benz.com"
elif field.field_type == 'number':
return "42"
elif field.field_type == 'date':
return "2024-06-18"
elif field.field_type == 'checkbox':
return "on"
elif field.field_type == 'radio':
return field.value or "option1"
elif 'name' in field.name.lower():
return "Test Benutzer"
elif 'username' in field.name.lower():
return "admin"
elif 'ip' in field.name.lower():
return "192.168.1.100"
elif 'port' in field.name.lower():
return "80"
else:
return f"Test_{field.name}"
def submit_form(self, form: Form, test_data: Dict[str, str], base_url: str) -> Dict:
"""Sendet Formular-Daten und gibt Response zurück"""
# Action URL bestimmen
if form.action.startswith('http'):
url = form.action
else:
url = urljoin(base_url, form.action)
# Daten vorbereiten
form_data = {}
for field in form.fields:
if field.name in test_data:
form_data[field.name] = test_data[field.name]
elif field.field_type not in ['submit', 'button']:
form_data[field.name] = self.generate_test_data(field)
try:
if form.method == 'GET':
# GET-Request mit Query-Parametern
query_string = urllib.parse.urlencode(form_data)
full_url = f"{url}?{query_string}"
request = urllib.request.Request(full_url)
else:
# POST-Request
data = urllib.parse.urlencode(form_data).encode('utf-8')
request = urllib.request.Request(url, data=data)
request.add_header('Content-Type', 'application/x-www-form-urlencoded')
# Cookies hinzufügen
if self.session_cookies:
cookie_header = '; '.join([f'{k}={v}' for k, v in self.session_cookies.items()])
request.add_header('Cookie', cookie_header)
with urllib.request.urlopen(request) as response:
response_html = response.read().decode('utf-8')
status_code = response.getcode()
return {
'success': 200 <= status_code < 400,
'status_code': status_code,
'html': response_html,
'form_data': form_data
}
except urllib.error.HTTPError as e:
return {
'success': False,
'status_code': e.code,
'error': str(e),
'form_data': form_data
}
except Exception as e:
return {
'success': False,
'error': str(e),
'form_data': form_data
}
def validate_field(self, field: FormField, value: str) -> Dict:
"""Validiert ein Feld mit gegebenem Wert"""
errors = []
# Required-Validierung
if field.required and not value.strip():
errors.append(f"Feld '{field.name}' ist erforderlich")
# Pattern-Validierung
if field.pattern and value:
try:
if not re.match(field.pattern, value):
errors.append(f"Feld '{field.name}' entspricht nicht dem Pattern '{field.pattern}'")
except re.error:
errors.append(f"Ungültiges Pattern für Feld '{field.name}': {field.pattern}")
# Type-spezifische Validierung
if value and field.field_type == 'email':
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if not re.match(email_pattern, value):
errors.append(f"Ungültige Email-Adresse: {value}")
elif value and field.field_type == 'url':
try:
parsed = urlparse(value)
if not parsed.scheme or not parsed.netloc:
errors.append(f"Ungültige URL: {value}")
except:
errors.append(f"Ungültige URL: {value}")
elif value and field.field_type == 'number':
try:
float(value)
except ValueError:
errors.append(f"'{value}' ist keine gültige Zahl")
return {
'valid': len(errors) == 0,
'errors': errors,
'field': field.name,
'value': value
}
def test_form_validation(self, form: Form) -> List[Dict]:
"""Testet Formular-Validierung mit verschiedenen Daten"""
validation_results = []
# 1. Test mit leeren Required-Feldern
for field in form.fields:
if field.required:
result = self.validate_field(field, "")
validation_results.append({
'test_type': 'required_field_empty',
'field': field.name,
'expected_invalid': True,
'actual_valid': result['valid'],
'passed': not result['valid'], # Sollte ungültig sein
'errors': result['errors']
})
# 2. Test mit ungültigen Email-Adressen
for field in form.fields:
if field.field_type == 'email':
invalid_emails = ['invalid-email', 'test@', '@domain.com', 'test..test@domain.com']
for invalid_email in invalid_emails:
result = self.validate_field(field, invalid_email)
validation_results.append({
'test_type': 'invalid_email',
'field': field.name,
'value': invalid_email,
'expected_invalid': True,
'actual_valid': result['valid'],
'passed': not result['valid'],
'errors': result['errors']
})
# 3. Test mit gültigen Daten
valid_test_data = {}
for field in form.fields:
if field.field_type not in ['submit', 'button']:
valid_test_data[field.name] = self.generate_test_data(field)
for field in form.fields:
if field.name in valid_test_data:
result = self.validate_field(field, valid_test_data[field.name])
validation_results.append({
'test_type': 'valid_data',
'field': field.name,
'value': valid_test_data[field.name],
'expected_invalid': False,
'actual_valid': result['valid'],
'passed': result['valid'],
'errors': result['errors']
})
return validation_results
def test_form_submission(self, form: Form, base_url: str) -> Dict:
"""Testet Formular-Submission"""
print(f"🧪 Teste Formular: {form.name} ({form.method}{form.action})")
# Test-Daten generieren
test_data = {}
for field in form.fields:
if field.field_type not in ['submit', 'button']:
test_data[field.name] = self.generate_test_data(field)
print(f" 📝 Test-Daten: {list(test_data.keys())}")
# Formular senden
start_time = time.time()
result = self.submit_form(form, test_data, base_url)
execution_time = time.time() - start_time
# Validierungs-Tests
validation_results = self.test_form_validation(form)
return {
'form_name': form.name,
'method': form.method,
'action': form.action,
'fields_count': len(form.fields),
'test_data': test_data,
'submission_result': result,
'validation_results': validation_results,
'execution_time': execution_time,
'timestamp': time.strftime('%Y-%m-%d %H:%M:%S')
}
def test_page_forms(self, path: str) -> List[Dict]:
"""Testet alle Formulare auf einer Seite"""
print(f"🔍 Scanne Formulare auf: {self.base_url}{path}")
# Seite laden
html = self.fetch_page(path)
if not html:
return []
# Formulare finden
forms = self.find_forms(html)
print(f"{len(forms)} Formulare gefunden")
# Jedes Formular testen
results = []
for form in forms:
result = self.test_form_submission(form, self.base_url + path)
results.append(result)
return results
def generate_report(self, test_results: List[Dict], output_file: str = "simple_form_test_report.html"):
"""Generiert einen einfachen HTML-Report"""
total_forms = len(test_results)
successful_submissions = len([r for r in test_results if r['submission_result'].get('success', False)])
# Validierungs-Statistiken
total_validations = sum(len(r['validation_results']) for r in test_results)
passed_validations = sum(len([v for v in r['validation_results'] if v['passed']]) for r in test_results)
html_report = f"""<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MYP Formular Test Report</title>
<style>
body {{
font-family: Arial, sans-serif;
margin: 20px;
background-color: #f5f5f5;
}}
.container {{
max-width: 1200px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}}
.header {{
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 20px;
text-align: center;
margin: -20px -20px 20px -20px;
border-radius: 8px 8px 0 0;
}}
.stats {{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin-bottom: 30px;
}}
.stat-card {{
background: #f8f9fa;
padding: 15px;
border-radius: 6px;
text-align: center;
border: 1px solid #dee2e6;
}}
.stat-number {{
font-size: 2em;
font-weight: bold;
color: #333;
}}
.form-result {{
border: 1px solid #dee2e6;
border-radius: 6px;
margin-bottom: 20px;
overflow: hidden;
}}
.form-header {{
background: #e9ecef;
padding: 15px;
border-bottom: 1px solid #dee2e6;
}}
.form-content {{
padding: 15px;
}}
.success {{ color: #28a745; }}
.failure {{ color: #dc3545; }}
.warning {{ color: #ffc107; }}
.test-data {{
background: #f8f9fa;
padding: 10px;
border-radius: 4px;
margin: 10px 0;
font-family: monospace;
font-size: 0.9em;
}}
.validation-result {{
margin: 5px 0;
padding: 5px 10px;
border-radius: 4px;
border-left: 4px solid #dee2e6;
}}
.validation-passed {{
background: #d4edda;
border-left-color: #28a745;
}}
.validation-failed {{
background: #f8d7da;
border-left-color: #dc3545;
}}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🧪 MYP Formular Test Report</h1>
<p>Generiert am {time.strftime('%d.%m.%Y um %H:%M:%S')}</p>
</div>
<div class="stats">
<div class="stat-card">
<div class="stat-number">{total_forms}</div>
<div>Formulare getestet</div>
</div>
<div class="stat-card">
<div class="stat-number {'success' if successful_submissions == total_forms else 'warning' if successful_submissions > 0 else 'failure'}">{successful_submissions}</div>
<div>Erfolgreiche Submissions</div>
</div>
<div class="stat-card">
<div class="stat-number">{total_validations}</div>
<div>Validierungs-Tests</div>
</div>
<div class="stat-card">
<div class="stat-number {'success' if passed_validations == total_validations else 'warning' if passed_validations > 0 else 'failure'}">{passed_validations}</div>
<div>Validierungen bestanden</div>
</div>
</div>
<h2>📋 Detaillierte Ergebnisse</h2>
"""
# Formular-spezifische Ergebnisse
for result in test_results:
submission = result['submission_result']
success_class = 'success' if submission.get('success', False) else 'failure'
html_report += f"""
<div class="form-result">
<div class="form-header">
<h3>📝 {result['form_name']}</h3>
<p><strong>Method:</strong> {result['method']} | <strong>Action:</strong> {result['action']} | <strong>Felder:</strong> {result['fields_count']}</p>
</div>
<div class="form-content">
<h4>Submission-Ergebnis: <span class="{success_class}">{'✅ Erfolgreich' if submission.get('success', False) else '❌ Fehlgeschlagen'}</span></h4>
{f'<p><strong>Status Code:</strong> {submission.get("status_code", "N/A")}</p>' if 'status_code' in submission else ''}
{f'<p><strong>Fehler:</strong> {submission.get("error", "N/A")}</p>' if 'error' in submission else ''}
<h4>Test-Daten:</h4>
<div class="test-data">{json.dumps(result['test_data'], indent=2, ensure_ascii=False)}</div>
<h4>Validierungs-Ergebnisse:</h4>
"""
# Validierungs-Ergebnisse
for validation in result['validation_results']:
validation_class = 'validation-passed' if validation['passed'] else 'validation-failed'
status_icon = '' if validation['passed'] else ''
html_report += f"""
<div class="validation-result {validation_class}">
<strong>{status_icon} {validation['test_type']}</strong> - Feld: {validation['field']}
{f"<br>Wert: <code>{validation.get('value', 'N/A')}</code>" if 'value' in validation else ''}
{f"<br>Fehler: {', '.join(validation['errors'])}" if validation['errors'] else ''}
</div>
"""
html_report += f"""
<p><small>⏱️ Ausführungszeit: {result['execution_time']:.2f}s</small></p>
</div>
</div>
"""
html_report += """
</div>
</body>
</html>"""
try:
with open(output_file, 'w', encoding='utf-8') as f:
f.write(html_report)
print(f"📊 Report erstellt: {output_file}")
return output_file
except Exception as e:
print(f"❌ Fehler beim Report-Erstellen: {e}")
return ""
def main():
"""Haupt-CLI-Interface"""
if len(sys.argv) < 2:
print("""
🧪 Vereinfachter MYP Formular Tester
Verwendung:
python simple_form_tester.py <base_url> [path]
Beispiele:
python simple_form_tester.py http://localhost:5000
python simple_form_tester.py http://localhost:5000 /login
python simple_form_tester.py http://localhost:5000 /admin/add_printer
Testet alle Formulare auf der angegebenen Seite und generiert einen HTML-Report.
""")
return
base_url = sys.argv[1]
path = sys.argv[2] if len(sys.argv) > 2 else '/'
print(f"""
{'='*60}
🧪 MYP FORMULAR TESTER (Vereinfacht)
{'='*60}
🎯 Basis-URL: {base_url}
📍 Pfad: {path}
🕒 Gestartet: {time.strftime('%d.%m.%Y um %H:%M:%S')}
{'='*60}
""")
# Tester initialisieren
tester = SimpleFormTester(base_url)
# Tests ausführen
try:
results = tester.test_page_forms(path)
if results:
# Report generieren
report_file = tester.generate_report(results)
# Zusammenfassung
total_forms = len(results)
successful = len([r for r in results if r['submission_result'].get('success', False)])
print(f"""
{'='*60}
🎉 TESTS ABGESCHLOSSEN
{'='*60}
📊 ZUSAMMENFASSUNG:
• Formulare getestet: {total_forms}
• Erfolgreiche Submissions: {successful}
• Erfolgsrate: {successful/total_forms*100:.1f}%
📋 Report: {report_file}
{'='*60}
""")
else:
print("⚠️ Keine Formulare gefunden oder Fehler beim Laden der Seite")
except Exception as e:
print(f"❌ Fehler beim Testen: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
main()

View File

@ -0,0 +1,245 @@
#!/usr/bin/env python3
"""
Intelligentes Template-Analyse-Tool für MYP Admin Panel
Systematische Identifikation und Behebung aller Template-Probleme
Autor: MYP Team - Till Tomczak
Datum: 2025-06-19
"""
import re
import os
import json
from typing import Dict, List, Set, Tuple
from pathlib import Path
class TemplateAnalyzer:
"""
Intelligenter Template-Analyzer für systematische Problemerkennung
"""
def __init__(self, template_path: str, blueprint_path: str):
self.template_path = template_path
self.blueprint_path = blueprint_path
self.template_endpoints: Set[str] = set()
self.available_endpoints: Set[str] = set()
self.endpoint_mapping: Dict[str, str] = {}
self.problems: List[Dict] = []
self.corrections: List[Dict] = []
def analyze_template_endpoints(self) -> Set[str]:
"""
1. Jinja2 Syntax-Analyse: Extrahiere alle url_for() Aufrufe
"""
print("🔍 PHASE 1: Template Endpoint-Analyse")
with open(self.template_path, 'r', encoding='utf-8') as f:
template_content = f.read()
# Regex für url_for() Aufrufe in Jinja2-Templates
url_for_pattern = r"{{\s*url_for\(['\"]([^'\"]+)['\"][^}]*\)\s*}}"
matches = re.findall(url_for_pattern, template_content)
self.template_endpoints = set(matches)
print(f" ✓ Gefundene Template-Endpoints: {len(self.template_endpoints)}")
for endpoint in sorted(self.template_endpoints):
print(f" - {endpoint}")
return self.template_endpoints
def analyze_blueprint_routes(self) -> Set[str]:
"""
2. Backend Blueprint-Analyse: Scanne alle registrierten Routen
"""
print("\n🔍 PHASE 2: Blueprint Route-Analyse")
with open(self.blueprint_path, 'r', encoding='utf-8') as f:
blueprint_content = f.read()
# Regex für Blueprint-Routen
route_pattern = r'@admin_blueprint\.route\(["\']([^"\']+)["\'][^)]*\)\s*@admin_required\s*def\s+([a-zA-Z_][a-zA-Z0-9_]*)'
matches = re.findall(route_pattern, blueprint_content, re.MULTILINE | re.DOTALL)
# Erstelle verfügbare Endpoints mit admin.-Prefix
for route_path, function_name in matches:
endpoint = f"admin.{function_name}"
self.available_endpoints.add(endpoint)
self.endpoint_mapping[function_name] = endpoint
# Zusätzlich: API-Blueprint-Routen
api_route_pattern = r'@admin_api_blueprint\.route\(["\']([^"\']+)["\'][^)]*\)\s*@admin_required\s*def\s+([a-zA-Z_][a-zA-Z0-9_]*)'
api_matches = re.findall(api_route_pattern, blueprint_content, re.MULTILINE | re.DOTALL)
for route_path, function_name in api_matches:
endpoint = f"admin_api.{function_name}"
self.available_endpoints.add(endpoint)
self.endpoint_mapping[function_name] = endpoint
print(f" ✓ Verfügbare Blueprint-Endpoints: {len(self.available_endpoints)}")
for endpoint in sorted(self.available_endpoints):
print(f" - {endpoint}")
return self.available_endpoints
def cross_reference_validation(self) -> List[Dict]:
"""
3. Cross-Reference Validierung: Vergleiche Template vs. Blueprint
"""
print("\n🔍 PHASE 3: Cross-Reference Validierung")
# Finde fehlende oder falsche Referenzen
missing_endpoints = self.template_endpoints - self.available_endpoints
unused_endpoints = self.available_endpoints - self.template_endpoints
for endpoint in missing_endpoints:
problem = {
'type': 'missing_endpoint',
'endpoint': endpoint,
'description': f'Template referenziert nicht existierenden Endpoint: {endpoint}',
'severity': 'critical'
}
# Versuche ähnliche Endpoints zu finden
suggestions = self._find_similar_endpoints(endpoint)
if suggestions:
problem['suggestions'] = suggestions
self.problems.append(problem)
print(f" ❌ Problematische Endpoints: {len(missing_endpoints)}")
for endpoint in missing_endpoints:
print(f" - {endpoint}")
print(f" ⚠️ Ungenutzte Endpoints: {len(unused_endpoints)}")
for endpoint in unused_endpoints:
print(f" - {endpoint}")
return self.problems
def _find_similar_endpoints(self, target: str) -> List[str]:
"""
Finde ähnliche Endpoints basierend auf String-Ähnlichkeit
"""
suggestions = []
target_parts = target.split('.')
for available in self.available_endpoints:
available_parts = available.split('.')
# Ähnlichkeits-Heuristiken
if len(target_parts) == len(available_parts):
# Gleiche Struktur
if target_parts[-1] in available_parts[-1] or available_parts[-1] in target_parts[-1]:
suggestions.append(available)
# Ähnliche Funktionsnamen
if target_parts[-1] in available_parts[-1]:
suggestions.append(available)
return suggestions[:3] # Maximal 3 Vorschläge
def generate_corrections(self) -> List[Dict]:
"""
4. Auto-Fix Generator: Generiere MultiEdit-Korrekturen
"""
print("\n🔧 PHASE 4: Korrektur-Generierung")
with open(self.template_path, 'r', encoding='utf-8') as f:
template_content = f.read()
for problem in self.problems:
if problem['type'] == 'missing_endpoint' and 'suggestions' in problem:
old_endpoint = problem['endpoint']
suggested_endpoint = problem['suggestions'][0] # Beste Suggestion
# Erstelle Korrektur
old_pattern = f"url_for('{old_endpoint}'"
new_pattern = f"url_for('{suggested_endpoint}'"
# Prüfe ob Pattern im Template vorkommt
if old_pattern in template_content:
correction = {
'old_string': old_pattern,
'new_string': new_pattern,
'description': f'Korrigiere {old_endpoint}{suggested_endpoint}',
'confidence': 'high'
}
self.corrections.append(correction)
print(f" ✓ Generierte Korrekturen: {len(self.corrections)}")
for correction in self.corrections:
print(f" - {correction['description']}")
return self.corrections
def generate_report(self) -> Dict:
"""
Generiere strukturierten Analysebericht
"""
return {
'summary': {
'template_endpoints': len(self.template_endpoints),
'available_endpoints': len(self.available_endpoints),
'problems_found': len(self.problems),
'corrections_generated': len(self.corrections)
},
'template_endpoints': list(self.template_endpoints),
'available_endpoints': list(self.available_endpoints),
'problems': self.problems,
'corrections': self.corrections,
'endpoint_mapping': self.endpoint_mapping
}
def main():
"""
Hauptfunktion für Template-Analyse
"""
print("🚀 MYP Template-Analyse-Tool")
print("=" * 50)
template_path = "/mnt/c/Users/TTOMCZA.EMEA/Dev/Projektarbeit-MYP/backend/templates/admin.html"
blueprint_path = "/mnt/c/Users/TTOMCZA.EMEA/Dev/Projektarbeit-MYP/backend/blueprints/admin_unified.py"
analyzer = TemplateAnalyzer(template_path, blueprint_path)
# Durchführung der Analyse
analyzer.analyze_template_endpoints()
analyzer.analyze_blueprint_routes()
analyzer.cross_reference_validation()
analyzer.generate_corrections()
# Generiere Bericht
report = analyzer.generate_report()
print("\n📊 ANALYSEBERICHT")
print("=" * 50)
print(f"Template-Endpoints: {report['summary']['template_endpoints']}")
print(f"Verfügbare Endpoints: {report['summary']['available_endpoints']}")
print(f"Gefundene Probleme: {report['summary']['problems_found']}")
print(f"Generierte Korrekturen: {report['summary']['corrections_generated']}")
if report['problems']:
print("\n❌ GEFUNDENE PROBLEME:")
for i, problem in enumerate(report['problems'], 1):
print(f" {i}. {problem['description']}")
if 'suggestions' in problem:
print(f" Vorschläge: {', '.join(problem['suggestions'])}")
if report['corrections']:
print("\n🔧 EMPFOHLENE KORREKTUREN:")
for i, correction in enumerate(report['corrections'], 1):
print(f" {i}. {correction['description']}")
print(f" Alt: {correction['old_string']}")
print(f" Neu: {correction['new_string']}")
# Speichere Bericht als JSON
with open('/mnt/c/Users/TTOMCZA.EMEA/Dev/Projektarbeit-MYP/backend/template_analysis_report.json', 'w', encoding='utf-8') as f:
json.dump(report, f, indent=2, ensure_ascii=False)
print(f"\n💾 Bericht gespeichert: template_analysis_report.json")
return report
if __name__ == "__main__":
main()

View File

@ -0,0 +1,212 @@
#!/usr/bin/env python3
"""
Erweiterte Template-Problemanalyse für MYP Admin Panel
Vollständige Identifikation aller Template-Probleme mit Kontextanalyse
Autor: MYP Team - Till Tomczak
Datum: 2025-06-19
"""
import re
import json
from typing import Dict, List, Set, Tuple
class AdvancedTemplateAnalyzer:
"""
Erweiterte Template-Problemanalyse mit detaillierter Kontextverarbeitung
"""
def __init__(self):
self.template_path = "/mnt/c/Users/TTOMCZA.EMEA/Dev/Projektarbeit-MYP/backend/templates/admin.html"
self.blueprint_path = "/mnt/c/Users/TTOMCZA.EMEA/Dev/Projektarbeit-MYP/backend/blueprints/admin_unified.py"
self.app_path = "/mnt/c/Users/TTOMCZA.EMEA/Dev/Projektarbeit-MYP/backend/app.py"
self.problems = []
self.corrections = []
self.all_endpoints = set()
def analyze_all_endpoints(self):
"""
Analysiere alle verfügbaren Endpoints aus allen Quellen
"""
print("🔍 Vollständige Endpoint-Analyse")
# 1. Admin Blueprint Endpoints
with open(self.blueprint_path, 'r', encoding='utf-8') as f:
blueprint_content = f.read()
# Admin Blueprint Routen
admin_routes = re.findall(r'@admin_blueprint\.route\(["\']([^"\']+)["\'][^)]*\)\s*@admin_required\s*def\s+([a-zA-Z_][a-zA-Z0-9_]*)', blueprint_content, re.MULTILINE | re.DOTALL)
for route_path, function_name in admin_routes:
self.all_endpoints.add(f"admin.{function_name}")
# Admin API Blueprint Routen
api_routes = re.findall(r'@admin_api_blueprint\.route\(["\']([^"\']+)["\'][^)]*\)\s*@admin_required\s*def\s+([a-zA-Z_][a-zA-Z0-9_]*)', blueprint_content, re.MULTILINE | re.DOTALL)
for route_path, function_name in api_routes:
self.all_endpoints.add(f"admin_api.{function_name}")
# 2. App.py Endpoints (Haupt-Routen)
with open(self.app_path, 'r', encoding='utf-8') as f:
app_content = f.read()
# Haupt-App Routen ohne Blueprint
app_routes = re.findall(r'@app\.route\(["\']([^"\']+)["\'][^)]*\)\s*(?:@[a-zA-Z_][a-zA-Z0-9_]*\s*)*def\s+([a-zA-Z_][a-zA-Z0-9_]*)', app_content, re.MULTILINE | re.DOTALL)
for route_path, function_name in app_routes:
self.all_endpoints.add(function_name)
print(f" ✓ Insgesamt {len(self.all_endpoints)} Endpoints gefunden")
def analyze_template_problems(self):
"""
Analysiere spezifische Template-Probleme
"""
print("\n🔍 Template-Problem-Analyse")
with open(self.template_path, 'r', encoding='utf-8') as f:
template_content = f.read()
# Problem 1: Fehlende Blueprint-Referenz für jobs_page
if "jobs.jobs_page" in template_content:
self.problems.append({
'type': 'incorrect_blueprint_reference',
'line': 179,
'issue': "jobs.jobs_page existiert nicht als Blueprint",
'current': "url_for('jobs.jobs_page')",
'correct': "url_for('jobs_page')",
'description': "Referenz auf jobs_page ohne Blueprint-Prefix"
})
# Problem 2: Überprüfe komplexe url_for Konstrukte
complex_url_pattern = r"url_for\(['\"]([^'\"]+)['\"].*if.*else.*\)"
complex_matches = re.findall(complex_url_pattern, template_content)
for match in complex_matches:
if match not in self.all_endpoints:
self.problems.append({
'type': 'complex_url_for_construct',
'issue': f"Komplexes url_for Konstrukt mit möglicherweise nicht existierendem Endpoint: {match}",
'current': match,
'description': "Komplexe bedingte url_for Referenz"
})
# Problem 3: Überprüfe Parameter-basierte url_for Aufrufe
param_url_pattern = r"url_for\(['\"]([^'\"]+)['\"][^)]+\)"
param_matches = re.findall(param_url_pattern, template_content)
for match in param_matches:
if match not in self.all_endpoints:
self.problems.append({
'type': 'parametrized_url_for',
'issue': f"Parametrisierter url_for Aufruf mit möglicherweise nicht existierendem Endpoint: {match}",
'current': match,
'description': "URL-Parameter-basierte Referenz"
})
print(f"{len(self.problems)} Template-Probleme identifiziert")
def generate_fixes(self):
"""
Generiere konkrete Fixes für alle identifizierten Probleme
"""
print("\n🔧 Fix-Generierung")
with open(self.template_path, 'r', encoding='utf-8') as f:
template_content = f.read()
for problem in self.problems:
if problem['type'] == 'incorrect_blueprint_reference':
# Fix für jobs.jobs_page → jobs_page
old_string = "{{ url_for('jobs.jobs_page') if 'jobs' in url_for.__globals__ else '#' }}"
new_string = "{{ url_for('jobs_page') }}"
if old_string in template_content:
self.corrections.append({
'old_string': old_string,
'new_string': new_string,
'description': 'Korrigiere jobs.jobs_page → jobs_page',
'line': problem.get('line', 'unknown'),
'confidence': 'high'
})
print(f"{len(self.corrections)} Korrekturen generiert")
def generate_detailed_report(self):
"""
Generiere detaillierten Analysebericht
"""
return {
'analysis_summary': {
'total_endpoints': len(self.all_endpoints),
'problems_found': len(self.problems),
'corrections_available': len(self.corrections),
'analysis_scope': ['admin.html', 'admin_unified.py', 'app.py']
},
'endpoints_discovered': sorted(list(self.all_endpoints)),
'problems_identified': self.problems,
'corrections_generated': self.corrections,
'recommendations': [
"Verwende konsistente Blueprint-Referenzen",
"Vermeide komplexe bedingte url_for Konstrukte",
"Überprüfe alle Parameter-basierten URL-Generierungen",
"Implementiere einheitliche Namenskonventionen"
]
}
def main():
"""
Hauptfunktion für erweiterte Template-Analyse
"""
print("🚀 MYP Template-Problemanalyse Tool")
print("=" * 60)
analyzer = AdvancedTemplateAnalyzer()
# Vollständige Analyse
analyzer.analyze_all_endpoints()
analyzer.analyze_template_problems()
analyzer.generate_fixes()
# Generiere detaillierten Bericht
report = analyzer.generate_detailed_report()
print("\n📊 DETAILLIERTER ANALYSEBERICHT")
print("=" * 60)
print(f"Gesamte Endpoints: {report['analysis_summary']['total_endpoints']}")
print(f"Identifizierte Probleme: {report['analysis_summary']['problems_found']}")
print(f"Verfügbare Korrekturen: {report['analysis_summary']['corrections_available']}")
if report['problems_identified']:
print("\n❌ IDENTIFIZIERTE PROBLEME:")
for i, problem in enumerate(report['problems_identified'], 1):
print(f" {i}. {problem['issue']}")
print(f" Typ: {problem['type']}")
if 'line' in problem:
print(f" Zeile: {problem['line']}")
print(f" Aktuell: {problem.get('current', 'N/A')}")
print(f" Korrekt: {problem.get('correct', 'N/A')}")
print()
if report['corrections_generated']:
print("🔧 GENERIERTE KORREKTUREN:")
for i, correction in enumerate(report['corrections_generated'], 1):
print(f" {i}. {correction['description']}")
print(f" Vertrauen: {correction['confidence']}")
print(f" Zeile: {correction['line']}")
print(f" Alt: {correction['old_string']}")
print(f" Neu: {correction['new_string']}")
print()
print("💡 EMPFEHLUNGEN:")
for rec in report['recommendations']:
print(f"{rec}")
# Speichere erweiterten Bericht
with open('/mnt/c/Users/TTOMCZA.EMEA/Dev/Projektarbeit-MYP/backend/template_problem_report.json', 'w', encoding='utf-8') as f:
json.dump(report, f, indent=2, ensure_ascii=False)
print(f"\n💾 Detaillierter Bericht gespeichert: template_problem_report.json")
return report
if __name__ == "__main__":
main()

View File

@ -0,0 +1,226 @@
#!/usr/bin/env python3
"""
Finale Template-Validierung für MYP Admin Panel
Abschließende Verifikation aller Template-Endpoints nach Problembehebeung
Autor: MYP Team - Till Tomczak
Datum: 2025-06-19
"""
import re
import json
from typing import Dict, List, Set, Tuple
class FinalTemplateValidator:
"""
Finale Template-Validierung mit vollständiger Endpoint-Verifikation
"""
def __init__(self):
self.template_path = "/mnt/c/Users/TTOMCZA.EMEA/Dev/Projektarbeit-MYP/backend/templates/admin.html"
self.blueprint_path = "/mnt/c/Users/TTOMCZA.EMEA/Dev/Projektarbeit-MYP/backend/blueprints/admin_unified.py"
self.app_path = "/mnt/c/Users/TTOMCZA.EMEA/Dev/Projektarbeit-MYP/backend/app.py"
self.all_available_endpoints = set()
self.template_references = []
self.validation_results = []
def collect_all_endpoints(self):
"""
Sammle alle verfügbaren Endpoints aus allen Quellen
"""
print("🔍 Vollständige Endpoint-Sammlung")
# 1. Admin Blueprint Endpoints
with open(self.blueprint_path, 'r', encoding='utf-8') as f:
blueprint_content = f.read()
admin_routes = re.findall(
r'@admin_blueprint\.route\(["\']([^"\']+)["\'][^)]*\)\s*@admin_required\s*def\s+([a-zA-Z_][a-zA-Z0-9_]*)',
blueprint_content,
re.MULTILINE | re.DOTALL
)
for route_path, function_name in admin_routes:
self.all_available_endpoints.add(f"admin.{function_name}")
# 2. Admin API Blueprint Endpoints
api_routes = re.findall(
r'@admin_api_blueprint\.route\(["\']([^"\']+)["\'][^)]*\)\s*@admin_required\s*def\s+([a-zA-Z_][a-zA-Z0-9_]*)',
blueprint_content,
re.MULTILINE | re.DOTALL
)
for route_path, function_name in api_routes:
self.all_available_endpoints.add(f"admin_api.{function_name}")
# 3. Haupt-App Endpoints
with open(self.app_path, 'r', encoding='utf-8') as f:
app_content = f.read()
app_routes = re.findall(
r'@app\.route\(["\']([^"\']+)["\'][^)]*\)\s*(?:@[a-zA-Z_][a-zA-Z0-9_]*\s*)*def\s+([a-zA-Z_][a-zA-Z0-9_]*)',
app_content,
re.MULTILINE | re.DOTALL
)
for route_path, function_name in app_routes:
self.all_available_endpoints.add(function_name)
print(f"{len(self.all_available_endpoints)} Endpoints verfügbar")
def extract_template_references(self):
"""
Extrahiere alle url_for Referenzen aus dem Template
"""
print("\n🔍 Template-Referenz-Extraktion")
with open(self.template_path, 'r', encoding='utf-8') as f:
template_content = f.read()
# Finde alle url_for Aufrufe mit Zeilennummern
lines = template_content.split('\n')
for line_num, line in enumerate(lines, 1):
url_for_matches = re.findall(r"url_for\(['\"]([^'\"]+)['\"][^)]*\)", line)
for match in url_for_matches:
self.template_references.append({
'line': line_num,
'endpoint': match,
'context': line.strip()
})
print(f"{len(self.template_references)} Template-Referenzen gefunden")
def validate_all_references(self):
"""
Validiere alle Template-Referenzen gegen verfügbare Endpoints
"""
print("\n🔍 Referenz-Validierung")
valid_count = 0
invalid_count = 0
for ref in self.template_references:
endpoint = ref['endpoint']
is_valid = endpoint in self.all_available_endpoints
result = {
'line': ref['line'],
'endpoint': endpoint,
'is_valid': is_valid,
'context': ref['context']
}
if not is_valid:
# Versuche ähnliche Endpoints zu finden
suggestions = self._find_similar_endpoints(endpoint)
if suggestions:
result['suggestions'] = suggestions
invalid_count += 1
else:
valid_count += 1
self.validation_results.append(result)
print(f" ✅ Gültige Referenzen: {valid_count}")
print(f" ❌ Ungültige Referenzen: {invalid_count}")
return invalid_count == 0
def _find_similar_endpoints(self, target: str) -> List[str]:
"""
Finde ähnliche Endpoints für Vorschläge
"""
suggestions = []
target_parts = target.split('.')
target_func = target_parts[-1] if '.' in target else target
for available in self.all_available_endpoints:
available_parts = available.split('.')
available_func = available_parts[-1] if '.' in available else available
# Exakte Funktionsnamen-Übereinstimmung
if target_func == available_func:
suggestions.append(available)
# Ähnliche Namen
elif target_func in available_func or available_func in target_func:
suggestions.append(available)
return suggestions[:3]
def generate_final_report(self):
"""
Generiere finalen Validierungsbericht
"""
valid_refs = [r for r in self.validation_results if r['is_valid']]
invalid_refs = [r for r in self.validation_results if not r['is_valid']]
return {
'validation_summary': {
'total_endpoints_available': len(self.all_available_endpoints),
'total_template_references': len(self.template_references),
'valid_references': len(valid_refs),
'invalid_references': len(invalid_refs),
'validation_success': len(invalid_refs) == 0
},
'available_endpoints': sorted(list(self.all_available_endpoints)),
'template_references': self.template_references,
'validation_results': self.validation_results,
'invalid_references': invalid_refs,
'validation_status': 'PASSED' if len(invalid_refs) == 0 else 'FAILED'
}
def main():
"""
Finale Template-Validierung
"""
print("🎯 MYP Template-Validierung - Finale Überprüfung")
print("=" * 70)
validator = FinalTemplateValidator()
# Vollständige Validierung
validator.collect_all_endpoints()
validator.extract_template_references()
is_valid = validator.validate_all_references()
# Generiere finalen Bericht
report = validator.generate_final_report()
print("\n📊 FINALE VALIDIERUNGSERGEBNISSE")
print("=" * 70)
print(f"Status: {report['validation_status']}")
print(f"Verfügbare Endpoints: {report['validation_summary']['total_endpoints_available']}")
print(f"Template-Referenzen: {report['validation_summary']['total_template_references']}")
print(f"Gültige Referenzen: {report['validation_summary']['valid_references']}")
print(f"Ungültige Referenzen: {report['validation_summary']['invalid_references']}")
if report['invalid_references']:
print("\n❌ UNGÜLTIGE REFERENZEN:")
for ref in report['invalid_references']:
print(f" • Zeile {ref['line']}: {ref['endpoint']}")
print(f" Kontext: {ref['context']}")
if 'suggestions' in ref:
print(f" Vorschläge: {', '.join(ref['suggestions'])}")
print()
else:
print("\n✅ ALLE TEMPLATE-REFERENZEN SIND GÜLTIG!")
print(" Das Admin-Template ist vollständig korrekt konfiguriert.")
print("\n📋 TEMPLATE-REFERENZEN DETAILS:")
for ref in report['template_references']:
status = "" if ref['endpoint'] in report['available_endpoints'] else ""
print(f" {status} Zeile {ref['line']:3d}: {ref['endpoint']}")
# Speichere finalen Bericht
with open('/mnt/c/Users/TTOMCZA.EMEA/Dev/Projektarbeit-MYP/backend/template_validation_final_report.json', 'w', encoding='utf-8') as f:
json.dump(report, f, indent=2, ensure_ascii=False)
print(f"\n💾 Finaler Validierungsbericht gespeichert: template_validation_final_report.json")
if report['validation_status'] == 'PASSED':
print("\n🎉 TEMPLATE-VALIDIERUNG ERFOLGREICH ABGESCHLOSSEN!")
return True
else:
print("\n⚠️ TEMPLATE-VALIDIERUNG FEHLGESCHLAGEN - Korrekturen erforderlich")
return False
if __name__ == "__main__":
main()