Files
root 88fbaa5702 v2.6.1c (Lyra): Admin gebruikersbeheer opnieuw ontworpen + CLI reset
Nieuwe features:
- Admin gebruikerslijst met zoeken/filter op gebruikersnaam en rol
- Profiel bewerken pagina met wachtwoord wijzigen en rol wijzigen
- Nieuwe gebruiker aanmaken via aparte pagina
- CLI commando cli/reset-admin-password.php voor admin wachtword reset + lockout reset

Architectuur:
- /admin/users: lijst met zoekveld, rol filter, bewerk/verwijder acties
- /admin/users-edit?user=<naam>: profiel, wachtwoord, rol, verwijderen
- /admin/users-new: nieuwe gebruiker aanmaken
- AdminAuth::clearLockout() public methode voor CLI gebruik

Documentatie:
- guide/nl/en/admin-beheerder/gebruikers.md herschreven
- 15 nieuwe admin vertaalkeys in NL/EN/DE
- Release notes: docs/release-notes/v2.6.1c.md

Tests:
- Pentest: 30/30 geslaagd, 0 vulnerabilities
- WCAG 2.1 AA: 25/25 geslaagd, 100% compliance
2026-08-17 15:10:40 +00:00

94 lines
5.0 KiB
Twig

{% extends "layouts/admin.twig" %}
{% block title %}{{ ta.users|default('Gebruikers') }} - {{ ta.admin_title|default('CodePress Admin') }}{% endblock %}
{% block content %}
<h2 class="mb-4"><i class="bi bi-people"></i> {{ ta.users|default('Gebruikers') }}</h2>
<div class="card shadow-sm">
<div class="card-header d-flex justify-content-between align-items-center flex-wrap gap-2">
<div class="d-flex align-items-center gap-2">
<i class="bi bi-list"></i> {{ ta.users_list|default('Gebruikerslijst') }}
</div>
<a href="/admin/users-new" class="btn btn-primary btn-sm">
<i class="bi bi-plus-circle"></i> {{ ta.new_user|default('Nieuwe gebruiker') }}
</a>
</div>
<div class="card-body">
<form method="GET" action="/admin/users" class="row g-2 mb-3">
<div class="col-md-6">
<div class="input-group">
<span class="input-group-text"><i class="bi bi-search"></i></span>
<input type="text" class="form-control" name="search" value="{{ search|default('') }}" placeholder="{{ ta.search_users|default('Zoek op gebruikersnaam, e-mail of auteur naam...') }}">
</div>
</div>
<div class="col-md-4">
<select class="form-select" name="role">
<option value="">{{ ta.all_roles|default('Alle rollen') }}</option>
{% for roleKey, roleLabel in roles %}
<option value="{{ roleKey }}" {{ role_filter == roleKey ? 'selected' : '' }}>{{ roleLabel }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-2">
<button type="submit" class="btn btn-outline-primary w-100">
<i class="bi bi-funnel"></i> {{ ta.filter|default('Filteren') }}
</button>
</div>
</form>
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead>
<tr>
<th>{{ ta.username|default('Gebruikersnaam') }}</th>
<th>{{ ta.col_role|default('Rol') }}</th>
<th>{{ ta.login_email|default('Login e-mail') }}</th>
<th>{{ ta.col_created|default('Aangemaakt') }}</th>
<th>{{ ta.col_actions|default('Acties') }}</th>
</tr>
</thead>
<tbody>
{% for username, data in users %}
<tr>
<td>
<i class="bi bi-person-circle"></i>
<a href="/admin/users-edit?user={{ username }}">{{ username }}</a>
{% if username == user.username %}
<span class="badge bg-info">{{ ta.you|default('Jij') }}</span>
{% endif %}
</td>
<td>
<span class="badge bg-{{ data.role == 'admin' ? 'danger' : (data.role == 'content-manager' ? 'primary' : (data.role == 'bi-manager' ? 'success' : 'warning')) }}">
{{ data.role_label|default(data.role) }}
</span>
</td>
<td class="text-muted">{{ data.email|default('-') }}</td>
<td class="text-muted">{{ data.created|default(ta.unknown|default('Onbekend')) }}</td>
<td>
<a href="/admin/users-edit?user={{ username }}" class="btn btn-sm btn-outline-primary" title="{{ ta.edit_profile|default('Profiel bewerken') }}">
<i class="bi bi-pencil"></i>
</a>
{% if username != user.username %}
<form method="POST" action="/admin/users" class="d-inline" onsubmit="return confirm('{{ ta.confirm_delete_user|default('Weet je zeker dat je deze gebruiker wilt verwijderen?') }}')">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="delete_username" value="{{ username }}">
<button type="submit" class="btn btn-sm btn-outline-danger" title="{{ ta.delete|default('Verwijderen') }}">
<i class="bi bi-trash"></i>
</button>
</form>
{% endif %}
</td>
</tr>
{% else %}
<tr>
<td colspan="5" class="text-muted text-center py-4">{{ ta.no_users|default('Geen gebruikers gevonden.') }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}