161 lines
6.6 KiB
HTML
161 lines
6.6 KiB
HTML
{{template "kopf" .}}
|
|
|
|
<div class="seitenkopf">
|
|
<div class="seitenkopf-titel">
|
|
<h1>Zugänge {{template "hilfelink" "zugaenge"}}</h1>
|
|
<span class="hilfe">Ein eigener Key je Mensch und je Agent. Nur so steht im
|
|
Protokoll, wer etwas geschrieben hat — und ein einzelner Zugang lässt
|
|
sich zurückziehen, ohne alle anderen zu stören.</span>
|
|
</div>
|
|
</div>
|
|
|
|
{{if .Data.NewKey}}
|
|
<div class="karte key-anzeige">
|
|
<strong>Key für „{{.Data.NewKeyName}}“</strong>
|
|
<code class="key-wert">{{.Data.NewKey}}</code>
|
|
<span class="hilfe">Wird nur jetzt angezeigt — gespeichert ist nur eine Prüfsumme.
|
|
Geht der Key verloren, muss ein neuer erzeugt werden.</span>
|
|
|
|
{{/* Drei Clients, drei Schreibweisen für denselben Endpunkt. Der Block steht
|
|
hier ausgeschrieben, weil der Klartext-Key nur auf dieser Seite ein
|
|
einziges Mal zu sehen ist — wer ihn erst aus dem README zusammensetzen
|
|
müsste, hätte ihn dann schon nicht mehr. */}}
|
|
<details class="key-anleitung">
|
|
<summary>MCP-Client einrichten</summary>
|
|
|
|
<strong>Claude Code</strong>
|
|
<pre><code>claude mcp add --transport http munin-{{.Project.Slug}} {{.Data.ServerURL}}/mcp \
|
|
--header "Authorization: Bearer {{.Data.NewKey}}"</code></pre>
|
|
|
|
<strong>Cline</strong> <span class="hilfe">(<code>cline_mcp_settings.json</code>)</span>
|
|
<pre><code>{
|
|
"mcpServers": {
|
|
"munin-{{.Project.Slug}}": {
|
|
"type": "streamableHttp",
|
|
"url": "{{.Data.ServerURL}}/mcp",
|
|
"headers": { "Authorization": "Bearer {{.Data.NewKey}}" },
|
|
"autoApprove": ["recall", "get", "list", "related"]
|
|
}
|
|
}
|
|
}</code></pre>
|
|
|
|
<strong>OpenCode</strong> <span class="hilfe">(<code>opencode.json</code>)</span>
|
|
<pre><code>{
|
|
"mcp": {
|
|
"munin-{{.Project.Slug}}": {
|
|
"type": "remote",
|
|
"url": "{{.Data.ServerURL}}/mcp",
|
|
"enabled": true,
|
|
"headers": { "Authorization": "Bearer {{.Data.NewKey}}" }
|
|
}
|
|
}
|
|
}</code></pre>
|
|
</details>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if .Data.Ungenutzt}}
|
|
<div class="meldung fehler">
|
|
{{if eq .Data.Ungenutzt 1}}Ein aktiver Zugang wurde{{else}}{{.Data.Ungenutzt}} aktive Zugänge wurden{{end}}
|
|
seit über 90 Tagen nicht benutzt. Jeder davon ist ein offener Zugang zu diesem
|
|
Projekt. Wenn niemand mehr weiß, wofür ein Key da ist, ist Zurückziehen meist
|
|
die richtige Wahl — ein neuer ist schnell angelegt.
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if .Data.BaldAbgelaufen}}
|
|
<div class="meldung hinweis">
|
|
{{if eq .Data.BaldAbgelaufen 1}}Ein Zugang läuft{{else}}{{.Data.BaldAbgelaufen}} Zugänge laufen{{end}}
|
|
in den nächsten 14 Tagen ab. Wird er weiter gebraucht: einen neuen anlegen und in den
|
|
Clients austauschen, bevor der alte nicht mehr gilt.
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if .Data.Keys}}
|
|
<div class="tabelle-huelle">
|
|
<table class="tabelle">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Rolle</th>
|
|
<th>Angelegt</th>
|
|
<th>Zuletzt benutzt</th>
|
|
<th>Gültig bis</th>
|
|
<th>Status</th>
|
|
<th class="schmal rechts"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{{$csrf := .CSRFToken}}{{$slug := .Project.Slug}}{{$jetzt := .Data.Jetzt}}
|
|
{{range .Data.Keys}}
|
|
<tr {{if not (.Valid $jetzt)}}class="gedaempft"{{end}}>
|
|
<td>{{.Name}}</td>
|
|
<td><code>{{.Role}}</code></td>
|
|
<td>{{datum .CreatedAt}}</td>
|
|
<td>{{if .LastUsedAt.IsZero}}<span class="hilfe">nie</span>{{else}}{{datum .LastUsedAt}}{{end}}</td>
|
|
<td>{{if .ExpiresAt.IsZero}}<span class="hilfe">unbegrenzt</span>{{else}}{{bisTag .ExpiresAt}}{{end}}</td>
|
|
<td>
|
|
{{if .Revoked}}zurückgezogen{{else if .Expired $jetzt}}abgelaufen{{else}}aktiv{{end}}
|
|
{{if .ExpiresSoon $jetzt}}<span class="marke warnung" title="Läuft in den nächsten 14 Tagen ab">läuft bald ab</span>{{end}}
|
|
{{if .Unused $jetzt}}<span class="marke warnung" title="Seit über 90 Tagen nicht benutzt">ungenutzt</span>{{end}}
|
|
</td>
|
|
<td class="schmal rechts">
|
|
{{if .Valid $jetzt}}
|
|
<form method="POST" action="/p/{{$slug}}/keys/revoke" class="reihe"
|
|
data-confirm="Key „{{.Name}}“ zurückziehen? Alle Clients, die ihn benutzen, verlieren sofort den Zugang.">
|
|
<input type="hidden" name="csrf_token" value="{{$csrf}}">
|
|
<input type="hidden" name="id" value="{{.ID}}">
|
|
<button type="submit" class="warnung">Zurückziehen</button>
|
|
</form>
|
|
{{end}}
|
|
</td>
|
|
</tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{{else}}
|
|
<div class="leer">
|
|
<p>Noch kein Zugang angelegt.</p>
|
|
<p class="hilfe">Ohne Key kann sich niemand mit diesem Projekt verbinden.</p>
|
|
</div>
|
|
{{end}}
|
|
|
|
<section class="abschnitt">
|
|
<h2>Neuer Zugang</h2>
|
|
|
|
<div class="karte">
|
|
<form method="POST" action="/p/{{.Project.Slug}}/keys/create" class="formular">
|
|
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
|
|
|
|
<div class="feld mittel">
|
|
<label for="name">Name</label>
|
|
<span class="hilfe">Wer oder was benutzt diesen Key?</span>
|
|
<input type="text" id="name" name="name" required placeholder="z.B. tom-cline oder ci-pipeline">
|
|
</div>
|
|
|
|
<div class="feld mittel">
|
|
<label for="role">Rolle</label>
|
|
<select id="role" name="role">
|
|
<option value="read">read — nur lesen und suchen</option>
|
|
<option value="write" selected>write — zusätzlich schreiben</option>
|
|
<option value="admin">admin — zusätzlich Zugänge verwalten</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="feld kurz">
|
|
<label for="expires">Gültig bis</label>
|
|
<span class="hilfe">Optional. Leer = unbegrenzt. Gilt bis einschließlich dieses Tages,
|
|
danach wie zurückgezogen. Sinnvoll für Zugänge auf Zeit, etwa für ein Projekt oder
|
|
eine Person, die nur eine Weile dabei ist.</span>
|
|
<input type="date" id="expires" name="expires" min="{{.Data.Heute}}">
|
|
</div>
|
|
|
|
<div class="formular-aktionen">
|
|
<button type="submit">Key erzeugen</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</section>
|
|
|
|
{{template "fuss" .}}
|