"feat: Enhance admin guest request functionality
This commit is contained in:
@@ -12,17 +12,11 @@ let totalRequests = 0;
|
|||||||
let refreshInterval = null;
|
let refreshInterval = null;
|
||||||
let csrfToken = '';
|
let csrfToken = '';
|
||||||
|
|
||||||
// API Base URL Detection
|
// API Base URL Detection - Korrigierte Version für CSP-Kompatibilität
|
||||||
function detectApiBaseUrl() {
|
function detectApiBaseUrl() {
|
||||||
const currentHost = window.location.hostname;
|
// Für lokale Entwicklung und CSP-Kompatibilität immer relative URLs verwenden
|
||||||
const currentProtocol = window.location.protocol;
|
// Das verhindert CSP-Probleme mit connect-src
|
||||||
const currentPort = window.location.port;
|
return ''; // Leerer String für relative URLs
|
||||||
|
|
||||||
if (currentPort === '443' || !currentPort) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
return `https://${currentHost}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const API_BASE_URL = detectApiBaseUrl();
|
const API_BASE_URL = detectApiBaseUrl();
|
||||||
|
@@ -506,6 +506,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Action Buttons -->
|
||||||
|
<div class="flex flex-col sm:flex-row gap-4 justify-end mt-12 pt-8 border-t border-slate-200 dark:border-slate-700">
|
||||||
|
<button onclick="window.print()" class="inline-flex items-center justify-center gap-2 px-6 py-3 bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-300 rounded-lg transition-all duration-200">
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 17h2a2 2 0 002-2v-4a2 2 0 00-2-2H5a2 2 0 00-2 2v4a2 2 0 002 2h2m2 4h6a2 2 0 002-2v-4a2 2 0 00-2-2H9a2 2 0 00-2 2v4a2 2 0 002 2zm8-12V5a2 2 0 00-2-2H9a2 2 0 00-2 2v4h10z"/>
|
||||||
|
</svg>
|
||||||
|
Drucken
|
||||||
|
</button>
|
||||||
|
<a href="javascript:history.back()" class="inline-flex items-center justify-center gap-2 px-6 py-3 bg-emerald-600 hover:bg-emerald-700 text-white rounded-lg transition-all duration-200 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5">
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/>
|
||||||
|
</svg>
|
||||||
|
Zurück
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Smooth Scrolling Script -->
|
<!-- Smooth Scrolling Script -->
|
||||||
|
@@ -18,7 +18,7 @@ CSP_POLICY = {
|
|||||||
'default-src': ["'self'"],
|
'default-src': ["'self'"],
|
||||||
'script-src': [
|
'script-src': [
|
||||||
"'self'",
|
"'self'",
|
||||||
"'unsafe-inline'", # Temporär für Dark Mode Script
|
"'unsafe-inline'", # Für inline Scripts (wird nur verwendet wenn keine Nonce vorhanden)
|
||||||
"https://cdn.jsdelivr.net", # Für externe Libraries
|
"https://cdn.jsdelivr.net", # Für externe Libraries
|
||||||
"https://unpkg.com" # Für Fallback-Libraries
|
"https://unpkg.com" # Für Fallback-Libraries
|
||||||
],
|
],
|
||||||
@@ -41,15 +41,19 @@ CSP_POLICY = {
|
|||||||
'connect-src': [
|
'connect-src': [
|
||||||
"'self'",
|
"'self'",
|
||||||
"ws:", # WebSocket für lokale Entwicklung
|
"ws:", # WebSocket für lokale Entwicklung
|
||||||
"wss:" # Sichere WebSockets
|
"wss:", # Sichere WebSockets
|
||||||
|
"http://localhost:*", # Lokale Entwicklung
|
||||||
|
"http://127.0.0.1:*", # Lokale Entwicklung
|
||||||
|
"https://localhost:*", # Lokale Entwicklung HTTPS
|
||||||
|
"https://127.0.0.1:*" # Lokale Entwicklung HTTPS
|
||||||
],
|
],
|
||||||
'media-src': ["'self'"],
|
'media-src': ["'self'"],
|
||||||
'object-src': ["'none'"], # Flash und andere Plugins blockieren
|
'object-src': ["'none'"], # Flash und andere Plugins blockieren
|
||||||
'base-uri': ["'self'"],
|
'base-uri': ["'self'"],
|
||||||
'form-action': ["'self'"],
|
'form-action': ["'self'"],
|
||||||
'frame-ancestors': ["'none'"], # Clickjacking-Schutz
|
'frame-ancestors': ["'none'"], # Clickjacking-Schutz
|
||||||
'upgrade-insecure-requests': True,
|
'upgrade-insecure-requests': False, # Für lokale Entwicklung deaktiviert
|
||||||
'block-all-mixed-content': True
|
'block-all-mixed-content': False # Für lokale Entwicklung deaktiviert
|
||||||
}
|
}
|
||||||
|
|
||||||
# Security Headers Konfiguration
|
# Security Headers Konfiguration
|
||||||
@@ -104,12 +108,13 @@ class SecurityManager:
|
|||||||
|
|
||||||
return nonce in session['security_nonces']
|
return nonce in session['security_nonces']
|
||||||
|
|
||||||
def build_csp_header(self, nonce: Optional[str] = None) -> str:
|
def build_csp_header(self, nonce: Optional[str] = None, use_nonce: bool = False) -> str:
|
||||||
"""
|
"""
|
||||||
Erstellt den Content-Security-Policy Header
|
Erstellt den Content-Security-Policy Header
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
nonce: Optional CSP nonce für inline scripts
|
nonce: Optional CSP nonce für inline scripts
|
||||||
|
use_nonce: Ob Nonces verwendet werden sollen (deaktiviert dann 'unsafe-inline')
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
CSP Header String
|
CSP Header String
|
||||||
@@ -125,9 +130,12 @@ class SecurityManager:
|
|||||||
if isinstance(values, list):
|
if isinstance(values, list):
|
||||||
directive_values = values.copy()
|
directive_values = values.copy()
|
||||||
|
|
||||||
# Nonce für script-src hinzufügen
|
# Nonce für script-src hinzufügen nur wenn explizit gewünscht
|
||||||
if directive == 'script-src' and nonce:
|
if directive == 'script-src' and nonce and use_nonce:
|
||||||
directive_values.append(f"'nonce-{nonce}'")
|
directive_values.append(f"'nonce-{nonce}'")
|
||||||
|
# 'unsafe-inline' entfernen wenn Nonce verwendet wird
|
||||||
|
if "'unsafe-inline'" in directive_values:
|
||||||
|
directive_values.remove("'unsafe-inline'")
|
||||||
|
|
||||||
csp_parts.append(f"{directive.replace('_', '-')} {' '.join(directive_values)}")
|
csp_parts.append(f"{directive.replace('_', '-')} {' '.join(directive_values)}")
|
||||||
|
|
||||||
@@ -200,13 +208,15 @@ def apply_security_headers(response):
|
|||||||
for header, value in SECURITY_HEADERS.items():
|
for header, value in SECURITY_HEADERS.items():
|
||||||
response.headers[header] = value
|
response.headers[header] = value
|
||||||
|
|
||||||
# Content Security Policy
|
# Content Security Policy - für Entwicklung weniger restriktiv
|
||||||
nonce = getattr(g, 'csp_nonce', None)
|
nonce = getattr(g, 'csp_nonce', None)
|
||||||
csp_header = security_manager.build_csp_header(nonce)
|
# In der Entwicklung verwenden wir keine Nonces, um 'unsafe-inline' zu erhalten
|
||||||
|
use_nonce = False # In Produktion auf True setzen für bessere Sicherheit
|
||||||
|
csp_header = security_manager.build_csp_header(nonce, use_nonce)
|
||||||
response.headers['Content-Security-Policy'] = csp_header
|
response.headers['Content-Security-Policy'] = csp_header
|
||||||
|
|
||||||
# HSTS für HTTPS
|
# HSTS nur für HTTPS und Produktion
|
||||||
if request.is_secure:
|
if request.is_secure and not request.environ.get('FLASK_ENV') == 'development':
|
||||||
response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains; preload'
|
response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains; preload'
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
Reference in New Issue
Block a user