(int) $_SESSION['user_id'], 'fullname' => $_SESSION['user_name'] ?? '', 'email' => $_SESSION['user_email'] ?? '', ]; } function requireLogin(): void { if (!isLoggedIn()) { header('Location: /login/login.php'); exit; } } function hasPermission(string $permission): bool { // Stub — extend with role checks when roles are introduced return isLoggedIn(); } // --------------------------------------------------------------------------- // Login / Logout // --------------------------------------------------------------------------- /** * Attempt login with email + plain-text password. * Returns user row array on success, null on failure. */ function loginUser(string $email, string $password): ?array { $pdo = getDBConnection(); $stmt = $pdo->prepare( 'SELECT id, fullname, email, password FROM users WHERE email = ? AND active = 1 LIMIT 1' ); $stmt->execute([strtolower(trim($email))]); $user = $stmt->fetch(); if (!$user || !password_verify($password, $user['password'])) { return null; } // Rehash on cost/algorithm upgrade if (password_needs_rehash($user['password'], PASSWORD_DEFAULT)) { $pdo->prepare('UPDATE users SET password = ? WHERE id = ?') ->execute([password_hash($password, PASSWORD_DEFAULT), $user['id']]); } session_regenerate_id(true); $_SESSION['user_id'] = $user['id']; $_SESSION['user_name'] = $user['fullname']; $_SESSION['user_email'] = $user['email']; return $user; } /** * Destroy session completely and clear the session cookie. */ function logoutUser(): void { $_SESSION = []; if (ini_get('session.use_cookies')) { $p = session_get_cookie_params(); setcookie( session_name(), '', time() - 42000, $p['path'], $p['domain'], $p['secure'], $p['httponly'] ); } session_destroy(); } // --------------------------------------------------------------------------- // Registration // --------------------------------------------------------------------------- /** * Register a new user. * Returns ['success' => true, 'user_id' => int] * or ['success' => false, 'error' => string] */ function registerUser(array $data): array { $pdo = getDBConnection(); $email = strtolower(trim($data['email'] ?? '')); // Duplicate email check $stmt = $pdo->prepare('SELECT id FROM users WHERE email = ? LIMIT 1'); $stmt->execute([$email]); if ($stmt->fetch()) { return ['success' => false, 'error' => 'An account with that email already exists.']; } $stmt = $pdo->prepare(' INSERT INTO users (fullname, email, password, company, mobilephone, industry, role, city, state, postcode, country, active, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, NOW()) '); $stmt->execute([ trim($data['fullname'] ?? ''), $email, password_hash($data['password'], PASSWORD_DEFAULT), trim($data['company'] ?? ''), trim($data['mobilephone'] ?? ''), $data['industry'] ?? '', $data['role'] ?? '', trim($data['city'] ?? ''), $data['state'] ?? '', trim($data['postcode'] ?? ''), $data['country'] ?? 'Australia', ]); return ['success' => true, 'user_id' => (int) $pdo->lastInsertId()]; } // --------------------------------------------------------------------------- // Password reset // --------------------------------------------------------------------------- /** * Create a password-reset token for $email (1-hour expiry). * Returns the raw token string, or null if the email doesn't exist. */ function createPasswordResetToken(string $email): ?string { $pdo = getDBConnection(); $email = strtolower(trim($email)); $stmt = $pdo->prepare('SELECT id FROM users WHERE email = ? AND active = 1 LIMIT 1'); $stmt->execute([$email]); if (!$stmt->fetch()) { return null; } // Remove any previous tokens for this email $pdo->prepare('DELETE FROM password_resets WHERE email = ?')->execute([$email]); $token = bin2hex(random_bytes(32)); $pdo->prepare( 'INSERT INTO password_resets (email, token, created_at, expires_at) VALUES (?, ?, NOW(), DATE_ADD(NOW(), INTERVAL 1 HOUR))' )->execute([$email, $token]); return $token; } /** * Validate a reset token. Returns the associated email on success, null if invalid/expired. */ function validatePasswordResetToken(string $token): ?string { $pdo = getDBConnection(); $stmt = $pdo->prepare( 'SELECT email FROM password_resets WHERE token = ? AND expires_at > NOW() LIMIT 1' ); $stmt->execute([$token]); $row = $stmt->fetch(); return $row ? $row['email'] : null; } /** * Update the user's password and delete the reset token. */ function resetPassword(string $token, string $newPassword): bool { $pdo = getDBConnection(); $email = validatePasswordResetToken($token); if (!$email) { return false; } $pdo->prepare('UPDATE users SET password = ? WHERE email = ?') ->execute([password_hash($newPassword, PASSWORD_DEFAULT), $email]); $pdo->prepare('DELETE FROM password_resets WHERE email = ?')->execute([$email]); return true; } /** * Change password for currently logged-in user after verifying old password. * Returns true on success, false if old password is wrong. */ function changePassword(int $userId, string $oldPassword, string $newPassword): bool { $pdo = getDBConnection(); $stmt = $pdo->prepare('SELECT password FROM users WHERE id = ? LIMIT 1'); $stmt->execute([$userId]); $user = $stmt->fetch(); if (!$user || !password_verify($oldPassword, $user['password'])) { return false; } $pdo->prepare('UPDATE users SET password = ? WHERE id = ?') ->execute([password_hash($newPassword, PASSWORD_DEFAULT), $userId]); return true; }