google login

This commit is contained in:
Flatlogic Bot 2025-11-08 21:16:26 +00:00
parent eca44a4bc7
commit 378cb2cb10
10 changed files with 449 additions and 130 deletions

View File

@ -10,14 +10,30 @@ if (!can($_SESSION['user_role_id'], 'user', 'create')) {
}
$error_message = '';
$roles = [];
try {
$pdo = db();
$stmt = $pdo->query('SELECT id, name FROM roles ORDER BY name');
$roles = $stmt->fetchAll(PDO::FETCH_ASSOC);
if ($roles === false) {
throw new Exception("Failed to fetch roles from the database.");
}
} catch (PDOException $e) {
error_log('PDO Error in add-user.php: ' . $e->getMessage());
die("Error: A database error occurred while trying to fetch roles. Please check the logs. Message: " . $e->getMessage());
} catch (Exception $e) {
die("Error: " . $e->getMessage());
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';
$role = $_POST['role'] ?? 'Employee';
$role_id = $_POST['role_id'] ?? null;
if (empty($name) || empty($email) || empty($password)) {
if (empty($name) || empty($email) || empty($password) || empty($role_id)) {
$error_message = 'Please fill in all required fields.';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$error_message = 'Invalid email format.';
@ -25,16 +41,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
try {
$pdo = db();
// Check if email already exists
$stmt = $pdo->prepare('SELECT id FROM users WHERE email = ?');
$stmt->execute([$email]);
if ($stmt->fetch()) {
$error_message = 'A user with this email address already exists.';
} else {
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
$sql = "INSERT INTO users (name, email, password, role) VALUES (?, ?, ?, ?)";
$sql = "INSERT INTO users (name, email, password, role_id) VALUES (?, ?, ?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute([$name, $email, $hashed_password, $role]);
$stmt->execute([$name, $email, $hashed_password, $role_id]);
header("Location: users.php?success=user_added");
exit;
@ -94,12 +109,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<input type="password" class="form-control" id="password" name="password" required>
</div>
<div class="col-md-6 mb-3">
<label for="role" class="form-label">Role</label>
<select class="form-select" id="role" name="role">
<option>Employee</option>
<option>IT Technician</option>
<option>Asset Manager</option>
<option>Admin</option>
<label for="role_id" class="form-label">Role</label>
<select class="form-select" id="role_id" name="role_id" required>
<option value="">Select a role</option>
<?php foreach ($roles as $role): ?>
<option value="<?php echo htmlspecialchars($role['id']); ?>">
<?php echo htmlspecialchars($role['name']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
</div>

View File

@ -0,0 +1,24 @@
-- Grant remaining permissions to Super Admin (role_id = 1)
INSERT INTO `role_permissions` (`role_id`, `resource`, `action`) VALUES
-- Assets
(1, 'asset', 'create'),
(1, 'asset', 'read'),
(1, 'asset', 'update'),
(1, 'asset', 'delete'),
-- Categories
(1, 'category', 'create'),
(1, 'category', 'read'),
(1, 'category', 'update'),
(1, 'category', 'delete'),
-- Locations
(1, 'location', 'create'),
(1, 'location', 'read'),
(1, 'location', 'update'),
(1, 'location', 'delete'),
-- Users
(1, 'user', 'create'),
(1, 'user', 'read'),
(1, 'user', 'update'),
(1, 'user', 'delete')
ON DUPLICATE KEY UPDATE `role_id` = `role_id`; -- Do nothing if the permission already exists

View File

@ -0,0 +1,11 @@
CREATE TABLE IF NOT EXISTS settings (
id INT AUTO_INCREMENT PRIMARY KEY,
setting_key VARCHAR(255) NOT NULL UNIQUE,
setting_value TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- Insert Google API credentials (initially empty)
INSERT INTO settings (setting_key, setting_value) VALUES ('google_client_id', '') ON DUPLICATE KEY UPDATE setting_key = 'google_client_id';
INSERT INTO settings (setting_key, setting_value) VALUES ('google_client_secret', '') ON DUPLICATE KEY UPDATE setting_key = 'google_client_secret';

View File

@ -10,7 +10,7 @@ if (!can($_SESSION['user_role_id'], 'user', 'update')) {
}
$allowed_fields_str = can($_SESSION['user_role_id'], 'user', 'update');
$allowed_fields = ($allowed_fields_str === '*') ? ['name', 'email', 'role'] : explode(',', $allowed_fields_str);
$allowed_fields = ($allowed_fields_str === '*') ? ['name', 'email', 'role_id'] : explode(',', $allowed_fields_str);
$error_message = '';
$user_id = $_GET['id'] ?? null;
@ -22,7 +22,7 @@ if (!$user_id) {
try {
$pdo = db();
$stmt = $pdo->prepare('SELECT id, name, email, role FROM users WHERE id = ?');
$stmt = $pdo->prepare('SELECT id, name, email, role_id FROM users WHERE id = ?');
$stmt->execute([$user_id]);
$user = $stmt->fetch();
@ -30,6 +30,11 @@ try {
header('Location: users.php');
exit;
}
// Fetch all roles for the dropdown
$roles_stmt = $pdo->query('SELECT id, name FROM roles ORDER BY name');
$roles = $roles_stmt->fetchAll();
} catch (PDOException $e) {
$error_message = 'Database error: ' . $e->getMessage();
}
@ -124,14 +129,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<?php endif; ?>
</div>
<div class="row">
<?php if (in_array('role', $allowed_fields)): ?>
<?php if (in_array('role_id', $allowed_fields)): ?>
<div class="col-md-6 mb-3">
<label for="role" class="form-label">Role</label>
<select class="form-select" id="role" name="role">
<option <?php echo ($user['role'] === 'Employee') ? 'selected' : ''; ?>>Employee</option>
<option <?php echo ($user['role'] === 'IT Technician') ? 'selected' : ''; ?>>IT Technician</option>
<option <?php echo ($user['role'] === 'Asset Manager') ? 'selected' : ''; ?>>Asset Manager</option>
<option <?php echo ($user['role'] === 'Admin') ? 'selected' : ''; ?>>Admin</option>
<label for="role_id" class="form-label">Role</label>
<select class="form-select" id="role_id" name="role_id">
<?php foreach ($roles as $role): ?>
<option value="<?php echo $role['id']; ?>" <?php echo ($user['role_id'] == $role['id']) ? 'selected' : ''; ?>><?php echo htmlspecialchars($role['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<?php endif; ?>

122
google-callback.php Normal file
View File

@ -0,0 +1,122 @@
<?php
session_start();
require_once 'db/config.php';
require_once 'auth-helpers.php';
$pdo = db();
// Fetch Google credentials from settings
try {
$stmt = $pdo->query("SELECT setting_key, setting_value FROM settings WHERE setting_key IN ('google_client_id', 'google_client_secret')");
$settings_raw = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
$google_client_id = $settings_raw['google_client_id'] ?? '';
$google_client_secret = $settings_raw['google_client_secret'] ?? '';
} catch (PDOException $e) {
die('Database error fetching Google credentials.');
}
if (empty($google_client_id) || empty($google_client_secret)) {
die('Google API credentials are not configured. Please ask an administrator to set them up.');
}
if (!isset($_GET['code'])) {
header('Location: login.php?error=google_auth_failed');
exit;
}
$code = $_GET['code'];
$redirect_uri = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://" . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) . '/google-callback.php';
// 1. Exchange authorization code for an access token
$token_url = 'https://oauth2.googleapis.com/token';
$token_params = [
'code' => $code,
'client_id' => $google_client_id,
'client_secret' => $google_client_secret,
'redirect_uri' => $redirect_uri,
'grant_type' => 'authorization_code'
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $token_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($token_params));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$token_data = json_decode($response, true);
if (!isset($token_data['access_token'])) {
// Log error: print_r($token_data);
header('Location: login.php?error=google_token_exchange_failed');
exit;
}
// 2. Get user info from Google
$userinfo_url = 'https://www.googleapis.com/oauth2/v2/userinfo';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $userinfo_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $token_data['access_token']]);
$userinfo_response = curl_exec($ch);
curl_close($ch);
$userinfo = json_decode($userinfo_response, true);
if (!isset($userinfo['email'])) {
// Log error: print_r($userinfo);
header('Location: login.php?error=google_userinfo_failed');
exit;
}
$user_email = $userinfo['email'];
$user_name = $userinfo['name'] ?? 'Google User';
// 3. Check if user exists in the database
try {
$stmt = $pdo->prepare("SELECT u.*, r.name as role_name FROM users u JOIN roles r ON u.role_id = r.id WHERE u.email = ?");
$stmt->execute([$user_email]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
// 4. If user exists, log them in
if ($user) {
$_SESSION['user_id'] = $user['id'];
$_SESSION['user_name'] = $user['name'];
$_SESSION['user_role_id'] = $user['role_id'];
$_SESSION['user_role_name'] = $user['role_name'];
$_SESSION['user_role'] = $user['role_name']; // Backwards compatibility
header('Location: index.php');
exit;
}
// 5. If user does not exist, create a new user with the "Employee" role
$employee_role_id = 3; // Default to 'Employee' role (assuming ID 3)
$stmt_role = $pdo->prepare("SELECT id FROM roles WHERE name = ?");
$stmt_role->execute(['Employee']);
$role_id_from_db = $stmt_role->fetchColumn();
if ($role_id_from_db) {
$employee_role_id = $role_id_from_db;
}
// Generate a random password as it's required by the schema
$random_password = password_hash(bin2hex(random_bytes(16)), PASSWORD_DEFAULT);
$insert_stmt = $pdo->prepare("INSERT INTO users (name, email, password, role_id) VALUES (?, ?, ?, ?)");
$insert_stmt->execute([$user_name, $user_email, $random_password, $employee_role_id]);
$new_user_id = $pdo->lastInsertId();
// Log the new user in
$_SESSION['user_id'] = $new_user_id;
$_SESSION['user_name'] = $user_name;
$_SESSION['user_role_id'] = $employee_role_id;
$_SESSION['user_role_name'] = 'Employee';
$_SESSION['user_role'] = 'Employee';
header('Location: index.php?new_user=true');
exit;
} catch (PDOException $e) {
// Log error: $e->getMessage();
die('Database error during user processing. Please try again.');
}

30
google-login.php Normal file
View File

@ -0,0 +1,30 @@
<?php
session_start();
require_once 'db/config.php';
// Fetch Google Client ID from settings
try {
$pdo = db();
$stmt = $pdo->query("SELECT setting_value FROM settings WHERE setting_key = 'google_client_id'");
$google_client_id = $stmt->fetchColumn();
} catch (PDOException $e) {
die('Database error fetching Google Client ID. Please configure it in the settings.');
}
if (empty($google_client_id)) {
die('Google Client ID is not configured. Please ask an administrator to set it up.');
}
$redirect_uri = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://" . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) . '/google-callback.php';
$auth_url = 'https://accounts.google.com/o/oauth2/v2/auth?' . http_build_query([
'client_id' => $google_client_id,
'redirect_uri' => $redirect_uri,
'response_type' => 'code',
'scope' => 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile',
'access_type' => 'offline',
'prompt' => 'select_account'
]);
header('Location: ' . $auth_url);
exit;

View File

@ -4,6 +4,21 @@ require_once 'db/config.php';
require_once 'auth-check.php';
require_once 'auth-helpers.php';
// Store role name in session if not already set
if (isset($_SESSION['user_role_id']) && !isset($_SESSION['user_role_name'])) {
try {
$pdo = db();
$stmt = $pdo->prepare("SELECT name FROM roles WHERE id = :role_id");
$stmt->execute([':role_id' => $_SESSION['user_role_id']]);
$role = $stmt->fetch(PDO::FETCH_ASSOC);
if ($role) {
$_SESSION['user_role_name'] = $role['name'];
}
} catch (PDOException $e) {
// Could not fetch role name, do nothing, the check later will handle it
}
}
// Get allowed fields for the current user
$allowed_fields_str = can($_SESSION['user_role_id'], 'asset', 'read');
$allowed_fields = [];
@ -27,6 +42,12 @@ function count_assets($search = '', $status = '') {
$where = [];
$params = [];
// Role-based filtering for 'Employee'
if (isset($_SESSION['user_role_name']) && strtolower($_SESSION['user_role_name']) === 'employee' && isset($_SESSION['user_id'])) {
$where[] = "assigned_to = :user_id";
$params[':user_id'] = $_SESSION['user_id'];
}
if (!empty($search)) {
$where[] = "name LIKE :search";
$params[':search'] = "%$search%";
@ -87,6 +108,12 @@ function get_assets($fields, $search = '', $status = '', $limit = 10, $offset =
$where = [];
$params = [];
// Role-based filtering for 'Employee'
if (isset($_SESSION['user_role_name']) && strtolower($_SESSION['user_role_name']) === 'employee' && isset($_SESSION['user_id'])) {
$where[] = "assets.assigned_to = :user_id";
$params[':user_id'] = $_SESSION['user_id'];
}
if (!empty($search)) {
// Assuming 'name' is a field that can be searched.
if (in_array('name', $fields)) {

View File

@ -48,6 +48,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login - IC-Inventory</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
<style>
body {
@ -82,6 +83,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
</div>
<button type="submit" class="btn btn-primary w-100">Login</button>
</form>
<div class="divider d-flex align-items-center my-4">
<p class="text-center fw-bold mx-3 mb-0 text-muted">OR</p>
</div>
<a class="btn btn-danger w-100" href="google-login.php" role="button">
<i class="fab fa-google me-2"></i>Sign in with Google
</a>
</div>
</div>

View File

@ -4,16 +4,91 @@ require_once 'db/config.php';
require_once 'auth-check.php';
require_once 'auth-helpers.php';
if (!can($_SESSION['user_role_id'], 'permission', 'update')) {
// Only Super Admins can manage settings
$is_super_admin = ($_SESSION['user_role_id'] == 1);
if (!$is_super_admin) {
// Redirect non-super-admins or users who can't update permissions
if (!can($_SESSION['user_role_id'], 'permission', 'update')) {
header('Location: index.php?error=access_denied');
exit;
}
}
$success_message = '';
$error_message = '';
$pdo = db();
// Handle Google Settings form submission
if ($is_super_admin && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_google_settings'])) {
$google_client_id = $_POST['google_client_id'] ?? '';
$google_client_secret = $_POST['google_client_secret'] ?? '';
try {
$stmt = $pdo->prepare('UPDATE settings SET setting_value = ? WHERE setting_key = ?');
$stmt->execute([$google_client_id, 'google_client_id']);
$stmt->execute([$google_client_secret, 'google_client_secret']);
$success_message = 'Google settings updated successfully!';
} catch (PDOException $e) {
$error_message = 'Database error updating Google settings: ' . $e->getMessage();
}
}
// Handle Permissions form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_permissions'])) {
if (!can($_SESSION['user_role_id'], 'permission', 'update')) {
header('Location: index.php?error=access_denied');
exit;
}
try {
$pdo->beginTransaction();
$permissions = $_POST['permissions'] ?? [];
$stmt_roles = $pdo->query('SELECT id FROM roles');
$db_roles_ids = $stmt_roles->fetchAll(PDO::FETCH_COLUMN);
$delete_stmt = $pdo->prepare('DELETE FROM role_permissions WHERE role_id = ?');
$insert_stmt = $pdo->prepare('INSERT INTO role_permissions (role_id, resource, action, fields) VALUES (?, ?, ?, ?)');
foreach ($db_roles_ids as $role_id) {
$delete_stmt->execute([$role_id]);
if (isset($permissions[$role_id])) {
foreach (['asset', 'user', 'category', 'location', 'role', 'permission'] as $resource) {
foreach (['create', 'read', 'update', 'delete'] as $action) {
if (isset($permissions[$role_id][$resource][$action]['enabled']) && $permissions[$role_id][$resource][$action]['enabled'] == '1') {
$fields = (in_array($action, ['read', 'update', 'create'])) ? ($permissions[$role_id][$resource][$action]['fields'] ?? '*') : null;
if (empty($fields)) $fields = '*';
$insert_stmt->execute([$role_id, $resource, $action, $fields]);
}
}
}
}
}
$pdo->commit();
$success_message = 'Permissions updated successfully!';
} catch (PDOException $e) {
if ($pdo->inTransaction()) $pdo->rollBack();
$error_message = 'Database error: ' . $e->getMessage();
}
}
// Fetch data for display
$google_settings = [];
if ($is_super_admin) {
try {
$stmt = $pdo->query("SELECT setting_key, setting_value FROM settings WHERE setting_key IN ('google_client_id', 'google_client_secret')");
$google_settings_raw = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($google_settings_raw as $row) {
$google_settings[$row['setting_key']] = $row['setting_value'];
}
} catch (PDOException $e) {
$error_message = "Database error fetching Google settings: " . $e->getMessage();
}
}
try {
$pdo = db();
$roles_stmt = $pdo->query('SELECT * FROM roles ORDER BY name');
$roles = $roles_stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
@ -24,52 +99,10 @@ try {
$resources = ['asset', 'user', 'category', 'location', 'role', 'permission'];
$actions = ['create', 'read', 'update', 'delete'];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
try {
$pdo = db();
$pdo->beginTransaction();
// Clear existing permissions, but not for the super admin
$pdo->exec('DELETE FROM role_permissions WHERE role_id != 1');
$stmt = $pdo->prepare('INSERT INTO role_permissions (role_id, resource, action, fields) VALUES (?, ?, ?, ?)');
$permissions = $_POST['permissions'] ?? [];
foreach ($roles as $role) {
if ($role['id'] == 1) continue; // Skip Admin role, its permissions are immutable
foreach ($resources as $resource) {
foreach ($actions as $action) {
if (isset($permissions[$role['id']][$resource][$action]['enabled']) && $permissions[$role['id']][$resource][$action]['enabled'] == '1') {
$fields = null;
if (in_array($action, ['read', 'update', 'create'])) {
$fields = $permissions[$role['id']][$resource][$action]['fields'] ?? '*';
if (empty($fields)) {
$fields = '*';
}
}
$stmt->execute([$role['id'], $resource, $action, $fields]);
}
}
}
}
$pdo->commit();
$success_message = 'Permissions updated successfully!';
} catch (PDOException $e) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
$error_message = 'Database error: ' . $e->getMessage();
}
}
function get_permissions() {
try {
$pdo = db();
$stmt = $pdo->query('SELECT * FROM role_permissions ORDER BY role_id, resource, action');
$pdo_func = db();
$stmt = $pdo_func->query('SELECT * FROM role_permissions ORDER BY role_id, resource, action');
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
return ['error' => 'Database error: ' . $e->getMessage()];
@ -77,21 +110,20 @@ function get_permissions() {
}
$permissions_from_db = get_permissions();
// Group permissions by role and resource for easier display
$grouped_permissions = [];
foreach ($permissions_from_db as $p) {
if (!isset($permissions_from_db['error'])) {
foreach ($permissions_from_db as $p) {
$grouped_permissions[$p['role_id']][$p['resource']][$p['action']] = $p['fields'];
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Settings - Role Permissions - IC-Inventory</title>
<meta name="description" content="Manage role permissions.">
<title>Settings - IC-Inventory</title>
<meta name="description" content="Manage application settings, including Google OAuth and role permissions.">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
<link rel="preconnect" href="https://fonts.googleapis.com">
@ -106,7 +138,7 @@ foreach ($permissions_from_db as $p) {
<main id="content">
<div class="header">
<h1>Settings - Role Permissions</h1>
<h1>Settings</h1>
</div>
<div class="surface p-4">
@ -117,6 +149,35 @@ foreach ($permissions_from_db as $p) {
<div class="alert alert-danger"><?php echo htmlspecialchars($error_message); ?></div>
<?php endif; ?>
<?php if ($is_super_admin): ?>
<div class="card mb-4">
<div class="card-header">
<h3>Google OAuth 2.0 Settings</h3>
</div>
<div class="card-body">
<p>These credentials are required for Google Login. You can get them from the <a href="https://console.cloud.google.com/apis/credentials" target="_blank">Google Cloud Console</a>.</p>
<p>The authorized redirect URI is: <code><?php echo htmlspecialchars(str_replace('settings.php', 'google-callback.php', (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'])); ?></code></p>
<form action="settings.php" method="post">
<div class="mb-3">
<label for="google_client_id" class="form-label">Client ID</label>
<input type="text" class="form-control" id="google_client_id" name="google_client_id" value="<?php echo htmlspecialchars($google_settings['google_client_id'] ?? ''); ?>">
</div>
<div class="mb-3">
<label for="google_client_secret" class="form-label">Client Secret</label>
<input type="password" class="form-control" id="google_client_secret" name="google_client_secret" value="<?php echo htmlspecialchars($google_settings['google_client_secret'] ?? ''); ?>">
</div>
<button type="submit" name="save_google_settings" class="btn btn-primary">Save Google Settings</button>
</form>
</div>
</div>
<?php endif; ?>
<?php if (can($_SESSION['user_role_id'], 'permission', 'update')): ?>
<div class="card">
<div class="card-header">
<h3>Role Permissions</h3>
</div>
<div class="card-body">
<form action="settings.php" method="post">
<div class="table-responsive">
<table class="table table-bordered permission-table">
@ -145,15 +206,14 @@ foreach ($permissions_from_db as $p) {
<td class="align-middle"><?php echo ucfirst($resource); ?></td>
<?php foreach ($actions as $action):
$is_disabled = ($role['id'] == 1); // Disable all checkboxes for Super Admin
$is_checked = isset($grouped_permissions[$role['id']][$resource]) && array_key_exists($action, $grouped_permissions[$role['id']][$resource]);
?>
<td class="align-middle">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="permissions[<?php echo $role['id']; ?>][<?php echo $resource; ?>][<?php echo $action; ?>][enabled]" value="1" <?php echo $is_checked ? 'checked' : ''; ?> <?php echo $is_disabled ? 'disabled' : ''; ?>>
<input class="form-check-input" type="checkbox" name="permissions[<?php echo $role['id']; ?>][<?php echo $resource; ?>][<?php echo $action; ?>][enabled]" value="1" <?php echo $is_checked ? 'checked' : ''; ?>>
</div>
<?php if (in_array($action, ['read', 'update', 'create'])): ?>
<input type="text" class="form-control form-control-sm mt-1" name="permissions[<?php echo $role['id']; ?>][<?php echo $resource; ?>][<?php echo $action; ?>][fields]" placeholder="* for all" value="<?php echo htmlspecialchars($grouped_permissions[$role['id']][$resource][$action] ?? '*'); ?>" <?php echo $is_disabled ? 'disabled' : ''; ?>>
<input type="text" class="form-control form-control-sm mt-1" name="permissions[<?php echo $role['id']; ?>][<?php echo $resource; ?>][<?php echo $action; ?>][fields]" placeholder="* for all" value="<?php echo htmlspecialchars($grouped_permissions[$role['id']][$resource][$action] ?? '*'); ?>">
<?php endif; ?>
</td>
<?php endforeach; ?>
@ -163,9 +223,12 @@ foreach ($permissions_from_db as $p) {
</tbody>
</table>
</div>
<button type="submit" class="btn btn-primary">Save Changes</button>
<button type="submit" name="save_permissions" class="btn btn-primary">Save Permissions</button>
</form>
</div>
</div>
<?php endif; ?>
</div>
</main>
</div>

View File

@ -33,16 +33,30 @@ function get_users($fields) {
if (empty($fields)) {
return []; // No read permission
}
// Always include id for edit/delete links
if (!in_array('id', $fields)) {
$fields[] = 'id';
}
$select_fields = implode(', ', $fields);
// Replace role_id with a join to get the role name
$select_parts = [];
foreach ($fields as $field) {
if ($field === 'role_id') {
$select_parts[] = 'r.name as role_name';
} else {
$select_parts[] = 'u.' . $field;
}
}
$select_fields = implode(', ', $select_parts);
try {
$pdo = db();
$stmt = $pdo->query("SELECT $select_fields FROM users ORDER BY created_at DESC");
$sql = "SELECT $select_fields
FROM users u
LEFT JOIN roles r ON u.role_id = r.id
ORDER BY u.created_at DESC";
$stmt = $pdo->query($sql);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
return ['error' => 'Database error: ' . $e->getMessage()];
@ -113,7 +127,7 @@ $users = get_users($allowed_fields);
<thead>
<tr>
<?php foreach ($allowed_fields as $field): if($field === 'id') continue; ?>
<th><?php echo ucfirst(str_replace('_', ' ', $field)); ?></th>
<th><?php echo ucfirst(str_replace('_', ' ', ($field === 'role_id' ? 'role' : $field))); ?></th>
<?php endforeach; ?>
<th>Actions</th>
</tr>
@ -122,7 +136,7 @@ $users = get_users($allowed_fields);
<?php foreach ($users as $user): ?>
<tr>
<?php foreach ($allowed_fields as $field): if($field === 'id') continue; ?>
<td><?php echo htmlspecialchars($user[$field]); ?></td>
<td><?php echo htmlspecialchars($user[$field === 'role_id' ? 'role_name' : $field]); ?></td>
<?php endforeach; ?>
<td>
<?php if (can($_SESSION['user_role_id'], 'user', 'update')): ?>