@php use App\Support\Badges\BadgeDomain; use App\Support\Badges\BadgeRenderer; use App\Support\Links\RequiredPermissionsLinks; use Illuminate\Support\Carbon; $tenant = $this->currentTenant(); $vm = $this->viewModel(); $overview = is_array($vm['overview'] ?? null) ? $vm['overview'] : []; $counts = is_array($overview['counts'] ?? null) ? $overview['counts'] : []; $featureImpacts = is_array($overview['feature_impacts'] ?? null) ? $overview['feature_impacts'] : []; $freshness = is_array($overview['freshness'] ?? null) ? $overview['freshness'] : []; $filters = is_array($vm['filters'] ?? null) ? $vm['filters'] : []; $selectedFeatures = is_array($filters['features'] ?? null) ? $filters['features'] : []; $overall = $overview['overall'] ?? null; $overallSpec = $overall !== null ? BadgeRenderer::spec(BadgeDomain::VerificationReportOverall, $overall) : null; $copy = is_array($vm['copy'] ?? null) ? $vm['copy'] : []; $copyApplication = (string) ($copy['application'] ?? ''); $copyDelegated = (string) ($copy['delegated'] ?? ''); $missingApplication = (int) ($counts['missing_application'] ?? 0); $missingDelegated = (int) ($counts['missing_delegated'] ?? 0); $presentCount = (int) ($counts['present'] ?? 0); $errorCount = (int) ($counts['error'] ?? 0); $missingTotal = $missingApplication + $missingDelegated + $errorCount; $requiredTotal = $missingTotal + $presentCount; $adminConsentUrl = $tenant ? RequiredPermissionsLinks::adminConsentUrl($tenant) : null; $adminConsentPrimaryUrl = $tenant ? RequiredPermissionsLinks::adminConsentPrimaryUrl($tenant) : RequiredPermissionsLinks::adminConsentGuideUrl(); $adminConsentLabel = $adminConsentUrl ? 'Open admin consent' : 'Admin consent guide'; $reRunUrl = $this->reRunVerificationUrl(); $manageProviderConnectionUrl = $this->manageProviderConnectionUrl(); $lastRefreshedAt = is_string($freshness['last_refreshed_at'] ?? null) ? (string) $freshness['last_refreshed_at'] : null; $lastRefreshedLabel = $lastRefreshedAt ? Carbon::parse($lastRefreshedAt)->diffForHumans() : 'Unknown'; $isStale = (bool) ($freshness['is_stale'] ?? true); $hasStoredPermissionData = $lastRefreshedAt !== null; $issues = []; if ($missingApplication > 0) { $issues[] = [ 'severity' => 'Blocker', 'title' => 'Missing application permissions', 'description' => "{$missingApplication} required application permission(s) are missing.", 'links' => array_values(array_filter([ ['label' => $adminConsentLabel, 'url' => $adminConsentPrimaryUrl, 'external' => true], $manageProviderConnectionUrl ? ['label' => 'Manage provider connection', 'url' => $manageProviderConnectionUrl, 'external' => false] : null, ['label' => 'Re-run verification', 'url' => $reRunUrl, 'external' => false], ])), ]; } if ($missingDelegated > 0) { $issues[] = [ 'severity' => 'Warning', 'title' => 'Missing delegated permissions', 'description' => "{$missingDelegated} delegated permission(s) are missing.", 'links' => [ ['label' => $adminConsentLabel, 'url' => $adminConsentPrimaryUrl, 'external' => true], ['label' => 'Re-run verification', 'url' => $reRunUrl, 'external' => false], ], ]; } if ($errorCount > 0) { $issues[] = [ 'severity' => 'Warning', 'title' => 'Verification results need review', 'description' => "{$errorCount} permission row(s) are in an unknown/error state and require follow-up.", 'links' => [ ['label' => 'Re-run verification', 'url' => $reRunUrl, 'external' => false], $manageProviderConnectionUrl ? ['label' => 'Manage provider connection', 'url' => $manageProviderConnectionUrl, 'external' => false] : ['label' => 'Admin consent guide', 'url' => RequiredPermissionsLinks::adminConsentGuideUrl(), 'external' => true], ], ]; } if ($isStale) { $issues[] = [ 'severity' => 'Warning', 'title' => 'Freshness warning', 'description' => $hasStoredPermissionData ? "Permission data is older than 30 days (last refresh {$lastRefreshedLabel})." : 'No stored verification data is available yet.', 'links' => [ ['label' => 'Start verification', 'url' => $reRunUrl, 'external' => false], ], ]; } @endphp
Review what’s missing for this tenant and copy the missing permissions for admin consent.
Stored-data view only. Last refreshed: {{ $lastRefreshedLabel }}{{ $isStale ? ' (stale)' : '' }}.
@if ($overallSpec) {{ $overallSpec->label }} @endif
Missing (app)
{{ (int) ($counts['missing_application'] ?? 0) }}
Missing (delegated)
{{ (int) ($counts['missing_delegated'] ?? 0) }}
Present
{{ (int) ($counts['present'] ?? 0) }}
Errors
{{ (int) ($counts['error'] ?? 0) }}
@if (! $hasStoredPermissionData)
Keine Daten verfügbar
Für diesen Tenant liegen noch keine gespeicherten Verifikationsdaten vor. Start verification.
@endif
Guidance
Who can fix this? Global Administrator / Privileged Role Administrator.
Primary next step: {{ $adminConsentLabel }}
@if ($reRunUrl)
After granting consent: Re-run verification
@endif
Copy missing application permissions Copy missing delegated permissions
@if (is_array($featureImpacts) && $featureImpacts !== [])
@foreach ($featureImpacts as $impact) @php $featureKey = is_array($impact) ? ($impact['feature'] ?? null) : null; $featureKey = is_string($featureKey) ? $featureKey : null; $missingCount = is_array($impact) ? (int) ($impact['missing'] ?? 0) : 0; $isBlocked = is_array($impact) ? (bool) ($impact['blocked'] ?? false) : false; if ($featureKey === null) { continue; } $selected = in_array($featureKey, $selectedFeatures, true); @endphp
{{ $featureKey }}
{{ $missingCount }} missing
{{ $isBlocked ? 'Blocked' : ($missingCount > 0 ? 'At risk' : 'OK') }}
@endforeach
@endif
Missing application permissions
Newline-separated list for admin consent.
Close
@if ($copyApplication === '')
Nothing to copy — no missing application permissions in the current feature filter.
@else
Copied Copy

                                
@endif
Missing delegated permissions
Newline-separated list for delegated consent.
Close
@if ($copyDelegated === '')
Nothing to copy — no missing delegated permissions in the current feature filter.
@else
Copied Copy

                                
@endif
@if ($issues === [])
No blockers or warnings detected from stored data.
@else
@foreach ($issues as $issue) @php $severity = (string) ($issue['severity'] ?? 'Warning'); $severityColor = $severity === 'Blocker' ? 'danger' : 'warning'; $title = (string) ($issue['title'] ?? 'Issue'); $description = (string) ($issue['description'] ?? ''); $links = is_array($issue['links'] ?? null) ? $issue['links'] : []; @endphp
{{ $severity }}
{{ $title }}
{{ $description }}
@if ($links !== [])
@foreach ($links as $link) @php $label = is_array($link) ? (string) ($link['label'] ?? '') : ''; $url = is_array($link) ? (string) ($link['url'] ?? '') : ''; $external = is_array($link) ? (bool) ($link['external'] ?? false) : false; @endphp @if ($label !== '' && $url !== '') {{ $label }} @endif @endforeach
@endif
@endforeach
@endif
{{ $presentCount }} permission(s) currently pass.
{{ $requiredTotal > 0 ? "Out of {$requiredTotal} required permissions, {$presentCount} are currently granted." : 'No required permissions are configured yet.' }}
Expand technical details
@if (! $tenant)
No tenant selected.
@else
Native permission matrix
Search doesn’t affect copy actions. Feature filters do.
{{ $this->table }}
@endif