From a7ee569fffe5e8fc3dcc21c6df7ac72cc454b259 Mon Sep 17 00:00:00 2001 From: Esenjin Date: Tue, 24 Dec 2024 22:13:10 +0100 Subject: [PATCH] =?UTF-8?q?am=C3=A9lioration=20de=20la=20gestion=20utilisa?= =?UTF-8?q?teurs=20(partie=201)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- auth.php | 100 +++++++++++++++++++++++++++++----------------- config.php | 45 ++++++++++++++------- database.php | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++ database.sql | 30 ++++++++++++++ 4 files changed, 234 insertions(+), 52 deletions(-) create mode 100644 database.php create mode 100644 database.sql diff --git a/auth.php b/auth.php index 3106be3..7d44d24 100644 --- a/auth.php +++ b/auth.php @@ -1,22 +1,64 @@ config = require 'config.php'; + $this->db = Database::getInstance(); + } + + public function login($username, $password) { + // Vérifier les tentatives de connexion + $attempts = $this->db->checkLoginAttempts($username); + if ($attempts >= $this->config['security']['max_login_attempts']) { + return ['success' => false, 'error' => 'too_many_attempts']; + } + + $stmt = $this->db->prepare(' + SELECT id, username, password_hash, role, description + FROM users + WHERE username = :username + '); + + $stmt->bindValue(':username', $username, SQLITE3_TEXT); + $result = $stmt->execute(); + $user = $result->fetchArray(SQLITE3_ASSOC); + + // Enregistrer la tentative + $this->db->logLoginAttempt($username); + + if ($user && password_verify($password, $user['password_hash'])) { + $_SESSION['auth_time'] = time(); + $_SESSION['user_id'] = $user['id']; + $_SESSION['username'] = $user['username']; + $_SESSION['role'] = $user['role']; + $_SESSION['description'] = $user['description']; + + // Log de connexion réussie + $this->db->logActivity($user['id'], 'login'); + + return ['success' => true, 'user' => [ + 'username' => $user['username'], + 'role' => $user['role'], + 'description' => $user['description'] + ]]; + } + + return ['success' => false, 'error' => 'invalid_credentials']; } public function isAuthenticated() { - if (!isset($_SESSION['auth_time']) || !isset($_SESSION['username'])) { + if (!isset($_SESSION['auth_time']) || !isset($_SESSION['user_id'])) { return false; } - // Vérifier si la session n'a pas expiré $elapsed = time() - $_SESSION['auth_time']; - if ($elapsed > $this->config['session_duration']) { + if ($elapsed > $this->config['security']['session_duration']) { $this->logout(); return false; } @@ -24,36 +66,25 @@ class Auth { return true; } - public function login($username, $password) { - if (!isset($this->config['users'][$username])) { + public function hasPermission($action) { + if (!$this->isAuthenticated()) { return false; } - - if ($this->config['users'][$username]['password'] === $password) { - $_SESSION['auth_time'] = time(); - $_SESSION['username'] = $username; - $_SESSION['user_description'] = $this->config['users'][$username]['description']; - return true; - } - return false; + + $role = $_SESSION['role']; + return isset($this->config['roles'][$role][$action]) && + $this->config['roles'][$role][$action]; } public function logout() { - session_destroy(); - } - - public function getCurrentUser() { - if ($this->isAuthenticated()) { - return [ - 'username' => $_SESSION['username'], - 'description' => $_SESSION['user_description'] - ]; + if (isset($_SESSION['user_id'])) { + $this->db->logActivity($_SESSION['user_id'], 'logout'); } - return null; + session_destroy(); } } -// Point d'entrée API pour l'authentification +// Point d'entrée API if ($_SERVER['REQUEST_METHOD'] === 'POST') { header('Content-Type: application/json'); @@ -64,15 +95,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { switch ($data['action']) { case 'login': if (isset($data['username']) && isset($data['password'])) { - $success = $auth->login($data['username'], $data['password']); - if ($success) { - $user = $auth->getCurrentUser(); - echo json_encode(['success' => true, 'user' => $user]); - } else { - echo json_encode(['success' => false, 'error' => 'Identifiants incorrects']); - } - } else { - echo json_encode(['success' => false, 'error' => 'Identifiants manquants']); + $result = $auth->login($data['username'], $data['password']); + echo json_encode($result); } break; @@ -82,11 +106,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { break; case 'check': - $isAuthenticated = $auth->isAuthenticated(); - $user = $isAuthenticated ? $auth->getCurrentUser() : null; echo json_encode([ - 'authenticated' => $isAuthenticated, - 'user' => $user + 'authenticated' => $auth->isAuthenticated(), + 'user' => $auth->isAuthenticated() ? [ + 'username' => $_SESSION['username'], + 'role' => $_SESSION['role'], + 'description' => $_SESSION['description'] + ] : null ]); break; } diff --git a/config.php b/config.php index 7ac6d20..e642809 100644 --- a/config.php +++ b/config.php @@ -1,21 +1,36 @@ [ - 'admin' => [ - 'password' => 'votre_mot_de_passe_admin', // À changer ! - 'description' => 'Administrateur' - ], - 'user1' => [ - 'password' => 'votre_mot_de_passe_user1', // À changer ! - 'description' => 'Utilisateur 1' - ], - 'invite' => [ - 'password' => 'votre_mot_de_passe_invite', // À changer ! - 'description' => 'Invité' - ] + 'db' => [ + 'path' => __DIR__ . '/database.sqlite' ], - 'session_duration' => 3600, // Durée de la session en secondes (1 heure) - // Vous pouvez ajouter autant d'utilisateurs que nécessaire + 'security' => [ + 'session_duration' => 3600, + 'max_login_attempts' => 3, + 'attempt_window' => 1800 // 30 minutes + ], + 'roles' => [ + 'admin' => [ + 'upload' => true, + 'download' => true, + 'delete' => true, + 'rename' => true, + 'view_logs' => true + ], + 'user' => [ + 'upload' => true, + 'download' => true, + 'delete' => false, + 'rename' => false, + 'view_logs' => false + ], + 'visitor' => [ + 'upload' => false, + 'download' => true, + 'delete' => false, + 'rename' => false, + 'view_logs' => false + ] + ] ]; ?> diff --git a/database.php b/database.php new file mode 100644 index 0000000..8ad8a05 --- /dev/null +++ b/database.php @@ -0,0 +1,111 @@ +db = new SQLite3($config['db']['path']); + $this->db->enableExceptions(true); + } + + public static function getInstance() { + if (self::$instance === null) { + self::$instance = new self(); + } + return self::$instance; + } + + public function logActivity($userId, $actionType, $details = '') { + $stmt = $this->db->prepare(' + INSERT INTO activity_logs (user_id, action_type, details, ip_address) + VALUES (:user_id, :action_type, :details, :ip) + '); + + $stmt->bindValue(':user_id', $userId, SQLITE3_INTEGER); + $stmt->bindValue(':action_type', $actionType, SQLITE3_TEXT); + $stmt->bindValue(':details', $details, SQLITE3_TEXT); + $stmt->bindValue(':ip', $_SERVER['REMOTE_ADDR'], SQLITE3_TEXT); + + return $stmt->execute(); + } + + public function getActivityLogs($filters = []) { + $query = ' + SELECT + al.*, + u.username, + u.role + FROM activity_logs al + LEFT JOIN users u ON al.user_id = u.id + WHERE 1=1 + '; + + $params = []; + + if (!empty($filters['action_type'])) { + $query .= ' AND action_type = :action_type'; + $params[':action_type'] = $filters['action_type']; + } + + if (!empty($filters['date_from'])) { + $query .= ' AND created_at >= :date_from'; + $params[':date_from'] = $filters['date_from']; + } + + if (!empty($filters['date_to'])) { + $query .= ' AND created_at <= :date_to'; + $params[':date_to'] = $filters['date_to']; + } + + $query .= ' ORDER BY created_at ' . + (!empty($filters['order']) && $filters['order'] === 'asc' ? 'ASC' : 'DESC'); + + $stmt = $this->db->prepare($query); + + foreach ($params as $key => $value) { + $stmt->bindValue($key, $value); + } + + $result = $stmt->execute(); + $logs = []; + + while ($row = $result->fetchArray(SQLITE3_ASSOC)) { + $logs[] = $row; + } + + return $logs; + } + + public function checkLoginAttempts($username) { + $config = require 'config.php'; + $window = $config['security']['attempt_window']; + + $stmt = $this->db->prepare(' + SELECT COUNT(*) as attempts + FROM login_attempts + WHERE username = :username + AND attempt_time > datetime("now", "-' . $window . ' seconds") + '); + + $stmt->bindValue(':username', $username, SQLITE3_TEXT); + $result = $stmt->execute(); + $row = $result->fetchArray(); + + return $row['attempts']; + } + + public function logLoginAttempt($username) { + $stmt = $this->db->prepare(' + INSERT INTO login_attempts (username, ip_address) + VALUES (:username, :ip) + '); + + $stmt->bindValue(':username', $username, SQLITE3_TEXT); + $stmt->bindValue(':ip', $_SERVER['REMOTE_ADDR'], SQLITE3_TEXT); + + return $stmt->execute(); + } +} +?> diff --git a/database.sql b/database.sql new file mode 100644 index 0000000..1b2f8e2 --- /dev/null +++ b/database.sql @@ -0,0 +1,30 @@ +-- schema.sql +CREATE TABLE users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username VARCHAR(50) UNIQUE NOT NULL, + password_hash VARCHAR(255) NOT NULL, + role VARCHAR(20) NOT NULL CHECK (role IN ('admin', 'user', 'visitor')), + description TEXT, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE login_attempts ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + ip_address VARCHAR(45) NOT NULL, + attempt_time DATETIME DEFAULT CURRENT_TIMESTAMP, + username VARCHAR(50) +); + +CREATE TABLE activity_logs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER, + action_type VARCHAR(20) NOT NULL CHECK (action_type IN ('login', 'logout', 'upload', 'download', 'delete', 'rename')), + details TEXT, + ip_address VARCHAR(45), + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id) +); + +-- Insertion d'un utilisateur admin par défaut (mot de passe: admin123) +INSERT INTO users (username, password_hash, role, description) +VALUES ('admin', '$2y$10$YourHashedPasswordHere', 'admin', 'Administrateur principal');