carolina.
This commit is contained in:
parent
e7f0e4ac1b
commit
d4e5497406
@ -1,93 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Add Device - Passkey Authentication</title>
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
<script src="/static/simplewebauthn-browser.min.js"></script>
|
||||
<script src="/static/qrcodejs/qrcode.min.js"></script>
|
||||
<script src="/static/awaitable-websocket.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<!-- Device Addition View -->
|
||||
<div id="deviceAdditionView" class="view active">
|
||||
<h1>📱 Add Device</h1>
|
||||
<div id="deviceAdditionStatus"></div>
|
||||
|
||||
<div id="deviceLinkSection">
|
||||
<h2>Device Addition Link</h2>
|
||||
<div class="token-info">
|
||||
<p><strong>Share this link to add this account to another device:</strong></p>
|
||||
|
||||
<div class="qr-container">
|
||||
<div id="qrCode" class="qr-code"></div>
|
||||
<p><small>Scan this QR code with your other device</small></p>
|
||||
</div>
|
||||
|
||||
<div class="link-container">
|
||||
<p class="link-text" id="deviceLinkText">Loading...</p>
|
||||
<button class="copy-button" onclick="copyDeviceLink()">Copy Link</button>
|
||||
</div>
|
||||
|
||||
<p><small>⚠️ This link expires in 24 hours and can only be used once.</small></p>
|
||||
<p><strong>Human-readable code:</strong> <code id="deviceToken"></code></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button onclick="window.location.href='/auth/profile'" class="btn-secondary">
|
||||
Back to Profile
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/static/app.js"></script>
|
||||
<script>
|
||||
// Initialize the device addition view when page loads
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
initializeApp();
|
||||
// Auto-generate device link when page loads
|
||||
generateDeviceLink();
|
||||
});
|
||||
|
||||
// Generate device link function
|
||||
function generateDeviceLink() {
|
||||
clearStatus('deviceAdditionStatus');
|
||||
showStatus('deviceAdditionStatus', 'Generating device link...', 'info');
|
||||
|
||||
fetch('/api/create-device-link', {
|
||||
method: 'POST',
|
||||
credentials: 'include'
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.error) throw new Error(result.error);
|
||||
|
||||
// Update UI with the link
|
||||
document.getElementById('deviceLinkText').textContent = result.addition_link;
|
||||
document.getElementById('deviceToken').textContent = result.token;
|
||||
|
||||
// Store link globally for copy function
|
||||
window.currentDeviceLink = result.addition_link;
|
||||
|
||||
// Generate QR code
|
||||
const qrCodeEl = document.getElementById('qrCode');
|
||||
qrCodeEl.innerHTML = '';
|
||||
new QRCode(qrCodeEl, {
|
||||
text: result.addition_link,
|
||||
width: 200,
|
||||
height: 200,
|
||||
colorDark: '#000000',
|
||||
colorLight: '#ffffff',
|
||||
correctLevel: QRCode.CorrectLevel.M
|
||||
});
|
||||
|
||||
showStatus('deviceAdditionStatus', 'Device link generated successfully!', 'success');
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error generating device link:', error);
|
||||
showStatus('deviceAdditionStatus', `Failed to generate device link: ${error.message}`, 'error');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
36
static/profile-dialog.css
Normal file
36
static/profile-dialog.css
Normal file
@ -0,0 +1,36 @@
|
||||
/* Profile page dialog styles */
|
||||
|
||||
.container.dialog-open {
|
||||
filter: blur(2px);
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* Dialog styling */
|
||||
#deviceLinkDialog {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 999;
|
||||
color: black;
|
||||
background: white;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
||||
padding: 2rem;
|
||||
max-width: 500px;
|
||||
width: 90%;
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#deviceLinkDialog::backdrop {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
|
||||
/* Prevent scrolling when dialog is open */
|
||||
body.dialog-open {
|
||||
overflow: hidden;
|
||||
}
|
@ -15,12 +15,12 @@
|
||||
<h1>👋 Welcome!</h1>
|
||||
<div id="userInfo" class="user-info"></div>
|
||||
<div id="profileStatus"></div>
|
||||
|
||||
|
||||
<h2>Your Passkeys</h2>
|
||||
<div id="credentialList" class="credential-list">
|
||||
<p>Loading credentials...</p>
|
||||
</div>
|
||||
|
||||
|
||||
<button onclick="addNewCredential()" class="btn-primary">
|
||||
Add New Passkey
|
||||
</button>
|
||||
@ -31,31 +31,27 @@
|
||||
Logout
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Device Link Dialog -->
|
||||
<dialog id="deviceLinkDialog">
|
||||
<h1>📱 Add Device</h1>
|
||||
<div id="deviceAdditionStatus"></div>
|
||||
|
||||
|
||||
<div id="deviceLinkSection">
|
||||
<h2>Device Addition Link</h2>
|
||||
<div class="token-info">
|
||||
<p><strong>Share this link to add this account to another device:</strong></p>
|
||||
|
||||
<div class="qr-container">
|
||||
<div id="qrCode" class="qr-code"></div>
|
||||
<p><small>Scan this QR code with your other device</small></p>
|
||||
<p><a href="#" id="deviceLinkText"></a></p>
|
||||
</div>
|
||||
|
||||
<div class="link-container">
|
||||
<p class="link-text" id="deviceLinkText">Loading...</p>
|
||||
<button class="copy-button" onclick="copyDeviceLink()">Copy Link</button>
|
||||
</div>
|
||||
|
||||
<p><small>⚠️ This link expires in 24 hours and can only be used once.</small></p>
|
||||
|
||||
<p>
|
||||
<strong>Scan the above code and visit the URL on another device.</strong><br>
|
||||
<small>⚠️ Expires in 24 hours and can only be used once.</small>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<button onclick="closeDeviceLinkDialog()" class="btn-secondary">
|
||||
Close
|
||||
</button>
|
||||
|
@ -61,28 +61,39 @@ function closeDeviceLinkDialog() {
|
||||
}
|
||||
|
||||
// Generate device link function
|
||||
function generateDeviceLink() {
|
||||
async function generateDeviceLink() {
|
||||
clearStatus('deviceAdditionStatus')
|
||||
showStatus('deviceAdditionStatus', 'Generating device link...', 'info')
|
||||
|
||||
fetch('/api/create-device-link', {
|
||||
method: 'POST',
|
||||
credentials: 'include'
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.error) throw new Error(result.error)
|
||||
try {
|
||||
const response = await fetch('/api/create-device-link', {
|
||||
method: 'POST',
|
||||
credentials: 'include'
|
||||
})
|
||||
|
||||
const result = await response.json()
|
||||
|
||||
if (result.error) {
|
||||
throw new Error(result.error)
|
||||
}
|
||||
|
||||
// Update UI with the link
|
||||
const deviceLinkText = document.getElementById('deviceLinkText')
|
||||
const deviceToken = document.getElementById('deviceToken')
|
||||
|
||||
if (deviceLinkText) {
|
||||
deviceLinkText.textContent = result.addition_link
|
||||
}
|
||||
deviceLinkText.href = result.addition_link
|
||||
deviceLinkText.textContent = result.addition_link.replace(/^[a-z]+:\/\//i, '')
|
||||
|
||||
if (deviceToken) {
|
||||
deviceToken.textContent = result.token
|
||||
// Add click event listener for copying the link
|
||||
deviceLinkText.addEventListener('click', function(e) {
|
||||
e.preventDefault() // Prevent navigation
|
||||
navigator.clipboard.writeText(deviceLinkText.href).then(() => {
|
||||
closeDeviceLinkDialog() // Close the dialog
|
||||
showStatus('deviceAdditionStatus', 'Device registration link copied', 'success') // Display status
|
||||
}).catch(() => {
|
||||
showStatus('deviceAdditionStatus', 'Failed to copy device registration link', 'error')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Store link globally for copy function
|
||||
@ -103,10 +114,9 @@ function generateDeviceLink() {
|
||||
}
|
||||
|
||||
clearStatus('deviceAdditionStatus')
|
||||
})
|
||||
.catch(error => {
|
||||
} catch (error) {
|
||||
showStatus('deviceAdditionStatus', `Failed to generate device link: ${error.message}`, 'error')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Make functions available globally for onclick handlers
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* Passkey Authentication - Main Styles */
|
||||
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
@ -11,7 +11,7 @@ body {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.container {
|
||||
.container {
|
||||
background: white;
|
||||
padding: 40px;
|
||||
border-radius: 15px;
|
||||
@ -59,7 +59,7 @@ input[type="text"]:focus {
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
button {
|
||||
button {
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
margin-bottom: 15px;
|
||||
@ -326,18 +326,3 @@ button:disabled {
|
||||
color: #495057;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
background: #28a745;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.copy-button:hover {
|
||||
background: #218838;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user