From 378cb2cb1087985df880472db3bd1c4401a01f0e Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 8 Nov 2025 21:16:26 +0000 Subject: [PATCH] google login --- add-user.php | 41 ++- ...t_remaining_permissions_to_super_admin.sql | 24 ++ db/migrations/015_create_settings_table.sql | 11 + edit-user.php | 22 +- google-callback.php | 122 ++++++++ google-login.php | 30 ++ index.php | 29 +- login.php | 7 + settings.php | 269 +++++++++++------- users.php | 24 +- 10 files changed, 449 insertions(+), 130 deletions(-) create mode 100644 db/migrations/014_grant_remaining_permissions_to_super_admin.sql create mode 100644 db/migrations/015_create_settings_table.sql create mode 100644 google-callback.php create mode 100644 google-login.php diff --git a/add-user.php b/add-user.php index 12d7f04..6e612bc 100644 --- a/add-user.php +++ b/add-user.php @@ -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') {
- - + + + +
@@ -117,4 +134,4 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { feather.replace(); - \ No newline at end of file + diff --git a/db/migrations/014_grant_remaining_permissions_to_super_admin.sql b/db/migrations/014_grant_remaining_permissions_to_super_admin.sql new file mode 100644 index 0000000..3cbd58c --- /dev/null +++ b/db/migrations/014_grant_remaining_permissions_to_super_admin.sql @@ -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 diff --git a/db/migrations/015_create_settings_table.sql b/db/migrations/015_create_settings_table.sql new file mode 100644 index 0000000..7e171a9 --- /dev/null +++ b/db/migrations/015_create_settings_table.sql @@ -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'; diff --git a/edit-user.php b/edit-user.php index a2e81b3..82bfa56 100644 --- a/edit-user.php +++ b/edit-user.php @@ -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') {
- +
- - + + +
diff --git a/google-callback.php b/google-callback.php new file mode 100644 index 0000000..199d300 --- /dev/null +++ b/google-callback.php @@ -0,0 +1,122 @@ +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.'); +} diff --git a/google-login.php b/google-login.php new file mode 100644 index 0000000..dfb1fa7 --- /dev/null +++ b/google-login.php @@ -0,0 +1,30 @@ +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; diff --git a/index.php b/index.php index 38409aa..8d69e64 100644 --- a/index.php +++ b/index.php @@ -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)) { @@ -311,4 +338,4 @@ function getStatusClass($status) { feather.replace(); - + \ No newline at end of file diff --git a/login.php b/login.php index b1557f8..450f8be 100644 --- a/login.php +++ b/login.php @@ -48,6 +48,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { Login - IC-Inventory +