- Removed `COMMON_ERRORS.md` file to streamline documentation. - Added `Flask-Limiter` for rate limiting and `redis` for session management in `requirements.txt`. - Expanded `ROADMAP.md` to include completed security features and planned enhancements for version 2.2. - Enhanced `setup_myp.sh` for ultra-secure kiosk installation, including system hardening and security configurations. - Updated `app.py` to integrate CSRF protection and improved logging setup. - Refactored user model to include username and active status for better user management. - Improved job scheduler with uptime tracking and task management features. - Updated various templates for a more cohesive user interface and experience.
135 lines
5.2 KiB
Python
135 lines
5.2 KiB
Python
from flask import Blueprint, request, jsonify, session
|
|
from werkzeug.security import check_password_hash, generate_password_hash
|
|
import subprocess
|
|
import os
|
|
import logging
|
|
|
|
# Logger für Kiosk-Aktivitäten
|
|
kiosk_logger = logging.getLogger('kiosk')
|
|
|
|
# Blueprint erstellen
|
|
kiosk_bp = Blueprint('kiosk', __name__, url_prefix='/api/kiosk')
|
|
|
|
# Sicheres Passwort-Hash für Kiosk-Deaktivierung
|
|
KIOSK_PASSWORD_HASH = generate_password_hash("744563017196A")
|
|
|
|
@kiosk_bp.route('/status', methods=['GET'])
|
|
def get_kiosk_status():
|
|
"""Kiosk-Status abrufen."""
|
|
try:
|
|
# Prüfen ob Kiosk-Modus aktiv ist
|
|
kiosk_active = os.path.exists('/tmp/kiosk_active')
|
|
|
|
return jsonify({
|
|
"active": kiosk_active,
|
|
"message": "Kiosk-Status erfolgreich abgerufen"
|
|
})
|
|
except Exception as e:
|
|
kiosk_logger.error(f"Fehler beim Abrufen des Kiosk-Status: {str(e)}")
|
|
return jsonify({"error": "Fehler beim Abrufen des Status"}), 500
|
|
|
|
|
|
@kiosk_bp.route('/deactivate', methods=['POST'])
|
|
def deactivate_kiosk():
|
|
"""Kiosk-Modus mit Passwort deaktivieren."""
|
|
try:
|
|
data = request.get_json()
|
|
if not data or 'password' not in data:
|
|
return jsonify({"error": "Passwort erforderlich"}), 400
|
|
|
|
password = data['password']
|
|
|
|
# Passwort überprüfen
|
|
if not check_password_hash(KIOSK_PASSWORD_HASH, password):
|
|
kiosk_logger.warning(f"Fehlgeschlagener Kiosk-Deaktivierungsversuch von IP: {request.remote_addr}")
|
|
return jsonify({"error": "Ungültiges Passwort"}), 401
|
|
|
|
# Kiosk deaktivieren
|
|
try:
|
|
# Kiosk-Service stoppen
|
|
subprocess.run(['sudo', 'systemctl', 'stop', 'myp-kiosk'], check=True)
|
|
subprocess.run(['sudo', 'systemctl', 'disable', 'myp-kiosk'], check=True)
|
|
|
|
# Kiosk-Marker entfernen
|
|
if os.path.exists('/tmp/kiosk_active'):
|
|
os.remove('/tmp/kiosk_active')
|
|
|
|
# Normale Desktop-Umgebung wiederherstellen
|
|
subprocess.run(['sudo', 'systemctl', 'set-default', 'graphical.target'], check=True)
|
|
|
|
kiosk_logger.info(f"Kiosk-Modus erfolgreich deaktiviert von IP: {request.remote_addr}")
|
|
|
|
return jsonify({
|
|
"success": True,
|
|
"message": "Kiosk-Modus erfolgreich deaktiviert. System wird neu gestartet."
|
|
})
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
kiosk_logger.error(f"Fehler beim Deaktivieren des Kiosk-Modus: {str(e)}")
|
|
return jsonify({"error": "Fehler beim Deaktivieren des Kiosk-Modus"}), 500
|
|
|
|
except Exception as e:
|
|
kiosk_logger.error(f"Unerwarteter Fehler bei Kiosk-Deaktivierung: {str(e)}")
|
|
return jsonify({"error": "Unerwarteter Fehler"}), 500
|
|
|
|
|
|
@kiosk_bp.route('/activate', methods=['POST'])
|
|
def activate_kiosk():
|
|
"""Kiosk-Modus aktivieren (nur für Admins)."""
|
|
try:
|
|
# Hier könnte eine Admin-Authentifizierung hinzugefügt werden
|
|
|
|
# Kiosk aktivieren
|
|
try:
|
|
# Kiosk-Marker setzen
|
|
with open('/tmp/kiosk_active', 'w') as f:
|
|
f.write('1')
|
|
|
|
# Kiosk-Service aktivieren
|
|
subprocess.run(['sudo', 'systemctl', 'enable', 'myp-kiosk'], check=True)
|
|
subprocess.run(['sudo', 'systemctl', 'start', 'myp-kiosk'], check=True)
|
|
|
|
kiosk_logger.info(f"Kiosk-Modus erfolgreich aktiviert von IP: {request.remote_addr}")
|
|
|
|
return jsonify({
|
|
"success": True,
|
|
"message": "Kiosk-Modus erfolgreich aktiviert"
|
|
})
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
kiosk_logger.error(f"Fehler beim Aktivieren des Kiosk-Modus: {str(e)}")
|
|
return jsonify({"error": "Fehler beim Aktivieren des Kiosk-Modus"}), 500
|
|
|
|
except Exception as e:
|
|
kiosk_logger.error(f"Unerwarteter Fehler bei Kiosk-Aktivierung: {str(e)}")
|
|
return jsonify({"error": "Unerwarteter Fehler"}), 500
|
|
|
|
|
|
@kiosk_bp.route('/restart', methods=['POST'])
|
|
def restart_system():
|
|
"""System neu starten (nur nach Kiosk-Deaktivierung)."""
|
|
try:
|
|
data = request.get_json()
|
|
if not data or 'password' not in data:
|
|
return jsonify({"error": "Passwort erforderlich"}), 400
|
|
|
|
password = data['password']
|
|
|
|
# Passwort überprüfen
|
|
if not check_password_hash(KIOSK_PASSWORD_HASH, password):
|
|
kiosk_logger.warning(f"Fehlgeschlagener Neustart-Versuch von IP: {request.remote_addr}")
|
|
return jsonify({"error": "Ungültiges Passwort"}), 401
|
|
|
|
kiosk_logger.info(f"System-Neustart initiiert von IP: {request.remote_addr}")
|
|
|
|
# System nach kurzer Verzögerung neu starten
|
|
subprocess.Popen(['sudo', 'shutdown', '-r', '+1'])
|
|
|
|
return jsonify({
|
|
"success": True,
|
|
"message": "System wird in 1 Minute neu gestartet"
|
|
})
|
|
|
|
except Exception as e:
|
|
kiosk_logger.error(f"Fehler beim System-Neustart: {str(e)}")
|
|
return jsonify({"error": "Fehler beim Neustart"}), 500 |