amélioration de la gestion utilisateurs (partie 1)

This commit is contained in:
Esenjin 2024-12-24 22:13:10 +01:00
parent 51c7456ac0
commit a7ee569fff
4 changed files with 234 additions and 52 deletions

View File

@ -1,22 +1,64 @@
<?php
// auth.php
session_start();
require_once 'Database.php';
class Auth {
private $config;
private $db;
public function __construct() {
$this->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;
}

View File

@ -1,21 +1,36 @@
<?php
// config.php
return [
'users' => [
'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
]
]
];
?>

111
database.php Normal file
View File

@ -0,0 +1,111 @@
<?php
// Database.php
class Database {
private $db;
private static $instance = null;
private function __construct() {
$config = require 'config.php';
$this->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();
}
}
?>

30
database.sql Normal file
View File

@ -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');