google login
This commit is contained in:
parent
eca44a4bc7
commit
378cb2cb10
39
add-user.php
39
add-user.php
@ -10,14 +10,30 @@ if (!can($_SESSION['user_role_id'], 'user', 'create')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$error_message = '';
|
$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') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
$name = $_POST['name'] ?? '';
|
$name = $_POST['name'] ?? '';
|
||||||
$email = $_POST['email'] ?? '';
|
$email = $_POST['email'] ?? '';
|
||||||
$password = $_POST['password'] ?? '';
|
$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.';
|
$error_message = 'Please fill in all required fields.';
|
||||||
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
$error_message = 'Invalid email format.';
|
$error_message = 'Invalid email format.';
|
||||||
@ -25,16 +41,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
try {
|
try {
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
|
||||||
// Check if email already exists
|
|
||||||
$stmt = $pdo->prepare('SELECT id FROM users WHERE email = ?');
|
$stmt = $pdo->prepare('SELECT id FROM users WHERE email = ?');
|
||||||
$stmt->execute([$email]);
|
$stmt->execute([$email]);
|
||||||
if ($stmt->fetch()) {
|
if ($stmt->fetch()) {
|
||||||
$error_message = 'A user with this email address already exists.';
|
$error_message = 'A user with this email address already exists.';
|
||||||
} else {
|
} else {
|
||||||
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
$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 = $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");
|
header("Location: users.php?success=user_added");
|
||||||
exit;
|
exit;
|
||||||
@ -94,12 +109,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
<input type="password" class="form-control" id="password" name="password" required>
|
<input type="password" class="form-control" id="password" name="password" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 mb-3">
|
<div class="col-md-6 mb-3">
|
||||||
<label for="role" class="form-label">Role</label>
|
<label for="role_id" class="form-label">Role</label>
|
||||||
<select class="form-select" id="role" name="role">
|
<select class="form-select" id="role_id" name="role_id" required>
|
||||||
<option>Employee</option>
|
<option value="">Select a role</option>
|
||||||
<option>IT Technician</option>
|
<?php foreach ($roles as $role): ?>
|
||||||
<option>Asset Manager</option>
|
<option value="<?php echo htmlspecialchars($role['id']); ?>">
|
||||||
<option>Admin</option>
|
<?php echo htmlspecialchars($role['name']); ?>
|
||||||
|
</option>
|
||||||
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -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
|
||||||
11
db/migrations/015_create_settings_table.sql
Normal file
11
db/migrations/015_create_settings_table.sql
Normal 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';
|
||||||
@ -10,7 +10,7 @@ if (!can($_SESSION['user_role_id'], 'user', 'update')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$allowed_fields_str = 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 = '';
|
$error_message = '';
|
||||||
$user_id = $_GET['id'] ?? null;
|
$user_id = $_GET['id'] ?? null;
|
||||||
@ -22,7 +22,7 @@ if (!$user_id) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$pdo = db();
|
$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]);
|
$stmt->execute([$user_id]);
|
||||||
$user = $stmt->fetch();
|
$user = $stmt->fetch();
|
||||||
|
|
||||||
@ -30,6 +30,11 @@ try {
|
|||||||
header('Location: users.php');
|
header('Location: users.php');
|
||||||
exit;
|
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) {
|
} catch (PDOException $e) {
|
||||||
$error_message = 'Database error: ' . $e->getMessage();
|
$error_message = 'Database error: ' . $e->getMessage();
|
||||||
}
|
}
|
||||||
@ -124,14 +129,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<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">
|
<div class="col-md-6 mb-3">
|
||||||
<label for="role" class="form-label">Role</label>
|
<label for="role_id" class="form-label">Role</label>
|
||||||
<select class="form-select" id="role" name="role">
|
<select class="form-select" id="role_id" name="role_id">
|
||||||
<option <?php echo ($user['role'] === 'Employee') ? 'selected' : ''; ?>>Employee</option>
|
<?php foreach ($roles as $role): ?>
|
||||||
<option <?php echo ($user['role'] === 'IT Technician') ? 'selected' : ''; ?>>IT Technician</option>
|
<option value="<?php echo $role['id']; ?>" <?php echo ($user['role_id'] == $role['id']) ? 'selected' : ''; ?>><?php echo htmlspecialchars($role['name']); ?></option>
|
||||||
<option <?php echo ($user['role'] === 'Asset Manager') ? 'selected' : ''; ?>>Asset Manager</option>
|
<?php endforeach; ?>
|
||||||
<option <?php echo ($user['role'] === 'Admin') ? 'selected' : ''; ?>>Admin</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|||||||
122
google-callback.php
Normal file
122
google-callback.php
Normal 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
30
google-login.php
Normal 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;
|
||||||
27
index.php
27
index.php
@ -4,6 +4,21 @@ require_once 'db/config.php';
|
|||||||
require_once 'auth-check.php';
|
require_once 'auth-check.php';
|
||||||
require_once 'auth-helpers.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
|
// Get allowed fields for the current user
|
||||||
$allowed_fields_str = can($_SESSION['user_role_id'], 'asset', 'read');
|
$allowed_fields_str = can($_SESSION['user_role_id'], 'asset', 'read');
|
||||||
$allowed_fields = [];
|
$allowed_fields = [];
|
||||||
@ -27,6 +42,12 @@ function count_assets($search = '', $status = '') {
|
|||||||
$where = [];
|
$where = [];
|
||||||
$params = [];
|
$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)) {
|
if (!empty($search)) {
|
||||||
$where[] = "name LIKE :search";
|
$where[] = "name LIKE :search";
|
||||||
$params[':search'] = "%$search%";
|
$params[':search'] = "%$search%";
|
||||||
@ -87,6 +108,12 @@ function get_assets($fields, $search = '', $status = '', $limit = 10, $offset =
|
|||||||
$where = [];
|
$where = [];
|
||||||
$params = [];
|
$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)) {
|
if (!empty($search)) {
|
||||||
// Assuming 'name' is a field that can be searched.
|
// Assuming 'name' is a field that can be searched.
|
||||||
if (in_array('name', $fields)) {
|
if (in_array('name', $fields)) {
|
||||||
|
|||||||
@ -48,6 +48,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Login - IC-Inventory</title>
|
<title>Login - IC-Inventory</title>
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
<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(); ?>">
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
@ -82,6 +83,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary w-100">Login</button>
|
<button type="submit" class="btn btn-primary w-100">Login</button>
|
||||||
</form>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
269
settings.php
269
settings.php
@ -4,16 +4,91 @@ require_once 'db/config.php';
|
|||||||
require_once 'auth-check.php';
|
require_once 'auth-check.php';
|
||||||
require_once 'auth-helpers.php';
|
require_once 'auth-helpers.php';
|
||||||
|
|
||||||
if (!can($_SESSION['user_role_id'], 'permission', 'update')) {
|
// Only Super Admins can manage settings
|
||||||
header('Location: index.php?error=access_denied');
|
$is_super_admin = ($_SESSION['user_role_id'] == 1);
|
||||||
exit;
|
|
||||||
|
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 = '';
|
$success_message = '';
|
||||||
$error_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 {
|
try {
|
||||||
$pdo = db();
|
|
||||||
$roles_stmt = $pdo->query('SELECT * FROM roles ORDER BY name');
|
$roles_stmt = $pdo->query('SELECT * FROM roles ORDER BY name');
|
||||||
$roles = $roles_stmt->fetchAll(PDO::FETCH_ASSOC);
|
$roles = $roles_stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
@ -24,52 +99,10 @@ try {
|
|||||||
$resources = ['asset', 'user', 'category', 'location', 'role', 'permission'];
|
$resources = ['asset', 'user', 'category', 'location', 'role', 'permission'];
|
||||||
$actions = ['create', 'read', 'update', 'delete'];
|
$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() {
|
function get_permissions() {
|
||||||
try {
|
try {
|
||||||
$pdo = db();
|
$pdo_func = db();
|
||||||
$stmt = $pdo->query('SELECT * FROM role_permissions ORDER BY role_id, resource, action');
|
$stmt = $pdo_func->query('SELECT * FROM role_permissions ORDER BY role_id, resource, action');
|
||||||
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
return ['error' => 'Database error: ' . $e->getMessage()];
|
return ['error' => 'Database error: ' . $e->getMessage()];
|
||||||
@ -77,21 +110,20 @@ function get_permissions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$permissions_from_db = get_permissions();
|
$permissions_from_db = get_permissions();
|
||||||
|
|
||||||
// Group permissions by role and resource for easier display
|
|
||||||
$grouped_permissions = [];
|
$grouped_permissions = [];
|
||||||
foreach ($permissions_from_db as $p) {
|
if (!isset($permissions_from_db['error'])) {
|
||||||
$grouped_permissions[$p['role_id']][$p['resource']][$p['action']] = $p['fields'];
|
foreach ($permissions_from_db as $p) {
|
||||||
|
$grouped_permissions[$p['role_id']][$p['resource']][$p['action']] = $p['fields'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Settings - Role Permissions - IC-Inventory</title>
|
<title>Settings - IC-Inventory</title>
|
||||||
<meta name="description" content="Manage role permissions.">
|
<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 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="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
@ -106,7 +138,7 @@ foreach ($permissions_from_db as $p) {
|
|||||||
|
|
||||||
<main id="content">
|
<main id="content">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h1>Settings - Role Permissions</h1>
|
<h1>Settings</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="surface p-4">
|
<div class="surface p-4">
|
||||||
@ -117,54 +149,85 @@ foreach ($permissions_from_db as $p) {
|
|||||||
<div class="alert alert-danger"><?php echo htmlspecialchars($error_message); ?></div>
|
<div class="alert alert-danger"><?php echo htmlspecialchars($error_message); ?></div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<form action="settings.php" method="post">
|
<?php if ($is_super_admin): ?>
|
||||||
<div class="table-responsive">
|
<div class="card mb-4">
|
||||||
<table class="table table-bordered permission-table">
|
<div class="card-header">
|
||||||
<thead>
|
<h3>Google OAuth 2.0 Settings</h3>
|
||||||
<tr>
|
|
||||||
<th>Role</th>
|
|
||||||
<th>Resource</th>
|
|
||||||
<th>Create</th>
|
|
||||||
<th>Read (Fields)</th>
|
|
||||||
<th>Update (Fields)</th>
|
|
||||||
<th>Delete</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php foreach ($roles as $role): ?>
|
|
||||||
<?php foreach ($resources as $resource_idx => $resource): ?>
|
|
||||||
<tr>
|
|
||||||
<?php if ($resource_idx === 0): ?>
|
|
||||||
<td rowspan="<?php echo count($resources); ?>" class="align-middle">
|
|
||||||
<strong><?php echo htmlspecialchars($role['name']); ?></strong>
|
|
||||||
<?php if ($role['id'] == 1): ?>
|
|
||||||
<span class="badge bg-primary">Super Admin</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<?php endif; ?>
|
|
||||||
<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' : ''; ?>>
|
|
||||||
</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' : ''; ?>>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary">Save Changes</button>
|
<div class="card-body">
|
||||||
</form>
|
<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">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Role</th>
|
||||||
|
<th>Resource</th>
|
||||||
|
<th>Create</th>
|
||||||
|
<th>Read (Fields)</th>
|
||||||
|
<th>Update (Fields)</th>
|
||||||
|
<th>Delete</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($roles as $role): ?>
|
||||||
|
<?php foreach ($resources as $resource_idx => $resource): ?>
|
||||||
|
<tr>
|
||||||
|
<?php if ($resource_idx === 0): ?>
|
||||||
|
<td rowspan="<?php echo count($resources); ?>" class="align-middle">
|
||||||
|
<strong><?php echo htmlspecialchars($role['name']); ?></strong>
|
||||||
|
<?php if ($role['id'] == 1): ?>
|
||||||
|
<span class="badge bg-primary">Super Admin</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<?php endif; ?>
|
||||||
|
<td class="align-middle"><?php echo ucfirst($resource); ?></td>
|
||||||
|
|
||||||
|
<?php foreach ($actions as $action):
|
||||||
|
$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' : ''; ?>>
|
||||||
|
</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 endif; ?>
|
||||||
|
</td>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<button type="submit" name="save_permissions" class="btn btn-primary">Save Permissions</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
22
users.php
22
users.php
@ -33,16 +33,30 @@ function get_users($fields) {
|
|||||||
if (empty($fields)) {
|
if (empty($fields)) {
|
||||||
return []; // No read permission
|
return []; // No read permission
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always include id for edit/delete links
|
// Always include id for edit/delete links
|
||||||
if (!in_array('id', $fields)) {
|
if (!in_array('id', $fields)) {
|
||||||
$fields[] = 'id';
|
$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 {
|
try {
|
||||||
$pdo = db();
|
$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);
|
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
return ['error' => 'Database error: ' . $e->getMessage()];
|
return ['error' => 'Database error: ' . $e->getMessage()];
|
||||||
@ -113,7 +127,7 @@ $users = get_users($allowed_fields);
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<?php foreach ($allowed_fields as $field): if($field === 'id') continue; ?>
|
<?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; ?>
|
<?php endforeach; ?>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -122,7 +136,7 @@ $users = get_users($allowed_fields);
|
|||||||
<?php foreach ($users as $user): ?>
|
<?php foreach ($users as $user): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<?php foreach ($allowed_fields as $field): if($field === 'id') continue; ?>
|
<?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; ?>
|
<?php endforeach; ?>
|
||||||
<td>
|
<td>
|
||||||
<?php if (can($_SESSION['user_role_id'], 'user', 'update')): ?>
|
<?php if (can($_SESSION['user_role_id'], 'user', 'update')): ?>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user