diff --git a/admin_platform_users.php b/admin_platform_users.php new file mode 100644 index 0000000..1026284 --- /dev/null +++ b/admin_platform_users.php @@ -0,0 +1,293 @@ +
Access Denied. You do not have permission to manage platform users.
'; + render_footer(); + exit; +} + +$pdo = db(); +$message = ''; +$error = ''; + +// Handle Actions +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $action = $_POST['action'] ?? ''; + + if ($action === 'create' || $action === 'edit') { + $id = isset($_POST['id']) ? (int)$_POST['id'] : null; + $email = trim($_POST['email'] ?? ''); + $fullName = trim($_POST['full_name'] ?? ''); + $password = $_POST['password'] ?? ''; + $selectedPermissions = $_POST['permissions'] ?? []; + + if (empty($email) || empty($fullName)) { + $error = t('error_required'); + } else { + try { + $pdo->beginTransaction(); + + if ($action === 'create') { + // Check if email exists + $stmtCheck = $pdo->prepare("SELECT id FROM users WHERE email = ?"); + $stmtCheck->execute([$email]); + if ($stmtCheck->fetch()) { + $error = t('error_email_exists'); + } else { + if (empty($password)) { + $error = t('error_required'); + } else { + $stmt = $pdo->prepare("INSERT INTO users (email, password, full_name, role, status) VALUES (?, ?, ?, 'admin', 'active')"); + $stmt->execute([$email, password_hash($password, PASSWORD_DEFAULT), $fullName]); + $id = (int)$pdo->lastInsertId(); + $message = t('user_created'); + } + } + } else { // Edit + // Check if email exists for other user + $stmtCheck = $pdo->prepare("SELECT id FROM users WHERE email = ? AND id != ?"); + $stmtCheck->execute([$email, $id]); + if ($stmtCheck->fetch()) { + $error = t('error_email_exists'); + } else { + $sql = "UPDATE users SET email = ?, full_name = ? WHERE id = ?"; + $params = [$email, $fullName, $id]; + + if (!empty($password)) { + $sql = "UPDATE users SET email = ?, full_name = ?, password = ? WHERE id = ?"; + $params = [$email, $fullName, password_hash($password, PASSWORD_DEFAULT), $id]; + } + + $stmt = $pdo->prepare($sql); + $stmt->execute($params); + $message = t('user_updated'); + } + } + + if (!$error && $id) { + // Update Permissions + $pdo->prepare("DELETE FROM user_permissions WHERE user_id = ?")->execute([$id]); + + if (!empty($selectedPermissions)) { + $stmtPerm = $pdo->prepare("INSERT INTO user_permissions (user_id, permission_id) VALUES (?, ?)"); + foreach ($selectedPermissions as $permId) { + $stmtPerm->execute([$id, $permId]); + } + } + } + + if (!$error) { + $pdo->commit(); + } else { + $pdo->rollBack(); + } + + } catch (Exception $e) { + $pdo->rollBack(); + $error = $e->getMessage(); + } + } + } elseif ($action === 'delete') { + $id = (int)($_POST['id'] ?? 0); + if ($id === $_SESSION['user_id']) { + $error = "You cannot delete your own account."; + } else { + $pdo->prepare("DELETE FROM users WHERE id = ? AND role = 'admin'")->execute([$id]); + $message = t('user_deleted'); + } + } +} + +// Fetch Users +$stmtUsers = $pdo->query("SELECT id, email, full_name, created_at FROM users WHERE role = 'admin' ORDER BY created_at DESC"); +$users = $stmtUsers->fetchAll(); + +// Fetch Permissions +$stmtPerms = $pdo->query("SELECT id, slug, name, description FROM permissions ORDER BY name ASC"); +$allPermissions = $stmtPerms->fetchAll(); + +render_header(t('nav_platform_users'), 'platform_users', true); +?> + +
+
+ +
+
+
+

+ +
+ + +
+ + +
+ + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ID
# + + + + +
+
+
+
+
+
+ + + + + +
+ + +
+ + + + \ No newline at end of file diff --git a/admin_shippers.php b/admin_shippers.php index 064cb66..930730f 100644 --- a/admin_shippers.php +++ b/admin_shippers.php @@ -6,6 +6,14 @@ require_once __DIR__ . '/includes/layout.php'; $errors = []; $flash = null; +// Check permission +if (!has_permission('manage_shippers')) { + render_header(t('shippers'), 'shippers'); + echo '
Access Denied. You do not have permission to manage shippers.
'; + render_footer(); + exit; +} + // Handle action (Approve / Reject / Delete if necessary) if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'], $_POST['user_id'])) { $userId = (int)$_POST['user_id']; diff --git a/admin_truck_owners.php b/admin_truck_owners.php index 8e0ac9e..f812709 100644 --- a/admin_truck_owners.php +++ b/admin_truck_owners.php @@ -6,6 +6,14 @@ require_once __DIR__ . '/includes/layout.php'; $errors = []; $flash = null; +// Check permission +if (!has_permission('manage_truck_owners')) { + render_header(t('truck_owners'), 'truck_owners'); + echo '
Access Denied. You do not have permission to manage truck owners.
'; + render_footer(); + exit; +} + if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'], $_POST['user_id'])) { $userId = (int)$_POST['user_id']; $action = $_POST['action']; diff --git a/db/migrations/add_platform_permissions.php b/db/migrations/add_platform_permissions.php new file mode 100644 index 0000000..6a79462 --- /dev/null +++ b/db/migrations/add_platform_permissions.php @@ -0,0 +1,67 @@ +exec(" + CREATE TABLE IF NOT EXISTS permissions ( + id INT AUTO_INCREMENT PRIMARY KEY, + slug VARCHAR(100) NOT NULL UNIQUE, + name VARCHAR(100) NOT NULL, + description TEXT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + "); + + // 2. Create user_permissions table + $pdo->exec(" + CREATE TABLE IF NOT EXISTS user_permissions ( + user_id INT NOT NULL, + permission_id INT NOT NULL, + PRIMARY KEY (user_id, permission_id), + FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, + FOREIGN KEY (permission_id) REFERENCES permissions(id) ON DELETE CASCADE + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + "); + + // 3. Seed default permissions + $permissions = [ + ['slug' => 'manage_platform_users', 'name' => 'Manage Platform Users', 'description' => 'Create and manage admin users and their permissions.'], + ['slug' => 'manage_shippers', 'name' => 'Manage Shippers', 'description' => 'View, approve, and edit shipper accounts.'], + ['slug' => 'manage_truck_owners', 'name' => 'Manage Truck Owners', 'description' => 'View, approve, and edit truck owner accounts.'], + ['slug' => 'manage_shipments', 'name' => 'Manage Shipments', 'description' => 'View and edit shipments.'], + ['slug' => 'manage_content', 'name' => 'Manage Content', 'description' => 'Edit FAQs, Landing Pages, and other content.'], + ['slug' => 'manage_settings', 'name' => 'Manage Settings', 'description' => 'Edit global application settings.'], + ['slug' => 'view_reports', 'name' => 'View Reports', 'description' => 'Access dashboard reports and statistics.'] + ]; + + $stmtInsert = $pdo->prepare("INSERT IGNORE INTO permissions (slug, name, description) VALUES (:slug, :name, :description)"); + + foreach ($permissions as $perm) { + $stmtInsert->execute($perm); + } + + // 4. Assign all permissions to existing admins + // First, get all permission IDs + $stmtPerms = $pdo->query("SELECT id FROM permissions"); + $allPermIds = $stmtPerms->fetchAll(PDO::FETCH_COLUMN); + + // Get all admin users + $stmtAdmins = $pdo->query("SELECT id FROM users WHERE role = 'admin'"); + $adminIds = $stmtAdmins->fetchAll(PDO::FETCH_COLUMN); + + $stmtAssign = $pdo->prepare("INSERT IGNORE INTO user_permissions (user_id, permission_id) VALUES (:uid, :pid)"); + + foreach ($adminIds as $uid) { + foreach ($allPermIds as $pid) { + $stmtAssign->execute(['uid' => $uid, 'pid' => $pid]); + } + } + + echo "Permissions tables created and seeded successfully."; + +} catch (PDOException $e) { + echo "Error: " . $e->getMessage(); +} diff --git a/includes/app.php b/includes/app.php index eadc88d..9b99ab8 100644 --- a/includes/app.php +++ b/includes/app.php @@ -192,6 +192,18 @@ $translations = [ 'welcome_back_owner' => 'Find loads and submit your best rate.', 'total_offers' => 'Total Offers', 'won_shipments' => 'Won Shipments', + 'nav_platform_users' => 'Platform Users', + 'manage_permissions' => 'Manage Permissions', + 'create_user' => 'Create User', + 'edit_user' => 'Edit User', + 'delete_user' => 'Delete User', + 'confirm_delete' => 'Are you sure you want to delete this user?', + 'permissions' => 'Permissions', + 'no_users' => 'No platform users found.', + 'user_created' => 'User created successfully.', + 'user_updated' => 'User updated successfully.', + 'user_deleted' => 'User deleted successfully.', + 'error_email_exists' => 'Email already exists.' ), "ar" => array ( 'app_name' => 'CargoLink', @@ -372,6 +384,18 @@ $translations = [ 'welcome_back_owner' => 'ابحث عن الأحمال وقدم أفضل سعر لديك.', 'total_offers' => 'إجمالي العروض', 'won_shipments' => 'الشحنات الفائزة', + 'nav_platform_users' => 'مستخدمو المنصة', + 'manage_permissions' => 'إدارة الصلاحيات', + 'create_user' => 'إنشاء مستخدم', + 'edit_user' => 'تعديل المستخدم', + 'delete_user' => 'حذف المستخدم', + 'confirm_delete' => 'هل أنت متأكد أنك تريد حذف هذا المستخدم؟', + 'permissions' => 'الصلاحيات', + 'no_users' => 'لم يتم العثور على مستخدمين.', + 'user_created' => 'تم إنشاء المستخدم بنجاح.', + 'user_updated' => 'تم تحديث المستخدم بنجاح.', + 'user_deleted' => 'تم حذف المستخدم بنجاح.', + 'error_email_exists' => 'البريد الإلكتروني موجود بالفعل.' ) ]; @@ -549,3 +573,35 @@ function get_setting(string $key, $default = ''): string $settings = get_settings(); return $settings[$key] ?? $default; } + +function has_permission(string $permissionSlug, ?int $userId = null): bool +{ + if ($userId === null) { + if (!isset($_SESSION['user_id'])) { + return false; + } + $userId = $_SESSION['user_id']; + } + + static $cache = []; + $key = $userId . ':' . $permissionSlug; + + if (isset($cache[$key])) { + return $cache[$key]; + } + + try { + $stmt = db()->prepare( + "SELECT 1 + FROM user_permissions up + JOIN permissions p ON up.permission_id = p.id + WHERE up.user_id = ? AND p.slug = ?" + ); + $stmt->execute([$userId, $permissionSlug]); + $result = (bool) $stmt->fetchColumn(); + $cache[$key] = $result; + return $result; + } catch (Throwable $e) { + return false; + } +} \ No newline at end of file diff --git a/includes/layout.php b/includes/layout.php index 267e0bd..8408915 100644 --- a/includes/layout.php +++ b/includes/layout.php @@ -1,7 +1,7 @@ "> + +
+ + @@ -214,7 +218,7 @@ function render_admin_sidebar(string $active = 'dashboard'): void { $settingsActive = in_array($active, ['company_profile', 'integrations', 'notification_templates']); $locationsActive = in_array($active, ['countries', 'cities']); - $usersActive = in_array($active, ['shippers', 'truck_owners', 'register']); + $usersActive = in_array($active, ['shippers', 'truck_owners', 'register', 'platform_users']); $pagesActive = in_array($active, ['faqs', 'landing_pages']); ?>
@@ -153,4 +153,4 @@ render_header('Login / Reset Password', 'login');
- \ No newline at end of file + \ No newline at end of file