store->selectCollection(self::COLLECTION_NAME)->find( ['tid' => $tenant], ['sort' => ['label' => 1]] ); $roles = []; foreach ($cursor as $entry) { $role = (array)$entry; // Ensure permissions is an array if (isset($role['permissions'])) { $role['permissions'] = (array)$role['permissions']; } $roles[] = $role; } return $roles; } /** * Fetch role by tenant and role ID */ public function fetchByRid(string $tenant, string $rid): ?array { $entry = $this->store->selectCollection(self::COLLECTION_NAME)->findOne([ 'tid' => $tenant, 'rid' => $rid ]); if (!$entry) { return null; } return (array)$entry; } /** * Create a new role */ public function createRole(string $tenant, array $roleData): array { $roleData['tid'] = $tenant; $roleData['rid'] = $roleData['rid'] ?? UUID::v4(); $roleData['label'] = $roleData['label'] ?? 'Unnamed Role'; $roleData['description'] = $roleData['description'] ?? ''; $roleData['permissions'] = $roleData['permissions'] ?? []; $roleData['system'] = $roleData['system'] ?? false; $this->store->selectCollection(self::COLLECTION_NAME)->insertOne($roleData); return $this->fetchByRid($tenant, $roleData['rid']); } /** * Update an existing role */ public function updateRole(string $tenant, string $rid, array $updates): bool { // Prevent updating system flag unset($updates['tid'], $updates['rid'], $updates['system']); if (empty($updates)) { return false; } $result = $this->store->selectCollection(self::COLLECTION_NAME)->updateOne( ['tid' => $tenant, 'rid' => $rid], ['$set' => $updates] ); return $result->getModifiedCount() > 0; } /** * Delete a role */ public function deleteRole(string $tenant, string $rid): bool { // Check if role is system role $role = $this->fetchByRid($tenant, $rid); if (!$role || ($role['system'] ?? false)) { return false; // Cannot delete system roles } $result = $this->store->selectCollection(self::COLLECTION_NAME)->deleteOne([ 'tid' => $tenant, 'rid' => $rid ]); return $result->getDeletedCount() > 0; } /** * Count users assigned to a role */ public function countUsersInRole(string $tenant, string $rid): int { $count = $this->store->selectCollection('user_accounts')->countDocuments([ 'tid' => $tenant, 'roles' => $rid ]); return (int)$count; } /** * Get all available permissions from modules * Grouped by category with metadata */ public function availablePermissions(): array { return $this->moduleManager->availablePermissions(); } }