merge: agent session work

This commit is contained in:
Ahmed Darrazi 2025-12-30 00:51:23 +01:00
commit 3b538c23a6
4 changed files with 222 additions and 4 deletions

View File

@ -3,7 +3,6 @@
namespace App\Services\Intune;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
class GroupPolicyConfigurationNormalizer implements PolicyTypeNormalizer
{
@ -47,7 +46,12 @@ public function normalize(?array $snapshot, string $policyType, ?string $platfor
$definitionId = $definitionValue['#Definition_Id'] ?? null;
$category = $definitionValue['#Definition_categoryPath'] ?? '-';
$enabled = (bool) ($definitionValue['enabled'] ?? false);
$path = $definitionValue['definition@odata.bind'] ?? (is_string($definitionId) ? $definitionId : "definitionValues[{$index}]");
$path = $this->buildDiffPath(
definition: $definition,
definitionId: $definitionId,
categoryPath: $category,
index: $index,
);
$value = $this->formatGroupPolicyValue($definitionValue, $enabled);
$dataType = $this->inferGroupPolicyDataType($definitionValue);
@ -59,7 +63,7 @@ public function normalize(?array $snapshot, string $policyType, ?string $platfor
'data_type' => $dataType,
'value' => $value,
'description' => '-',
'path' => is_string($path) ? Str::limit($path, 200) : "definitionValues[{$index}]",
'path' => $path,
'raw' => $definitionValue,
];
}
@ -159,4 +163,19 @@ private function formatGroupPolicyValue(array $definitionValue, bool $enabled):
return implode(' | ', array_values(array_filter($parts, static fn ($part) => $part !== '')));
}
private function buildDiffPath(mixed $definition, mixed $definitionId, mixed $categoryPath, int $index): string
{
$label = is_string($definition) && $definition !== '' ? $definition : "definitionValues[{$index}]";
if (is_string($definitionId) && $definitionId !== '') {
$label .= " ({$definitionId})";
}
if (is_string($categoryPath) && $categoryPath !== '' && $categoryPath !== '-') {
return $categoryPath.' > '.$label;
}
return $label;
}
}

View File

@ -26,6 +26,121 @@ public function normalize(?array $snapshot, string $policyType, ?string $platfor
*/
public function flattenForDiff(?array $snapshot, string $policyType, ?string $platform = null): array
{
return $this->defaultNormalizer->flattenForDiff($snapshot, $policyType, $platform);
$normalized = $this->normalize($snapshot ?? [], $policyType, $platform);
$map = [];
if (isset($normalized['settings_table']['rows']) && is_array($normalized['settings_table']['rows'])) {
$title = $normalized['settings_table']['title'] ?? 'Settings';
$prefix = is_string($title) && $title !== '' ? $title.' > ' : '';
$rows = $normalized['settings_table']['rows'];
$baseLabels = array_values(array_filter(array_map(function (mixed $row): ?string {
if (! is_array($row)) {
return null;
}
return $this->buildSettingsCatalogDiffLabel($row, includePath: false);
}, $rows)));
$labelCounts = array_count_values($baseLabels);
foreach ($rows as $row) {
if (! is_array($row)) {
continue;
}
$baseLabel = $this->buildSettingsCatalogDiffLabel($row, includePath: false);
$label = $baseLabel;
if (($labelCounts[$baseLabel] ?? 0) > 1) {
$path = $row['path'] ?? null;
$pathLabel = is_string($path) && $path !== '' ? $path : null;
$label = $this->buildSettingsCatalogDiffLabel($row, includePath: true);
if ($pathLabel !== null) {
$label .= ' @ '.$pathLabel;
}
}
$key = $prefix.$label;
$map[$key] = $row['value'] ?? null;
}
}
foreach ($normalized['settings'] ?? [] as $block) {
if (! is_array($block)) {
continue;
}
$title = $block['title'] ?? null;
$prefix = is_string($title) && $title !== '' ? $title.' > ' : '';
if (($block['type'] ?? null) === 'table') {
foreach ($block['rows'] ?? [] as $row) {
if (! is_array($row)) {
continue;
}
$key = $prefix.($row['path'] ?? $row['label'] ?? 'entry');
$map[$key] = $row['value'] ?? null;
}
continue;
}
foreach ($block['entries'] ?? [] as $entry) {
if (! is_array($entry)) {
continue;
}
$key = $prefix.($entry['key'] ?? 'entry');
$map[$key] = $entry['value'] ?? null;
}
}
return $map;
}
/**
* @param array<string, mixed> $row
*/
private function buildSettingsCatalogDiffLabel(array $row, bool $includePath): string
{
$category = $row['category'] ?? null;
$definition = $row['definition'] ?? null;
$definitionId = $row['definition_id'] ?? null;
$label = is_string($definition) && $definition !== '' ? $definition : 'Setting';
if ($includePath) {
$path = $row['path'] ?? null;
if (is_string($path) && $path !== '') {
$label = $path;
}
if (
is_string($label)
&& is_string($definitionId)
&& $definitionId !== ''
&& is_string($definition)
&& $definition !== ''
) {
$parts = explode(' > ', $label);
if ($parts !== [] && end($parts) === $definitionId) {
$parts[count($parts) - 1] = $definition;
$label = implode(' > ', $parts);
}
}
}
if (is_string($category) && $category !== '' && $category !== '-') {
$label = $category.' > '.$label;
}
return $label;
}
}

View File

@ -0,0 +1,29 @@
<?php
use App\Services\Intune\PolicyNormalizer;
test('group policy configuration normalized diff keys use definition display names', function () {
$flat = app(PolicyNormalizer::class)->flattenForDiff(
snapshot: [
'id' => 'gpo-1',
'displayName' => 'Admin Templates Alpha',
'@odata.type' => '#microsoft.graph.groupPolicyConfiguration',
'definitionValues' => [
[
'enabled' => true,
'definition@odata.bind' => 'https://graph.microsoft.com/beta/deviceManagement/groupPolicyDefinitions(\'def-1\')',
'#Definition_Id' => 'def-1',
'#Definition_displayName' => 'Block legacy auth',
'#Definition_categoryPath' => 'Windows Components\\Security Options',
],
],
],
policyType: 'groupPolicyConfiguration',
platform: 'windows',
);
$keys = array_keys($flat);
expect($keys)->toContain('Administrative Template settings > Windows Components\\Security Options > Block legacy auth (def-1)');
expect(implode("\n", $keys))->not->toContain('graph.microsoft.com');
});

View File

@ -0,0 +1,55 @@
<?php
use App\Models\SettingsCatalogCategory;
use App\Models\SettingsCatalogDefinition;
use App\Services\Intune\PolicyNormalizer;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
test('settings catalog normalized diff keys use definition display names', function () {
SettingsCatalogCategory::create([
'category_id' => 'cat-1',
'display_name' => 'Account Management',
'description' => null,
]);
SettingsCatalogDefinition::create([
'definition_id' => 'device_vendor_msft_accountmanagement_userprofilemanagement_deletionpolicy',
'display_name' => 'Deletion Policy',
'description' => null,
'help_text' => null,
'category_id' => 'cat-1',
'ux_behavior' => null,
'raw' => [],
]);
$flat = app(PolicyNormalizer::class)->flattenForDiff(
snapshot: [
'@odata.type' => '#microsoft.graph.deviceManagementConfigurationPolicy',
'id' => 'scp-policy-1',
'name' => 'Settings Catalog Policy',
'platforms' => 'windows10',
'technologies' => 'mdm',
'settings' => [
[
'id' => 's1',
'settingInstance' => [
'@odata.type' => '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance',
'settingDefinitionId' => 'device_vendor_msft_accountmanagement_userprofilemanagement_deletionpolicy',
'choiceSettingValue' => [
'value' => 'enabled',
],
],
],
],
],
policyType: 'settingsCatalogPolicy',
platform: 'windows',
);
$keys = array_keys($flat);
expect($keys)->toContain('Settings > Account Management > Deletion Policy');
expect(implode("\n", $keys))->not->toContain('device_vendor_msft_accountmanagement_userprofilemanagement_deletionpolicy');
});