Current directory: /home/klas4s23/domains/585455.klas4s23.mid-ica.nl/public_html/Gastenboek/uploads
<?php
session_start();
include "db.php";
// Check if user is logged in and is admin
if (!isset($_SESSION['user_id']) || !isset($_SESSION['is_admin']) || $_SESSION['is_admin'] != 1) {
header("Location: login.php");
exit();
}
$success_message = "";
$error_message = "";
// Create banned_until column if it doesn't exist
try {
// Check if the column exists
$checkColumn = $conn->query("SHOW COLUMNS FROM users LIKE 'banned_until'");
if ($checkColumn->rowCount() == 0) {
// Add the column
$conn->exec("ALTER TABLE users ADD COLUMN banned_until DATETIME NULL");
$success_message = "Added 'banned_until' column to users table. User ban feature is now available.";
}
} catch (PDOException $e) {
$error_message = "Error checking/adding banned_until column: " . $e->getMessage();
}
// Handle user action requests
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// Handle single user deletion
if (isset($_POST['delete_user'])) {
$delete_id = (int)$_POST['user_id'];
// Don't allow deleting self
if ($delete_id == $_SESSION['user_id']) {
$error_message = "You cannot delete your own admin account.";
} else {
try {
$stmt = $conn->prepare("DELETE FROM users WHERE id = ?");
$stmt->execute([$delete_id]);
$success_message = "User deleted successfully.";
} catch (PDOException $e) {
$error_message = "Error deleting user: " . $e->getMessage();
}
}
}
// Handle duplicate admin accounts cleanup
if (isset($_POST['cleanup_duplicates'])) {
try {
// Find the oldest admin account (to keep) and remove any others
$stmt = $conn->prepare("
SELECT MIN(id) as keep_id
FROM users
WHERE username = 'admin' AND is_admin = 1
");
$stmt->execute();
$keep = $stmt->fetch();
if ($keep && isset($keep['keep_id'])) {
// Delete all admin accounts except the oldest one
$stmt = $conn->prepare("
DELETE FROM users
WHERE username = 'admin' AND is_admin = 1 AND id != ?
");
$stmt->execute([$keep['keep_id']]);
$deleted = $stmt->rowCount();
if ($deleted > 0) {
$success_message = "Successfully removed $deleted duplicate admin accounts.";
} else {
$success_message = "No duplicate admin accounts found.";
}
}
} catch (PDOException $e) {
$error_message = "Error cleaning up duplicates: " . $e->getMessage();
}
}
// Handle batch user actions
if (isset($_POST['batch_action']) && isset($_POST['selected_users'])) {
$action = $_POST['batch_action'];
$selected_users = $_POST['selected_users'];
if (empty($selected_users)) {
$error_message = "No users selected.";
} else {
switch($action) {
case 'view_lists':
// Redirect to view lists page with selected user IDs
$user_ids = implode(',', $selected_users);
header("Location: admin_user_lists.php?user_ids=$user_ids");
exit();
break;
case 'delete_lists':
try {
$deleted_count = 0;
foreach ($selected_users as $user_id) {
// Don't delete admin lists
$check = $conn->prepare("SELECT is_admin FROM users WHERE id = ?");
$check->execute([$user_id]);
$user = $check->fetch();
if (!$user || $user['is_admin'] == 1) continue;
$stmt = $conn->prepare("DELETE FROM word_lists WHERE user_id = ?");
$stmt->execute([$user_id]);
$deleted_count += $stmt->rowCount();
}
$success_message = "Successfully deleted $deleted_count lists from selected users.";
} catch (PDOException $e) {
$error_message = "Error deleting lists: " . $e->getMessage();
}
break;
case 'ban_users':
// Create banned_until column if it doesn't exist
try {
$conn->query("SELECT banned_until FROM users LIMIT 1");
} catch (PDOException $e) {
$conn->exec("ALTER TABLE users ADD COLUMN banned_until DATETIME NULL");
}
try {
$banned_count = 0;
foreach ($selected_users as $user_id) {
// Don't ban other admins
$check = $conn->prepare("SELECT is_admin FROM users WHERE id = ?");
$check->execute([$user_id]);
$user = $check->fetch();
if (!$user || ($user['is_admin'] == 1 && $user_id != $_SESSION['user_id'])) continue;
$stmt = $conn->prepare("UPDATE users SET banned_until = '9999-12-31 23:59:59' WHERE id = ?");
$stmt->execute([$user_id]);
$banned_count += $stmt->rowCount();
}
$success_message = "Successfully banned $banned_count users permanently.";
} catch (PDOException $e) {
$error_message = "Error banning users: " . $e->getMessage();
}
break;
case 'timeout_users':
// Get timeout duration
$duration = isset($_POST['timeout_duration']) ? (int)$_POST['timeout_duration'] : 24;
// Create banned_until column if it doesn't exist
try {
$conn->query("SELECT banned_until FROM users LIMIT 1");
} catch (PDOException $e) {
$conn->exec("ALTER TABLE users ADD COLUMN banned_until DATETIME NULL");
}
try {
$timeout_count = 0;
$timeout_until = date('Y-m-d H:i:s', strtotime("+$duration hours"));
foreach ($selected_users as $user_id) {
// Don't timeout other admins
$check = $conn->prepare("SELECT is_admin FROM users WHERE id = ?");
$check->execute([$user_id]);
$user = $check->fetch();
if (!$user || ($user['is_admin'] == 1 && $user_id != $_SESSION['user_id'])) continue;
$stmt = $conn->prepare("UPDATE users SET banned_until = ? WHERE id = ?");
$stmt->execute([$timeout_until, $user_id]);
$timeout_count += $stmt->rowCount();
}
$success_message = "Successfully timed out $timeout_count users for $duration hours (until $timeout_until).";
} catch (PDOException $e) {
$error_message = "Error timing out users: " . $e->getMessage();
}
break;
case 'remove_restrictions':
try {
$unrestricted_count = 0;
foreach ($selected_users as $user_id) {
$stmt = $conn->prepare("UPDATE users SET banned_until = NULL WHERE id = ?");
$stmt->execute([$user_id]);
$unrestricted_count += $stmt->rowCount();
}
$success_message = "Successfully removed restrictions from $unrestricted_count users.";
} catch (PDOException $e) {
$error_message = "Error removing restrictions: " . $e->getMessage();
}
break;
default:
$error_message = "Invalid action selected.";
break;
}
}
}
}
// Get all users - using DISTINCT to avoid duplicates
try {
$stmt = $conn->prepare("
SELECT DISTINCT u.id, u.username, u.is_admin, u.profile_photo, u.banned_until,
(SELECT COUNT(*) FROM word_lists WHERE user_id = u.id) as list_count,
(SELECT COUNT(*) FROM word_lists WHERE user_id = u.id AND public = 1) as public_list_count
FROM users u
ORDER BY u.id
");
$stmt->execute();
$users = $stmt->fetchAll();
// Check for duplicate admin accounts
$stmt = $conn->prepare("
SELECT COUNT(*) as count
FROM users
WHERE username = 'admin' AND is_admin = 1
");
$stmt->execute();
$admin_check = $stmt->fetch();
$has_duplicate_admins = ($admin_check && $admin_check['count'] > 1);
} catch (PDOException $e) {
$error_message = "Error fetching users: " . $e->getMessage();
$users = [];
$has_duplicate_admins = false;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Panel - ELearner</title>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="font-styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<style>
.profile-thumbnail {
width: 40px;
height: 40px;
border-radius: 50%;
object-fit: cover;
}
.profile-placeholder {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #e5e7eb;
display: flex;
align-items: center;
justify-content: center;
color: #9ca3af;
}
.timeout-form {
display: none;
}
.action-form.with-timeout .timeout-form {
display: block;
}
</style>
</head>
<body class="bg-gray-100 min-h-screen">
<div class="container mx-auto px-4 py-4 sm:py-8">
<header class="bg-white rounded-lg shadow-md p-4 sm:p-6 mb-6 sm:mb-8">
<div class="flex flex-wrap items-center justify-between">
<div class="flex items-center">
<a href="homepage.php">
<img src="images/icon-e-learner-blue.png" alt="ELearner Logo" class="h-10 sm:h-12 mr-3 sm:mr-4">
</a>
<div>
<h1 class="text-2xl sm:text-3xl font-bold text-blue-600">ELearner</h1>
<p class="text-sm sm:text-base text-gray-600">Admin Panel</p>
</div>
</div>
<nav id="desktopMenu" class="hidden md:block">
<ul class="flex space-x-4 sm:space-x-6">
<li><a href="homepage.php" class="text-blue-500 font-medium hover:underline">Home</a></li>
<li><a href="index.php" class="text-blue-500 font-medium hover:underline">Vocabulary Tool</a></li>
<li><a href="my_lists.php" class="text-blue-500 font-medium hover:underline">My Lists</a></li>
<li><a href="list_hub.php" class="text-blue-500 font-medium hover:underline">List Hub</a></li>
<li><a href="profile.php" class="text-blue-500 font-medium hover:underline">My Profile</a></li>
<li><a href="admin.php" class="text-purple-500 font-medium hover:underline">Admin</a></li>
<li><a href="logout.php" class="text-red-500 font-medium hover:underline">Logout</a></li>
<li>
<button id="fontToggleBtn" class="bg-purple-500 text-white px-3 py-1 rounded hover:bg-purple-600">
Toggle Font
</button>
</li>
</ul>
</nav>
<!-- Mobile menu button -->
<button id="mobileMenuBtn" class="md:hidden p-2 rounded text-blue-600 hover:bg-blue-100">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
</svg>
</button>
</div>
<!-- Mobile menu, hidden by default -->
<nav id="mobileMenu" class="md:hidden hidden mt-4 pb-2">
<ul class="flex flex-col space-y-3">
<li><a href="homepage.php" class="block text-blue-500 font-medium hover:underline">Home</a></li>
<li><a href="index.php" class="block text-blue-500 font-medium hover:underline">Vocabulary Tool</a></li>
<li><a href="my_lists.php" class="block text-blue-500 font-medium hover:underline">My Lists</a></li>
<li><a href="list_hub.php" class="block text-blue-500 font-medium hover:underline">List Hub</a></li>
<li><a href="profile.php" class="block text-blue-500 font-medium hover:underline">My Profile</a></li>
<li><a href="admin.php" class="block text-purple-500 font-medium hover:underline">Admin</a></li>
<li><a href="logout.php" class="block text-red-500 font-medium hover:underline">Logout</a></li>
<li>
<button id="mobileFontToggleBtn" class="bg-purple-500 text-white px-3 py-1 rounded hover:bg-purple-600">
Toggle Font
</button>
</li>
</ul>
</nav>
</header>
<main class="bg-white rounded-lg shadow-md p-4 sm:p-6">
<h2 class="text-xl sm:text-2xl font-bold mb-6">User Management</h2>
<?php if ($success_message): ?>
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded mb-4" role="alert">
<p><?php echo $success_message; ?></p>
</div>
<?php endif; ?>
<?php if ($error_message): ?>
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4" role="alert">
<p><?php echo $error_message; ?></p>
</div>
<?php endif; ?>
<?php if ($has_duplicate_admins): ?>
<div class="bg-yellow-100 border border-yellow-400 text-yellow-700 px-4 py-3 rounded mb-4" role="alert">
<p class="font-bold">Duplicate Admin Accounts Detected</p>
<p>There are multiple admin accounts with the username 'admin'. This can cause issues with the admin panel.</p>
<form method="post" class="mt-2">
<button type="submit" name="cleanup_duplicates" class="bg-blue-500 text-white px-3 py-1 rounded hover:bg-blue-600">
Clean Up Duplicates
</button>
</form>
</div>
<?php endif; ?>
<!-- Batch action form -->
<form method="post" id="batchActionForm" class="action-form mb-4">
<div class="flex flex-wrap items-end gap-2 mb-4">
<div>
<label for="batch_action" class="block text-sm font-medium text-gray-700 mb-1">Action</label>
<select id="batch_action" name="batch_action" class="border border-gray-300 rounded px-3 py-2">
<option value="">Select an action...</option>
<option value="view_lists">View User Lists</option>
<option value="delete_lists">Delete All Lists</option>
<option value="ban_users">Ban Users Permanently</option>
<option value="timeout_users">Timeout Users</option>
<option value="remove_restrictions">Remove All Restrictions</option>
</select>
</div>
<div class="timeout-form">
<label for="timeout_duration" class="block text-sm font-medium text-gray-700 mb-1">Timeout Duration (hours)</label>
<input type="number" id="timeout_duration" name="timeout_duration" min="1" max="720" value="24" class="border border-gray-300 rounded px-3 py-2 w-24">
</div>
<button type="submit" class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700">
Apply to Selected Users
</button>
<div class="ml-auto">
<button type="button" id="selectAllBtn" class="text-blue-600 hover:underline">Select All</button>
<span class="mx-2 text-gray-500">|</span>
<button type="button" id="selectNoneBtn" class="text-blue-600 hover:underline">Deselect All</button>
</div>
</div>
<div class="overflow-x-auto">
<table class="min-w-full bg-white border">
<thead>
<tr class="bg-gray-200 text-gray-700">
<th class="py-2 px-4 border-b text-left w-10">
<input type="checkbox" id="selectAll" class="rounded">
</th>
<th class="py-2 px-4 border-b text-left">ID</th>
<th class="py-2 px-4 border-b text-left">Photo</th>
<th class="py-2 px-4 border-b text-left">Username</th>
<th class="py-2 px-4 border-b text-left">Role</th>
<th class="py-2 px-4 border-b text-left">Status</th>
<th class="py-2 px-4 border-b text-left">Total Lists</th>
<th class="py-2 px-4 border-b text-left">Public Lists</th>
<th class="py-2 px-4 border-b text-left">Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($users as $user):
$now = new DateTime();
$is_banned = !empty($user['banned_until']) && new DateTime($user['banned_until']) > $now;
$is_perm_banned = !empty($user['banned_until']) && $user['banned_until'] == '9999-12-31 23:59:59';
?>
<tr class="hover:bg-gray-50 <?= $user['is_admin'] == 1 ? 'bg-purple-50' : ($is_banned ? 'bg-red-50' : '') ?>">
<td class="py-2 px-4 border-b">
<?php if ($user['id'] != $_SESSION['user_id']): ?>
<input type="checkbox" name="selected_users[]" value="<?= $user['id'] ?>" class="user-checkbox rounded">
<?php endif; ?>
</td>
<td class="py-2 px-4 border-b"><?= $user['id'] ?></td>
<td class="py-2 px-4 border-b">
<?php if (!empty($user['profile_photo']) && file_exists($user['profile_photo'])): ?>
<img src="<?= htmlspecialchars($user['profile_photo']) ?>" alt="Profile Photo" class="profile-thumbnail">
<?php else: ?>
<div class="profile-placeholder">
<i class="fas fa-user"></i>
</div>
<?php endif; ?>
</td>
<td class="py-2 px-4 border-b"><?= htmlspecialchars($user['username']) ?></td>
<td class="py-2 px-4 border-b">
<?php if ($user['is_admin'] == 1): ?>
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-purple-100 text-purple-800">
<i class="fas fa-crown mr-1"></i> Admin
</span>
<?php else: ?>
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
<i class="fas fa-user mr-1"></i> User
</span>
<?php endif; ?>
</td>
<td class="py-2 px-4 border-b">
<?php if ($is_perm_banned): ?>
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800">
<i class="fas fa-ban mr-1"></i> Banned
</span>
<?php elseif ($is_banned): ?>
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800" title="Until <?= $user['banned_until'] ?>">
<i class="fas fa-clock mr-1"></i> Timeout
</span>
<?php else: ?>
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
<i class="fas fa-check mr-1"></i> Active
</span>
<?php endif; ?>
</td>
<td class="py-2 px-4 border-b"><?= $user['list_count'] ?></td>
<td class="py-2 px-4 border-b"><?= $user['public_list_count'] ?></td>
<td class="py-2 px-4 border-b">
<?php if ($user['id'] != $_SESSION['user_id']): ?>
<div class="flex gap-2">
<a href="admin_user_lists.php?user_ids=<?= $user['id'] ?>" class="text-blue-500 hover:text-blue-700">
<i class="fas fa-list"></i>
</a>
<form method="post" onsubmit="return confirm('Are you sure you want to delete this user? This action cannot be undone.');" class="inline">
<input type="hidden" name="user_id" value="<?= $user['id'] ?>">
<button type="submit" name="delete_user" class="text-red-500 hover:text-red-700">
<i class="fas fa-trash-alt"></i>
</button>
</form>
</div>
<?php else: ?>
<span class="text-gray-400"><i class="fas fa-user-shield"></i> Current User</span>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</form>
<div class="mt-6 border-t pt-6">
<h3 class="text-lg font-bold mb-4">System Information</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="bg-gray-50 p-4 rounded">
<h4 class="font-medium mb-2">Database Tables</h4>
<ul class="list-disc pl-5 space-y-1">
<li>Users: <?= count($users) ?> total accounts</li>
<?php
// Get total list count
$stmt = $conn->query("SELECT COUNT(*) as count FROM word_lists");
$lists_count = $stmt->fetch();
// Get public list count
$stmt = $conn->query("SELECT COUNT(*) as count FROM word_lists WHERE public = 1");
$public_lists_count = $stmt->fetch();
// Get words count
$stmt = $conn->query("SELECT COUNT(*) as count FROM list_words");
$words_count = $stmt->fetch();
?>
<li>Word Lists: <?= $lists_count ? $lists_count['count'] : 0 ?> total (<?= $public_lists_count ? $public_lists_count['count'] : 0 ?> public)</li>
<li>List Words: <?= $words_count ? $words_count['count'] : 0 ?> total word entries</li>
</ul>
</div>
<div class="bg-gray-50 p-4 rounded">
<h4 class="font-medium mb-2">Setup Tools</h4>
<ul class="space-y-2">
<li><a href="setup_lists_tables.php" class="text-blue-500 hover:underline">Set Up Word Lists Tables</a></li>
<li><a href="setup_admin.php" class="text-blue-500 hover:underline">Set Up Admin User</a></li>
<li><a href="fix_admin.php" class="text-blue-500 hover:underline">Repair Admin Account</a></li>
<li><a href="setup_profile_photo.php" class="text-blue-500 hover:underline">Set Up Profile Photo Feature</a></li>
<li><a href="setup_public_lists.php" class="text-blue-500 hover:underline">Set Up Public Lists</a></li>
<li><a href="setup_copied_lists.php" class="text-blue-500 hover:underline">Set Up Copied Lists</a></li>
<li><a href="setup_list_likes.php" class="text-blue-500 hover:underline">Set Up List Likes Feature</a></li>
<li><a href="setup_reviews_table.php" class="text-blue-500 hover:underline">Set Up User Reviews</a></li>
<li><a href="setup_bio.php" class="text-blue-500 hover:underline">Set Up User Bio Feature</a></li>
</ul>
</div>
</div>
</div>
</main>
</div>
<script>
// Mobile menu toggle
document.getElementById("mobileMenuBtn").addEventListener("click", function() {
const mobileMenu = document.getElementById("mobileMenu");
mobileMenu.classList.toggle("hidden");
});
// Copy font toggle functionality to mobile button
if (document.getElementById("mobileFontToggleBtn")) {
document.getElementById("mobileFontToggleBtn").addEventListener("click", function() {
document.getElementById("fontToggleBtn").click();
});
}
// Handle the select all checkbox
document.getElementById('selectAll').addEventListener('change', function() {
const checkboxes = document.querySelectorAll('.user-checkbox');
checkboxes.forEach(checkbox => {
checkbox.checked = this.checked;
});
});
// Select All button
document.getElementById('selectAllBtn').addEventListener('click', function() {
const checkboxes = document.querySelectorAll('.user-checkbox');
checkboxes.forEach(checkbox => {
checkbox.checked = true;
});
document.getElementById('selectAll').checked = true;
});
// Select None button
document.getElementById('selectNoneBtn').addEventListener('click', function() {
const checkboxes = document.querySelectorAll('.user-checkbox');
checkboxes.forEach(checkbox => {
checkbox.checked = false;
});
document.getElementById('selectAll').checked = false;
});
// Show timeout input when timeout option is selected
document.getElementById('batch_action').addEventListener('change', function() {
const form = document.getElementById('batchActionForm');
if (this.value === 'timeout_users') {
form.classList.add('with-timeout');
} else {
form.classList.remove('with-timeout');
}
});
// Validation before form submission
document.getElementById('batchActionForm').addEventListener('submit', function(e) {
const action = document.getElementById('batch_action').value;
const selectedUsers = document.querySelectorAll('.user-checkbox:checked');
if (!action) {
e.preventDefault();
alert('Please select an action.');
return;
}
if (selectedUsers.length === 0) {
e.preventDefault();
alert('Please select at least one user.');
return;
}
if (action === 'ban_users' || action === 'delete_lists') {
if (!confirm('Are you sure you want to perform this action? This cannot be undone.')) {
e.preventDefault();
}
}
});
</script>
<script src="font-toggle.js"></script>
</body>
</html>