## Summary <!-- Kurz: Was ändert sich und warum? --> ## Spec-Driven Development (SDD) - [ ] Es gibt eine Spec unter `specs/<NNN>-<feature>/` - [ ] Enthaltene Dateien: `plan.md`, `tasks.md`, `spec.md` - [ ] Spec beschreibt Verhalten/Acceptance Criteria (nicht nur Implementation) - [ ] Wenn sich Anforderungen während der Umsetzung geändert haben: Spec/Plan/Tasks wurden aktualisiert ## Implementation - [ ] Implementierung entspricht der Spec - [ ] Edge cases / Fehlerfälle berücksichtigt - [ ] Keine unbeabsichtigten Änderungen außerhalb des Scopes ## Tests - [ ] Tests ergänzt/aktualisiert (Pest/PHPUnit) - [ ] Relevante Tests lokal ausgeführt (`./vendor/bin/sail artisan test` oder `php artisan test`) ## Migration / Config / Ops (falls relevant) - [ ] Migration(en) enthalten und getestet - [ ] Rollback bedacht (rückwärts kompatibel, sichere Migration) - [ ] Neue Env Vars dokumentiert (`.env.example` / Doku) - [ ] Queue/cron/storage Auswirkungen geprüft ## UI (Filament/Livewire) (falls relevant) - [ ] UI-Flows geprüft - [ ] Screenshots/Notizen hinzugefügt ## Notes <!-- Links, Screenshots, Follow-ups, offene Punkte --> Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.local> Reviewed-on: #4
124 lines
3.7 KiB
PHP
124 lines
3.7 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Graph;
|
|
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class GroupResolver
|
|
{
|
|
public function __construct(
|
|
private readonly MicrosoftGraphClient $graphClient,
|
|
) {}
|
|
|
|
/**
|
|
* Resolve group IDs to group objects with display names.
|
|
*
|
|
* Uses POST /directoryObjects/getByIds endpoint.
|
|
* Missing IDs are marked as orphaned.
|
|
*
|
|
* @param array $groupIds Array of group IDs to resolve
|
|
* @param string $tenantId Target tenant ID
|
|
* @return array Keyed array: ['group-id' => ['id' => ..., 'displayName' => ..., 'orphaned' => bool]]
|
|
*/
|
|
public function resolveGroupIds(array $groupIds, string $tenantId, array $options = []): array
|
|
{
|
|
if (empty($groupIds)) {
|
|
return [];
|
|
}
|
|
|
|
// Create cache key
|
|
$cacheKey = $this->getCacheKey($groupIds, $tenantId);
|
|
|
|
return Cache::remember($cacheKey, 300, function () use ($groupIds, $tenantId, $options) {
|
|
return $this->fetchAndResolveGroups($groupIds, $tenantId, $options);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Fetch groups from Graph API and resolve orphaned IDs.
|
|
*/
|
|
private function fetchAndResolveGroups(array $groupIds, string $tenantId, array $options = []): array
|
|
{
|
|
try {
|
|
$response = $this->graphClient->request(
|
|
'POST',
|
|
'/directoryObjects/getByIds',
|
|
array_merge($options, [
|
|
'tenant' => $tenantId,
|
|
'json' => [
|
|
'ids' => array_values($groupIds),
|
|
'types' => ['group'],
|
|
],
|
|
])
|
|
);
|
|
|
|
$resolvedGroups = $response->data['value'] ?? [];
|
|
|
|
// Create result map
|
|
$result = [];
|
|
$resolvedIds = [];
|
|
|
|
// Add resolved groups
|
|
foreach ($resolvedGroups as $group) {
|
|
$groupId = $group['id'];
|
|
$resolvedIds[] = $groupId;
|
|
$result[$groupId] = [
|
|
'id' => $groupId,
|
|
'displayName' => $group['displayName'] ?? null,
|
|
'orphaned' => false,
|
|
];
|
|
}
|
|
|
|
// Add orphaned groups (not in response)
|
|
foreach ($groupIds as $groupId) {
|
|
if (! in_array($groupId, $resolvedIds)) {
|
|
$result[$groupId] = [
|
|
'id' => $groupId,
|
|
'displayName' => null,
|
|
'orphaned' => true,
|
|
];
|
|
}
|
|
}
|
|
|
|
Log::debug('Resolved group IDs', [
|
|
'tenant_id' => $tenantId,
|
|
'requested' => count($groupIds),
|
|
'resolved' => count($resolvedIds),
|
|
'orphaned' => count($groupIds) - count($resolvedIds),
|
|
]);
|
|
|
|
return $result;
|
|
} catch (GraphException $e) {
|
|
Log::warning('Failed to resolve group IDs', [
|
|
'tenant_id' => $tenantId,
|
|
'group_ids' => $groupIds,
|
|
'error' => $e->getMessage(),
|
|
'context' => $e->context,
|
|
]);
|
|
|
|
// Return all as orphaned on failure
|
|
$result = [];
|
|
foreach ($groupIds as $groupId) {
|
|
$result[$groupId] = [
|
|
'id' => $groupId,
|
|
'displayName' => null,
|
|
'orphaned' => true,
|
|
];
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generate cache key for group resolution.
|
|
*/
|
|
private function getCacheKey(array $groupIds, string $tenantId): string
|
|
{
|
|
sort($groupIds);
|
|
|
|
return "groups:{$tenantId}:".md5(implode(',', $groupIds));
|
|
}
|
|
}
|