- Add SettingsCatalogCategoryResolver service with 3-tier caching
- Add SettingsCatalogCategory model and migration
- Add warm-cache commands for definitions and categories
- Update PolicyNormalizer to display categories in settings table
- Fix extraction of nested children in choiceSettingValue
- Add category inheritance from parent settings
- Skip template IDs with {tenantid} placeholder in Graph API calls
- Update Livewire table with Category, Data Type, and Description columns
Related tests updated and passing.
235 lines
10 KiB
PHP
235 lines
10 KiB
PHP
<?php
|
|
|
|
use App\Models\SettingsCatalogCategory;
|
|
use App\Models\SettingsCatalogDefinition;
|
|
use App\Services\Intune\PolicyNormalizer;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Tests\TestCase;
|
|
|
|
uses(TestCase::class);
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(function () {
|
|
$this->normalizer = app(PolicyNormalizer::class);
|
|
});
|
|
|
|
it('flattens settings catalog setting instances into a table', function () {
|
|
$snapshot = [
|
|
'@odata.type' => '#microsoft.graph.deviceManagementConfigurationPolicy',
|
|
'settings' => [
|
|
[
|
|
'id' => 's1',
|
|
'settingInstance' => [
|
|
'@odata.type' => '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance',
|
|
'settingDefinitionId' => 'device_vendor_msft_policy_config_system_minimumpinlength',
|
|
'simpleSettingValue' => [
|
|
'@odata.type' => '#microsoft.graph.deviceManagementConfigurationIntegerSettingValue',
|
|
'value' => 12,
|
|
],
|
|
],
|
|
],
|
|
[
|
|
'id' => 's2',
|
|
'settingInstance' => [
|
|
'@odata.type' => '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance',
|
|
'settingDefinitionId' => 'device_vendor_msft_policy_config_system_usebiometrics',
|
|
'choiceSettingValue' => [
|
|
'value' => 'device_vendor_msft_policy_config_system_usebiometrics_true',
|
|
],
|
|
],
|
|
],
|
|
[
|
|
'id' => 'group',
|
|
'settingInstance' => [
|
|
'@odata.type' => '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance',
|
|
'settingDefinitionId' => 'device_vendor_msft_policy_config_system_group',
|
|
'groupSettingCollectionValue' => [
|
|
[
|
|
'children' => [
|
|
[
|
|
'@odata.type' => '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance',
|
|
'settingDefinitionId' => 'device_vendor_msft_policy_config_system_child',
|
|
'simpleSettingValue' => [
|
|
'value' => true,
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
[
|
|
'id' => 'unknown',
|
|
'settingInstance' => [
|
|
'@odata.type' => '#microsoft.graph.someUnknownSettingInstance',
|
|
'settingDefinitionId' => 'unknown_definition',
|
|
'foo' => 'bar',
|
|
],
|
|
],
|
|
],
|
|
];
|
|
|
|
$result = $this->normalizer->normalize($snapshot, 'settingsCatalogPolicy', 'windows');
|
|
|
|
expect($result['status'])->toBe('success');
|
|
expect($result)->toHaveKey('settings_table');
|
|
|
|
$rows = collect($result['settings_table']['rows']);
|
|
|
|
// Use definition_id field for lookup (raw ID), definition field now contains display name
|
|
$minimumPinLength = $rows->firstWhere('definition_id', 'device_vendor_msft_policy_config_system_minimumpinlength');
|
|
expect($minimumPinLength)->not->toBeNull();
|
|
expect($minimumPinLength['definition'])->toContain('Minimum'); // Display name
|
|
expect($minimumPinLength['data_type'])->toBe('Number'); // User-friendly type
|
|
expect($minimumPinLength['value'])->toBe('12');
|
|
expect($minimumPinLength)->toHaveKey('category');
|
|
expect($minimumPinLength)->toHaveKey('description');
|
|
|
|
$useBiometrics = $rows->firstWhere('definition_id', 'device_vendor_msft_policy_config_system_usebiometrics');
|
|
expect($useBiometrics)->not->toBeNull();
|
|
expect($useBiometrics['definition'])->toContain('Usebiometrics'); // Display name (prettified)
|
|
expect($useBiometrics['value'])->toBe('Enabled'); // Formatted from "usebiometrics_true" -> "Enabled"
|
|
|
|
$child = $rows->firstWhere('definition_id', 'device_vendor_msft_policy_config_system_child');
|
|
expect($child)->not->toBeNull();
|
|
expect($child['definition'])->toContain('Child'); // Display name (prettified)
|
|
expect($child['value'])->toBe('Enabled'); // Formatted from boolean true -> "Enabled"
|
|
expect($child['path'])->toContain('group'); // Path contains parent definition IDs
|
|
|
|
$unknown = $rows->firstWhere('definition_id', 'unknown_definition');
|
|
expect($unknown)->not->toBeNull();
|
|
expect($unknown['definition'])->toBe('Unknown Definition'); // Prettified fallback
|
|
expect($unknown['value'])->toContain('foo');
|
|
});
|
|
|
|
it('inherits category from nearest ancestor when child categories are missing', function () {
|
|
$categoryId = 'cat-windows-hello';
|
|
$parentDefinitionId = 'device_vendor_msft_passportforwork_biometrics_usebiometrics';
|
|
$groupDefinitionId = 'device_vendor_msft_passportforwork_{tenantid}';
|
|
$childDefinitionId = 'device_vendor_msft_passportforwork_{tenantid}_policies_pincomplexity_expiration';
|
|
|
|
SettingsCatalogCategory::create([
|
|
'category_id' => $categoryId,
|
|
'display_name' => 'Windows Hello For Business',
|
|
'description' => 'Windows Hello settings',
|
|
]);
|
|
|
|
SettingsCatalogDefinition::create([
|
|
'definition_id' => $parentDefinitionId,
|
|
'display_name' => 'Allow Use of Biometrics',
|
|
'description' => 'Enable biometrics',
|
|
'category_id' => $categoryId,
|
|
'raw' => ['id' => $parentDefinitionId],
|
|
]);
|
|
|
|
$snapshot = [
|
|
'@odata.type' => '#microsoft.graph.deviceManagementConfigurationPolicy',
|
|
'settings' => [
|
|
[
|
|
'id' => '0',
|
|
'settingInstance' => [
|
|
'@odata.type' => '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance',
|
|
'settingDefinitionId' => $parentDefinitionId,
|
|
'choiceSettingValue' => [
|
|
'value' => "{$parentDefinitionId}_true",
|
|
'children' => [
|
|
[
|
|
'@odata.type' => '#microsoft.graph.deviceManagementConfigurationGroupSettingInstance',
|
|
'settingDefinitionId' => $groupDefinitionId,
|
|
'groupSettingValue' => [
|
|
'children' => [
|
|
[
|
|
'@odata.type' => '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance',
|
|
'settingDefinitionId' => $childDefinitionId,
|
|
'simpleSettingValue' => [
|
|
'value' => 0,
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
];
|
|
|
|
$result = $this->normalizer->normalize($snapshot, 'settingsCatalogPolicy', 'windows');
|
|
|
|
$rows = collect($result['settings_table']['rows']);
|
|
$group = $rows->firstWhere('definition_id', $groupDefinitionId);
|
|
$child = $rows->firstWhere('definition_id', $childDefinitionId);
|
|
|
|
expect($group)->not->toBeNull();
|
|
expect($child)->not->toBeNull();
|
|
expect($group['category'])->toBe('Windows Hello For Business');
|
|
expect($child['category'])->toBe('Windows Hello For Business');
|
|
});
|
|
|
|
it('uses the only known category for template settings without ancestors', function () {
|
|
$categoryId = 'cat-windows-hello';
|
|
$rootDefinitionId = 'device_vendor_msft_passportforwork_biometrics_usebiometrics';
|
|
$groupDefinitionId = 'device_vendor_msft_passportforwork_{tenantid}';
|
|
$childDefinitionId = 'device_vendor_msft_passportforwork_{tenantid}_policies_pincomplexity_expiration';
|
|
|
|
SettingsCatalogCategory::create([
|
|
'category_id' => $categoryId,
|
|
'display_name' => 'Windows Hello For Business',
|
|
'description' => 'Windows Hello settings',
|
|
]);
|
|
|
|
SettingsCatalogDefinition::create([
|
|
'definition_id' => $rootDefinitionId,
|
|
'display_name' => 'Allow Use of Biometrics',
|
|
'description' => 'Enable biometrics',
|
|
'category_id' => $categoryId,
|
|
'raw' => ['id' => $rootDefinitionId],
|
|
]);
|
|
|
|
$snapshot = [
|
|
'@odata.type' => '#microsoft.graph.deviceManagementConfigurationPolicy',
|
|
'settings' => [
|
|
[
|
|
'id' => 'root',
|
|
'settingInstance' => [
|
|
'@odata.type' => '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance',
|
|
'settingDefinitionId' => $rootDefinitionId,
|
|
'choiceSettingValue' => [
|
|
'value' => "{$rootDefinitionId}_true",
|
|
],
|
|
],
|
|
],
|
|
[
|
|
'id' => 'group',
|
|
'settingInstance' => [
|
|
'@odata.type' => '#microsoft.graph.deviceManagementConfigurationGroupSettingInstance',
|
|
'settingDefinitionId' => $groupDefinitionId,
|
|
'groupSettingValue' => [
|
|
'children' => [
|
|
[
|
|
'@odata.type' => '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance',
|
|
'settingDefinitionId' => $childDefinitionId,
|
|
'simpleSettingValue' => [
|
|
'value' => 0,
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
];
|
|
|
|
$result = $this->normalizer->normalize($snapshot, 'settingsCatalogPolicy', 'windows');
|
|
|
|
$rows = collect($result['settings_table']['rows']);
|
|
$group = $rows->firstWhere('definition_id', $groupDefinitionId);
|
|
$child = $rows->firstWhere('definition_id', $childDefinitionId);
|
|
|
|
expect($group)->not->toBeNull();
|
|
expect($child)->not->toBeNull();
|
|
expect($group['category'])->toBe('Windows Hello For Business');
|
|
expect($child['category'])->toBe('Windows Hello For Business');
|
|
});
|