fieldwitness/frontends/web/templates/setup_recovery.html
Aaron D. Lee 490f9d4a1d Rebrand SooSeF to FieldWitness
Complete project rebrand for better positioning in the press freedom
and digital security space. FieldWitness communicates both field
deployment and evidence testimony — appropriate for the target audience
of journalists, NGOs, and human rights organizations.

Rename mapping:
- soosef → fieldwitness (package, CLI, all imports)
- soosef.stegasoo → fieldwitness.stego
- soosef.verisoo → fieldwitness.attest
- ~/.soosef/ → ~/.fwmetadata/ (innocuous data dir name)
- SOOSEF_DATA_DIR → FIELDWITNESS_DATA_DIR
- SoosefConfig → FieldWitnessConfig
- SoosefError → FieldWitnessError

Also includes:
- License switch from MIT to GPL-3.0
- C2PA bridge module (Phase 0-2 MVP): cert.py, export.py, vendor_assertions.py
- README repositioned to lead with provenance/federation, stego backgrounded
- Threat model skeleton at docs/security/threat-model.md
- Planning docs: docs/planning/c2pa-integration.md, docs/planning/gtm-feasibility.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 15:05:13 -04:00

178 lines
7.1 KiB
HTML

{% extends "base.html" %}
{% block title %}Recovery Key Setup - Stego{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-md-8 col-lg-6">
<div class="card">
<div class="card-header text-center">
<i class="bi bi-shield-lock fs-1 d-block mb-2"></i>
<h5 class="mb-0">Recovery Key Setup</h5>
<small class="text-muted">Step 2 of 2</small>
</div>
<div class="card-body">
<!-- Explanation -->
<div class="alert alert-info">
<i class="bi bi-info-circle me-2"></i>
<strong>What is a recovery key?</strong><br>
If you forget your admin password, this key is the ONLY way to reset it.
Save it somewhere safe - it will not be shown again.
</div>
<!-- Recovery Key Display -->
<div class="mb-4">
<label class="form-label">
<i class="bi bi-key-fill me-1"></i> Your Recovery Key
</label>
<div class="input-group">
<input type="text" class="form-control font-monospace text-center"
id="recoveryKey" value="{{ recovery_key }}" readonly
style="font-size: 1.1em; letter-spacing: 0.5px;">
<button class="btn btn-outline-secondary" type="button"
onclick="copyToClipboard()" title="Copy to clipboard">
<i class="bi bi-clipboard" id="copyIcon"></i>
</button>
</div>
</div>
<!-- QR Code (if available) -->
{% if qr_base64 %}
<div class="mb-4 text-center">
<label class="form-label d-block">
<i class="bi bi-qr-code me-1"></i> QR Code
</label>
<img src="data:image/png;base64,{{ qr_base64 }}"
alt="Recovery Key QR Code" class="img-fluid border rounded"
style="max-width: 200px;" id="qrImage">
<div class="mt-2">
<small class="text-muted">Scan with your phone's camera app</small>
</div>
</div>
{% endif %}
<!-- Download Options -->
<div class="mb-4">
<label class="form-label">
<i class="bi bi-download me-1"></i> Download Options
</label>
<div class="d-flex gap-2 flex-wrap">
<button class="btn btn-outline-primary btn-sm" onclick="downloadTextFile()">
<i class="bi bi-file-text me-1"></i> Text File
</button>
{% if qr_base64 %}
<button class="btn btn-outline-primary btn-sm" onclick="downloadQRImage()">
<i class="bi bi-image me-1"></i> QR Image
</button>
{% endif %}
</div>
</div>
<hr>
<!-- Confirmation Form -->
<form method="POST" id="recoveryForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<input type="hidden" name="recovery_key" value="{{ recovery_key }}">
<!-- Confirm checkbox -->
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" id="confirmSaved"
onchange="updateButtons()">
<label class="form-check-label" for="confirmSaved">
I have saved my recovery key in a secure location
</label>
</div>
<div class="d-flex gap-2 justify-content-between">
<!-- Skip button (no recovery) -->
<button type="submit" name="action" value="skip"
class="btn btn-outline-secondary"
onclick="return confirm('Are you sure? Without a recovery key, there is NO way to reset your password if you forget it.')">
<i class="bi bi-skip-forward me-1"></i> Skip (No Recovery)
</button>
<!-- Save button (with key) -->
<button type="submit" name="action" value="save"
class="btn btn-primary" id="saveBtn" disabled>
<i class="bi bi-check-lg me-1"></i> Continue
</button>
</div>
</form>
</div>
</div>
<!-- Security Notes -->
<div class="card mt-3">
<div class="card-header">
<i class="bi bi-shield-check me-2"></i>Security Notes
</div>
<div class="card-body small">
<ul class="mb-0">
<li>The recovery key is <strong>not stored</strong> - only a hash is saved</li>
<li>Keep it separate from your password (different location)</li>
<li>Anyone with this key can reset admin passwords</li>
<li>If you lose it and forget your password, you must recreate the database</li>
</ul>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
// Copy recovery key to clipboard
function copyToClipboard() {
const keyInput = document.getElementById('recoveryKey');
navigator.clipboard.writeText(keyInput.value).then(() => {
const icon = document.getElementById('copyIcon');
icon.className = 'bi bi-clipboard-check';
setTimeout(() => { icon.className = 'bi bi-clipboard'; }, 2000);
});
}
// Download as text file
function downloadTextFile() {
const key = document.getElementById('recoveryKey').value;
const content = `Stego Recovery Key
=====================
${key}
IMPORTANT:
- Keep this file in a secure location
- Anyone with this key can reset admin passwords
- Do not store with your password
Generated: ${new Date().toISOString()}
`;
const blob = new Blob([content], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'stego-recovery-key.txt';
a.click();
URL.revokeObjectURL(url);
}
// Download QR as image
function downloadQRImage() {
const img = document.getElementById('qrImage');
if (!img) return;
const a = document.createElement('a');
a.href = img.src;
a.download = 'stego-recovery-qr.png';
a.click();
}
// Enable save button when checkbox is checked
function updateButtons() {
const checkbox = document.getElementById('confirmSaved');
const saveBtn = document.getElementById('saveBtn');
saveBtn.disabled = !checkbox.checked;
}
</script>
{% endblock %}