['super_admin', 'admin', 'accountant', 'employee', 'viewer'], 'admin' => ['accountant', 'employee', 'viewer'], // Cannot create other admins default => [] }; if (!in_array($data['role'] ?? '', $allowedRoles, true)) { json_error('غير مصرح لك بإنشاء مستخدم بهذا الدور', 403); } // 2. Validation $errors = Validator::validate($data, [ 'name' => 'required', 'email' => 'required|email', 'phone' => 'required', 'password' => 'required', 'role' => 'required' ]); if ($errors) { json_error('Validation Failed', 422, $errors); } $db = Database::getInstance(); // 3. Encrypt sensitive data $encryptedName = Encryption::encrypt($data['name']); $encryptedEmail = Encryption::encrypt($data['email']); $emailHash = hash('sha256', strtolower($data['email'])); // For fast lookup during login $encryptedPhone = Encryption::encrypt($data['phone']); $phoneHash = hash('sha256', preg_replace('/[^0-9+]/', '', $data['phone'])); // 3. Determine Tenant ID $tenantId = null; if ($decoded['role'] === 'super_admin') { if (empty($data['tenant_id'])) { json_error('يجب اختيار المكتب المحاسبي', 422); } $tenantId = $data['tenant_id']; } else { $tenantId = $decoded['tenant_id']; } // --- QUOTA CHECK --- \App\Middleware\QuotaMiddleware::checkUserQuota($tenantId); // ------------------- // 4. Save to Database try { $stmt = $db->prepare("INSERT INTO users (id, tenant_id, name, email, email_hash, phone, phone_hash, password_hash, role, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); $stmt->execute([ \App\Core\Database::generateUuid(), $tenantId, $encryptedName, $encryptedEmail, $emailHash, $encryptedPhone, $phoneHash, password_hash($data['password'], PASSWORD_DEFAULT), $data['role'], date('Y-m-d H:i:s') ]); json_success(null, 'تم إضافة المستخدم بنجاح'); AuditLogger::log('user.created', 'user', null, null, [ 'name' => $data['name'], 'email' => $data['email'], 'role' => $data['role'], ], $decoded); } catch (\Exception $e) { if (str_contains($e->getMessage(), 'Duplicate entry')) { json_error('البريد الإلكتروني مسجل مسبقاً', 409); } json_error('حدث خطأ أثناء حفظ البيانات', 500); }