461 lines
20 KiB
PHP
461 lines
20 KiB
PHP
<?php
|
|
require_once __DIR__ . '/includes/header.php';
|
|
|
|
if (!canView('users')) {
|
|
redirect('index.php');
|
|
}
|
|
|
|
$error = '';
|
|
$success = '';
|
|
|
|
$modules = [
|
|
'inbound' => 'البريد الوارد',
|
|
'outbound' => 'البريد الصادر',
|
|
'internal' => 'البريد الداخلي',
|
|
'users' => 'إدارة المستخدمين',
|
|
'settings' => 'الإعدادات',
|
|
'reports' => 'التقارير'
|
|
];
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$action = $_POST['action'] ?? '';
|
|
$username = $_POST['username'] ?? '';
|
|
$full_name = $_POST['full_name'] ?? '';
|
|
$role = $_POST['role'] ?? 'staff';
|
|
$password = $_POST['password'] ?? '';
|
|
$id = $_POST['id'] ?? 0;
|
|
|
|
// Global permissions (legacy/fallback)
|
|
$can_view = isset($_POST['can_view_global']) ? 1 : 0;
|
|
$can_add = isset($_POST['can_add_global']) ? 1 : 0;
|
|
$can_edit = isset($_POST['can_edit_global']) ? 1 : 0;
|
|
$can_delete = isset($_POST['can_delete_global']) ? 1 : 0;
|
|
|
|
if ($action === 'add') {
|
|
if (!canAdd('users')) redirect('users.php');
|
|
if ($username && $password && $full_name) {
|
|
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
|
try {
|
|
$pdo = db();
|
|
$pdo->beginTransaction();
|
|
|
|
$stmt = $pdo->prepare("INSERT INTO users (username, password, full_name, role, can_view, can_add, can_edit, can_delete) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
|
$stmt->execute([$username, $hashed_password, $full_name, $role, $can_view, $can_add, $can_edit, $can_delete]);
|
|
$user_id = $pdo->lastInsertId();
|
|
|
|
// Save page permissions
|
|
$perm_stmt = $pdo->prepare("INSERT INTO user_permissions (user_id, page, can_view, can_add, can_edit, can_delete) VALUES (?, ?, ?, ?, ?, ?)");
|
|
foreach ($modules as $module => $label) {
|
|
$m_view = isset($_POST["perm_{$module}_view"]) ? 1 : 0;
|
|
$m_add = isset($_POST["perm_{$module}_add"]) ? 1 : 0;
|
|
$m_edit = isset($_POST["perm_{$module}_edit"]) ? 1 : 0;
|
|
$m_delete = isset($_POST["perm_{$module}_delete"]) ? 1 : 0;
|
|
$perm_stmt->execute([$user_id, $module, $m_view, $m_add, $m_edit, $m_delete]);
|
|
}
|
|
|
|
$pdo->commit();
|
|
$_SESSION['success'] = 'تم إضافة المستخدم بنجاح';
|
|
redirect('users.php');
|
|
} catch (PDOException $e) {
|
|
if (isset($pdo)) $pdo->rollBack();
|
|
if ($e->getCode() == 23000) {
|
|
$error = 'اسم المستخدم موجود مسبقاً';
|
|
} else {
|
|
$error = 'حدث خطأ: ' . $e->getMessage();
|
|
}
|
|
}
|
|
} else {
|
|
$error = 'يرجى ملء جميع الحقول المطلوبة';
|
|
}
|
|
} elseif ($action === 'edit') {
|
|
if (!canEdit('users')) redirect('users.php');
|
|
if ($username && $full_name && $id) {
|
|
try {
|
|
$pdo = db();
|
|
$pdo->beginTransaction();
|
|
|
|
if ($password) {
|
|
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
|
$stmt = $pdo->prepare("UPDATE users SET username = ?, full_name = ?, role = ?, password = ?, can_view = ?, can_add = ?, can_edit = ?, can_delete = ? WHERE id = ?");
|
|
$stmt->execute([$username, $full_name, $role, $hashed_password, $can_view, $can_add, $can_edit, $can_delete, $id]);
|
|
} else {
|
|
$stmt = $pdo->prepare("UPDATE users SET username = ?, full_name = ?, role = ?, can_view = ?, can_add = ?, can_edit = ?, can_delete = ? WHERE id = ?");
|
|
$stmt->execute([$username, $full_name, $role, $can_view, $can_add, $can_edit, $can_delete, $id]);
|
|
}
|
|
|
|
// Update page permissions
|
|
$pdo->prepare("DELETE FROM user_permissions WHERE user_id = ?")->execute([$id]);
|
|
$perm_stmt = $pdo->prepare("INSERT INTO user_permissions (user_id, page, can_view, can_add, can_edit, can_delete) VALUES (?, ?, ?, ?, ?, ?)");
|
|
foreach ($modules as $module => $label) {
|
|
$m_view = isset($_POST["perm_{$module}_view"]) ? 1 : 0;
|
|
$m_add = isset($_POST["perm_{$module}_add"]) ? 1 : 0;
|
|
$m_edit = isset($_POST["perm_{$module}_edit"]) ? 1 : 0;
|
|
$m_delete = isset($_POST["perm_{$module}_delete"]) ? 1 : 0;
|
|
$perm_stmt->execute([$id, $module, $m_view, $m_add, $m_edit, $m_delete]);
|
|
}
|
|
|
|
$pdo->commit();
|
|
|
|
// Refresh own session if editing self
|
|
if ($id == $_SESSION['user_id']) {
|
|
unset($_SESSION['permissions']);
|
|
}
|
|
|
|
$_SESSION['success'] = 'تم تحديث بيانات المستخدم بنجاح';
|
|
redirect('users.php');
|
|
} catch (PDOException $e) {
|
|
if (isset($pdo)) $pdo->rollBack();
|
|
$error = 'حدث خطأ: ' . $e->getMessage();
|
|
}
|
|
} else {
|
|
$error = 'يرجى ملء جميع الحقول المطلوبة';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) {
|
|
if (!canDelete('users')) redirect('users.php');
|
|
if ($_GET['id'] != $_SESSION['user_id']) {
|
|
$stmt = db()->prepare("DELETE FROM users WHERE id = ?");
|
|
$stmt->execute([$_GET['id']]);
|
|
$_SESSION['success'] = 'تم حذف المستخدم بنجاح';
|
|
redirect('users.php');
|
|
} else {
|
|
$error = 'لا يمكنك حذف حسابك الحالي';
|
|
}
|
|
}
|
|
|
|
// Get session messages
|
|
if (isset($_SESSION['success'])) {
|
|
$success = $_SESSION['success'];
|
|
unset($_SESSION['success']);
|
|
}
|
|
if (isset($_SESSION['error'])) {
|
|
$error = $_SESSION['error'];
|
|
unset($_SESSION['error']);
|
|
}
|
|
|
|
$stmt = db()->query("SELECT * FROM users ORDER BY created_at DESC");
|
|
$users = $stmt->fetchAll();
|
|
|
|
// Fetch permissions for all users
|
|
$user_perms = [];
|
|
$perm_stmt = db()->query("SELECT * FROM user_permissions");
|
|
while ($row = $perm_stmt->fetch()) {
|
|
$user_perms[$row['user_id']][$row['page']] = $row;
|
|
}
|
|
|
|
// Handle Deep Link for Edit
|
|
$deepLinkData = null;
|
|
if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) {
|
|
$stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
|
|
$stmt->execute([$_GET['id']]);
|
|
$deepLinkData = $stmt->fetch();
|
|
if ($deepLinkData) {
|
|
$deepLinkData['page_permissions'] = $user_perms[$deepLinkData['id']] ?? [];
|
|
}
|
|
}
|
|
?>
|
|
|
|
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
|
<h1 class="h2">إدارة المستخدمين والصلاحيات</h1>
|
|
<?php if (canAdd('users')): ?>
|
|
<button type="button" class="btn btn-primary shadow-sm" onclick="openUserModal('add')">
|
|
<i class="fas fa-user-plus me-1"></i> إضافة مستخدم جديد
|
|
</button>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php if ($success): ?>
|
|
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
|
<?= $success ?>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($error): ?>
|
|
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
|
<?= $error ?>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="card shadow-sm border-0 mb-4">
|
|
<div class="card-body p-0">
|
|
<div class="table-responsive">
|
|
<table class="table table-hover align-middle mb-0">
|
|
<thead class="bg-light">
|
|
<tr>
|
|
<th class="ps-4">الاسم الكامل</th>
|
|
<th>اسم المستخدم</th>
|
|
<th>الدور</th>
|
|
<th>تاريخ الإنشاء</th>
|
|
<th class="pe-4 text-center">الإجراءات</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($users as $user): ?>
|
|
<tr>
|
|
<td class="ps-4 fw-bold"><?= htmlspecialchars($user['full_name']) ?></td>
|
|
<td><?= htmlspecialchars($user['username']) ?></td>
|
|
<td>
|
|
<?php if ($user['role'] === 'admin'): ?>
|
|
<span class="badge bg-danger">مدير</span>
|
|
<?php elseif ($user['role'] === 'clerk'): ?>
|
|
<span class="badge bg-warning text-dark">كاتب</span>
|
|
<?php else: ?>
|
|
<span class="badge bg-secondary">موظف</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?= $user['created_at'] ?></td>
|
|
<td class="pe-4 text-center">
|
|
<?php if (canEdit('users')): ?>
|
|
<button type="button" class="btn btn-sm btn-outline-primary"
|
|
onclick="openUserModal('edit', <?= htmlspecialchars(json_encode(array_merge($user, ['page_permissions' => $user_perms[$user['id']] ?? []])), ENT_QUOTES, 'UTF-8') ?>)">
|
|
<i class="fas fa-edit"></i> تعديل الصلاحيات
|
|
</button>
|
|
<?php endif; ?>
|
|
<?php if (canDelete('users') && $user['id'] != $_SESSION['user_id']): ?>
|
|
<a href="javascript:void(0)" onclick="confirmDelete(<?= $user['id'] ?>)" class="btn btn-sm btn-outline-danger">
|
|
<i class="fas fa-trash"></i> حذف
|
|
</a>
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- User Modal -->
|
|
<div class="modal fade" id="userModal" tabindex="-1" aria-labelledby="userModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content border-0 shadow">
|
|
<div class="modal-header bg-primary text-white">
|
|
<h5 class="modal-title fw-bold" id="userModalLabel">إضافة مستخدم جديد</h5>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<form id="userForm" method="POST">
|
|
<div class="modal-body p-4">
|
|
<input type="hidden" name="action" id="modalAction" value="add">
|
|
<input type="hidden" name="id" id="modalId" value="0">
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label fw-bold">الاسم الكامل</label>
|
|
<input type="text" name="full_name" id="modalFullName" class="form-control" required>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label fw-bold">اسم المستخدم</label>
|
|
<input type="text" name="username" id="modalUsername" class="form-control" required>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label fw-bold">كلمة المرور <span id="pwdHint" class="text-muted small"></span></label>
|
|
<input type="password" name="password" id="modalPassword" class="form-control">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label fw-bold">الدور</label>
|
|
<select name="role" id="modalRole" class="form-select" onchange="applyRolePresets(this.value)">
|
|
<option value="staff">موظف</option>
|
|
<option value="clerk">كاتب</option>
|
|
<option value="admin">مدير</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<hr>
|
|
|
|
<h6 class="fw-bold mb-3"><i class="fas fa-lock me-2 text-primary"></i> صلاحيات الوصول لكل صفحة</h6>
|
|
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered table-sm align-middle">
|
|
<thead class="bg-light">
|
|
<tr class="text-center">
|
|
<th class="text-start ps-3">الصفحة / الموديول</th>
|
|
<th>عرض</th>
|
|
<th>إضافة</th>
|
|
<th>تعديل</th>
|
|
<th>حذف</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($modules as $key => $label): ?>
|
|
<tr class="text-center">
|
|
<td class="text-start ps-3 fw-bold"><?= $label ?></td>
|
|
<td>
|
|
<input class="form-check-input" type="checkbox" name="perm_<?= $key ?>_view" id="perm_<?= $key ?>_view" value="1">
|
|
</td>
|
|
<td>
|
|
<input class="form-check-input" type="checkbox" name="perm_<?= $key ?>_add" id="perm_<?= $key ?>_add" value="1">
|
|
</td>
|
|
<td>
|
|
<input class="form-check-input" type="checkbox" name="perm_<?= $key ?>_edit" id="perm_<?= $key ?>_edit" value="1">
|
|
</td>
|
|
<td>
|
|
<input class="form-check-input" type="checkbox" name="perm_<?= $key ?>_delete" id="perm_<?= $key ?>_delete" value="1">
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Hidden legacy fields for backward compatibility if needed -->
|
|
<input type="hidden" name="can_view_global" id="permViewGlobal" value="1">
|
|
<input type="hidden" name="can_add_global" id="permAddGlobal" value="0">
|
|
<input type="hidden" name="can_edit_global" id="permEditGlobal" value="0">
|
|
<input type="hidden" name="can_delete_global" id="permDeleteGlobal" value="0">
|
|
</div>
|
|
<div class="modal-footer bg-light">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">إلغاء</button>
|
|
<button type="submit" class="btn btn-primary px-4">حفظ البيانات</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
let userModal;
|
|
const modules = <?= json_encode(array_keys($modules)) ?>;
|
|
|
|
function applyRolePresets(role) {
|
|
modules.forEach(m => {
|
|
const view = document.getElementById(`perm_${m}_view`);
|
|
const add = document.getElementById(`perm_${m}_add`);
|
|
const edit = document.getElementById(`perm_${m}_edit`);
|
|
const del = document.getElementById(`perm_${m}_delete`);
|
|
|
|
if (role === 'admin') {
|
|
view.checked = add.checked = edit.checked = del.checked = true;
|
|
} else if (role === 'clerk') {
|
|
if (m === 'users' || m === 'settings') {
|
|
view.checked = add.checked = edit.checked = del.checked = false;
|
|
} else {
|
|
view.checked = add.checked = edit.checked = true;
|
|
del.checked = (m === 'reports' ? false : false);
|
|
}
|
|
} else {
|
|
if (m === 'inbound' || m === 'outbound' || m === 'internal') {
|
|
view.checked = true;
|
|
add.checked = (m === 'internal'); // Staff can send internal mail
|
|
edit.checked = del.checked = false;
|
|
} else {
|
|
view.checked = add.checked = edit.checked = del.checked = false;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function openUserModal(action, data = null) {
|
|
if (!userModal) {
|
|
const modalEl = document.getElementById('userModal');
|
|
if (typeof bootstrap !== 'undefined') {
|
|
userModal = new bootstrap.Modal(modalEl);
|
|
} else {
|
|
console.error('Bootstrap not loaded');
|
|
return;
|
|
}
|
|
}
|
|
|
|
const label = document.getElementById('userModalLabel');
|
|
const modalAction = document.getElementById('modalAction');
|
|
const modalId = document.getElementById('modalId');
|
|
const modalPassword = document.getElementById('modalPassword');
|
|
const pwdHint = document.getElementById('pwdHint');
|
|
|
|
const fields = {
|
|
full_name: document.getElementById('modalFullName'),
|
|
username: document.getElementById('modalUsername'),
|
|
role: document.getElementById('modalRole')
|
|
};
|
|
|
|
modalAction.value = action;
|
|
|
|
if (action === 'add') {
|
|
label.textContent = 'إضافة مستخدم جديد';
|
|
modalId.value = '0';
|
|
Object.keys(fields).forEach(key => fields[key].value = '');
|
|
modalRole.value = 'staff';
|
|
applyRolePresets('staff');
|
|
modalPassword.required = true;
|
|
pwdHint.textContent = '';
|
|
} else {
|
|
label.textContent = 'تعديل بيانات المستخدم';
|
|
modalId.value = data.id;
|
|
Object.keys(fields).forEach(key => {
|
|
if (fields[key]) fields[key].value = data[key] || '';
|
|
});
|
|
|
|
// Set permissions checkboxes
|
|
modules.forEach(m => {
|
|
const p = data.page_permissions && data.page_permissions[m] ? data.page_permissions[m] : {};
|
|
document.getElementById(`perm_${m}_view`).checked = p.can_view == 1;
|
|
document.getElementById(`perm_${m}_add`).checked = p.can_add == 1;
|
|
document.getElementById(`perm_${m}_edit`).checked = p.can_edit == 1;
|
|
document.getElementById(`perm_${m}_delete`).checked = p.can_delete == 1;
|
|
});
|
|
|
|
modalPassword.required = false;
|
|
pwdHint.textContent = '(اتركه فارغاً للحفاظ على كلمة المرور الحالية)';
|
|
}
|
|
|
|
userModal.show();
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
<?php if ($deepLinkData): ?>
|
|
openUserModal('edit', <?= json_encode($deepLinkData) ?>);
|
|
<?php elseif (isset($_GET['action']) && $_GET['action'] === 'add'): ?>
|
|
openUserModal('add');
|
|
<?php endif; ?>
|
|
});
|
|
|
|
function confirmDelete(id) {
|
|
if (typeof Swal === 'undefined') {
|
|
if (confirm('هل أنت متأكد من الحذف؟')) {
|
|
window.location.href = 'users.php?action=delete&id=' + id;
|
|
}
|
|
return;
|
|
}
|
|
Swal.fire({
|
|
title: 'هل أنت متأكد؟',
|
|
text: "لا يمكن التراجع عن عملية الحذف!",
|
|
icon: 'warning',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#d33',
|
|
cancelButtonColor: '#3085d6',
|
|
confirmButtonText: 'نعم، احذف!',
|
|
cancelButtonText: 'إلغاء'
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
window.location.href = 'users.php?action=delete&id=' + id;
|
|
}
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.modal-content {
|
|
border-radius: 15px;
|
|
overflow: hidden;
|
|
}
|
|
.modal-header.bg-primary {
|
|
background-color: #0d6efd !important;
|
|
}
|
|
.form-check-input:checked {
|
|
background-color: #198754;
|
|
border-color: #198754;
|
|
}
|
|
.table-sm th, .table-sm td {
|
|
padding: 0.5rem;
|
|
}
|
|
</style>
|
|
|
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|