270 lines
14 KiB
PHP
270 lines
14 KiB
PHP
<?php
|
|
// admin_roles.php
|
|
require_once __DIR__ . '/includes/app.php';
|
|
require_once __DIR__ . '/includes/auth.php';
|
|
|
|
try {
|
|
db()->query('SELECT 1 FROM roles LIMIT 1');
|
|
} catch (Exception $e) {
|
|
ob_start();
|
|
require_once __DIR__ . '/db/migrations/migrate_roles.php';
|
|
ob_end_clean();
|
|
header('Location: ' . app_url('admin.php', ['page' => 'roles']));
|
|
exit;
|
|
}
|
|
|
|
require_permission('roles', 'view');
|
|
|
|
$pages = [
|
|
'dashboard' => t('Dashboard', 'لوحة التحكم'),
|
|
'classes' => t('Classes', 'الصفوف'),
|
|
'subjects' => t('Subjects', 'المواد'),
|
|
'teachers' => t('Teachers', 'المعلمين'),
|
|
'courses' => t('Courses', 'الدورات'),
|
|
'assignments' => t('Assignments', 'الواجبات'),
|
|
'students' => t('Students', 'الطلاب'),
|
|
'plans' => t('Plans', 'الخطط'),
|
|
'users' => t('Platform Users', 'مستخدمي المنصة'),
|
|
'roles' => t('Role Groups', 'مجموعات الصلاحيات'),
|
|
'integrations' => t('Integrations', 'عمليات الربط'),
|
|
'landing' => t('Landing Page', 'الصفحة الرئيسية'),
|
|
'profile' => t('Platform Profile', 'ملف المنصة'),
|
|
];
|
|
|
|
$action = $_GET['action'] ?? 'list';
|
|
$id = (int)($_GET['id'] ?? 0);
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$post_action = $_POST['action'] ?? $action;
|
|
$post_id = (int)($_POST['id'] ?? $id);
|
|
|
|
if ($post_action === 'delete' && $post_id > 0) {
|
|
require_permission('roles', 'delete');
|
|
// check if system role
|
|
$stmt = db()->prepare("SELECT is_system FROM roles WHERE id = ?");
|
|
$stmt->execute([$post_id]);
|
|
$role = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
if ($role && !$role['is_system']) {
|
|
$stmt = db()->prepare("DELETE FROM roles WHERE id = ?");
|
|
$stmt->execute([$post_id]);
|
|
}
|
|
header('Location: ' . app_url('admin.php', ['page' => 'roles']));
|
|
exit;
|
|
}
|
|
|
|
if ($post_action === 'edit' || $post_action === 'add') {
|
|
require_permission('roles', $post_action === 'add' ? 'add' : 'edit');
|
|
$name = trim($_POST['name'] ?? '');
|
|
$description = trim($_POST['description'] ?? '');
|
|
$perms = $_POST['perms'] ?? []; // e.g. ['classes' => ['view'=>1, 'add'=>1]]
|
|
|
|
if ($post_action === 'edit' && $post_id > 0) {
|
|
$stmt = db()->prepare("UPDATE roles SET name=?, description=? WHERE id=?");
|
|
$stmt->execute([$name, $description, $post_id]);
|
|
$role_id = $post_id;
|
|
} else {
|
|
$stmt = db()->prepare("INSERT INTO roles (name, description) VALUES (?, ?)");
|
|
$stmt->execute([$name, $description]);
|
|
$role_id = db()->lastInsertId();
|
|
}
|
|
|
|
// update permissions
|
|
if ($role_id) {
|
|
$stmt = db()->prepare("DELETE FROM role_permissions WHERE role_id = ?");
|
|
$stmt->execute([$role_id]);
|
|
|
|
$stmt = db()->prepare("INSERT INTO role_permissions (role_id, page, can_view, can_add, can_edit, can_delete) VALUES (?, ?, ?, ?, ?, ?)");
|
|
foreach ($pages as $p => $pname) {
|
|
if (isset($perms[$p])) {
|
|
$v = !empty($perms[$p]['view']) ? 1 : 0;
|
|
$a = !empty($perms[$p]['add']) ? 1 : 0;
|
|
$e = !empty($perms[$p]['edit']) ? 1 : 0;
|
|
$d = !empty($perms[$p]['delete']) ? 1 : 0;
|
|
if ($v || $a || $e || $d) {
|
|
$stmt->execute([$role_id, $p, $v, $a, $e, $d]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
header('Location: ' . app_url('admin.php', ['page' => 'roles']));
|
|
exit;
|
|
}
|
|
}
|
|
|
|
$roles = db()->query("SELECT * FROM roles ORDER BY id DESC")->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// Fetch permissions for all roles
|
|
$stmt = db()->query("SELECT * FROM role_permissions");
|
|
$all_perms = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$role_perms = [];
|
|
foreach ($all_perms as $p) {
|
|
$role_perms[$p['role_id']][$p['page']] = $p;
|
|
}
|
|
|
|
// Merge permissions into roles for JS
|
|
foreach ($roles as &$r) {
|
|
$r['permissions'] = $role_perms[$r['id']] ?? [];
|
|
}
|
|
unset($r);
|
|
|
|
?>
|
|
<div class="section-header mb-4 d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<h1 class="section-title mb-2"><?= h(t('Role Groups', 'مجموعات الصلاحيات')) ?></h1>
|
|
<p class="text-secondary mb-0"><?= h(t('Manage roles and their page permissions.', 'إدارة الأدوار وصلاحيات الصفحات الخاصة بها.')) ?></p>
|
|
</div>
|
|
<?php if (has_permission('roles', 'add')): ?>
|
|
<button class="btn btn-dark" data-bs-toggle="modal" data-bs-target="#roleModal" onclick="editRole(null)">
|
|
<?= h(t('Add Role Group', 'إضافة مجموعة صلاحيات')) ?>
|
|
</button>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="panel-card p-0 overflow-hidden">
|
|
<div class="table-responsive">
|
|
<table class="table table-hover align-middle mb-0">
|
|
<thead class="bg-light">
|
|
<tr>
|
|
<th class="px-4 py-3"><?= h(t('Role Name', 'اسم الدور')) ?></th>
|
|
<th class="py-3"><?= h(t('Description', 'الوصف')) ?></th>
|
|
<th class="px-4 py-3 text-end"><?= h(t('Actions', 'الإجراءات')) ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($roles as $r): ?>
|
|
<tr>
|
|
<td class="px-4 py-3 fw-bold text-dark">
|
|
<?= h($r['name']) ?>
|
|
<?php if ($r['is_system']): ?>
|
|
<span class="badge bg-secondary ms-2"><?= h(t('System', 'نظام')) ?></span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td class="py-3 text-secondary"><?= h($r['description']) ?></td>
|
|
<td class="px-4 py-3 text-end">
|
|
<div class="btn-group btn-group-sm">
|
|
<?php if (has_permission('roles', 'edit')): ?>
|
|
<button class="btn btn-outline-dark" onclick='editRole(<?= htmlspecialchars(json_encode($r), ENT_QUOTES) ?>)' data-bs-toggle="modal" data-bs-target="#roleModal">
|
|
<svg width="16" height="16" fill="currentColor" class="me-1" viewBox="0 0 16 16"><path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z"/></svg><?= h(t($r['is_system'] ? 'View' : 'Edit', $r['is_system'] ? 'عرض' : 'تعديل')) ?>
|
|
</button>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!$r['is_system'] && has_permission('roles', 'delete')): ?>
|
|
<form method="POST" action="admin_roles.php" class="d-inline" onsubmit="return confirm('<?= h(t('Delete this role?', 'حذف هذا الدور؟')) ?>');">
|
|
<input type="hidden" name="action" value="delete">
|
|
<input type="hidden" name="id" value="<?= h($r['id']) ?>">
|
|
<button class="btn btn-outline-danger" type="submit">
|
|
<svg width="16" height="16" fill="currentColor" class="me-1" viewBox="0 0 16 16"><path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/><path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/></svg><?= h(t('Delete', 'حذف')) ?>
|
|
</button>
|
|
</form>
|
|
<?php endif; ?>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php if (empty($roles)): ?>
|
|
<tr><td colspan="3" class="text-center py-4 text-secondary"><?= h(t('No roles found.', 'لا توجد أدوار.')) ?></td></tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Role Modal -->
|
|
<div class="modal fade" id="roleModal" tabindex="-1">
|
|
<div class="modal-dialog modal-lg">
|
|
<form class="modal-content" method="POST" action="admin_roles.php">
|
|
<input type="hidden" name="action" id="roleAction" value="add">
|
|
<input type="hidden" name="id" id="roleId" value="0">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="roleModalTitle"><?= h(t('Add Role Group', 'إضافة مجموعة صلاحيات')) ?></h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(t('Role Name', 'اسم الدور')) ?></label>
|
|
<input type="text" class="form-control" name="name" id="roleName" required>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(t('Description', 'الوصف')) ?></label>
|
|
<input type="text" class="form-control" name="description" id="roleDesc">
|
|
</div>
|
|
</div>
|
|
|
|
<h6 class="mt-4 mb-3"><?= h(t('Permissions', 'الصلاحيات')) ?></h6>
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered table-sm align-middle">
|
|
<thead class="bg-light text-center">
|
|
<tr>
|
|
<th class="text-start"><?= h(t('Page', 'الصفحة')) ?></th>
|
|
<th><?= h(t('View', 'عرض')) ?></th>
|
|
<th><?= h(t('Add', 'إضافة')) ?></th>
|
|
<th><?= h(t('Edit', 'تعديل')) ?></th>
|
|
<th><?= h(t('Delete', 'حذف')) ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="permissionsTbody">
|
|
<?php foreach($pages as $p => $pname): ?>
|
|
<tr>
|
|
<td class="text-start fw-bold"><?= h($pname) ?></td>
|
|
<td class="text-center"><input class="form-check-input perm-chk perm-chk-view" type="checkbox" name="perms[<?= h($p) ?>][view]" value="1" data-page="<?= h($p) ?>"></td>
|
|
<td class="text-center"><input class="form-check-input perm-chk perm-chk-add" type="checkbox" name="perms[<?= h($p) ?>][add]" value="1" data-page="<?= h($p) ?>"></td>
|
|
<td class="text-center"><input class="form-check-input perm-chk perm-chk-edit" type="checkbox" name="perms[<?= h($p) ?>][edit]" value="1" data-page="<?= h($p) ?>"></td>
|
|
<td class="text-center"><input class="form-check-input perm-chk perm-chk-delete" type="checkbox" name="perms[<?= h($p) ?>][delete]" value="1" data-page="<?= h($p) ?>"></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal"><?= h(t('Cancel', 'إلغاء')) ?></button>
|
|
<button type="submit" class="btn btn-dark" id="btnSaveRole"><?= h(t('Save', 'حفظ')) ?></button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function editRole(role) {
|
|
// reset checkboxes
|
|
document.querySelectorAll('.perm-chk').forEach(c => c.checked = false);
|
|
|
|
if (role) {
|
|
document.getElementById('roleAction').value = 'edit';
|
|
document.getElementById('roleId').value = role.id;
|
|
document.getElementById('roleModalTitle').innerText = '<?= h(t('Edit Role Group', 'تعديل مجموعة الصلاحيات')) ?>';
|
|
document.getElementById('roleName').value = role.name;
|
|
document.getElementById('roleDesc').value = role.description || '';
|
|
|
|
if (role.permissions) {
|
|
for (let p in role.permissions) {
|
|
let perms = role.permissions[p];
|
|
if (perms.can_view == 1) { let el = document.querySelector(`input[name="perms[${p}][view]"]`); if(el) el.checked = true; }
|
|
if (perms.can_add == 1) { let el = document.querySelector(`input[name="perms[${p}][add]"]`); if(el) el.checked = true; }
|
|
if (perms.can_edit == 1) { let el = document.querySelector(`input[name="perms[${p}][edit]"]`); if(el) el.checked = true; }
|
|
if (perms.can_delete == 1) { let el = document.querySelector(`input[name="perms[${p}][delete]"]`); if(el) el.checked = true; }
|
|
}
|
|
}
|
|
|
|
let isSystem = role.is_system == 1;
|
|
document.getElementById('roleName').readOnly = isSystem;
|
|
document.getElementById('roleDesc').readOnly = isSystem;
|
|
document.querySelectorAll('.perm-chk').forEach(c => c.disabled = isSystem);
|
|
document.getElementById('btnSaveRole').style.display = isSystem ? 'none' : 'block';
|
|
|
|
} else {
|
|
document.getElementById('roleAction').value = 'add';
|
|
document.getElementById('roleId').value = '0';
|
|
document.getElementById('roleModalTitle').innerText = '<?= h(t('Add Role Group', 'إضافة مجموعة صلاحيات')) ?>';
|
|
document.getElementById('roleName').value = '';
|
|
document.getElementById('roleDesc').value = '';
|
|
|
|
document.getElementById('roleName').readOnly = false;
|
|
document.getElementById('roleDesc').readOnly = false;
|
|
document.querySelectorAll('.perm-chk').forEach(c => c.disabled = false);
|
|
document.getElementById('btnSaveRole').style.display = 'block';
|
|
}
|
|
}
|
|
</script>
|