diff --git a/api/bootstrap.php b/api/bootstrap.php index 156527c..9fed1cc 100644 --- a/api/bootstrap.php +++ b/api/bootstrap.php @@ -29,12 +29,14 @@ if (!isset($_SESSION['user']) && isset($_COOKIE['telvero_remember'])) { if ($decoded && $decoded['expires'] > time()) { $_SESSION['user'] = $decoded['user']; $_SESSION['full_name'] = $decoded['full_name']; + $_SESSION['role'] = $decoded['role'] ?? 'agent'; } } // 3. CAPTURE DATA FOR WP PROTECTION $cap_user = $_SESSION['user'] ?? null; $cap_name = $_SESSION['full_name'] ?? null; +$cap_role = $_SESSION['role'] ?? null; // 4. LOAD WORDPRESS $wp_load = dirname(__DIR__) . '/wp-load.php'; @@ -49,6 +51,7 @@ if (file_exists($wp_load)) { if ($cap_user && !isset($_SESSION['user'])) { $_SESSION['user'] = $cap_user; $_SESSION['full_name'] = $cap_name; + $_SESSION['role'] = $cap_role; } // 6. LOAD COMPOSER AUTOLOAD diff --git a/api/middleware/auth.php b/api/middleware/auth.php index 4243122..9e5dd8f 100644 --- a/api/middleware/auth.php +++ b/api/middleware/auth.php @@ -3,6 +3,27 @@ * Authentication middleware and handlers */ +/** + * Check if role column exists in sales_users table + * @param mysqli $db Database connection + * @return bool + */ +function roleColumnExists(mysqli $db): bool +{ + static $exists = null; + if ($exists === null) { + $result = $db->query("SHOW COLUMNS FROM sales_users LIKE 'role'"); + $exists = ($result && $result->num_rows > 0); + + // If column doesn't exist, try to add it + if (!$exists) { + $db->query("ALTER TABLE sales_users ADD COLUMN role VARCHAR(50) DEFAULT 'agent'"); + $exists = true; + } + } + return $exists; +} + /** * Handle login action * @param mysqli $db Database connection @@ -13,7 +34,14 @@ function handleLogin(mysqli $db): void $input = json_decode(file_get_contents('php://input'), true); $username = $input['username'] ?? ''; - $stmt = $db->prepare("SELECT password, full_name FROM sales_users WHERE username = ?"); + // Check if role column exists and use appropriate query + $hasRoleColumn = roleColumnExists($db); + + if ($hasRoleColumn) { + $stmt = $db->prepare("SELECT password, full_name, role FROM sales_users WHERE username = ?"); + } else { + $stmt = $db->prepare("SELECT password, full_name, 'agent' as role FROM sales_users WHERE username = ?"); + } $stmt->bind_param("s", $username); $stmt->execute(); $res = $stmt->get_result()->fetch_assoc(); @@ -21,17 +49,23 @@ function handleLogin(mysqli $db): void if ($res && password_verify($input['password'], $res['password'])) { $_SESSION['user'] = $username; $_SESSION['full_name'] = $res['full_name']; + $_SESSION['role'] = $res['role'] ?? 'agent'; // Recovery cookie payload $cookie_payload = base64_encode(json_encode([ 'user' => $username, 'full_name' => $res['full_name'], + 'role' => $res['role'] ?? 'agent', 'expires' => MIDNIGHT_TIMESTAMP ])); setcookie('telvero_remember', $cookie_payload, MIDNIGHT_TIMESTAMP, '/', '', isset($_SERVER['HTTPS']), true); - echo json_encode(['success' => true, 'user' => $res['full_name']]); + echo json_encode([ + 'success' => true, + 'user' => $res['full_name'], + 'role' => $res['role'] ?? 'agent' + ]); } else { http_response_code(401); echo json_encode(['error' => 'Login mislukt']); @@ -47,7 +81,8 @@ function handleCheckSession(): void if (isset($_SESSION['user'])) { echo json_encode([ 'authenticated' => true, - 'user' => $_SESSION['full_name'] ?? $_SESSION['user'] + 'user' => $_SESSION['full_name'] ?? $_SESSION['user'], + 'role' => $_SESSION['role'] ?? 'agent' ]); } else { echo json_encode(['authenticated' => false]); @@ -74,6 +109,33 @@ function isAuthenticated(): bool return isset($_SESSION['user']); } +/** + * Check if user has administrator role + * @return bool + */ +function isAdmin(): bool +{ + return isset($_SESSION['role']) && $_SESSION['role'] === 'administrator'; +} + +/** + * Get current user's role + * @return string + */ +function getUserRole(): string +{ + return $_SESSION['role'] ?? 'agent'; +} + +/** + * Get current username + * @return string|null + */ +function getCurrentUsername(): ?string +{ + return $_SESSION['user'] ?? null; +} + /** * Require authentication - exits if not authenticated * @return void @@ -86,3 +148,50 @@ function requireAuth(): void exit; } } + +/** + * Require administrator role - exits if not admin + * Logs unauthorized access attempts + * @param mysqli $db Database connection for logging + * @param string $page The page being accessed + * @return void + */ +function requireAdmin(mysqli $db, string $page): void +{ + if (!isAuthenticated()) { + logUnauthorizedAccess($db, null, $page, 'not_authenticated'); + http_response_code(403); + die("Toegang geweigerd. Log eerst in."); + } + + if (!isAdmin()) { + logUnauthorizedAccess($db, getCurrentUsername(), $page, 'insufficient_permissions'); + http_response_code(403); + die("Toegang geweigerd. U heeft geen toegang tot deze pagina."); + } +} + +/** + * Log unauthorized access attempt to the database + * @param mysqli $db Database connection + * @param string|null $username The username attempting access (null if not logged in) + * @param string $page The page being accessed + * @param string $reason The reason for denial + * @return void + */ +function logUnauthorizedAccess(mysqli $db, ?string $username, string $page, string $reason): void +{ + $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; + $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown'; + $details = json_encode([ + 'page' => $page, + 'reason' => $reason, + 'ip' => $ip, + 'user_agent' => $userAgent + ]); + + $stmt = $db->prepare("INSERT INTO sales_logs (username, action_type, details, created_at) VALUES (?, 'unauthorized_access', ?, NOW())"); + $usernameForLog = $username ?? 'anonymous'; + $stmt->bind_param("ss", $usernameForLog, $details); + $stmt->execute(); +} diff --git a/index.html b/index.html index c950552..60029b8 100644 --- a/index.html +++ b/index.html @@ -5,7 +5,7 @@ Telvero Sales Panel V1 - +