First Upload

This commit is contained in:
friloo 2026-07-01 18:26:57 +02:00 committed by GitHub
parent efc6fcbafa
commit c61677d47f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 3921 additions and 0 deletions

304
extension/options.html Normal file
View file

@ -0,0 +1,304 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>OpenNIT Vault &ndash; Einstellungen</title>
<style>
/* ── Reset & Base ──────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
body {
font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-size: 14px;
color: #212529;
background: #f4f6f9;
margin: 0; padding: 0;
min-height: 100vh;
}
/* ── Main navbar (AdminLTE style) ─────────────────────────────────────── */
.main-header {
background: #343a40;
border-bottom: 3px solid #007bff;
padding: 0 1.25rem;
height: 56px;
display: flex;
align-items: center;
gap: 1rem;
position: sticky;
top: 0;
z-index: 100;
box-shadow: 0 2px 6px rgba(0,0,0,.25);
}
.brand-logo {
width: 36px; height: 36px;
border-radius: 6px;
background: none;
display: flex; align-items: center; justify-content: center;
overflow: hidden; flex-shrink: 0;
}
.brand-logo img { width: 26px; height: 26px; object-fit: contain; }
.brand-text {
color: #fff;
font-size: 1rem;
font-weight: 700;
letter-spacing: .01em;
white-space: nowrap;
}
.brand-sep { color: rgba(255,255,255,.35); margin: 0 2px; font-weight: 300; }
.brand-sub { color: #adb5bd; font-weight: 400; font-size: .95rem; }
.header-user {
margin-left: auto;
display: flex;
align-items: center;
gap: .5rem;
color: #dee2e6;
font-size: .82rem;
}
.user-badge {
background: rgba(255,255,255,.1);
border: 1px solid rgba(255,255,255,.15);
border-radius: 20px;
padding: 3px 10px 3px 6px;
display: flex;
align-items: center;
gap: 5px;
font-size: .78rem;
}
.user-dot { width: 7px; height: 7px; background: #28a745; border-radius: 50%; }
/* ── Content wrapper ──────────────────────────────────────────────────── */
.content-wrapper { max-width: 680px; margin: 0 auto; padding: 1.5rem 1.25rem; }
/* ── Card (AdminLTE .card) ───────────────────────────────────────────── */
.card {
background: #fff;
border: none;
border-radius: .35rem;
box-shadow: 0 1px 3px rgba(0,0,0,.08), 0 1px 2px rgba(0,0,0,.06);
margin-bottom: 1.25rem;
}
.card-header {
background: #f8f9fa;
border-bottom: 1px solid #dee2e6;
padding: .75rem 1.25rem;
border-radius: .35rem .35rem 0 0;
display: flex;
align-items: center;
gap: .5rem;
}
.card-header h3 {
margin: 0;
font-size: .9rem;
font-weight: 600;
color: #343a40;
line-height: 1;
}
.card-header .card-tools { margin-left: auto; }
.card-body { padding: 1.25rem; }
/* ── Form controls ───────────────────────────────────────────────────── */
.form-group { margin-bottom: 1rem; }
.form-group:last-child { margin-bottom: 0; }
label.control-label {
display: block;
font-size: .78rem;
font-weight: 700;
color: #6c757d;
text-transform: uppercase;
letter-spacing: .04em;
margin-bottom: .35rem;
}
.form-control {
display: block;
width: 100%;
padding: .45rem .75rem;
font-size: .9rem;
color: #495057;
background: #fff;
border: 1px solid #ced4da;
border-radius: .25rem;
transition: border-color .15s, box-shadow .15s;
}
.form-control:focus {
outline: none;
border-color: #80bdff;
box-shadow: 0 0 0 .2rem rgba(0,123,255,.25);
}
.form-text { font-size: .78rem; color: #6c757d; margin-top: .25rem; line-height: 1.5; }
/* ── Buttons ─────────────────────────────────────────────────────────── */
.btn {
display: inline-flex;
align-items: center;
gap: .35rem;
padding: .4rem .85rem;
font-size: .875rem;
font-weight: 600;
border: 1px solid transparent;
border-radius: .25rem;
cursor: pointer;
transition: background .15s, border-color .15s, color .15s;
text-decoration: none;
}
.btn-primary { background: #007bff; border-color: #007bff; color: #fff; }
.btn-primary:hover { background: #0069d9; border-color: #0062cc; }
.btn-default { background: #fff; border-color: #ced4da; color: #212529; }
.btn-default:hover { background: #f8f9fa; border-color: #adb5bd; }
.btn-sm { padding: .28rem .65rem; font-size: .8rem; }
.btn-group { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; margin-top: .75rem; }
/* ── Alerts ──────────────────────────────────────────────────────────── */
.alert { padding: .65rem 1rem; border-radius: .25rem; font-size: .85rem; margin-top: .75rem; border: 1px solid transparent; }
.alert-success { background: #d4edda; color: #155724; border-color: #c3e6cb; }
.alert-danger { background: #f8d7da; color: #721c24; border-color: #f5c6cb; }
.alert-info { background: #d1ecf1; color: #0c5460; border-color: #bee5eb; }
.save-ok { color: #28a745; font-size: .82rem; font-weight: 600; display: inline-flex; align-items: center; gap: 4px; }
/* ── Spinner ─────────────────────────────────────────────────────────── */
.fa-spin-sm {
display: inline-block;
width: 12px; height: 12px;
border: 2px solid #dee2e6;
border-top-color: #007bff;
border-radius: 50%;
animation: sp .7s linear infinite;
vertical-align: middle;
}
@keyframes sp { to { transform: rotate(360deg); } }
/* ── Steps list ──────────────────────────────────────────────────────── */
.steps-list { list-style: none; margin: 0; padding: 0; }
.steps-list li {
display: flex;
gap: .875rem;
align-items: flex-start;
padding: .5rem 0;
border-bottom: 1px solid #f1f3f5;
font-size: .875rem;
color: #495057;
line-height: 1.55;
}
.steps-list li:last-child { border-bottom: none; padding-bottom: 0; }
.step-badge {
min-width: 22px; height: 22px;
background: #007bff;
color: #fff;
border-radius: 50%;
display: flex; align-items: center; justify-content: center;
font-size: .7rem;
font-weight: 700;
flex-shrink: 0;
margin-top: .15rem;
}
</style>
</head>
<body>
<!-- Main Header -->
<nav class="main-header">
<div class="brand-logo"><img src="icon128.png" alt=""></div>
<span class="brand-text" id="optTitle">OpenNIT Vault</span>
<div class="header-user" id="headerStatus" style="display:none;">
<span class="user-badge">
<span class="user-dot"></span>
<span id="headerUser"></span>
</span>
</div>
</nav>
<div class="content-wrapper">
<!-- Connection card -->
<div class="card">
<div class="card-header">
<h3>Server-Verbindung</h3>
</div>
<div class="card-body">
<div class="form-group">
<label class="control-label" for="serverUrl">Server-URL</label>
<input type="url" class="form-control" id="serverUrl"
placeholder="https://ihre-opennit.firma.de"
value="">
<span class="form-text">Adresse Ihrer OpenNIT-Instanz &ndash; ohne abschlie&szlig;enden Slash.</span>
</div>
<!-- SSO-Anmeldung (empfohlen) -->
<div class="btn-group">
<button class="btn btn-primary" id="btnSso">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:2px;"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/><polyline points="10 17 15 12 10 7"/><line x1="15" y1="12" x2="3" y2="12"/></svg>
Mit OpenNIT anmelden
</button>
<button class="btn btn-default" id="btnLogout" style="display:none;">Abmelden</button>
<span id="ssoMsg"></span>
</div>
<span class="form-text">Empfohlen: Anmeldung wie an OpenNIT (lokal + 2FA / Microsoft 365 / Keycloak). Der Zugang wird automatisch erneuert.</span>
<div id="statusMsg"></div>
<!-- Erweitert: manueller Token -->
<details style="margin-top:1rem;">
<summary style="cursor:pointer;font-size:.82rem;color:#6c757d;font-weight:600;">Erweitert: manueller Token</summary>
<div style="margin-top:.75rem;">
<div class="form-group">
<label class="control-label" for="apiToken">API-Token</label>
<input type="password" class="form-control" id="apiToken"
placeholder="Token aus dem Vault einf&uuml;gen&hellip;">
<span class="form-text">Alternative ohne SSO (z. B. Kiosk/Headless): Vault &rarr; &bdquo;Extension&ldquo; &rarr; Token generieren.</span>
</div>
<div class="btn-group">
<button class="btn btn-default btn-sm" id="btnSave">Token speichern</button>
<button class="btn btn-default btn-sm" id="btnTest">Verbindung testen</button>
<span id="savedMsg"></span>
</div>
</div>
</details>
</div>
</div>
<!-- Security card -->
<div class="card">
<div class="card-header">
<h3>Sicherheit</h3>
</div>
<div class="card-body">
<div class="form-group">
<label class="control-label" for="lockDuration">PIN-Sperre: erneut fragen</label>
<select class="form-control" id="lockDuration">
<option value="5">Nach 5 Minuten</option>
<option value="15">Nach 15 Minuten</option>
<option value="60">Nach 1 Stunde</option>
<option value="session">Bis der Browser geschlossen wird</option>
</select>
<span class="form-text">Ist im Web-Tresor ein <strong>Tresor-PIN</strong> aktiv, verlangt die Erweiterung diesen PIN <strong>serverseitig erzwungen</strong>, damit ein gestohlener Token allein nichts nützt. Diese Einstellung legt nur fest, <em>wie lange</em> eine Entsperrung gilt. Ohne gesetzten Tresor-PIN entfällt die Sperre.</span>
</div>
<div class="form-group">
<label class="control-label"><input type="checkbox" id="clipClear" checked> Zwischenablage nach 30&nbsp;Sekunden leeren</label>
<span class="form-text">Kopierte Passwörter und 2FA-Codes werden nach kurzer Zeit automatisch aus der Zwischenablage entfernt.</span>
</div>
<div class="btn-group">
<button class="btn btn-primary btn-sm" id="btnSaveSec">Speichern</button>
<span id="savedSecMsg"></span>
</div>
</div>
</div>
<!-- Setup card -->
<div class="card">
<div class="card-header">
<h3>Einrichtungsschritte</h3>
</div>
<div class="card-body">
<ul class="steps-list">
<li><span class="step-badge">1</span><span>Öffnen Sie den <strong>Passwort-Vault</strong> in Ihrer OpenNIT-Anwendung.</span></li>
<li><span class="step-badge">2</span><span>Klicken Sie auf <strong>&bdquo;Extension&ldquo;</strong> in der Toolbar und generieren Sie einen API-Token.</span></li>
<li><span class="step-badge">3</span><span>Fügen Sie den Token oben in das Token-Feld ein und klicken Sie auf <strong>Speichern</strong>.</span></li>
<li><span class="step-badge">4</span><span>Fokussieren Sie ein Login-Feld auf einer Website &ndash; Vault-Vorschl&auml;ge erscheinen automatisch.</span></li>
</ul>
</div>
</div>
</div><!-- /.content-wrapper -->
<script src="options.js"></script>
</body>
</html>