Tul xxx Tul
User / IP
:
216.73.216.146
Host / Server
:
45.84.207.204 / aircan.me
System
:
Linux lt-bnk-web1726.main-hosting.eu 5.14.0-611.36.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Mar 3 11:23:52 EST 2026 x86_64
Command
|
Upload
|
Create
Mass Deface
|
Jumping
|
Symlink
|
Reverse Shell
Ping
|
Port Scan
|
DNS Lookup
|
Whois
|
Header
|
cURL
:
/
home
/
u931257429
/
domains
/
aircan.me
/
public_html
/
comidarapidafran2
/
admin
/
Viewing: update_profile.php
<?php include '../components/connect.php'; require_once '../components/admin_roles.php'; session_start(); $embedded = isset($_GET['embed']) && $_GET['embed'] === '1'; $admin_id = $_SESSION['admin_id'] ?? null; if(!$admin_id){ header('location:admin_login.php'); exit(); } ensureAdminRolesSchema($conn); $currentRole = getRoleBySession($conn); $target_id = isset($_GET['id']) ? (int)$_GET['id'] : (int)$admin_id; if($target_id <= 0){ addAdminFlashMessage('Selecciona un usuario válido.'); header('location:admin_accounts.php'); exit(); } $editing_self = ($target_id === (int)$admin_id); if(!$editing_self && !adminHasPermission($currentRole, 'admin_accounts')){ enforceAdminPermission('admin_accounts'); } $select_target = $conn->prepare("SELECT id, name, password, webauthn_required FROM `admin` WHERE id = ? LIMIT 1"); $select_target->execute([$target_id]); $target_account = $select_target->fetch(PDO::FETCH_ASSOC); if(!$target_account){ addAdminFlashMessage('El usuario seleccionado no existe.'); header('location:admin_accounts.php'); exit(); } $current_name = $target_account['name']; $prev_pass = $target_account['password']; $webauthn_required = (int)($target_account['webauthn_required'] ?? 0); $messages = []; if(isset($_POST['submit'])){ $name = trim($_POST['name'] ?? ''); $name = filter_var($name, FILTER_SANITIZE_STRING); if($name !== ''){ if($name !== $current_name){ $select_name = $conn->prepare("SELECT id FROM `admin` WHERE name = ? AND id != ? LIMIT 1"); $select_name->execute([$name, $target_id]); if($select_name->rowCount() > 0){ $messages[] = 'El nombre de usuario ya está en uso.'; }else{ $update_name = $conn->prepare("UPDATE `admin` SET name = ? WHERE id = ?"); $update_name->execute([$name, $target_id]); $current_name = $name; $messages[] = 'Nombre actualizado con éxito!'; } } } $empty_hash = 'da39a3ee5e6b4b0d3255bfef95601890afd80709'; $old_pass_raw = $_POST['old_pass'] ?? ''; $new_pass_raw = $_POST['new_pass'] ?? ''; $confirm_pass_raw = $_POST['confirm_pass'] ?? ''; $old_pass = sha1($old_pass_raw); $new_pass = sha1($new_pass_raw); $confirm_pass = sha1($confirm_pass_raw); $new_pass_provided = $new_pass_raw !== '' || $confirm_pass_raw !== ''; if($editing_self){ if($old_pass_raw !== ''){ if($old_pass !== $prev_pass){ $messages[] = 'Contraseña antigua no coincide!'; }elseif($new_pass !== $confirm_pass){ $messages[] = 'Confirmar contraseña no coincide!'; }elseif($new_pass === $empty_hash){ $messages[] = 'Por favor ingrese nueva contraseña!'; }else{ $update_pass = $conn->prepare("UPDATE `admin` SET password = ? WHERE id = ?"); $update_pass->execute([$confirm_pass, $target_id]); $prev_pass = $confirm_pass; $messages[] = 'Actualización de contraseña con éxito!'; } } }else{ if($new_pass_provided){ if($new_pass_raw === '' || $confirm_pass_raw === ''){ $messages[] = 'Ingresa y confirma la nueva contraseña.'; }elseif($new_pass !== $confirm_pass){ $messages[] = 'Confirmar contraseña no coincide!'; }elseif($new_pass === $empty_hash){ $messages[] = 'Por favor ingrese una contraseña válida!'; }else{ $update_pass = $conn->prepare("UPDATE `admin` SET password = ? WHERE id = ?"); $update_pass->execute([$confirm_pass, $target_id]); $messages[] = 'Contraseña restablecida con éxito!'; } } } $new_required = isset($_POST['webauthn_required']) ? 1 : 0; if ($new_required !== $webauthn_required) { try { $update_required = $conn->prepare("UPDATE `admin` SET webauthn_required = ? WHERE id = ?"); $update_required->execute([$new_required, $target_id]); $webauthn_required = $new_required; $messages[] = $webauthn_required ? 'Huella requerida para iniciar sesión.' : 'Huella no requerida para iniciar sesión.'; } catch (PDOException $ignored) { } } if(empty($messages)){ $messages[] = 'No se realizaron cambios.'; } } $webauthn_credentials = []; $webauthn_credential_count = 0; try { $webauthn_stmt = $conn->prepare("SELECT id, created_at, last_used_at FROM `admin_webauthn_credentials` WHERE admin_id = ? ORDER BY created_at DESC"); $webauthn_stmt->execute([$target_id]); $webauthn_credentials = $webauthn_stmt->fetchAll(PDO::FETCH_ASSOC) ?: []; $webauthn_credential_count = count($webauthn_credentials); } catch (PDOException $ignored) { } $embedPayload = null; $embedStatus = 'info'; $embedShouldClose = false; if ($embedded && $_SERVER['REQUEST_METHOD'] === 'POST' && !empty($messages)) { $joined = strtolower(implode(' | ', array_map(static fn($v) => (string)$v, $messages))); if (strpos($joined, 'éxito') !== false || strpos($joined, 'exito') !== false || strpos($joined, 'actualiz') !== false || strpos($joined, 'restablec') !== false) { $embedStatus = 'success'; $embedShouldClose = true; } elseif (strpos($joined, 'no coincide') !== false || strpos($joined, 'por favor') !== false || strpos($joined, 'uso') !== false) { $embedStatus = 'warning'; } if (strpos($joined, 'no se realizaron cambios') !== false) { $embedStatus = 'info'; $embedShouldClose = false; } $embedPayload = [ 'type' => 'users:modalResult', 'modal' => 'profile', 'status' => $embedStatus, 'messages' => array_values(array_map(static fn($v) => (string)$v, $messages)), 'close' => $embedShouldClose, ]; } $businessName = getBusinessName($conn); $businessLogoVersion = getBusinessLogoVersion($conn); $iconHref = '../icon.php?size=64' . ($businessLogoVersion !== '' ? '&v=' . rawurlencode($businessLogoVersion) : ''); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Actualizar Usuario | <?= htmlspecialchars($businessName); ?></title> <link rel="icon" href="<?= htmlspecialchars($iconHref); ?>" type="image/png"> <!-- font awesome cdn link --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css"> <!-- custom css file link --> <link rel="stylesheet" href="../css/admin_style.css"> <style> body.update-profile-page { min-height: 100vh; background: linear-gradient(135deg, #f5f9ff 0%, #fff7f3 100%); } body.update-profile-page.embed { min-height: 0; background: transparent; padding: 0; margin: 0; } html, body.update-profile-page.embed { margin: 0; background: transparent; } .update-profile-page.embed .form-container { padding: 0; max-width: none; display: block; min-height: 0; align-items: stretch; justify-content: flex-start; } .update-profile-page.embed .form-card { border-radius: 0; box-shadow: none; border: none; padding: 1.3rem 1.35rem 1.5rem; background: #fff; width: 100%; max-width: 640px; margin: 0 auto; } .update-profile-page .page-heading { padding: 24px 24px 0; } .update-profile-page .heading-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; } .update-profile-page .section-title { font-size: 2.25rem; font-weight: 900; color: #141421; margin: 0; } .update-profile-page .section-subtitle { margin: 6px 0 0; color: rgba(20, 20, 33, 0.68); font-weight: 600; } .update-profile-page .heading-back { display: inline-flex; align-items: center; gap: 8px; padding: 10px 14px; border-radius: 999px; text-decoration: none; font-weight: 700; color: rgba(20, 20, 33, 0.82); background: rgba(255, 255, 255, 0.75); border: 1px solid rgba(20, 20, 33, 0.12); box-shadow: 0 12px 28px rgba(17, 24, 39, 0.08); backdrop-filter: blur(10px); transition: transform .2s ease, box-shadow .2s ease; } .update-profile-page .heading-back:hover { transform: translateY(-2px); box-shadow: 0 14px 34px rgba(17, 24, 39, 0.12); } .update-profile-page .form-container { padding: 12px 24px 48px; max-width: 860px; margin: 0 auto; } .update-profile-page .form-card { position: relative; overflow: hidden; background: rgba(255, 255, 255, 0.82); border-radius: 20px; padding: 2.2rem 2.4rem; box-shadow: 0 22px 50px rgba(17, 24, 39, 0.14); border: 1px solid rgba(226, 232, 240, 0.95); backdrop-filter: blur(12px); } .update-profile-page .form-card::before { content: ''; position: absolute; inset: -70% -55% auto auto; height: 260px; width: 260px; background: radial-gradient(150px at top right, rgba(14, 165, 233, 0.16), transparent 70%); transform: rotate(10deg); pointer-events: none; } .update-profile-page .form-card h3 { margin: 0 0 1.6rem; font-size: 1.65rem; font-weight: 800; color: #1f2937; } .update-profile-page .field { margin-bottom: 1.1rem; } .update-profile-page .field label { display: block; font-weight: 700; margin-bottom: 0.55rem; color: rgba(15, 23, 42, 0.88); } .update-profile-page .field-icon { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-radius: 16px; background: rgba(255, 255, 255, 0.9); border: 1px solid rgba(20, 20, 33, 0.12); box-shadow: 0 14px 30px rgba(15, 21, 45, 0.08); backdrop-filter: blur(10px); } .update-profile-page .field-icon i { color: rgba(48, 49, 73, 0.7); } .update-profile-page .field-icon input { border: none; outline: none; background: transparent; width: auto; flex: 1; min-width: 0; font-size: 1rem; font-weight: 600; color: #303149; } .update-profile-page .message-inline { margin: 0 0 0.9rem; padding: 10px 12px; border-radius: 14px; border: 1px solid rgba(20, 20, 33, 0.12); background: rgba(255, 255, 255, 0.72); color: rgba(20, 20, 33, 0.82); font-weight: 700; } .update-profile-page .actions { display: flex; justify-content: flex-end; margin-top: 1.8rem; } .update-profile-page .btn-modern { display: inline-flex; align-items: center; justify-content: center; gap: 10px; padding: 12px 18px; border-radius: 14px; border: none; cursor: pointer; background: linear-gradient(135deg, #0ea5e9, #2563eb); color: #fff; font-weight: 800; box-shadow: 0 14px 28px rgba(37, 99, 235, 0.22); transition: transform .2s ease, box-shadow .2s ease; } .update-profile-page .btn-modern:hover { transform: translateY(-2px); box-shadow: 0 16px 34px rgba(37, 99, 235, 0.28); } .update-profile-page .webauthn-card { margin-top: 1.5rem; padding: 1.25rem 1.2rem; border-radius: 18px; background: rgba(255, 255, 255, 0.72); border: 1px solid rgba(20, 20, 33, 0.12); box-shadow: 0 14px 30px rgba(15, 21, 45, 0.08); } .update-profile-page .webauthn-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap; } .update-profile-page .webauthn-title { margin: 0; font-weight: 900; color: #141421; font-size: 1.05rem; } .update-profile-page .webauthn-subtitle { margin: 6px 0 0; color: rgba(20, 20, 33, 0.68); font-weight: 700; font-size: 0.92rem; } .update-profile-page .webauthn-switch { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-radius: 16px; background: rgba(255, 255, 255, 0.9); border: 1px solid rgba(20, 20, 33, 0.12); margin-top: 14px; font-weight: 800; color: rgba(20, 20, 33, 0.82); } .update-profile-page .webauthn-switch input { width: 18px; height: 18px; } .update-profile-page .webauthn-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 14px; } .update-profile-page .btn-soft { display: inline-flex; align-items: center; justify-content: center; gap: 10px; padding: 12px 16px; border-radius: 14px; border: 1px solid rgba(20, 20, 33, 0.12); cursor: pointer; background: rgba(15, 23, 42, 0.82); color: #fff; font-weight: 800; box-shadow: 0 14px 28px rgba(15, 23, 42, 0.18); transition: transform .2s ease, box-shadow .2s ease, background .2s ease; } .update-profile-page .btn-soft:hover { transform: translateY(-2px); box-shadow: 0 16px 34px rgba(15, 23, 42, 0.22); background: rgba(15, 23, 42, 0.92); } .update-profile-page .btn-soft--danger { background: rgba(220, 38, 38, 0.92); border-color: rgba(220, 38, 38, 0.28); box-shadow: 0 14px 28px rgba(220, 38, 38, 0.18); } .update-profile-page .btn-soft--danger:hover { background: rgba(220, 38, 38, 1); box-shadow: 0 16px 34px rgba(220, 38, 38, 0.22); } .update-profile-page .webauthn-list { margin-top: 14px; display: grid; gap: 10px; } .update-profile-page .webauthn-item { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 14px; border-radius: 16px; background: rgba(255, 255, 255, 0.9); border: 1px solid rgba(20, 20, 33, 0.12); } .update-profile-page .webauthn-item strong { display: block; font-weight: 900; color: rgba(20, 20, 33, 0.88); } .update-profile-page .webauthn-item span { display: block; color: rgba(20, 20, 33, 0.68); font-weight: 700; font-size: 0.9rem; margin-top: 4px; } @media (max-width: 720px) { .update-profile-page .page-heading { padding: 18px 18px 0; } .update-profile-page .form-container { padding: 14px 18px 44px; } .update-profile-page .form-card { padding: 1.75rem 1.5rem; } } @media (max-width: 520px) { .update-profile-page .form-card { padding: 1.5rem 1.2rem; } .update-profile-page .actions { justify-content: stretch; } .update-profile-page .btn-modern { width: 100%; } } </style> </head> <body class="update-profile-page<?= $embedded ? ' embed' : ''; ?>"> <?php if(!$embedded){ include '../components/admin_header.php'; } ?> <!-- admin profile update section starts --> <?php $backHref = $editing_self ? 'dashboard.php' : 'admin_accounts.php'; $pageTitle = $editing_self ? 'Perfil' : 'Usuarios'; $pageSubtitle = $editing_self ? 'Actualiza tu usuario y contraseña de acceso.' : 'Actualiza credenciales del usuario seleccionado.'; ?> <?php if(!$embedded): ?> <section class="page-heading"> <div class="heading-row"> <div> <h1 class="section-title"><?= htmlspecialchars($pageTitle); ?></h1> <p class="section-subtitle"><?= htmlspecialchars($pageSubtitle); ?></p> </div> <a href="<?= htmlspecialchars($backHref); ?>" class="heading-back"><i class="fa-solid fa-arrow-left"></i> Volver</a> </div> </section> <?php endif; ?> <section class="form-container"> <form action="" method="POST" class="form-card"> <h3><?= $editing_self ? 'Actualizar mi usuario' : 'Actualizar usuario: ' . htmlspecialchars($current_name); ?></h3> <?php if(!empty($messages) && !$embedded): ?> <?php foreach($messages as $notif): ?> <p class="message-inline"><?= htmlspecialchars($notif); ?></p> <?php endforeach; ?> <?php endif; ?> <div class="field"> <label for="upd_name">Nombre de usuario</label> <div class="field-icon"> <i class="fa-solid fa-user"></i> <input id="upd_name" type="text" name="name" maxlength="20" oninput="this.value = this.value.replace(/\s/g, '')" value="<?= htmlspecialchars($current_name); ?>" placeholder="Nombre de usuario"> </div> </div> <?php if($editing_self): ?> <div class="field"> <label for="upd_old">Contraseña actual</label> <div class="field-icon"> <i class="fa-solid fa-lock"></i> <input id="upd_old" type="password" name="old_pass" maxlength="20" placeholder="Ingrese su contraseña antigua" oninput="this.value = this.value.replace(/\s/g, '')"> <button type="button" class="pw-toggle" aria-label="Mostrar contraseña"><i class="fa-solid fa-eye"></i></button> </div> </div> <?php endif; ?> <div class="field"> <label for="upd_new">Nueva contraseña</label> <div class="field-icon"> <i class="fa-solid fa-key"></i> <input id="upd_new" type="password" name="new_pass" maxlength="20" placeholder="<?= $editing_self ? 'Ingrese su nueva contraseña' : 'Nueva contraseña (opcional)'; ?>" oninput="this.value = this.value.replace(/\s/g, '')"> <button type="button" class="pw-toggle" aria-label="Mostrar contraseña"><i class="fa-solid fa-eye"></i></button> </div> </div> <div class="field"> <label for="upd_confirm">Confirmar nueva contraseña</label> <div class="field-icon"> <i class="fa-solid fa-shield"></i> <input id="upd_confirm" type="password" name="confirm_pass" maxlength="20" placeholder="Confirme la nueva contraseña" oninput="this.value = this.value.replace(/\s/g, '')"> <button type="button" class="pw-toggle" aria-label="Mostrar contraseña"><i class="fa-solid fa-eye"></i></button> </div> </div> <div class="webauthn-card" data-admin-id="<?= (int)$target_id; ?>"> <div class="webauthn-head"> <div> <p class="webauthn-title">Huella / Passkeys</p> <p class="webauthn-subtitle"><span id="webauthnCount"><?= (int)$webauthn_credential_count; ?></span> registrada(s)</p> </div> </div> <label class="webauthn-switch"> <input type="checkbox" name="webauthn_required" value="1" <?= $webauthn_required ? 'checked' : ''; ?>> Requerir huella para iniciar sesión </label> <div class="webauthn-actions"> <button type="button" class="btn-soft" id="btnRegisterPasskey"><i class="fa-solid fa-fingerprint"></i> Registrar huella</button> </div> <div class="webauthn-list" id="webauthnList"> <?php if(!empty($webauthn_credentials)): ?> <?php foreach($webauthn_credentials as $cred): ?> <?php $created = (string)($cred['created_at'] ?? ''); $last = (string)($cred['last_used_at'] ?? ''); $label = $last !== '' ? ('Último uso: ' . $last) : 'Sin uso aún'; ?> <div class="webauthn-item" data-credential-internal-id="<?= (int)$cred['id']; ?>"> <div> <strong>Registrada: <?= htmlspecialchars($created); ?></strong> <span><?= htmlspecialchars($label); ?></span> </div> <button type="button" class="btn-soft btn-soft--danger btnDeletePasskey" data-credential-internal-id="<?= (int)$cred['id']; ?>"><i class="fa-solid fa-trash"></i> Eliminar</button> </div> <?php endforeach; ?> <?php else: ?> <div class="webauthn-item" id="webauthnEmpty"> <div> <strong>No hay huellas registradas</strong> <span>Registra una huella en este perfil para iniciar sesión con Windows Hello.</span> </div> </div> <?php endif; ?> </div> </div> <div class="actions"> <button type="submit" name="submit" class="btn-modern"><i class="fa-solid fa-floppy-disk"></i> Guardar cambios</button> </div> </form> </section> <script> (function(){ if(document.documentElement.dataset.pwToggleInit === '1') return; document.documentElement.dataset.pwToggleInit = '1'; document.addEventListener('click', (e) => { const btn = e.target.closest?.('.pw-toggle'); if(!btn) return; const wrap = btn.closest('.field-icon'); const input = wrap?.querySelector('input'); if(!input) return; if(input.type !== 'password' && input.type !== 'text') return; const isPassword = input.type === 'password'; input.type = isPassword ? 'text' : 'password'; const icon = btn.querySelector('i'); if(icon){ icon.classList.toggle('fa-eye', !isPassword); icon.classList.toggle('fa-eye-slash', isPassword); } btn.setAttribute('aria-label', isPassword ? 'Ocultar contraseña' : 'Mostrar contraseña'); }); const embedded = <?= $embedded ? 'true' : 'false'; ?>; if(!embedded) return; function sendSize(){ try { const card = document.querySelector('.form-card'); if(!card) return; const rect = card.getBoundingClientRect(); const extra = 34; const height = Math.ceil(rect.height + extra); window.parent && window.parent.postMessage({ type: 'users:embedSize', height }, window.location.origin); } catch (e) {} } window.addEventListener('load', () => { sendSize(); setTimeout(sendSize, 60); setTimeout(sendSize, 220); }); window.addEventListener('resize', sendSize); })(); </script> <script> (function(){ const card = document.querySelector('.webauthn-card'); if(!card) return; const adminId = Number(card.getAttribute('data-admin-id') || '0'); const btnRegister = document.getElementById('btnRegisterPasskey'); const list = document.getElementById('webauthnList'); const countEl = document.getElementById('webauthnCount'); function base64UrlToArrayBuffer(base64url) { const base64 = (base64url || '').replace(/-/g, '+').replace(/_/g, '/'); const pad = base64.length % 4; const padded = pad ? base64 + '='.repeat(4 - pad) : base64; const binary = atob(padded); const bytes = new Uint8Array(binary.length); for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i); return bytes.buffer; } function arrayBufferToBase64Url(buffer) { const bytes = new Uint8Array(buffer); let binary = ''; for (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i]); const base64 = btoa(binary); return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, ''); } function setCount(n){ if(!countEl) return; countEl.textContent = String(n); } function triggerResize(){ try { window.dispatchEvent(new Event('resize')); } catch (e) {} } if(btnRegister){ if (!window.PublicKeyCredential || typeof navigator.credentials?.create !== 'function') { btnRegister.disabled = true; btnRegister.style.opacity = '0.6'; btnRegister.title = 'Este navegador no soporta huella/passkeys.'; } else { btnRegister.addEventListener('click', async () => { try { btnRegister.disabled = true; const optionsRes = await fetch(`webauthn.php?action=register_options&id=${encodeURIComponent(String(adminId))}&_t=${Date.now()}`, { headers: { 'Accept': 'application/json' }, credentials: 'same-origin', cache: 'no-store' }); const optionsData = await optionsRes.json(); if(!optionsData?.ok) throw new Error(optionsData?.error || 'No se pudo iniciar el registro.'); const pk = optionsData.publicKey || {}; pk.challenge = base64UrlToArrayBuffer(pk.challenge); if(pk.user?.id) pk.user.id = base64UrlToArrayBuffer(pk.user.id); if(Array.isArray(pk.excludeCredentials)){ pk.excludeCredentials = pk.excludeCredentials.map((c) => ({ ...c, id: base64UrlToArrayBuffer(c.id) })); } const credential = await navigator.credentials.create({ publicKey: pk }); if(!credential) throw new Error('No se obtuvo respuesta de la huella.'); const transports = typeof credential.response?.getTransports === 'function' ? credential.response.getTransports() : []; const payload = { id: credential.id, rawId: arrayBufferToBase64Url(credential.rawId), type: credential.type, transports: Array.isArray(transports) ? transports : [], response: { clientDataJSON: arrayBufferToBase64Url(credential.response.clientDataJSON), attestationObject: arrayBufferToBase64Url(credential.response.attestationObject), } }; const verifyRes = await fetch(`webauthn.php?action=register_verify&id=${encodeURIComponent(String(adminId))}`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, credentials: 'same-origin', body: JSON.stringify(payload) }); const verifyData = await verifyRes.json(); if(!verifyData?.ok) throw new Error(verifyData?.error || 'No se pudo registrar la huella.'); window.location.reload(); } catch (err) { const msg = err?.message || 'Error registrando huella.'; if(window.Swal){ Swal.fire({ icon: 'error', title: 'Huella', text: msg }); } else { try { alert(msg); } catch (e) {} } } finally { btnRegister.disabled = false; } }); } } if(list){ list.addEventListener('click', async (e) => { const btn = e.target.closest?.('.btnDeletePasskey'); if(!btn) return; const credId = Number(btn.getAttribute('data-credential-internal-id') || '0'); if(!credId) return; try { btn.disabled = true; const res = await fetch(`webauthn.php?action=delete&id=${encodeURIComponent(String(adminId))}`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, credentials: 'same-origin', body: JSON.stringify({ credentialInternalId: credId }) }); const data = await res.json(); if(!data?.ok) throw new Error(data?.error || 'No se pudo eliminar.'); const item = btn.closest('.webauthn-item'); if(item) item.remove(); const remaining = list.querySelectorAll('.webauthn-item[data-credential-internal-id]').length; setCount(remaining); if(remaining === 0){ const empty = document.createElement('div'); empty.className = 'webauthn-item'; empty.id = 'webauthnEmpty'; empty.innerHTML = '<div><strong>No hay huellas registradas</strong><span>Registra una huella en este perfil para iniciar sesión con Windows Hello.</span></div>'; list.appendChild(empty); } triggerResize(); } catch (err) { const msg = err?.message || 'Error eliminando huella.'; if(window.Swal){ Swal.fire({ icon: 'error', title: 'Huella', text: msg }); } else { try { alert(msg); } catch (e) {} } } finally { btn.disabled = false; } }); } })(); </script> <!-- admin profile update section ends --> <?php if(!$embedded): ?> <!-- custom js file link --> <script src="../js/admin_script.js"></script> <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> <script> document.addEventListener('DOMContentLoaded', () => { const inlineMsgs = Array.from(document.querySelectorAll('.message-inline')); const headerMsgs = Array.from(document.querySelectorAll('.message')); const texts = []; inlineMsgs.forEach((n) => { const t = (n.textContent || '').trim(); if(t) texts.push(t); n.remove(); }); headerMsgs.forEach((n) => { const t = (n.querySelector('span')?.textContent || '').trim(); if(t) texts.push(t); n.remove(); }); if(!texts.length || !window.Swal) return; const Toast = Swal.mixin({ toast: true, position: 'top-end', showConfirmButton: false, timer: 3200, timerProgressBar: true, }); texts.forEach((t) => { const lower = t.toLowerCase(); const icon = lower.includes('éxito') || lower.includes('exito') || lower.includes('actualiz') || lower.includes('restablec') ? 'success' : (lower.includes('no coincide') || lower.includes('por favor') || lower.includes('no se') || lower.includes('uso') ? 'warning' : 'info'); Toast.fire({ icon, title: t }); }); }); </script> <?php elseif($embedPayload !== null): ?> <script> (function(){ const payload = <?= json_encode($embedPayload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>; try { window.parent && window.parent.postMessage(payload, window.location.origin); } catch (e) {} })(); </script> <?php endif; ?> </body> </html>
Coded With 💗 by
0x6ick