Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2cdf0d2169 |
+66
@@ -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():
|
||||
|
||||
@@ -53,8 +53,11 @@
|
||||
<option value="desc">Absteigend</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button class="btn btn-secondary w-100" onclick="resetFilters()">Filter zurücksetzen</button>
|
||||
<div class="col-md-3">
|
||||
<div class="d-flex gap-2">
|
||||
<button class="btn btn-secondary flex-grow-1" onclick="resetFilters()">Zurücksetzen</button>
|
||||
<button class="btn btn-success flex-grow-1" onclick="exportFilteredUsers()">Exportieren</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2 text-muted small" id="filter-count"></div>
|
||||
@@ -87,14 +90,14 @@
|
||||
Löschen
|
||||
</button>
|
||||
</form>
|
||||
<button type="button" class="btn btn-primary btn-sm"
|
||||
<button type="button" class="btn btn-primary btn-sm"
|
||||
data-username="{{ user.username }}"
|
||||
data-firstname="{{ user.name if user.name else '' }}"
|
||||
data-lastname="{{ user.last_name if user.last_name else '' }}"
|
||||
onclick="openEditUserModal(this)">
|
||||
Bearbeiten
|
||||
</button>
|
||||
<button type="button" class="btn btn-warning btn-sm"
|
||||
<button type="button" class="btn btn-warning btn-sm"
|
||||
onclick="openResetPasswordModal('{{ user.username }}')">
|
||||
Passwort zurücksetzen
|
||||
</button>
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user