Umut hat den Namen festgelegt: aus dem Arbeitstitel "Kant CMS" wird KantSites. Geändert in allen Seitentiteln der Verwaltung, im Wortmarken-Schriftzug von Anmeldung und Seitenleiste, in den Fußzeilen, in den Demoinhalten für eine frische Installation, in package.json, .claude/launch.json und der Dokumentation. Die Bezeichnung der Website in der Datenbank heißt jetzt ebenfalls KantSites. Nicht angefasst: die bereits gespeicherten Demoinhalte der lokalen Installation. Titel wie "Die Grundlage · Kant CMS" und der Text im Kopfbereich sind Inhalt, nicht Systemname - die gehören in den Editor, nicht in ein Skript, das Revisionen umschreibt. 219 PHP-Tests / 881 Assertions grün, Playwright-Editortest grün. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
111 lines
7.0 KiB
Twig
111 lines
7.0 KiB
Twig
{% extends 'admin/shell.html.twig' %}
|
||
{% set nav = 'users' %}
|
||
{% block title %}Benutzer{% endblock %}
|
||
{% block heading %}Benutzer{% endblock %}
|
||
{% block lead %}Jedes Konto hat genau eine Rolle. Ein Passwort oder eine Rolle zu ändern meldet alle offenen Sitzungen dieses Kontos ab – das ist der Weg, jemanden sofort auszusperren.{% endblock %}
|
||
{% block content %}
|
||
|
||
<details class="card"{% if app.flashes is not empty %} open{% endif %}>
|
||
<summary>Neues Konto anlegen</summary>
|
||
<form action="{{ path('admin_user_create') }}" method="post" class="card-body">
|
||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('users') }}">
|
||
<div class="fields">
|
||
<div>
|
||
<label for="new-username">Benutzername</label>
|
||
<input id="new-username" name="username" maxlength="100" required autocomplete="off" pattern="[a-z0-9][a-z0-9._-]{2,99}">
|
||
<p class="field-help">3 bis 100 Zeichen: Kleinbuchstaben, Ziffern, Punkt, Unterstrich, Bindestrich.</p>
|
||
</div>
|
||
<div>
|
||
<label for="new-password">Passwort</label>
|
||
<input id="new-password" name="password" type="password" required autocomplete="new-password" minlength="{{ minPassword }}" maxlength="{{ maxPassword }}">
|
||
<p class="field-help">Mindestens {{ minPassword }} Zeichen, höchstens {{ maxPassword }} Bytes. Gib es der Person auf einem anderen Weg als per E-Mail weiter; sie kann es unter „Mein Konto“ selbst ändern.</p>
|
||
</div>
|
||
<div>
|
||
<label for="new-role">Rolle</label>
|
||
<select id="new-role" name="role">
|
||
{% for value, label in roles %}<option value="{{ value }}"{{ value == 'ROLE_EDITOR' ? ' selected' : '' }}>{{ label }}</option>{% endfor %}
|
||
</select>
|
||
<p class="field-help">{% for value, help in roleHelp %}<strong>{{ roles[value] }}:</strong> {{ help }}{% if not loop.last %}<br>{% endif %}{% endfor %}</p>
|
||
</div>
|
||
</div>
|
||
<button class="primary" type="submit">Konto anlegen</button>
|
||
</form>
|
||
</details>
|
||
|
||
<div class="section-head"><h2>Konten <span class="count">{{ users|length }}</span></h2><span class="muted">Zeiten in UTC.</span></div>
|
||
<div class="rows">
|
||
{% for account in users %}
|
||
<article class="row row-stack">
|
||
<div class="row-line">
|
||
<span class="row-icon" aria-hidden="true">☺</span>
|
||
<div class="row-main">
|
||
<h3>{{ account.username }}{% if account.id == me %} <span class="pill">dein Konto</span>{% endif %}</h3>
|
||
<p>{{ account.roleName }}
|
||
· {% if account.lastLoginAt %}zuletzt angemeldet {{ account.lastLoginAt|date('d.m.Y H:i') }}{% else %}noch nie angemeldet{% endif %}
|
||
{% if account.passwordChangedAt %} · Passwort vom {{ account.passwordChangedAt|date('d.m.Y') }}{% endif %}
|
||
{% if account.createdAt %} · angelegt {{ account.createdAt|date('d.m.Y') }}{% endif %}
|
||
</p>
|
||
</div>
|
||
<span class="pill {{ 'ROLE_ADMIN' == account.role ? 'pill-live' : ('ROLE_PUBLISHER' == account.role ? 'pill-draft' : 'pill-off') }}">{{ account.roleName }}</span>
|
||
</div>
|
||
<details class="sheet">
|
||
<summary aria-label="Einstellungen von {{ account.username }}">Einstellungen</summary>
|
||
<div class="sheet-body">
|
||
<div class="sheet-part">
|
||
<h4>Rolle</h4>
|
||
{% if account.id == me %}
|
||
<p>Die eigene Rolle lässt sich hier nicht ändern. Das soll ein zweiter Administrator tun – sonst kann sich der letzte Administrator selbst die Rechte nehmen.</p>
|
||
{% else %}
|
||
<form action="{{ path('admin_user_role', {id: account.id}) }}" method="post">
|
||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('users') }}">
|
||
<div class="field">
|
||
<label for="role-{{ account.id }}">Rolle von {{ account.username }}</label>
|
||
<select id="role-{{ account.id }}" name="role">
|
||
{% for value, label in roles %}<option value="{{ value }}"{{ value == account.role ? ' selected' : '' }}>{{ label }}</option>{% endfor %}
|
||
</select>
|
||
<p class="field-help">Offene Sitzungen dieses Kontos werden dabei abgemeldet.</p>
|
||
</div>
|
||
<button class="secondary" type="submit">Rolle ändern</button>
|
||
</form>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<div class="sheet-part">
|
||
<h4>Passwort setzen</h4>
|
||
<p>Setzt ein neues Passwort, ohne das alte zu kennen – für den Fall, dass jemand nicht mehr hineinkommt. Alle offenen Sitzungen dieses Kontos werden abgemeldet.</p>
|
||
<form action="{{ path('admin_user_password', {id: account.id}) }}" method="post">
|
||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('users') }}">
|
||
<div class="field">
|
||
<label for="password-{{ account.id }}">Neues Passwort für {{ account.username }}</label>
|
||
<input id="password-{{ account.id }}" name="password" type="password" required autocomplete="new-password" minlength="{{ minPassword }}" maxlength="{{ maxPassword }}">
|
||
</div>
|
||
<button class="secondary" type="submit">Passwort setzen</button>
|
||
</form>
|
||
</div>
|
||
|
||
{% if account.id != me %}
|
||
<div class="sheet-part">
|
||
<h4>Konto löschen</h4>
|
||
<p>Entfernt „{{ account.username }}“. Gespeicherte Inhalte bleiben unberührt – Seiten und Fassungen hängen nicht am Konto. Das eigene Konto lässt sich nicht löschen; deshalb bleibt immer mindestens ein Administrator übrig.</p>
|
||
<form action="{{ path('admin_user_delete', {id: account.id}) }}" method="post">
|
||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('users') }}">
|
||
<button class="subtle danger-text" type="submit">Konto löschen</button>
|
||
</form>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</details>
|
||
</article>
|
||
{% endfor %}
|
||
</div>
|
||
|
||
<div class="card">
|
||
<div class="card-head"><h2>Wenn kein Konto mehr funktioniert</h2><span class="muted">Zugang über die Konsole</span></div>
|
||
<div class="card-body">
|
||
<p class="muted">Auf dem Server legt <code>php bin/console cms:user:create name --role=admin</code> ein Konto an; das Passwort wird verdeckt abgefragt und ein vorhandenes Konto nie überschrieben. Das ist der Weg zurück, wenn niemand mehr hineinkommt – er braucht Dateizugriff auf den Server und lässt sich hier nicht ersetzen.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<p class="footnote">KantSites · Arbeitsstand</p>
|
||
{% endblock %}
|