mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2025-11-17 19:16:25 +00:00
Update Appimagen
This commit is contained in:
@@ -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>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -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()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -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>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -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}")
|
||||||
|
|||||||
Reference in New Issue
Block a user