Sistema Contenedor Ibiza v2.0 - Despliegue Docker

This commit is contained in:
2026-02-01 00:26:47 -06:00
commit 4d07b4b14c
355 changed files with 110875 additions and 0 deletions

148
public/admin/telegram.php Normal file
View File

@@ -0,0 +1,148 @@
<?php
require_once __DIR__ . '/../../vendor/autoload.php';
use App\Controllers\TelegramController;
use App\Middleware\RoleMiddleware;
use App\Services\AuthService;
RoleMiddleware::admin();
$auth = new AuthService();
$controller = new TelegramController();
// Manejar acciones
if (isPost()) {
$action = post('action');
if ($action === 'setup') {
$controller->setup();
} elseif ($action === 'delete') {
$controller->delete();
}
}
// Obtener datos para la vista
$data = $controller->index();
$info = $data['info'];
$defaultUrl = $data['defaultUrl'];
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Telegram - Contenedor Ibiza</title>
<link rel="stylesheet" href="../assets/css/style.css">
<style>
.status-box {
padding: 1.5rem;
border-radius: 8px;
background-color: #f8fafc;
border: 1px solid #e2e8f0;
margin-bottom: 2rem;
}
.status-item {
margin-bottom: 0.5rem;
}
.status-label {
font-weight: 600;
color: #64748b;
}
.status-badge {
display: inline-block;
padding: 0.25rem 0.5rem;
border-radius: 9999px;
font-size: 0.85rem;
font-weight: 600;
}
.status-active { background-color: #dcfce7; color: #166534; }
.status-inactive { background-color: #fee2e2; color: #991b1b; }
</style>
</head>
<body>
<?php include '../partials/navbar.php'; ?>
<div class="container">
<h1 class="card-title mb-4">🤖 Gestión de Bot Telegram</h1>
<?php if ($msg = flash('success')): ?>
<div class="alert alert-success"><?= e($msg) ?></div>
<?php endif; ?>
<?php if ($msg = flash('error')): ?>
<div class="alert alert-danger"><?= e($msg) ?></div>
<?php endif; ?>
<div class="card">
<h3 class="mb-4">Estado del Webhook</h3>
<div class="status-box">
<?php if ($info && !empty($info['url'])): ?>
<div class="status-item">
<span class="status-label">Estado:</span>
<span class="status-badge status-active">Activo</span>
</div>
<div class="status-item">
<span class="status-label">URL:</span>
<code><?= e($info['url']) ?></code>
</div>
<div class="status-item">
<span class="status-label">Mensajes pendientes:</span>
<?= e($info['pending_update_count'] ?? 0) ?>
</div>
<?php if (!empty($info['last_error_message'])): ?>
<div class="status-item text-danger" style="margin-top: 1rem;">
<span class="status-label">Último error:</span>
<?= e($info['last_error_message']) ?>
(<?= date('d/m/Y H:i', $info['last_error_date'] ?? time()) ?>)
</div>
<?php endif; ?>
<?php else: ?>
<div class="status-item">
<span class="status-label">Estado:</span>
<span class="status-badge status-inactive">Inactivo / No configurado</span>
</div>
<?php endif; ?>
</div>
<h3 class="mb-4">Configuración</h3>
<form method="POST" class="mb-4">
<input type="hidden" name="csrf_token" value="<?= csrfToken() ?>">
<input type="hidden" name="action" value="setup">
<div class="form-group">
<label>URL del Webhook (HTTPS requerido)</label>
<input type="url" name="webhook_url" class="form-control"
value="<?= e($defaultUrl) ?>" required>
<small style="display: block; margin-top: 0.5rem; color: #64748b;">
Esta es la URL a la que Telegram enviará los mensajes. Debe ser pública y segura (HTTPS).
Por defecto, se sugiere la URL interna de tu sitio.
</small>
</div>
<button type="submit" class="btn btn-primary">
💾 Guardar Configuración
</button>
</form>
<?php if ($info && !empty($info['url'])): ?>
<hr style="margin: 2rem 0; border: 0; border-top: 1px solid #e2e8f0;">
<h3 class="mb-4 text-danger">Zona de Peligro</h3>
<form method="POST" onsubmit="return confirm('¿Estás seguro de desactivar el bot? Dejará de responder mensajes.');">
<input type="hidden" name="csrf_token" value="<?= csrfToken() ?>">
<input type="hidden" name="action" value="delete">
<button type="submit" class="btn btn-danger">
🚫 Borrar Webhook
</button>
<small style="display: block; margin-top: 0.5rem; color: #64748b;">
Esto desconectará el bot de tu servidor.
</small>
</form>
<?php endif; ?>
</div>
</div>
</body>
</html>

206
public/admin/usuarios.php Normal file
View File

@@ -0,0 +1,206 @@
<?php
require_once __DIR__ . '/../../vendor/autoload.php';
use App\Controllers\UserController;
use App\Middleware\RoleMiddleware;
// Middleware maneja la seguridad
$controller = new UserController();
$users = $controller->index(); // Maneja POST internamente y retorna lista para render
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gestión de Usuarios - Contenedor Ibiza</title>
<link rel="stylesheet" href="../assets/css/style.css">
<style>
.modal {
display: none;
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
background: rgba(0,0,0,0.5);
align-items: center;
justify-content: center;
z-index: 1000;
}
.modal-content {
background: white;
padding: 2rem;
border-radius: 1rem;
width: 100%;
max-width: 500px;
}
</style>
</head>
<body>
<?php include '../partials/navbar.php'; ?>
<div class="container">
<div class="card-header">
<h1 class="card-title">👥 Gestión de Usuarios</h1>
<button onclick="openModal('createModal')" class="btn btn-primary">Nuevo Usuario</button>
</div>
<?php if ($msg = flash('success')): ?>
<div class="alert alert-success"><?= e($msg) ?></div>
<?php endif; ?>
<?php if ($msg = flash('error')): ?>
<div class="alert alert-error"><?= e($msg) ?></div>
<?php endif; ?>
<div class="card">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Usuario</th>
<th>Nombre Completo</th>
<th>Rol</th>
<th>Estado</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
<?php foreach ($users as $u): ?>
<tr>
<td><?= e($u['username']) ?></td>
<td><?= e($u['full_name']) ?></td>
<td>
<?php
$roles = [
'admin' => 'Administrador',
'coordinador' => 'Coordinador',
'ayudante' => 'Ayudante'
];
echo $roles[$u['role']] ?? $u['role'];
?>
</td>
<td>
<?php if ($u['active']): ?>
<span class="badge badge-success">Activo</span>
<?php else: ?>
<span class="badge badge-danger">Inactivo</span>
<?php endif; ?>
</td>
<td>
<div class="flex">
<button onclick='editUser(<?= json_encode($u) ?>)' class="btn btn-sm btn-secondary">Editar</button>
<form method="POST" style="display:inline;">
<input type="hidden" name="csrf_token" value="<?= csrfToken() ?>">
<input type="hidden" name="action" value="toggle">
<input type="hidden" name="id" value="<?= $u['id'] ?>">
<?php if ($u['active']): ?>
<button type="submit" class="btn btn-sm btn-danger">Desactivar</button>
<?php else: ?>
<button type="submit" class="btn btn-sm btn-success">Activar</button>
<?php endif; ?>
</form>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- Modal Crear -->
<div id="createModal" class="modal">
<div class="modal-content">
<h2 class="mb-4">Nuevo Usuario</h2>
<form method="POST">
<input type="hidden" name="csrf_token" value="<?= csrfToken() ?>">
<input type="hidden" name="action" value="create">
<div class="form-group">
<label class="form-label">Nombre de Usuario</label>
<input type="text" name="username" class="form-control" required>
</div>
<div class="form-group">
<label class="form-label">Contraseña</label>
<input type="password" name="password" class="form-control" required>
</div>
<div class="form-group">
<label class="form-label">Nombre Completo</label>
<input type="text" name="full_name" class="form-control" required>
</div>
<div class="form-group">
<label class="form-label">Rol</label>
<select name="role" class="form-control">
<option value="ayudante">Ayudante</option>
<option value="coordinador">Coordinador</option>
<option value="admin">Administrador</option>
</select>
</div>
<div class="flex justify-end mt-4">
<button type="button" onclick="closeModal('createModal')" class="btn btn-secondary">Cancelar</button>
<button type="submit" class="btn btn-primary">Crear</button>
</div>
</form>
</div>
</div>
<!-- Modal Editar -->
<div id="editModal" class="modal">
<div class="modal-content">
<h2 class="mb-4">Editar Usuario</h2>
<form method="POST">
<input type="hidden" name="csrf_token" value="<?= csrfToken() ?>">
<input type="hidden" name="action" value="update">
<input type="hidden" name="id" id="edit_id">
<div class="form-group">
<label class="form-label">Nombre de Usuario</label>
<input type="text" name="username" id="edit_username" class="form-control" required>
</div>
<div class="form-group">
<label class="form-label">Nueva Contraseña (Dejar en blanco para no cambiar)</label>
<input type="password" name="password" class="form-control">
</div>
<div class="form-group">
<label class="form-label">Nombre Completo</label>
<input type="text" name="full_name" id="edit_fullname" class="form-control" required>
</div>
<div class="form-group">
<label class="form-label">Rol</label>
<select name="role" id="edit_role" class="form-control">
<option value="ayudante">Ayudante</option>
<option value="coordinador">Coordinador</option>
<option value="admin">Administrador</option>
</select>
</div>
<div class="flex justify-end mt-4">
<button type="button" onclick="closeModal('editModal')" class="btn btn-secondary">Cancelar</button>
<button type="submit" class="btn btn-primary">Guardar</button>
</div>
</form>
</div>
</div>
<script src="../assets/js/main.js"></script>
<script>
function editUser(user) {
document.getElementById('edit_id').value = user.id;
document.getElementById('edit_username').value = user.username;
document.getElementById('edit_fullname').value = user.full_name;
document.getElementById('edit_role').value = user.role;
openModal('editModal');
}
</script>
</body>
</html>