resolveScopeTagNames($scopeTagIds, $tenant); $metadata = $backupItem->metadata ?? []; $metadata['scope_tag_ids'] = $scopeTagIds; $metadata['scope_tag_names'] = $scopeTagNames; // Only fetch assignments if explicitly requested if (! $includeAssignments) { $metadata['assignment_count'] = 0; $backupItem->update([ 'assignments' => null, 'metadata' => $metadata, ]); return $backupItem->refresh(); } // Fetch assignments from Graph API $graphOptions = $tenant->graphOptions(); $tenantId = $graphOptions['tenant'] ?? $tenant->external_id ?? $tenant->tenant_id; $assignments = $this->assignmentFetcher->fetch($tenantId, $policyId, $graphOptions); if (empty($assignments)) { // No assignments or fetch failed $metadata['assignment_count'] = 0; $metadata['assignments_fetch_failed'] = true; $metadata['has_orphaned_assignments'] = false; $backupItem->update([ 'assignments' => [], // Return empty array instead of null 'metadata' => $metadata, ]); Log::warning('No assignments fetched for policy', [ 'tenant_id' => $tenantId, 'policy_id' => $policyId, 'backup_item_id' => $backupItem->id, ]); return $backupItem->refresh(); } // Extract group IDs and resolve for orphan detection $groupIds = $this->extractGroupIds($assignments); $hasOrphanedGroups = false; if (! empty($groupIds)) { $resolvedGroups = $this->groupResolver->resolveGroupIds($groupIds, $tenantId, $graphOptions); $hasOrphanedGroups = collect($resolvedGroups)->contains('orphaned', true); } // Update backup item with assignments and metadata $metadata['assignment_count'] = count($assignments); $metadata['assignments_fetch_failed'] = false; $metadata['has_orphaned_assignments'] = $hasOrphanedGroups; $backupItem->update([ 'assignments' => $assignments, 'metadata' => $metadata, ]); Log::info('Assignments enriched for backup item', [ 'tenant_id' => $tenantId, 'policy_id' => $policyId, 'backup_item_id' => $backupItem->id, 'assignment_count' => count($assignments), 'has_orphaned' => $hasOrphanedGroups, ]); return $backupItem->refresh(); } /** * Resolve scope tag IDs to display names. */ private function resolveScopeTagNames(array $scopeTagIds, Tenant $tenant): array { $scopeTags = $this->scopeTagResolver->resolve($scopeTagIds, $tenant); $names = []; foreach ($scopeTagIds as $id) { $scopeTag = collect($scopeTags)->firstWhere('id', $id); $names[] = $scopeTag['displayName'] ?? "Unknown (ID: {$id})"; } return $names; } /** * Extract group IDs from assignment array. */ private function extractGroupIds(array $assignments): array { $groupIds = []; foreach ($assignments as $assignment) { $target = $assignment['target'] ?? []; $odataType = $target['@odata.type'] ?? ''; if ($odataType === '#microsoft.graph.groupAssignmentTarget' && isset($target['groupId'])) { $groupIds[] = $target['groupId']; } } return array_unique($groupIds); } }