Update Appimagen

This commit is contained in:
MacRimi
2025-11-07 21:14:56 +01:00
parent ce44538240
commit 1f04134aac
4 changed files with 44 additions and 49 deletions

View File

@@ -189,16 +189,14 @@ export function Login({ onLogin }: LoginProps) {
<div className="bg-blue-500/10 border border-blue-500/20 rounded-lg p-3 flex items-start gap-2"> <div className="bg-blue-500/10 border border-blue-500/20 rounded-lg p-3 flex items-start gap-2">
<Shield className="h-5 w-5 text-blue-500 flex-shrink-0 mt-0.5" /> <Shield className="h-5 w-5 text-blue-500 flex-shrink-0 mt-0.5" />
<div> <div>
<p className="text-sm font-medium text-blue-500">Autenticación de Dos Factores</p> <p className="text-sm font-medium text-blue-500">Two-Factor Authentication</p>
<p className="text-xs text-blue-500 mt-1"> <p className="text-xs text-blue-500 mt-1">Enter the 6-digit code from your authentication app</p>
Introduce el código de 6 dígitos de tu aplicación de autenticación
</p>
</div> </div>
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="totp-code" className="text-sm"> <Label htmlFor="totp-code" className="text-sm">
Código de Autenticación Authentication Code
</Label> </Label>
<Input <Input
id="totp-code" id="totp-code"
@@ -213,7 +211,7 @@ export function Login({ onLogin }: LoginProps) {
autoFocus autoFocus
/> />
<p className="text-xs text-muted-foreground text-center"> <p className="text-xs text-muted-foreground text-center">
También puedes usar un código de respaldo (formato: XXXX-XXXX) You can also use a backup code (format: XXXX-XXXX)
</p> </p>
</div> </div>
@@ -228,7 +226,7 @@ export function Login({ onLogin }: LoginProps) {
}} }}
className="w-full" className="w-full"
> >
Volver al inicio de sesión Back to login
</Button> </Button>
</div> </div>
)} )}

View File

@@ -472,7 +472,7 @@ export function Settings() {
className="w-full bg-blue-500/10 hover:bg-blue-500/20 border-blue-500/20" className="w-full bg-blue-500/10 hover:bg-blue-500/20 border-blue-500/20"
> >
<Shield className="h-4 w-4 mr-2" /> <Shield className="h-4 w-4 mr-2" />
Habilitar Autenticación de Dos Factores Enable Two-Factor Authentication
</Button> </Button>
)} )}
@@ -480,29 +480,29 @@ export function Settings() {
<div className="space-y-3"> <div className="space-y-3">
<div className="bg-green-500/10 border border-green-500/20 rounded-lg p-3 flex items-center gap-2"> <div className="bg-green-500/10 border border-green-500/20 rounded-lg p-3 flex items-center gap-2">
<CheckCircle className="h-5 w-5 text-green-500" /> <CheckCircle className="h-5 w-5 text-green-500" />
<p className="text-sm text-green-500 font-medium">2FA está activado</p> <p className="text-sm text-green-500 font-medium">2FA is enabled</p>
</div> </div>
{!show2FADisable && ( {!show2FADisable && (
<Button onClick={() => setShow2FADisable(true)} variant="outline" className="w-full"> <Button onClick={() => setShow2FADisable(true)} variant="outline" className="w-full">
<Shield className="h-4 w-4 mr-2" /> <Shield className="h-4 w-4 mr-2" />
Desactivar 2FA Disable 2FA
</Button> </Button>
)} )}
{show2FADisable && ( {show2FADisable && (
<div className="space-y-4 border border-border rounded-lg p-4"> <div className="space-y-4 border border-border rounded-lg p-4">
<h3 className="font-semibold">Desactivar Autenticación de Dos Factores</h3> <h3 className="font-semibold">Disable Two-Factor Authentication</h3>
<p className="text-sm text-muted-foreground">Introduce tu contraseña para confirmar</p> <p className="text-sm text-muted-foreground">Enter your password to confirm</p>
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="disable-2fa-password">Contraseña</Label> <Label htmlFor="disable-2fa-password">Password</Label>
<div className="relative"> <div className="relative">
<Lock className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" /> <Lock className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Input <Input
id="disable-2fa-password" id="disable-2fa-password"
type="password" type="password"
placeholder="Introduce tu contraseña" placeholder="Enter your password"
value={disable2FAPassword} value={disable2FAPassword}
onChange={(e) => setDisable2FAPassword(e.target.value)} onChange={(e) => setDisable2FAPassword(e.target.value)}
className="pl-10" className="pl-10"
@@ -513,7 +513,7 @@ export function Settings() {
<div className="flex gap-2"> <div className="flex gap-2">
<Button onClick={handleDisable2FA} variant="destructive" className="flex-1" disabled={loading}> <Button onClick={handleDisable2FA} variant="destructive" className="flex-1" disabled={loading}>
{loading ? "Desactivando..." : "Desactivar 2FA"} {loading ? "Disabling..." : "Disable 2FA"}
</Button> </Button>
<Button <Button
onClick={() => { onClick={() => {
@@ -525,7 +525,7 @@ export function Settings() {
className="flex-1" className="flex-1"
disabled={loading} disabled={loading}
> >
Cancelar Cancel
</Button> </Button>
</div> </div>
</div> </div>
@@ -563,7 +563,7 @@ export function Settings() {
open={show2FASetup} open={show2FASetup}
onClose={() => setShow2FASetup(false)} onClose={() => setShow2FASetup(false)}
onSuccess={() => { onSuccess={() => {
setSuccess("2FA habilitado correctamente!") setSuccess("2FA enabled successfully!")
checkAuthStatus() checkAuthStatus()
}} }}
/> />

View File

@@ -121,9 +121,9 @@ export function TwoFactorSetup({ open, onClose, onSuccess }: TwoFactorSetupProps
<DialogHeader> <DialogHeader>
<DialogTitle className="flex items-center gap-2"> <DialogTitle className="flex items-center gap-2">
<Shield className="h-5 w-5 text-blue-500" /> <Shield className="h-5 w-5 text-blue-500" />
Configurar Autenticación de Dos Factores Setup Two-Factor Authentication
</DialogTitle> </DialogTitle>
<DialogDescription>Añade una capa extra de seguridad a tu cuenta</DialogDescription> <DialogDescription>Add an extra layer of security to your account</DialogDescription>
</DialogHeader> </DialogHeader>
{error && ( {error && (
@@ -137,22 +137,22 @@ export function TwoFactorSetup({ open, onClose, onSuccess }: TwoFactorSetupProps
<div className="space-y-4"> <div className="space-y-4">
<div className="bg-blue-500/10 border border-blue-500/20 rounded-lg p-4"> <div className="bg-blue-500/10 border border-blue-500/20 rounded-lg p-4">
<p className="text-sm text-blue-500"> <p className="text-sm text-blue-500">
La autenticación de dos factores (2FA) añade una capa extra de seguridad requiriendo un código de tu Two-factor authentication (2FA) adds an extra layer of security by requiring a code from your
aplicación de autenticación además de tu contraseña. authentication app in addition to your password.
</p> </p>
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<h4 className="font-medium">Necesitarás:</h4> <h4 className="font-medium">You will need:</h4>
<ul className="text-sm text-muted-foreground space-y-1 list-disc list-inside"> <ul className="text-sm text-muted-foreground space-y-1 list-disc list-inside">
<li>Una aplicación de autenticación (Google Authenticator, Authy, etc.)</li> <li>An authentication app (Google Authenticator, Authy, etc.)</li>
<li>Escanear un código QR o introducir una clave manualmente</li> <li>Scan a QR code or enter a key manually</li>
<li>Guardar códigos de respaldo de forma segura</li> <li>Store backup codes securely</li>
</ul> </ul>
</div> </div>
<Button onClick={handleSetupStart} className="w-full bg-blue-500 hover:bg-blue-600" disabled={loading}> <Button onClick={handleSetupStart} className="w-full bg-blue-500 hover:bg-blue-600" disabled={loading}>
{loading ? "Iniciando..." : "Comenzar Configuración"} {loading ? "Starting..." : "Start Setup"}
</Button> </Button>
</div> </div>
)} )}
@@ -160,10 +160,8 @@ export function TwoFactorSetup({ open, onClose, onSuccess }: TwoFactorSetupProps
{step === 2 && ( {step === 2 && (
<div className="space-y-4"> <div className="space-y-4">
<div className="space-y-2"> <div className="space-y-2">
<h4 className="font-medium">1. Escanea el código QR</h4> <h4 className="font-medium">1. Scan the QR code</h4>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">Open your authentication app and scan this QR code</p>
Abre tu aplicación de autenticación y escanea este código QR
</p>
{qrCode && ( {qrCode && (
<div className="flex justify-center p-4 bg-white rounded-lg"> <div className="flex justify-center p-4 bg-white rounded-lg">
<img src={qrCode || "/placeholder.svg"} alt="QR Code" width={200} height={200} className="rounded" /> <img src={qrCode || "/placeholder.svg"} alt="QR Code" width={200} height={200} className="rounded" />
@@ -172,14 +170,14 @@ export function TwoFactorSetup({ open, onClose, onSuccess }: TwoFactorSetupProps
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<h4 className="font-medium">O introduce la clave manualmente:</h4> <h4 className="font-medium">Or enter the key manually:</h4>
<div className="flex gap-2"> <div className="flex gap-2">
<Input value={secret} readOnly className="font-mono text-sm" /> <Input value={secret} readOnly className="font-mono text-sm" />
<Button <Button
variant="outline" variant="outline"
size="icon" size="icon"
onClick={() => copyToClipboard(secret, "secret")} onClick={() => copyToClipboard(secret, "secret")}
title="Copiar clave" title="Copy key"
> >
{copiedSecret ? <Check className="h-4 w-4 text-green-500" /> : <Copy className="h-4 w-4" />} {copiedSecret ? <Check className="h-4 w-4 text-green-500" /> : <Copy className="h-4 w-4" />}
</Button> </Button>
@@ -187,10 +185,8 @@ export function TwoFactorSetup({ open, onClose, onSuccess }: TwoFactorSetupProps
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<h4 className="font-medium">2. Introduce el código de verificación</h4> <h4 className="font-medium">2. Enter the verification code</h4>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">Enter the 6-digit code that appears in your app</p>
Introduce el código de 6 dígitos que aparece en tu aplicación
</p>
<Input <Input
type="text" type="text"
placeholder="000000" placeholder="000000"
@@ -204,10 +200,10 @@ export function TwoFactorSetup({ open, onClose, onSuccess }: TwoFactorSetupProps
<div className="flex gap-2"> <div className="flex gap-2">
<Button onClick={handleVerify} className="flex-1 bg-blue-500 hover:bg-blue-600" disabled={loading}> <Button onClick={handleVerify} className="flex-1 bg-blue-500 hover:bg-blue-600" disabled={loading}>
{loading ? "Verificando..." : "Verificar y Activar"} {loading ? "Verifying..." : "Verify and Enable"}
</Button> </Button>
<Button onClick={handleClose} variant="outline" className="flex-1 bg-transparent" disabled={loading}> <Button onClick={handleClose} variant="outline" className="flex-1 bg-transparent" disabled={loading}>
Cancelar Cancel
</Button> </Button>
</div> </div>
</div> </div>
@@ -218,30 +214,30 @@ export function TwoFactorSetup({ open, onClose, onSuccess }: TwoFactorSetupProps
<div className="bg-green-500/10 border border-green-500/20 rounded-lg p-4 flex items-start gap-2"> <div className="bg-green-500/10 border border-green-500/20 rounded-lg p-4 flex items-start gap-2">
<CheckCircle className="h-5 w-5 text-green-500 flex-shrink-0 mt-0.5" /> <CheckCircle className="h-5 w-5 text-green-500 flex-shrink-0 mt-0.5" />
<div> <div>
<p className="font-medium text-green-500">2FA Activado Correctamente</p> <p className="font-medium text-green-500">2FA Enabled Successfully</p>
<p className="text-sm text-green-500 mt-1"> <p className="text-sm text-green-500 mt-1">
Tu cuenta ahora está protegida con autenticación de dos factores Your account is now protected with two-factor authentication
</p> </p>
</div> </div>
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<h4 className="font-medium text-orange-500">Importante: Guarda tus códigos de respaldo</h4> <h4 className="font-medium text-orange-500">Important: Save your backup codes</h4>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Estos códigos te permitirán acceder a tu cuenta si pierdes acceso a tu aplicación de autenticación. These codes will allow you to access your account if you lose access to your authentication app. Store
Guárdalos en un lugar seguro. them in a safe place.
</p> </p>
<div className="bg-muted/50 rounded-lg p-4 space-y-2"> <div className="bg-muted/50 rounded-lg p-4 space-y-2">
<div className="flex justify-between items-center mb-2"> <div className="flex justify-between items-center mb-2">
<span className="text-sm font-medium">Códigos de Respaldo</span> <span className="text-sm font-medium">Backup Codes</span>
<Button variant="outline" size="sm" onClick={() => copyToClipboard(backupCodes.join("\n"), "codes")}> <Button variant="outline" size="sm" onClick={() => copyToClipboard(backupCodes.join("\n"), "codes")}>
{copiedCodes ? ( {copiedCodes ? (
<Check className="h-4 w-4 text-green-500 mr-2" /> <Check className="h-4 w-4 text-green-500 mr-2" />
) : ( ) : (
<Copy className="h-4 w-4 mr-2" /> <Copy className="h-4 w-4 mr-2" />
)} )}
Copiar Todos Copy All
</Button> </Button>
</div> </div>
<div className="grid grid-cols-2 gap-2"> <div className="grid grid-cols-2 gap-2">
@@ -255,7 +251,7 @@ export function TwoFactorSetup({ open, onClose, onSuccess }: TwoFactorSetupProps
</div> </div>
<Button onClick={handleFinish} className="w-full bg-blue-500 hover:bg-blue-600"> <Button onClick={handleFinish} className="w-full bg-blue-500 hover:bg-blue-600">
Finalizar Finish
</Button> </Button>
</div> </div>
)} )}

View File

@@ -319,12 +319,13 @@ def generate_totp_qr(username, secret):
qr = segno.make(uri) qr = segno.make(uri)
# Convert to SVG string # Convert to SVG string
buffer = io.StringIO() buffer = io.BytesIO()
qr.save(buffer, kind='svg', scale=4, border=2) qr.save(buffer, kind='svg', scale=4, border=2)
svg_content = buffer.getvalue() svg_bytes = buffer.getvalue()
svg_content = svg_bytes.decode('utf-8')
# Return as data URL # Return as data URL
svg_base64 = base64.b64encode(svg_content.encode()).decode() svg_base64 = base64.b64encode(svg_content.encode()).decode('utf-8')
return f"data:image/svg+xml;base64,{svg_base64}" return f"data:image/svg+xml;base64,{svg_base64}"
except Exception as e: except Exception as e:
print(f"Error generating QR code: {e}") print(f"Error generating QR code: {e}")