Security: never send API keys via email, add browser-based recovery UI, adjust rate limits
Investor Directive 1: Key recovery now shows key in browser after email verification code. - Removed sendRecoveryEmail function entirely - Recovery endpoint returns apiKey in JSON response (shown once in browser) - Added full recovery modal UI (email → code → key displayed) - Added "Lost your API key?" links throughout signup flow Investor Directive 3: Rate limits adjusted to match server capacity. - Global rate limit: 100/min → 30/min (server handles ~28 PDFs/min) - CORS: recover routes now restricted to docfast.dev origin
This commit is contained in:
parent
1af1b07fb3
commit
a177020186
5 changed files with 217 additions and 32 deletions
|
|
@ -188,6 +188,13 @@ html, body {
|
|||
overflow-x: hidden !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Recovery modal states */
|
||||
#recoverInitial, #recoverLoading, #recoverVerify, #recoverResult { display: none; }
|
||||
#recoverInitial.active { display: block; }
|
||||
#recoverLoading.active { display: flex; flex-direction: column; align-items: center; padding: 40px 0; text-align: center; }
|
||||
#recoverResult.active { display: block; }
|
||||
#recoverVerify.active { display: block; }
|
||||
</style>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
|
|
@ -349,7 +356,7 @@ html, body {
|
|||
<div class="signup-error" id="signupError"></div>
|
||||
<input type="email" id="signupEmail" placeholder="your.email@example.com" style="width:100%;padding:12px;border:1px solid var(--border);background:var(--bg);color:var(--fg);border-radius:8px;font-size:0.9rem;margin-bottom:16px;" required>
|
||||
<button class="btn btn-primary" style="width:100%" id="signupBtn">Generate API Key →</button>
|
||||
<p style="margin-top:16px;color:var(--muted);font-size:0.8rem;text-align:center;">100 free PDFs/month • All endpoints included</p>
|
||||
<p style="margin-top:16px;color:var(--muted);font-size:0.8rem;text-align:center;">100 free PDFs/month • All endpoints included<br><a href="#" class="open-recover" style="color:var(--muted)">Lost your API key? Recover it →</a></p>
|
||||
</div>
|
||||
|
||||
<div id="signupLoading">
|
||||
|
|
@ -370,7 +377,7 @@ html, body {
|
|||
<h2>🚀 Your API key is ready!</h2>
|
||||
<div class="warning-box">
|
||||
<span class="icon">⚠️</span>
|
||||
<span>Save your API key securely. Lost it? <a href="#" onclick="document.getElementById('recover-section').scrollIntoView()" style="color:#fbbf24">Recover via email</a></span>
|
||||
<span>Save your API key securely. Lost it? <a href="#" class="open-recover" style="color:#fbbf24">Recover via email</a></span>
|
||||
</div>
|
||||
<div style="background:var(--bg);border:1px solid var(--accent);border-radius:8px;padding:14px;font-family:monospace;font-size:0.82rem;word-break:break-all;margin:16px 0;position:relative;">
|
||||
<span id="apiKeyText"></span>
|
||||
|
|
@ -381,6 +388,50 @@ html, body {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Recovery Modal -->
|
||||
<div class="modal-overlay" id="recoverModal">
|
||||
<div class="modal">
|
||||
<button class="close" id="btn-close-recover">×</button>
|
||||
|
||||
<div id="recoverInitial" class="active">
|
||||
<h2>Recover your API key</h2>
|
||||
<p>Enter the email you signed up with. We'll send a verification code.</p>
|
||||
<div class="signup-error" id="recoverError"></div>
|
||||
<input type="email" id="recoverEmailInput" placeholder="your.email@example.com" style="width:100%;padding:12px;border:1px solid var(--border);background:var(--bg);color:var(--fg);border-radius:8px;font-size:0.9rem;margin-bottom:16px;" required>
|
||||
<button class="btn btn-primary" style="width:100%" id="recoverBtn">Send Verification Code →</button>
|
||||
<p style="margin-top:16px;color:var(--muted);font-size:0.8rem;text-align:center;">Your key will be shown here after verification — never sent via email</p>
|
||||
</div>
|
||||
|
||||
<div id="recoverLoading">
|
||||
<div class="spinner"></div>
|
||||
<p style="color:var(--muted);margin:0">Sending verification code…</p>
|
||||
</div>
|
||||
|
||||
<div id="recoverVerify">
|
||||
<h2>Enter verification code</h2>
|
||||
<p>We sent a 6-digit code to <strong id="recoverEmailDisplay"></strong></p>
|
||||
<div class="signup-error" id="recoverVerifyError"></div>
|
||||
<input type="text" id="recoverCode" placeholder="123456" maxlength="6" pattern="[0-9]{6}" inputmode="numeric" style="width:100%;padding:14px;border:1px solid var(--border);background:var(--bg);color:var(--fg);border-radius:8px;font-size:1.4rem;letter-spacing:0.3em;text-align:center;margin-bottom:16px;font-family:monospace;" required>
|
||||
<button class="btn btn-primary" style="width:100%" id="recoverVerifyBtn">Verify →</button>
|
||||
<p style="margin-top:16px;color:var(--muted);font-size:0.8rem;text-align:center;">Code expires in 15 minutes</p>
|
||||
</div>
|
||||
|
||||
<div id="recoverResult">
|
||||
<h2>🔑 Your API key</h2>
|
||||
<div class="warning-box">
|
||||
<span class="icon">⚠️</span>
|
||||
<span>Save your API key securely. This is the only time it will be shown.</span>
|
||||
</div>
|
||||
<div style="background:var(--bg);border:1px solid var(--accent);border-radius:8px;padding:14px;font-family:monospace;font-size:0.82rem;word-break:break-all;margin:16px 0;position:relative;">
|
||||
<span id="recoveredKeyText"></span>
|
||||
<button onclick="copyRecoveredKey()" id="copyRecoveredBtn" style="position:absolute;top:8px;right:8px;background:var(--accent);color:var(--bg);border:none;border-radius:4px;padding:4px 12px;cursor:pointer;font-size:0.8rem;">Copy</button>
|
||||
</div>
|
||||
<p style="margin-top:20px;color:var(--muted);font-size:0.9rem;"><a href="/docs">Read the docs →</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue