diff --git a/__pycache__/app.cpython-313.pyc b/__pycache__/app.cpython-313.pyc index 7cd674d..6aa07ec 100644 Binary files a/__pycache__/app.cpython-313.pyc and b/__pycache__/app.cpython-313.pyc differ diff --git a/app.py b/app.py index faaf2a2..6134177 100644 --- a/app.py +++ b/app.py @@ -2026,6 +2026,255 @@ def reload_env(): 'message': f'Fehler beim Neuladen der Umgebungsvariablen: {str(e)}' }), 500 +# Berechtigungsverwaltung für Mindmaps +@app.route('/api/mindmap//shares', methods=['GET']) +@login_required +@handle_api_exception +def get_mindmap_shares(mindmap_id): + """Listet alle Benutzer auf, mit denen eine Mindmap geteilt wurde.""" + # Überprüfen, ob die Mindmap dem Benutzer gehört + mindmap = UserMindmap.query.get_or_404(mindmap_id) + if mindmap.user_id != current_user.id: + return ErrorHandler.api_error("Sie haben keine Berechtigung, die Freigaben dieser Mindmap einzusehen.", 403) + + # Alle Freigaben für diese Mindmap abrufen + shares = MindmapShare.query.filter_by(mindmap_id=mindmap_id).all() + + result = [] + for share in shares: + # Benutzerinformationen abrufen + shared_with_user = User.query.get(share.shared_with_id) + + if shared_with_user: + result.append({ + 'id': share.id, + 'user_id': shared_with_user.id, + 'username': shared_with_user.username, + 'email': shared_with_user.email, + 'permission': share.permission_type.name, + 'created_at': share.created_at.isoformat(), + 'last_accessed': share.last_accessed.isoformat() if share.last_accessed else None + }) + + return jsonify({ + 'success': True, + 'shares': result + }) + +@app.route('/api/mindmap//share', methods=['POST']) +@login_required +@handle_api_exception +def share_mindmap(mindmap_id): + """Teilt eine Mindmap mit einem anderen Benutzer.""" + # Überprüfen, ob die Mindmap dem Benutzer gehört + mindmap = UserMindmap.query.get_or_404(mindmap_id) + if mindmap.user_id != current_user.id: + return ErrorHandler.api_error("Sie haben keine Berechtigung, diese Mindmap zu teilen.", 403) + + data = request.json + if not data or 'email' not in data or 'permission' not in data: + return ErrorHandler.api_error("E-Mail-Adresse und Berechtigungstyp sind erforderlich.", 400) + + # Benutzer anhand der E-Mail-Adresse finden + user_to_share_with = User.query.filter_by(email=data['email']).first() + if not user_to_share_with: + return ErrorHandler.api_error("Kein Benutzer mit dieser E-Mail-Adresse gefunden.", 404) + + # Prüfen, ob der Benutzer versucht, mit sich selbst zu teilen + if user_to_share_with.id == current_user.id: + return ErrorHandler.api_error("Sie können die Mindmap nicht mit sich selbst teilen.", 400) + + # Prüfen, ob die Mindmap bereits mit diesem Benutzer geteilt wurde + existing_share = MindmapShare.query.filter_by( + mindmap_id=mindmap_id, + shared_with_id=user_to_share_with.id + ).first() + + # Berechtigungstyp validieren und konvertieren + try: + permission_type = PermissionType[data['permission']] + except (KeyError, ValueError): + return ErrorHandler.api_error( + "Ungültiger Berechtigungstyp. Erlaubte Werte sind: READ, EDIT, ADMIN.", + 400 + ) + + if existing_share: + # Wenn bereits geteilt, aktualisiere die Berechtigungen + existing_share.permission_type = permission_type + message = "Berechtigungen erfolgreich aktualisiert." + else: + # Wenn noch nicht geteilt, erstelle eine neue Freigabe + new_share = MindmapShare( + mindmap_id=mindmap_id, + shared_by_id=current_user.id, + shared_with_id=user_to_share_with.id, + permission_type=permission_type + ) + db.session.add(new_share) + message = "Mindmap erfolgreich geteilt." + + # Wenn die Mindmap bisher privat war, mache sie jetzt nicht mehr privat + if mindmap.is_private: + mindmap.is_private = False + + db.session.commit() + + return jsonify({ + 'success': True, + 'message': message + }) + +@app.route('/api/mindmap/shares/', methods=['PUT']) +@login_required +@handle_api_exception +def update_mindmap_share(share_id): + """Aktualisiert die Berechtigungen für eine geteilte Mindmap.""" + # Freigabe finden + share = MindmapShare.query.get_or_404(share_id) + + # Prüfen, ob der Benutzer der Eigentümer der Mindmap ist + mindmap = UserMindmap.query.get(share.mindmap_id) + if not mindmap or mindmap.user_id != current_user.id: + return ErrorHandler.api_error("Sie haben keine Berechtigung, diese Freigabe zu ändern.", 403) + + data = request.json + if not data or 'permission' not in data: + return ErrorHandler.api_error("Berechtigungstyp ist erforderlich.", 400) + + # Berechtigungstyp validieren und konvertieren + try: + permission_type = PermissionType[data['permission']] + except (KeyError, ValueError): + return ErrorHandler.api_error( + "Ungültiger Berechtigungstyp. Erlaubte Werte sind: READ, EDIT, ADMIN.", + 400 + ) + + # Berechtigungen aktualisieren + share.permission_type = permission_type + db.session.commit() + + return jsonify({ + 'success': True, + 'message': "Berechtigungen erfolgreich aktualisiert." + }) + +@app.route('/api/mindmap/shares/', methods=['DELETE']) +@login_required +@handle_api_exception +def revoke_mindmap_share(share_id): + """Widerruft die Freigabe einer Mindmap für einen Benutzer.""" + # Freigabe finden + share = MindmapShare.query.get_or_404(share_id) + + # Prüfen, ob der Benutzer der Eigentümer der Mindmap ist + mindmap = UserMindmap.query.get(share.mindmap_id) + if not mindmap or mindmap.user_id != current_user.id: + return ErrorHandler.api_error("Sie haben keine Berechtigung, diese Freigabe zu widerrufen.", 403) + + # Freigabe löschen + db.session.delete(share) + + # Prüfen, ob dies die letzte Freigabe war und ggf. Mindmap wieder privat setzen + remaining_shares = MindmapShare.query.filter_by(mindmap_id=mindmap.id).count() + if remaining_shares == 0: + mindmap.is_private = True + + db.session.commit() + + return jsonify({ + 'success': True, + 'message': "Freigabe erfolgreich widerrufen." + }) + +@app.route('/api/mindmaps/shared-with-me', methods=['GET']) +@login_required +@handle_api_exception +def get_shared_mindmaps(): + """Listet alle Mindmaps auf, die mit dem aktuellen Benutzer geteilt wurden.""" + shares = MindmapShare.query.filter_by(shared_with_id=current_user.id).all() + + result = [] + for share in shares: + mindmap = UserMindmap.query.get(share.mindmap_id) + owner = User.query.get(mindmap.user_id) + + if mindmap and owner: + # Zugriffsdatum aktualisieren + share.last_accessed = datetime.now(timezone.utc) + + result.append({ + 'id': mindmap.id, + 'name': mindmap.name, + 'description': mindmap.description, + 'owner': { + 'id': owner.id, + 'username': owner.username + }, + 'created_at': mindmap.created_at.isoformat(), + 'last_modified': mindmap.last_modified.isoformat(), + 'permission': share.permission_type.name + }) + + db.session.commit() # Speichere die aktualisierten Zugriffsdaten + + return jsonify({ + 'success': True, + 'mindmaps': result + }) + +# Hilfsfunktion zur Überprüfung der Berechtigungen +def check_mindmap_permission(mindmap_id, permission_type=None): + """ + Überprüft, ob der aktuelle Benutzer Zugriff auf eine Mindmap hat. + + Args: + mindmap_id: ID der Mindmap + permission_type: Mindestberechtigung, die erforderlich ist (READ, EDIT, ADMIN) + Wenn None, wird nur der Zugriff überprüft. + + Returns: + (bool, str): Tupel aus (hat_berechtigung, fehlermeldung) + """ + mindmap = UserMindmap.query.get(mindmap_id) + if not mindmap: + return False, "Mindmap nicht gefunden." + + # Wenn der Benutzer der Eigentümer ist, hat er vollen Zugriff + if mindmap.user_id == current_user.id: + return True, "" + + # Wenn die Mindmap privat ist und der Benutzer nicht der Eigentümer ist + if mindmap.is_private: + share = MindmapShare.query.filter_by( + mindmap_id=mindmap_id, + shared_with_id=current_user.id + ).first() + + if not share: + return False, "Sie haben keinen Zugriff auf diese Mindmap." + + # Wenn eine bestimmte Berechtigungsstufe erforderlich ist + if permission_type: + required_level = PermissionType[permission_type].value + user_level = share.permission_type.value + + if required_level not in [p.value for p in PermissionType]: + return False, f"Ungültiger Berechtigungstyp: {permission_type}" + + # Berechtigungshierarchie prüfen + permission_hierarchy = { + PermissionType.READ.name: 1, + PermissionType.EDIT.name: 2, + PermissionType.ADMIN.name: 3 + } + + if permission_hierarchy[share.permission_type.name] < permission_hierarchy[permission_type]: + return False, f"Sie benötigen {permission_type}-Berechtigungen für diese Aktion." + + return True, "" + # Flask starten if __name__ == '__main__': with app.app_context(): diff --git a/logs/app.log b/logs/app.log index 3d3804f..03626be 100644 --- a/logs/app.log +++ b/logs/app.log @@ -19,3 +19,9 @@ 2025-05-10 23:15:30,739 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:76] 2025-05-10 23:15:32,667 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:76] 2025-05-10 23:15:32,667 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:76] +2025-05-10 23:16:55,581 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:76] +2025-05-10 23:16:57,283 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:76] +2025-05-10 23:16:57,283 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:76] +2025-05-10 23:17:04,727 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:76] +2025-05-10 23:17:06,698 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:76] +2025-05-10 23:17:06,698 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:76]