2025-08-25 21:19:15 +01:00
{{define "mfa_setup"}}
{{template "base" .}}
{{end}}
{{define "mfa_setup_content"}}
< div class = "max-w-lg mx-auto p-6" >
< h1 class = "text-2xl font-bold text-white mb-2" > Set up Multi‑ Factor Authentication< / h1 >
< p class = "text-gray-400 mb-6" > Scan the QR code below with your authenticator app (Google Authenticator, Authy, 1Password, etc.), or enter the secret manually, then enter a code to confirm.< / p >
< div class = "bg-slate-800 border border-slate-700 rounded p-4 mb-4" >
< div class = "flex items-start gap-4" >
< img alt = "QR Code" class = "bg-white rounded p-2" src = "https://api.qrserver.com/v1/create-qr-code/?size=180x180&data={{urlquery .OTPAuthURI}}" width = "180" height = "180" / >
< div class = "flex-1" >
< div class = "text-sm text-gray-400" > Secret< / div >
< div class = "font-mono text-lg text-white break-all" > {{.Secret}}< / div >
< div class = "text-sm text-gray-400 mt-2" > URI< / div >
< div class = "text-xs text-gray-300 break-all" > {{.OTPAuthURI}}< / div >
< / div >
< / div >
< / div >
< form id = "mfa-verify-form" class = "space-y-4" >
< div >
< label for = "code" class = "block text-sm font-medium text-gray-300 mb-2" > Enter 6‑ digit code< / label >
< input id = "code" name = "code" inputmode = "numeric" pattern = "[0-9]{6}" maxlength = "6" class = "form-input" placeholder = "123456" required / >
< / div >
< div class = "flex justify-end" >
< button type = "submit" class = "btn-primary" > < i class = "fas fa-check mr-2" > < / i > Verify and Enable< / button >
< / div >
< / form >
< / div >
{{end}}
{{define "mfa_setup_scripts"}}
< script >
function getCSRF ( ) {
const m = document . cookie . match ( /(?:^|; )csrf_token=([^;]+)/ ) ;
return m && m [ 1 ] ? decodeURIComponent ( m [ 1 ] ) : '' ;
}
document . addEventListener ( 'DOMContentLoaded' , ( ) => {
const form = document . getElementById ( 'mfa-verify-form' ) ;
if ( ! form ) return ;
form . addEventListener ( 'submit' , async ( e ) => {
e . preventDefault ( ) ;
const fd = new FormData ( form ) ;
const params = new URLSearchParams ( Array . from ( fd . entries ( ) ) ) ;
try {
2025-08-26 20:55:08 +01:00
const res = await fetch ( window . prefix ( '/editor/profile/mfa/verify' ) , { method : 'POST' , headers : { 'X-CSRF-Token' : getCSRF ( ) } , body : params } ) ;
2025-08-25 21:19:15 +01:00
const data = await res . json ( ) . catch ( ( ) => ( { } ) ) ;
if ( res . ok && data . success ) {
showNotification ( 'MFA enabled' , 'success' ) ;
2025-08-26 20:55:08 +01:00
window . location . href = window . prefix ( '/editor/profile' ) ;
2025-08-25 21:19:15 +01:00
} else {
throw new Error ( data . error || res . statusText ) ;
}
} catch ( e ) {
showNotification ( 'Verification failed: ' + e . message , 'error' ) ;
}
} ) ;
} ) ;
< / script >
{{end}}