Update: 2026-05-03 22:51:59
This commit is contained in:
@@ -16,6 +16,17 @@ if ($decoded['role'] !== 'super_admin' && $decoded['role'] !== 'admin') {
|
||||
|
||||
$data = input();
|
||||
|
||||
// 1. Role Authorization check (Prevent Role Escalation)
|
||||
$allowedRoles = match($decoded['role']) {
|
||||
'super_admin' => ['super_admin', 'admin', 'accountant', 'employee', 'viewer'],
|
||||
'admin' => ['accountant', 'employee', 'viewer'],
|
||||
default => []
|
||||
};
|
||||
|
||||
if (!in_array($data['role'] ?? '', $allowedRoles, true)) {
|
||||
json_error('غير مصرح لك بإنشاء مستخدم بهذا الدور', 403);
|
||||
}
|
||||
|
||||
// 2. Validation
|
||||
$errors = Validator::validate($data, [
|
||||
'name' => 'required',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Users List Endpoint (with Decryption)
|
||||
* Users List Endpoint (Role-Based & Tenant-Aware)
|
||||
*/
|
||||
|
||||
use App\Core\Database;
|
||||
@@ -9,26 +9,51 @@ use App\Middleware\AuthMiddleware;
|
||||
|
||||
// 1. Auth Check
|
||||
$decoded = AuthMiddleware::check();
|
||||
$db = Database::getInstance();
|
||||
|
||||
// 2. Simple Role-Based Access Control (RBAC)
|
||||
if ($decoded['role'] !== 'super_admin' && $decoded['role'] !== 'admin') {
|
||||
json_error('غير مصرح لك بالوصول لهذه البيانات', 403);
|
||||
$role = $decoded['role'];
|
||||
$tenantId = $decoded['tenant_id'] ?? null;
|
||||
|
||||
// 2. Build Query based on Role
|
||||
if ($role === 'super_admin') {
|
||||
// Super Admin sees ALL users from ALL tenants
|
||||
$stmt = $db->query("
|
||||
SELECT u.id, u.name, u.email, u.role, u.is_active, u.created_at, t.name as tenant_name, c.name as company_name
|
||||
FROM users u
|
||||
LEFT JOIN tenants t ON u.tenant_id = t.id
|
||||
LEFT JOIN companies c ON u.company_id = c.id
|
||||
");
|
||||
} elseif ($role === 'admin') {
|
||||
// Admin sees only users in THEIR tenant (Accounting Office)
|
||||
$stmt = $db->prepare("
|
||||
SELECT u.id, u.name, u.email, u.role, u.is_active, u.created_at, t.name as tenant_name, c.name as company_name
|
||||
FROM users u
|
||||
LEFT JOIN tenants t ON u.tenant_id = t.id
|
||||
LEFT JOIN companies c ON u.company_id = c.id
|
||||
WHERE u.tenant_id = ?
|
||||
");
|
||||
$stmt->execute([$tenantId]);
|
||||
} else {
|
||||
// Other roles shouldn't see user list
|
||||
json_error('Unauthorized', 403);
|
||||
}
|
||||
|
||||
// 3. Fetch Data
|
||||
$db = Database::getInstance();
|
||||
$stmt = $db->prepare("SELECT id, name, email, role, is_active, created_at FROM users");
|
||||
$stmt->execute();
|
||||
$users = $stmt->fetchAll();
|
||||
|
||||
// 4. Decrypt sensitive data for the UI
|
||||
// 3. Decrypt data and format
|
||||
foreach ($users as &$user) {
|
||||
// Try to decrypt. If it fails (e.g. data was plain text), keep original.
|
||||
// Decrypt User Name/Email
|
||||
$decryptedName = Encryption::decrypt($user['name']);
|
||||
$user['name'] = $decryptedName !== false ? $decryptedName : $user['name'];
|
||||
|
||||
$decryptedEmail = Encryption::decrypt($user['email']);
|
||||
$user['email'] = $decryptedEmail !== false ? $decryptedEmail : $user['email'];
|
||||
|
||||
// Decrypt Company Name (if exists)
|
||||
if ($user['company_name']) {
|
||||
$decryptedCompanyName = Encryption::decrypt($user['company_name']);
|
||||
$user['company_name'] = $decryptedCompanyName !== false ? $decryptedCompanyName : $user['company_name'];
|
||||
}
|
||||
}
|
||||
|
||||
json_success($users);
|
||||
|
||||
Reference in New Issue
Block a user