update admin und löschung
release-tag / release-image (push) Successful in 1m41s

This commit is contained in:
2026-05-15 09:08:50 +02:00
parent be7bd79fc7
commit 9ee6d3c919
10 changed files with 715 additions and 70 deletions
+91
View File
@@ -0,0 +1,91 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{.Title}} · SEND.NRW Chat</title>
<script src="https://unpkg.com/htmx.org@1.9.12"></script>
<link rel="stylesheet" href="/static/app.css">
</head>
<body>
<div class="shell">
<header class="topbar">
<a class="brand" href="/rooms">SEND.NRW Chat</a>
<form method="post" action="/logout">
<span class="user-pill">{{.Username}} · {{.User.Role}}</span>
<button class="ghost" type="submit">Logout</button>
</form>
</header>
<main class="grid-page">
<section class="hero card">
<div>
<p class="eyebrow">Administration</p>
<h1>Berechtigungen & Aufräumen</h1>
<p class="muted">Admins verwalten Rollen, Raumrechte und die Nachrichten-Retention.</p>
{{if .Notice}}<p class="notice">{{.Notice}}</p>{{end}}
</div>
</section>
<section class="card">
<h2>Benutzerrollen</h2>
<div class="table-list">
{{range .Users}}
<form class="table-row" method="post" action="/admin/users/{{.Username}}/role">
<div><strong>{{.Username}}</strong><br><small>{{.Email}} {{.Subject}}</small></div>
<div><small>Zuletzt: {{formatDateTime .LastSeen}}</small></div>
<select name="role">
{{$current := .Role}}
{{range $.Roles}}<option value="{{.}}" {{if eq . $current}}selected{{end}}>{{.}}</option>{{end}}
</select>
<button type="submit">Speichern</button>
</form>
{{end}}
</div>
</section>
<section class="card">
<h2>Raumrechte</h2>
<p class="muted">Mitglieder gelten bei der Regel <code>members</code>. Moderatoren dürfen member-Räume ebenfalls sehen/schreiben.</p>
<div class="stack">
{{range .Rooms}}
<form class="permission-card" method="post" action="/admin/rooms/{{.ID}}/permissions">
<div>
<h3>{{.Name}}</h3>
<p class="muted">{{.Description}}</p>
</div>
<label>Lesen
<select name="read_access">
{{$read := .ReadAccess}}
{{range $.AccessRules}}<option value="{{.}}" {{if eq . $read}}selected{{end}}>{{.}}</option>{{end}}
</select>
</label>
<label>Schreiben
<select name="write_access">
{{$write := .WriteAccess}}
{{range $.AccessRules}}<option value="{{.}}" {{if eq . $write}}selected{{end}}>{{.}}</option>{{end}}
</select>
</label>
<label>Mitglieder
<input name="members" value="{{join .Members ", "}}" placeholder="jan, anna, max">
</label>
<button type="submit">Rechte speichern</button>
</form>
{{end}}
</div>
</section>
<section class="card">
<h2>Alte Nachrichten löschen</h2>
<form method="post" action="/admin/cleanup" class="two-col-form">
<label>Aufbewahrung in Tagen
<input type="number" min="1" name="retention_days" value="90" required>
</label>
<button type="submit">Ältere Nachrichten löschen</button>
</form>
<p class="muted">Beispiel: 90 löscht alle Nachrichten, die älter als 90 Tage sind.</p>
</section>
</main>
</div>
</body>
</html>
+1 -1
View File
@@ -9,7 +9,7 @@
</head>
<body>
<div class="shell">
<header class="topbar"><a class="brand" href="/rooms">Go HTMX Chat</a></header>
<header class="topbar"><a class="brand" href="/rooms">SEND.NRW Chat</a></header>
<main class="center-card">
<section class="card login-card">
<p class="eyebrow">Willkommen</p>
+8 -2
View File
@@ -12,7 +12,8 @@
<header class="topbar">
<a class="brand" href="/rooms">SEND.NRW Chat</a>
<form method="post" action="/logout">
<span class="user-pill">{{.Username}}</span>
{{if .CanAdmin}}<a class="ghost link-button" href="/admin">Admin</a>{{end}}
<span class="user-pill">{{.Username}} · {{.User.Role}}</span>
<button class="ghost" type="submit">Logout</button>
</form>
</header>
@@ -23,7 +24,8 @@
<p class="eyebrow">Chatraum</p>
<h1>{{.Room.Name}}</h1>
<p class="muted">{{.Room.Description}}</p>
<div class="hint"></div>
<div class="hint">Lesen: {{.Room.ReadAccess}}<br>Schreiben: {{.Room.WriteAccess}}</div>
{{if .Room.Members}}<div class="hint">Mitglieder: {{join .Room.Members ", "}}</div>{{end}}
</aside>
<section class="chat-card card">
@@ -35,10 +37,14 @@
{{end}}
</div>
{{if .CanWrite}}
<form id="message-form" class="message-form" hx-post="/rooms/{{.Room.ID}}/messages" hx-swap="none" hx-on::after-request="if(event.detail.successful) this.reset()">
<input name="body" placeholder="Nachricht schreiben …" autocomplete="off" required maxlength="2000">
<button type="submit">Senden</button>
</form>
{{else}}
<div class="hint">Du hast in diesem Raum nur Leserechte.</div>
{{end}}
</section>
</main>
</div>
+21 -2
View File
@@ -12,7 +12,8 @@
<header class="topbar">
<a class="brand" href="/rooms">SEND.NRW Chat</a>
<form method="post" action="/logout">
<span class="user-pill">{{.Username}}</span>
{{if .CanAdmin}}<a class="ghost link-button" href="/admin">Admin</a>{{end}}
<span class="user-pill">{{.Username}} · {{.User.Role}}</span>
<button class="ghost" type="submit">Logout</button>
</form>
</header>
@@ -21,7 +22,7 @@
<div>
<p class="eyebrow">Räume</p>
<h1>Wähle einen Chatraum</h1>
<p class="muted">Nachrichten werden persistent gespeichert und live per Server-Sent Events verteilt.</p>
<p class="muted">Du siehst nur Räume, für die du Leserechte hast. Schreibrechte werden im Raum geprüft.</p>
</div>
</section>
@@ -30,18 +31,36 @@
<a class="room-card" href="/rooms/{{.ID}}">
<h2>{{.Name}}</h2>
<p>{{.Description}}</p>
<small>Lesen: {{.ReadAccess}} · Schreiben: {{.WriteAccess}}</small>
</a>
{{else}}
<div class="card"><p class="muted">Aktuell ist kein Raum für dich freigegeben.</p></div>
{{end}}
</section>
{{if .CanCreateRoom}}
<section class="card hero">
<h2>Neuen Raum erstellen</h2>
<form hx-post="/rooms" method="post" class="stack two-col-form">
<label>Name<input name="name" placeholder="Projekt Alpha" required minlength="2" maxlength="40"></label>
<label>Beschreibung<input name="description" placeholder="Worum geht es hier?" maxlength="120"></label>
<label>Wer darf sehen?
<select name="read_access">
{{range .AccessRules}}<option value="{{.}}">{{.}}</option>{{end}}
</select>
</label>
<label>Wer darf schreiben?
<select name="write_access">
{{range .AccessRules}}<option value="{{.}}">{{.}}</option>{{end}}
</select>
</label>
<label class="wide">Mitglieder für private Räume
<input name="members" placeholder="jan, anna, max">
</label>
<button type="submit">Raum erstellen</button>
</form>
</section>
{{end}}
</main>
</div>
</body>