diff --git a/admin/index.php b/admin/index.php index ad6e0d0..d4ebae2 100644 --- a/admin/index.php +++ b/admin/index.php @@ -13,6 +13,7 @@ Pedido inválido. Atualize a página e tente novamente."); + } + } ?>
"; + $csrfTokenHtml = htmlspecialchars(generate_csrf_token(), ENT_QUOTES, 'UTF-8'); + echo ""; + echo ""; + ?> "; + echo csrf_token_field(); foreach ($inputs as $input) { $id_safe = htmlspecialchars($input['id'], ENT_QUOTES, 'UTF-8'); $value_safe = htmlspecialchars($input['value'], ENT_QUOTES, 'UTF-8'); diff --git a/admin/materiais.php b/admin/materiais.php index 92ebca0..0a83b17 100644 --- a/admin/materiais.php +++ b/admin/materiais.php @@ -132,6 +132,7 @@ echo ""; ?>
+
@@ -175,13 +176,13 @@ // Delete material case "apagar": - if (!isset($_GET['id'])) { + if (!isset($_POST['id'])) { echo ""; break; } $stmt = $db->prepare("DELETE FROM materiais WHERE id = ?"); - $stmt->bind_param("s", $_GET['id']); + $stmt->bind_param("s", $_POST['id']); $stmt->execute(); $stmt->close(); acaoexecutada("Eliminação de Material"); @@ -208,6 +209,7 @@ echo ""; ?> +
@@ -298,7 +300,11 @@ echo "{$salaNome}"; echo ""; echo "Editar"; - echo "Apagar"; + echo ""; + echo csrf_token_field(); + echo ""; + echo ""; + echo ""; echo ""; echo ""; } diff --git a/admin/relatorios.php b/admin/relatorios.php index ebe2c5e..054c07f 100644 --- a/admin/relatorios.php +++ b/admin/relatorios.php @@ -1,11 +1,16 @@ Pedido inválido. Atualize a página e tente novamente.
"); + } // Guard: redirect pending TOTP/setup flows to completion if (isset($_SESSION['pending_totp_user'])) { header('Location: /login?step=totp'); exit(); } if (isset($_SESSION['pending_user_setup'])) { header('Location: /login?step=setup'); exit(); } @@ -164,6 +169,7 @@ public function Footer() {

Gere um relatório em PDF da utilização de salas para um dia específico.

+
diff --git a/admin/reservaemmassa.php b/admin/reservaemmassa.php index 71efdeb..c924dfc 100644 --- a/admin/reservaemmassa.php +++ b/admin/reservaemmassa.php @@ -296,9 +296,12 @@ function validateForm(event) { $stmtCheck = $db->prepare("SELECT 1 FROM reservas WHERE sala = ? AND tempo = ? AND data = ? LIMIT 1"); $stmtInsert = $db->prepare("INSERT INTO reservas (sala, tempo, data, requisitor, aprovado, motivo, extra) VALUES (?, ?, ?, ?, 1, ?, ?)"); + $db->begin_transaction(); + $lineNumber = 0; $successCount = 0; $errorCount = 0; + $insertErrorCount = 0; $duplicateCount = 0; $errors = []; $maxDisplayedErrors = 10; @@ -375,10 +378,17 @@ function validateForm(event) { $successCount++; } else { $errorCount++; + $insertErrorCount++; $recordError("Linha {$lineNumber}: Erro ao inserir reserva."); } } + if ($insertErrorCount > 0) { + $db->rollback(); + } else { + $db->commit(); + } + $stmtSalaExists->close(); $stmtRequisitorExists->close(); $stmtTempoExists->close(); @@ -462,6 +472,7 @@ function validateForm(event) {
+
@@ -690,6 +701,8 @@ function validateForm(event) { $reservas_duplicadas = 0; $erros = []; $num_semanas = 0; + $db->begin_transaction(); + // Create reservations for each week until we pass the end date $current_date = $first_date; @@ -740,6 +753,13 @@ function validateForm(event) { } // Send email notification to the user if any reservations were created + if (!empty($erros)) { + $db->rollback(); + $reservas_criadas = 0; + } else { + $db->commit(); + } + if ($reservas_criadas > 0) { sendRecurringWeeklyReservationsEmail( $db, diff --git a/login/index.php b/login/index.php index 0148806..a00f38e 100644 --- a/login/index.php +++ b/login/index.php @@ -1,8 +1,13 @@ ⚠️ MODO DE DESENVOLVIMENTO - Dados de teste | Base de dados de desenvolvimento
' : ''; - $content = $devModeBanner . ''; + $content = $devModeBanner . ''; render_login_template('Verificação de Segurança', $content); die(); } @@ -357,6 +368,7 @@ function start_authenticated_session($userId, $userName, $userEmail, $isAdmin) { $content .= '

Por favor, introduza o seu nome completo.

'; if (!empty($localAuthError)) { $content .= '
' . htmlspecialchars($localAuthError) . '
'; } $content .= '
'; + $content .= $csrfTokenField; $content .= ''; $content .= '
'; $content .= ''; @@ -399,6 +411,7 @@ function start_authenticated_session($userId, $userName, $userEmail, $isAdmin) { $content .= '
QR Code
'; $content .= '
Código manual:
' . htmlspecialchars($secret) . '
'; $content .= ''; + $content .= $csrfTokenField; $content .= ''; $content .= '
'; $content .= ''; @@ -454,6 +467,7 @@ function start_authenticated_session($userId, $userName, $userEmail, $isAdmin) {

Iniciar Sessão no ClassLink

+
@@ -486,6 +501,7 @@ function start_authenticated_session($userId, $userName, $userEmail, $isAdmin) {
+
@@ -539,7 +555,17 @@ function start_authenticated_session($userId, $userName, $userEmail, $isAdmin) { } else if (isset($_GET['error'])) { ?> getAccessToken('authorization_code', [ 'code' => $_GET['code'] ]); diff --git a/reservar/index.php b/reservar/index.php index f97e92c..c6a8c84 100644 --- a/reservar/index.php +++ b/reservar/index.php @@ -1,5 +1,6 @@ @@ -122,6 +127,7 @@ function clearBulkUserSelection() {

Reservar uma Sala

+
diff --git a/src/db.php b/src/db.php index c3b0a4a..fad1dd0 100644 --- a/src/db.php +++ b/src/db.php @@ -18,7 +18,9 @@ $db = new mysqli($db['servidor'], $db['user'], $db['password'], $dbName, $db['porta']); if ($db->connect_error) { - die("Ligação ao servidor falhou: " . $db->connect_error); + error_log("ClassLink DB connection failed: " . $db->connect_error); + http_response_code(500); + die("Ligação ao servidor falhou."); } $db->set_charset("utf8mb4"); @@ -112,4 +114,4 @@ // Constant for pre-registered user ID prefix define('PRE_REGISTERED_PREFIX', 'pre_'); -?> \ No newline at end of file +?>