257 lines
12 KiB
PHP
257 lines
12 KiB
PHP
<?php
|
|
$page_title = 'Manage Users - Bookmarkly';
|
|
|
|
// Add user-settings-page class to body for CSS targeting
|
|
$GLOBALS['body_class'] = 'user-settings-page';
|
|
|
|
require_once 'include/auth.php';
|
|
|
|
// --- Security Check: Only Admin can access this page ---
|
|
if (!isAdmin()) {
|
|
header('Location: index.php');
|
|
exit;
|
|
}
|
|
|
|
// Flash messages for feedback
|
|
$message = '';
|
|
$message_type = '';
|
|
if (isset($_SESSION['flash_message'])) {
|
|
$message = $_SESSION['flash_message']['text'];
|
|
$message_type = $_SESSION['flash_message']['type'];
|
|
unset($_SESSION['flash_message']);
|
|
}
|
|
|
|
// Handle POST requests for adding/deleting users
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$action = $_POST['action'] ?? '';
|
|
|
|
if ($action === 'add_user') {
|
|
$username = trim($_POST['username'] ?? '');
|
|
$password = $_POST['password'] ?? '';
|
|
$role = $_POST['role'] ?? 'user';
|
|
|
|
if (!empty($username) && !empty($password) && in_array($role, ['user', 'viewer', 'admin'])) {
|
|
// Check if username already exists
|
|
$stmt = $pdo->prepare("SELECT id FROM users WHERE username = ?");
|
|
$stmt->execute([$username]);
|
|
if ($stmt->fetch()) {
|
|
$_SESSION['flash_message'] = ['text' => 'Username already exists.', 'type' => 'warning'];
|
|
} else {
|
|
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
|
$stmt = $pdo->prepare("INSERT INTO users (username, password, role) VALUES (?, ?, ?)");
|
|
if ($stmt->execute([$username, $hashed_password, $role])) {
|
|
$_SESSION['flash_message'] = ['text' => 'User added successfully.', 'type' => 'success'];
|
|
} else {
|
|
$_SESSION['flash_message'] = ['text' => 'Error adding user.', 'type' => 'danger'];
|
|
}
|
|
}
|
|
} else {
|
|
$_SESSION['flash_message'] = ['text' => 'Username, password, and a valid role are required.', 'type' => 'warning'];
|
|
}
|
|
} elseif ($action === 'edit_user') {
|
|
$user_id = filter_input(INPUT_POST, 'user_id', FILTER_VALIDATE_INT);
|
|
$username = trim($_POST['username'] ?? '');
|
|
$role = $_POST['role'] ?? 'user';
|
|
$password = $_POST['password'] ?? ''; // Optional: for changing password
|
|
|
|
if ($user_id && !empty($username) && in_array($role, ['user', 'viewer', 'admin'])) {
|
|
// Check if new username already exists (and is not the current user)
|
|
$stmt = $pdo->prepare("SELECT id FROM users WHERE username = ? AND id != ?");
|
|
$stmt->execute([$username, $user_id]);
|
|
if ($stmt->fetch()) {
|
|
$_SESSION['flash_message'] = ['text' => 'Username already exists.', 'type' => 'warning'];
|
|
} else {
|
|
if (!empty($password)) {
|
|
// If password is provided, update it
|
|
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
|
$stmt = $pdo->prepare("UPDATE users SET username = ?, role = ?, password = ? WHERE id = ?");
|
|
$stmt->execute([$username, $role, $hashed_password, $user_id]);
|
|
} else {
|
|
// Otherwise, update without changing password
|
|
$stmt = $pdo->prepare("UPDATE users SET username = ?, role = ? WHERE id = ?");
|
|
$stmt->execute([$username, $role, $user_id]);
|
|
}
|
|
$_SESSION['flash_message'] = ['text' => 'User updated successfully.', 'type' => 'success'];
|
|
}
|
|
} else {
|
|
$_SESSION['flash_message'] = ['text' => 'Invalid data for updating user.', 'type' => 'warning'];
|
|
}
|
|
} elseif ($action === 'delete_user') {
|
|
$user_id = filter_input(INPUT_POST, 'user_id', FILTER_VALIDATE_INT);
|
|
if ($user_id && $user_id != 1) { // Prevent admin from deleting themselves
|
|
$stmt = $pdo->prepare("DELETE FROM users WHERE id = ?");
|
|
if ($stmt->execute([$user_id])) {
|
|
$_SESSION['flash_message'] = ['text' => 'User deleted successfully.', 'type' => 'success'];
|
|
} else {
|
|
$_SESSION['flash_message'] = ['text' => 'Error deleting user.', 'type' => 'danger'];
|
|
}
|
|
} else {
|
|
$_SESSION['flash_message'] = ['text' => 'Invalid user or action not allowed.', 'type' => 'danger'];
|
|
}
|
|
}
|
|
|
|
header('Location: user_settings.php');
|
|
exit;
|
|
}
|
|
|
|
// Fetch all users for display
|
|
$users_stmt = $pdo->query("SELECT id, username, role FROM users ORDER BY username");
|
|
$users = $users_stmt->fetchAll();
|
|
|
|
require_once 'include/header.php';
|
|
?>
|
|
|
|
<div class="container mt-4">
|
|
<h1>Manage Users</h1>
|
|
|
|
<?php if ($message): ?>
|
|
<div class="alert alert-<?php echo $message_type; ?> alert-dismissible fade show" role="alert">
|
|
<?php echo htmlspecialchars($message); ?>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<!-- Add User Form -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">Add New User</div>
|
|
<div class="card-body">
|
|
<form action="user_settings.php" method="POST">
|
|
<input type="hidden" name="action" value="add_user">
|
|
<div class="row">
|
|
<div class="col-md-4 mb-3">
|
|
<label for="username" class="form-label">Username</label>
|
|
<input type="text" class="form-control" id="username" name="username" required>
|
|
</div>
|
|
<div class="col-md-4 mb-3">
|
|
<label for="password" class="form-label">Password</label>
|
|
<input type="password" class="form-control" id="password" name="password" required>
|
|
</div>
|
|
<div class="col-md-2 mb-3">
|
|
<label for="role" class="form-label">Role</label>
|
|
<select class="form-select" id="role" name="role">
|
|
<option value="user" selected>User</option>
|
|
<option value="viewer">Viewer</option>
|
|
<option value="admin">Admin</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2 d-flex align-items-end mb-3">
|
|
<button type="submit" class="btn btn-primary w-100">Add User</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- User List -->
|
|
<div class="card">
|
|
<div class="card-header">Existing Users</div>
|
|
<div class="card-body">
|
|
<ul class="list-group">
|
|
<?php foreach ($users as $user): ?>
|
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<span class="fw-bold"><?php echo htmlspecialchars($user['username']); ?></span>
|
|
<span class="badge bg-secondary ms-2"><?php echo htmlspecialchars($user['role']); ?></span>
|
|
</div>
|
|
<?php if ($user['id'] != 1): // Don't show delete for admin user ?>
|
|
<div>
|
|
<button class="btn btn-sm btn-outline-secondary me-2" data-bs-toggle="modal" data-bs-target="#editUserModal" data-user-id="<?php echo $user['id']; ?>" data-username="<?php echo htmlspecialchars($user['username']); ?>" data-role="<?php echo $user['role']; ?>">
|
|
Edit
|
|
</button>
|
|
<form action="user_settings.php" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this user?');">
|
|
<input type="hidden" name="action" value="delete_user">
|
|
<input type="hidden" name="user_id" value="<?php echo $user['id']; ?>">
|
|
<button type="submit" class="btn btn-sm btn-outline-danger">Delete</button>
|
|
</form>
|
|
</div>
|
|
<?php endif; ?>
|
|
</li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Role Descriptions -->
|
|
<div class="card mt-4">
|
|
<div class="card-header"><?php echo translate('user_settings_roles_title'); ?></div>
|
|
<div class="card-body">
|
|
<dl class="row">
|
|
<dt class="col-sm-2"><?php echo translate('user_settings_role_admin'); ?></dt>
|
|
<dd class="col-sm-10"><?php echo translate('user_settings_role_admin_desc'); ?></dd>
|
|
|
|
<dt class="col-sm-2"><?php echo translate('user_settings_role_user'); ?></dt>
|
|
<dd class="col-sm-10"><?php echo translate('user_settings_role_user_desc'); ?></dd>
|
|
|
|
<dt class="col-sm-2"><?php echo translate('user_settings_role_viewer'); ?></dt>
|
|
<dd class="col-sm-10"><?php echo translate('user_settings_role_viewer_desc'); ?></dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Edit User Modal -->
|
|
<div class="modal fade" id="editUserModal" tabindex="-1" aria-labelledby="editUserModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="editUserModalLabel">Edit User</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<form action="user_settings.php" method="POST">
|
|
<div class="modal-body">
|
|
<input type="hidden" name="action" value="edit_user">
|
|
<input type="hidden" id="edit-user-id" name="user_id">
|
|
|
|
<div class="mb-3">
|
|
<label for="edit-username" class="form-label">Username</label>
|
|
<input type="text" class="form-control" id="edit-username" name="username" required>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="edit-role" class="form-label">Role</label>
|
|
<select class="form-select" id="edit-role" name="role">
|
|
<option value="user">User</option>
|
|
<option value="viewer">Viewer</option>
|
|
<option value="admin">Admin</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="edit-password" class="form-label">New Password (optional)</label>
|
|
<input type="password" class="form-control" id="edit-password" name="password">
|
|
<div class="form-text">Leave blank to keep the current password.</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
<button type="submit" class="btn btn-primary">Save Changes</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
var editUserModal = document.getElementById('editUserModal');
|
|
editUserModal.addEventListener('show.bs.modal', function (event) {
|
|
var button = event.relatedTarget;
|
|
var userId = button.getAttribute('data-user-id');
|
|
var username = button.getAttribute('data-username');
|
|
var role = button.getAttribute('data-role');
|
|
|
|
var modalTitle = editUserModal.querySelector('.modal-title');
|
|
var userIdInput = editUserModal.querySelector('#edit-user-id');
|
|
var usernameInput = editUserModal.querySelector('#edit-username');
|
|
var roleInput = editUserModal.querySelector('#edit-role');
|
|
|
|
modalTitle.textContent = 'Edit User: ' + username;
|
|
userIdInput.value = userId;
|
|
usernameInput.value = username;
|
|
roleInput.value = role;
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<?php require_once 'include/footer.php'; ?>
|