Quelltext des aktuellen Standes
<?php $this->layout('layouts/admin', [
'page_title' => 'Vault-Erweiterung',
'current_admin_page' => 'vault-extension',
]); ?>
<div class="settings-page">
<section class="settings-card">
<div class="settings-card-header">
<span class="settings-card-icon">📦</span>
<div>
<h2><?= $this->te('Browser-Erweiterung herunterladen') ?></h2>
<p class="settings-card-desc"><?= $this->te('ZIP herunterladen, entpacken und im Browser als „entpackte Erweiterung" laden. Die Anmeldung erfolgt per SSO – ein manueller Token ist nicht mehr nötig.') ?></p>
</div>
</div>
<div class="settings-card-body">
<a class="btn btn-primary" href="/admin/vault/extension/download">
<i class="fas fa-download"></i> <?= $this->te('Erweiterung als ZIP herunterladen') ?>
</a>
<ol style="margin:1rem 0 0; padding-left:1.2rem; font-size:.9rem; color:var(--gray-700); line-height:1.7;">
<li><?= $this->te('ZIP herunterladen und entpacken.') ?></li>
<li><?= $this->t('Im Browser <code>chrome://extensions</code> (bzw. <code>vivaldi://extensions</code>) öffnen und den <strong>Entwicklermodus</strong> aktivieren.') ?></li>
<li><?= $this->t('<strong>„Entpackte Erweiterung laden"</strong> wählen und den entpackten Ordner auswählen.') ?></li>
<li><?= $this->t('Erweiterungssymbol anklicken und <strong>„Mit OpenNIT anmelden"</strong> – fertig.') ?></li>
</ol>
</div>
</section>
<section class="settings-card">
<div class="settings-card-header">
<span class="settings-card-icon">🧩</span>
<div>
<h2><?= $this->te('SSO & Token-Lebensdauern') ?></h2>
<p class="settings-card-desc"><?= $this->te('Steuert die Anmeldung der Browser-Erweiterung (OAuth 2.0). Standardwerte sind sinnvoll vorbelegt.') ?></p>
</div>
</div>
<div class="settings-card-body">
<form method="POST" action="/admin/vault/extension">
<input type="hidden" name="_csrf" value="<?= $this->csrf() ?>">
<div class="form-group">
<label for="f-1aa9-access_ttl_min"><?= $this->te('Access-Token gültig (Minuten)') ?></label>
<input id="f-1aa9-access_ttl_min" type="number" min="1" max="1440" class="form-control form-control-sm" name="access_ttl_min" value="<?= (int)$access_ttl_min ?>">
<small class="text-muted"><?= $this->te('Kurzlebiges Arbeitstoken. Empfehlung: 15–60.') ?></small>
</div>
<div class="form-group">
<label for="f-1aa9-refresh_ttl_days"><?= $this->te('Refresh-Token gültig (Tage)') ?></label>
<input id="f-1aa9-refresh_ttl_days" type="number" min="1" max="180" class="form-control form-control-sm" name="refresh_ttl_days" value="<?= (int)$refresh_ttl_days ?>">
<small class="text-muted"><?= $this->te('Bestimmt, wie lange ohne erneute Anmeldung gearbeitet werden kann. Rotiert bei jeder Nutzung.') ?></small>
</div>
<div class="form-group">
<label for="f-1aa9-reauth_warn_days"><?= $this->te('Re-Auth-Vorwarnung (Tage vor Ablauf)') ?></label>
<input id="f-1aa9-reauth_warn_days" type="number" min="0" max="60" class="form-control form-control-sm" name="reauth_warn_days" value="<?= (int)$reauth_warn_days ?>">
</div>
<div class="form-group">
<label><?= $this->te('Erlaubte Redirect-URIs (eine pro Zeile)') ?></label>
<textarea class="form-control form-control-sm" name="redirect_uris" rows="3" placeholder="https://<extension-id>.chromiumapp.org/"><?= $this->e($redirect_uris) ?></textarea>
<small class="text-muted">
<?= $this->t('<strong>Leer lassen genügt für die Browser-Erweiterung</strong> – dann ist jede <code>*.chromiumapp.org</code>-Adresse erlaubt. Steht hier etwas, gilt <strong>ausschließlich</strong> das Eingetragene: Die Erweiterung braucht dann eine eigene Zeile, entweder ihre konkrete Adresse (<code>https://<extension-id>.chromiumapp.org/</code>) oder <code>*.chromiumapp.org</code> für alle. Weitere Zeilen für eigene Apps (z. B. <code>opennit://oauth/callback</code>) sind möglich; sie ersetzen den Standard nicht, sondern schalten ihn ab.') ?>
</small>
</div>
<button type="submit" class="btn btn-primary"><?= $this->te('Speichern') ?></button>
</form>
</div>
</section>
<section class="settings-card">
<div class="settings-card-header">
<span class="settings-card-icon">📱</span>
<div>
<h2><?= $this->te('Aktive Erweiterungs-Sitzungen') ?></h2>
<p class="settings-card-desc"><?= $this->te('Per SSO angemeldete Geräte. „Widerrufen" beendet die Sitzung sofort – das Gerät muss sich neu anmelden.') ?></p>
</div>
</div>
<div class="settings-card-body">
<?php if (empty($sessions)): ?>
<div class="empty-state"><?= $this->te('Keine aktiven SSO-Sitzungen.') ?></div>
<?php else: ?>
<div class="table-wrapper">
<table class="data-table">
<thead>
<tr>
<th scope="col"><?= $this->te('Benutzer') ?></th>
<th scope="col"><?= $this->te('Gerät') ?></th>
<th scope="col"><?= $this->te('Zuletzt genutzt') ?></th>
<th scope="col"><?= $this->te('Läuft ab') ?></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<?php foreach ($sessions as $s): ?>
<tr>
<td><?= $this->e($s['display_name'] ?: 'Unbekannt') ?></td>
<td><?= $this->e($s['device_label'] ?: 'Unbekannt') ?></td>
<td><?= !empty($s['last_used']) ? date('d.m.Y H:i', strtotime((string)$s['last_used'])) : '—' ?></td>
<td><?= !empty($s['refresh_expires_at']) ? date('d.m.Y', strtotime((string)$s['refresh_expires_at'])) : '—' ?></td>
<td style="text-align:right;">
<form method="POST" action="/admin/vault/extension/sessions/<?= (int)$s['lineage_id'] ?>/revoke"
onsubmit="return confirm('Diese Sitzung wirklich widerrufen? Das Gerät muss sich neu anmelden.');" style="margin:0;">
<input type="hidden" name="_csrf" value="<?= $this->csrf() ?>">
<button type="submit" class="btn btn-xs btn-danger"><?= $this->te('Widerrufen') ?></button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</section>
</div>