diff --git a/Web/app.py b/Web/app.py index ea3ee2e..c3a2d61 100755 --- a/Web/app.py +++ b/Web/app.py @@ -8628,6 +8628,72 @@ def register_csv(): mimetype='application/pdf' ) +@app.route('/export_users_csv', methods=['POST']) +def export_users_csv(): + """ + Exports a filtered list of users to a CSV file. + Receives a JSON array of usernames from the frontend. + """ + if 'username' not in session: + flash('Ihnen ist es nicht gestattet, diese Aktion auszuführen.', 'error') + return redirect(url_for('login')) + + usernames_json = request.form.get('usernames') + if not usernames_json: + flash('Keine Benutzer zum Exportieren ausgewählt.', 'error') + return redirect(url_for('user_del')) + + try: + target_usernames = json.loads(usernames_json) + except json.JSONDecodeError: + flash('Ungültige Daten beim Export übermittelt.', 'error') + return redirect(url_for('user_del')) + + # Fetch all users + all_users = us.get_all_users() + + # Create CSV in memory + si = io.StringIO() + # Delimiter set to semicolon (standard for Excel in German locales) + cw = csv.writer(si, delimiter=';') + + # Write headers + cw.writerow(['Benutzername', 'Vorname', 'Nachname', 'Administrator', 'Rechte-Preset']) + + for user in all_users: + encrypted_username = user.get('Username') + if not encrypted_username: + continue + + uname = decrypt_text(encrypted_username) + + # Only process users that were present in the frontend's filtered view + if uname in target_usernames: + try: + permissions_payload = us.get_effective_permissions(uname) + preset = permissions_payload.get('preset', 'standard_user') + except Exception: + preset = 'standard_user' + + try: + name = us.get_name(uname) or "" + last_name = us.get_last_name(uname) or "" + except Exception: + name = "" + last_name = "" + + admin_status = "Ja" if user.get('Admin', False) else "Nein" + + cw.writerow([uname, name, last_name, admin_status, preset]) + + # Prefix with BOM (Byte Order Mark) to ensure Excel reads UTF-8 (Umlauts) correctly + output = '\ufeff' + si.getvalue() + + return Response( + output, + mimetype="text/csv", + headers={"Content-disposition": "attachment; filename=benutzer_export.csv"} + ) @app.route('/user_del', methods=['GET']) def user_del(): diff --git a/Web/templates/user_del.html b/Web/templates/user_del.html index 1a86909..e6d49e1 100755 --- a/Web/templates/user_del.html +++ b/Web/templates/user_del.html @@ -53,8 +53,11 @@ -
- +
+
+ + +
@@ -87,14 +90,14 @@ Löschen - - @@ -313,6 +316,48 @@ applyFilters(); } + function exportFilteredUsers() { + var table = document.getElementById('user-table'); + var tbody = table.querySelector('tbody'); + var rows = Array.from(tbody.querySelectorAll('tr')); + + var visibleUsernames = []; + + // Sammle alle Benutzernamen, die durch den Filter aktuell NICHT versteckt sind + rows.forEach(function(row) { + if (row.style.display !== 'none') { + var cells = row.querySelectorAll('td'); + if (cells.length > 0) { + // Der Benutzername ist in der ersten Spalte (Index 0) + visibleUsernames.push(cells[0].textContent.trim()); + } + } + }); + + if (visibleUsernames.length === 0) { + alert('Keine Benutzer zum Exportieren vorhanden.'); + return; + } + + // Dynamisches Formular erstellen, um die gefilterten Daten per POST ans Backend zu senden + var form = document.createElement('form'); + form.method = 'POST'; + form.action = "{{ url_for('export_users_csv') }}"; // Passe dies ggf. an deinen Endpunktnamen an + + var input = document.createElement('input'); + input.type = 'hidden'; + input.name = 'usernames'; + input.value = JSON.stringify(visibleUsernames); + + form.appendChild(input); + document.body.appendChild(form); + + form.submit(); + + // Aufräumen + document.body.removeChild(form); + } + document.addEventListener('DOMContentLoaded', function() { applyFilters(); document.getElementById('filter-search').addEventListener('input', applyFilters); @@ -332,12 +377,12 @@ var username = button.getAttribute('data-username'); var name = button.getAttribute('data-firstname'); var lastName = button.getAttribute('data-lastname'); - + document.getElementById('edit-username').value = username; document.getElementById('edit-username-display').value = username; document.getElementById('edit-name').value = name; document.getElementById('edit-last-name').value = lastName; - + var modal = new bootstrap.Modal(document.getElementById('editUserModal')); modal.show(); } @@ -345,8 +390,7 @@ function openResetPasswordModal(username) { document.getElementById('reset-username').value = username; document.getElementById('username-display').value = username; - - // Open modal using Bootstrap + var modal = new bootstrap.Modal(document.getElementById('resetPasswordModal')); modal.show(); }