diff --git a/index.php b/index.php index 0c4fd9e..c920585 100644 --- a/index.php +++ b/index.php @@ -1,12 +1,24 @@ conn = $db; @@ -44,28 +46,55 @@ class User { // --- 2. CONNEXION --- public function login($email, $password) { - $query = "SELECT id, username, email, password, pairing_code, partner_id FROM " . $this->table_name . " WHERE email = :email LIMIT 0,1"; + $query = "SELECT id, username, email, password, pairing_code, partner_id, failed_attempts, locked_until FROM " . $this->table_name . " WHERE email = :email LIMIT 0,1"; $stmt = $this->conn->prepare($query); $stmt->bindParam(":email", $email); $stmt->execute(); - if ($stmt->rowCount() > 0) { - $row = $stmt->fetch(); - - // Vérification du mot de passe - if (password_verify($password, $row['password'])) { - return [ - "success" => true, - "user" => [ - "id" => $row['id'], - "username" => $row['username'], - "email" => $row['email'], - "pairing_code" => $row['pairing_code'], - "partner_id" => $row['partner_id'] - ] - ]; - } + if ($stmt->rowCount() === 0) { + return ["success" => false, "message" => "Identifiants incorrects."]; } + + $row = $stmt->fetch(); + + // Compte temporairement verrouillé après trop d'échecs + if ($row['locked_until'] && strtotime($row['locked_until']) > time()) { + return ["success" => false, "message" => "Trop de tentatives échouées. Réessaie dans quelques minutes."]; + } + + // Vérification du mot de passe + if (password_verify($password, $row['password'])) { + $reset = $this->conn->prepare("UPDATE " . $this->table_name . " SET failed_attempts = 0, locked_until = NULL WHERE id = :id"); + $reset->bindParam(":id", $row['id']); + $reset->execute(); + + return [ + "success" => true, + "user" => [ + "id" => $row['id'], + "username" => $row['username'], + "email" => $row['email'], + "pairing_code" => $row['pairing_code'], + "partner_id" => $row['partner_id'] + ] + ]; + } + + // Échec : on incrémente le compteur et on verrouille si le seuil est atteint + $attempts = $row['failed_attempts'] + 1; + if ($attempts >= $this->max_attempts) { + $lock = $this->conn->prepare("UPDATE " . $this->table_name . " SET failed_attempts = :attempts, locked_until = DATE_ADD(NOW(), INTERVAL :minutes MINUTE) WHERE id = :id"); + $lock->bindParam(":attempts", $attempts, PDO::PARAM_INT); + $lock->bindParam(":minutes", $this->lockout_minutes, PDO::PARAM_INT); + $lock->bindParam(":id", $row['id']); + $lock->execute(); + } else { + $incr = $this->conn->prepare("UPDATE " . $this->table_name . " SET failed_attempts = :attempts WHERE id = :id"); + $incr->bindParam(":attempts", $attempts, PDO::PARAM_INT); + $incr->bindParam(":id", $row['id']); + $incr->execute(); + } + return ["success" => false, "message" => "Identifiants incorrects."]; } diff --git a/webhook.php b/webhook.php index b192ade..80a9774 100755 --- a/webhook.php +++ b/webhook.php @@ -14,8 +14,10 @@ $database = new Database(); $secret = $database->webhook_secret; $payload = file_get_contents('php://input'); -$signatureHeader = $_SERVER['HTTP_X_HUB_SIGNATURE_256'] ?? ''; -$expectedSignature = 'sha256=' . hash_hmac('sha256', $payload, $secret); +// Gitea (auto-hébergé) envoie un hex brut dans X-Gitea-Signature, sans préfixe "sha256=" +// (contrairement à GitHub qui utilise X-Hub-Signature-256 avec le préfixe) +$signatureHeader = $_SERVER['HTTP_X_GITEA_SIGNATURE'] ?? ''; +$expectedSignature = hash_hmac('sha256', $payload, $secret); // Comparaison en temps constant pour éviter les attaques par timing if (!$signatureHeader || !hash_equals($expectedSignature, $signatureHeader)) {