feat: enrollment config subtypes (027)
This commit is contained in:
parent
057f2cbeb6
commit
4d5f6eb79b
@ -15,6 +15,9 @@ public function supports(string $policyType): bool
|
|||||||
'windowsAutopilotDeploymentProfile',
|
'windowsAutopilotDeploymentProfile',
|
||||||
'windowsEnrollmentStatusPage',
|
'windowsEnrollmentStatusPage',
|
||||||
'enrollmentRestriction',
|
'enrollmentRestriction',
|
||||||
|
'deviceEnrollmentLimitConfiguration',
|
||||||
|
'deviceEnrollmentPlatformRestrictionsConfiguration',
|
||||||
|
'deviceEnrollmentNotificationConfiguration',
|
||||||
], true);
|
], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,6 +37,18 @@ public function normalize(?array $snapshot, string $policyType, ?string $platfor
|
|||||||
$warnings[] = 'Restore is preview-only for Enrollment Restrictions.';
|
$warnings[] = 'Restore is preview-only for Enrollment Restrictions.';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($policyType === 'deviceEnrollmentLimitConfiguration') {
|
||||||
|
$warnings[] = 'Restore is preview-only for Enrollment Limits.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($policyType === 'deviceEnrollmentPlatformRestrictionsConfiguration') {
|
||||||
|
$warnings[] = 'Restore is preview-only for Platform Restrictions.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($policyType === 'deviceEnrollmentNotificationConfiguration') {
|
||||||
|
$warnings[] = 'Restore is preview-only for Enrollment Notifications.';
|
||||||
|
}
|
||||||
|
|
||||||
$generalEntries = [
|
$generalEntries = [
|
||||||
['key' => 'Type', 'value' => $policyType],
|
['key' => 'Type', 'value' => $policyType],
|
||||||
];
|
];
|
||||||
@ -68,6 +83,9 @@ public function normalize(?array $snapshot, string $policyType, ?string $platfor
|
|||||||
'windowsAutopilotDeploymentProfile' => $this->buildAutopilotBlock($snapshot),
|
'windowsAutopilotDeploymentProfile' => $this->buildAutopilotBlock($snapshot),
|
||||||
'windowsEnrollmentStatusPage' => $this->buildEnrollmentStatusPageBlock($snapshot),
|
'windowsEnrollmentStatusPage' => $this->buildEnrollmentStatusPageBlock($snapshot),
|
||||||
'enrollmentRestriction' => $this->buildEnrollmentRestrictionBlock($snapshot),
|
'enrollmentRestriction' => $this->buildEnrollmentRestrictionBlock($snapshot),
|
||||||
|
'deviceEnrollmentLimitConfiguration' => $this->buildEnrollmentLimitBlock($snapshot),
|
||||||
|
'deviceEnrollmentPlatformRestrictionsConfiguration' => $this->buildEnrollmentPlatformRestrictionsBlock($snapshot),
|
||||||
|
'deviceEnrollmentNotificationConfiguration' => $this->buildEnrollmentNotificationBlock($snapshot),
|
||||||
default => null,
|
default => null,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -319,6 +337,201 @@ private function buildEnrollmentRestrictionBlock(array $snapshot): ?array
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array{type: string, title: string, entries: array<int, array{key: string, value: mixed}>}|null
|
||||||
|
*/
|
||||||
|
private function buildEnrollmentLimitBlock(array $snapshot): ?array
|
||||||
|
{
|
||||||
|
$entries = [];
|
||||||
|
|
||||||
|
foreach ([
|
||||||
|
'priority' => 'Priority',
|
||||||
|
'version' => 'Version',
|
||||||
|
'deviceEnrollmentConfigurationType' => 'Configuration type',
|
||||||
|
'limit' => 'Enrollment limit',
|
||||||
|
'limitType' => 'Limit type',
|
||||||
|
] as $key => $label) {
|
||||||
|
$value = Arr::get($snapshot, $key);
|
||||||
|
|
||||||
|
if (is_int($value) || is_float($value)) {
|
||||||
|
$entries[] = ['key' => $label, 'value' => $value];
|
||||||
|
} elseif (is_string($value) && $value !== '') {
|
||||||
|
$entries[] = ['key' => $label, 'value' => $value];
|
||||||
|
} elseif (is_bool($value)) {
|
||||||
|
$entries[] = ['key' => $label, 'value' => $value ? 'Enabled' : 'Disabled'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$assigned = Arr::get($snapshot, 'assignments');
|
||||||
|
if (is_array($assigned) && $assigned !== []) {
|
||||||
|
$entries[] = ['key' => 'Assignments (snapshot)', 'value' => '[present]'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($entries === []) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'type' => 'keyValue',
|
||||||
|
'title' => 'Enrollment limits',
|
||||||
|
'entries' => $entries,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array{type: string, title: string, entries: array<int, array{key: string, value: mixed}>}|null
|
||||||
|
*/
|
||||||
|
private function buildEnrollmentPlatformRestrictionsBlock(array $snapshot): ?array
|
||||||
|
{
|
||||||
|
$entries = [];
|
||||||
|
|
||||||
|
foreach ([
|
||||||
|
'priority' => 'Priority',
|
||||||
|
'version' => 'Version',
|
||||||
|
'platformType' => 'Platform type',
|
||||||
|
'deviceEnrollmentConfigurationType' => 'Configuration type',
|
||||||
|
] as $key => $label) {
|
||||||
|
$value = Arr::get($snapshot, $key);
|
||||||
|
|
||||||
|
if (is_int($value) || is_float($value)) {
|
||||||
|
$entries[] = ['key' => $label, 'value' => $value];
|
||||||
|
} elseif (is_string($value) && $value !== '') {
|
||||||
|
$entries[] = ['key' => $label, 'value' => $value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$platformPayload = Arr::get($snapshot, 'platformRestrictions') ?? Arr::get($snapshot, 'platformRestriction');
|
||||||
|
if (is_array($platformPayload) && $platformPayload !== []) {
|
||||||
|
$prefix = (string) (Arr::get($snapshot, 'platformType') ?: 'Platform');
|
||||||
|
$this->appendPlatformRestrictionEntries($entries, $prefix, $platformPayload);
|
||||||
|
}
|
||||||
|
|
||||||
|
$typedRestrictions = [
|
||||||
|
'androidForWorkRestriction' => 'Android work profile',
|
||||||
|
'androidRestriction' => 'Android',
|
||||||
|
'iosRestriction' => 'iOS/iPadOS',
|
||||||
|
'macRestriction' => 'macOS',
|
||||||
|
'windowsRestriction' => 'Windows',
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($typedRestrictions as $key => $prefix) {
|
||||||
|
$restriction = Arr::get($snapshot, $key);
|
||||||
|
|
||||||
|
if (! is_array($restriction) || $restriction === []) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->appendPlatformRestrictionEntries($entries, $prefix, $restriction);
|
||||||
|
}
|
||||||
|
|
||||||
|
$assigned = Arr::get($snapshot, 'assignments');
|
||||||
|
if (is_array($assigned) && $assigned !== []) {
|
||||||
|
$entries[] = ['key' => 'Assignments (snapshot)', 'value' => '[present]'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($entries === []) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'type' => 'keyValue',
|
||||||
|
'title' => 'Platform restrictions (enrollment)',
|
||||||
|
'entries' => $entries,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int, array{key: string, value: mixed}> $entries
|
||||||
|
*/
|
||||||
|
private function appendPlatformRestrictionEntries(array &$entries, string $prefix, array $payload): void
|
||||||
|
{
|
||||||
|
$payload = Arr::except($payload, ['@odata.type']);
|
||||||
|
|
||||||
|
$platformBlocked = Arr::get($payload, 'platformBlocked');
|
||||||
|
if (is_bool($platformBlocked)) {
|
||||||
|
$entries[] = ['key' => "{$prefix}: Platform blocked", 'value' => $platformBlocked ? 'Enabled' : 'Disabled'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$personalBlocked = Arr::get($payload, 'personalDeviceEnrollmentBlocked');
|
||||||
|
if (is_bool($personalBlocked)) {
|
||||||
|
$entries[] = ['key' => "{$prefix}: Personal device enrollment blocked", 'value' => $personalBlocked ? 'Enabled' : 'Disabled'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$osMin = Arr::get($payload, 'osMinimumVersion');
|
||||||
|
$entries[] = [
|
||||||
|
'key' => "{$prefix}: OS minimum version",
|
||||||
|
'value' => (is_string($osMin) && $osMin !== '') ? $osMin : 'None',
|
||||||
|
];
|
||||||
|
|
||||||
|
$osMax = Arr::get($payload, 'osMaximumVersion');
|
||||||
|
$entries[] = [
|
||||||
|
'key' => "{$prefix}: OS maximum version",
|
||||||
|
'value' => (is_string($osMax) && $osMax !== '') ? $osMax : 'None',
|
||||||
|
];
|
||||||
|
|
||||||
|
$blockedManufacturers = Arr::get($payload, 'blockedManufacturers');
|
||||||
|
$entries[] = [
|
||||||
|
'key' => "{$prefix}: Blocked manufacturers",
|
||||||
|
'value' => (is_array($blockedManufacturers) && $blockedManufacturers !== [])
|
||||||
|
? array_values($blockedManufacturers)
|
||||||
|
: ['None'],
|
||||||
|
];
|
||||||
|
|
||||||
|
$blockedSkus = Arr::get($payload, 'blockedSkus');
|
||||||
|
$entries[] = [
|
||||||
|
'key' => "{$prefix}: Blocked SKUs",
|
||||||
|
'value' => (is_array($blockedSkus) && $blockedSkus !== [])
|
||||||
|
? array_values($blockedSkus)
|
||||||
|
: ['None'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array{type: string, title: string, entries: array<int, array{key: string, value: mixed}>}|null
|
||||||
|
*/
|
||||||
|
private function buildEnrollmentNotificationBlock(array $snapshot): ?array
|
||||||
|
{
|
||||||
|
$entries = [];
|
||||||
|
|
||||||
|
foreach ([
|
||||||
|
'priority' => 'Priority',
|
||||||
|
'version' => 'Version',
|
||||||
|
'deviceEnrollmentConfigurationType' => 'Configuration type',
|
||||||
|
'defaultLocale' => 'Default locale',
|
||||||
|
'notificationMessageTemplateId' => 'Notification message template ID',
|
||||||
|
] as $key => $label) {
|
||||||
|
$value = Arr::get($snapshot, $key);
|
||||||
|
|
||||||
|
if (is_int($value) || is_float($value)) {
|
||||||
|
$entries[] = ['key' => $label, 'value' => $value];
|
||||||
|
} elseif (is_string($value) && $value !== '') {
|
||||||
|
$entries[] = ['key' => $label, 'value' => $value];
|
||||||
|
} elseif (is_bool($value)) {
|
||||||
|
$entries[] = ['key' => $label, 'value' => $value ? 'Enabled' : 'Disabled'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$notificationMessages = Arr::get($snapshot, 'notificationMessages');
|
||||||
|
if (is_array($notificationMessages) && $notificationMessages !== []) {
|
||||||
|
$entries[] = ['key' => 'Notification messages', 'value' => sprintf('%d item(s)', count($notificationMessages))];
|
||||||
|
}
|
||||||
|
|
||||||
|
$assigned = Arr::get($snapshot, 'assignments');
|
||||||
|
if (is_array($assigned) && $assigned !== []) {
|
||||||
|
$entries[] = ['key' => 'Assignments (snapshot)', 'value' => '[present]'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($entries === []) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'type' => 'keyValue',
|
||||||
|
'title' => 'Enrollment notifications',
|
||||||
|
'entries' => $entries,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array<string, mixed>
|
* @return array<string, mixed>
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -167,7 +167,15 @@ private function resolveCanonicalPolicyType(string $policyType, array $policyDat
|
|||||||
return $this->resolveConfigurationPolicyType($policyData);
|
return $this->resolveConfigurationPolicyType($policyData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! in_array($policyType, ['enrollmentRestriction', 'windowsEnrollmentStatusPage'], true)) {
|
$enrollmentConfigurationTypes = [
|
||||||
|
'enrollmentRestriction',
|
||||||
|
'windowsEnrollmentStatusPage',
|
||||||
|
'deviceEnrollmentLimitConfiguration',
|
||||||
|
'deviceEnrollmentPlatformRestrictionsConfiguration',
|
||||||
|
'deviceEnrollmentNotificationConfiguration',
|
||||||
|
];
|
||||||
|
|
||||||
|
if (! in_array($policyType, $enrollmentConfigurationTypes, true)) {
|
||||||
return $policyType;
|
return $policyType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +183,18 @@ private function resolveCanonicalPolicyType(string $policyType, array $policyDat
|
|||||||
return 'windowsEnrollmentStatusPage';
|
return 'windowsEnrollmentStatusPage';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->isEnrollmentNotificationItem($policyData)) {
|
||||||
|
return 'deviceEnrollmentNotificationConfiguration';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->isEnrollmentLimitItem($policyData)) {
|
||||||
|
return 'deviceEnrollmentLimitConfiguration';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->isEnrollmentPlatformRestrictionsItem($policyData)) {
|
||||||
|
return 'deviceEnrollmentPlatformRestrictionsConfiguration';
|
||||||
|
}
|
||||||
|
|
||||||
return 'enrollmentRestriction';
|
return 'enrollmentRestriction';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,13 +275,77 @@ private function isEnrollmentStatusPageItem(array $policyData): bool
|
|||||||
|| (is_string($configurationType) && $configurationType === 'windows10EnrollmentCompletionPageConfiguration');
|
|| (is_string($configurationType) && $configurationType === 'windows10EnrollmentCompletionPageConfiguration');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function reclassifyEnrollmentConfigurationPoliciesIfNeeded(int $tenantId, string $externalId, string $policyType): void
|
private function isEnrollmentLimitItem(array $policyData): bool
|
||||||
{
|
{
|
||||||
if (! in_array($policyType, ['enrollmentRestriction', 'windowsEnrollmentStatusPage'], true)) {
|
$odataType = $policyData['@odata.type'] ?? $policyData['@OData.Type'] ?? null;
|
||||||
return;
|
$configurationType = $policyData['deviceEnrollmentConfigurationType'] ?? null;
|
||||||
|
|
||||||
|
return (is_string($odataType) && strcasecmp($odataType, '#microsoft.graph.deviceEnrollmentLimitConfiguration') === 0)
|
||||||
|
|| (is_string($configurationType) && strcasecmp($configurationType, 'deviceEnrollmentLimitConfiguration') === 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isEnrollmentPlatformRestrictionsItem(array $policyData): bool
|
||||||
|
{
|
||||||
|
$odataType = $policyData['@odata.type'] ?? $policyData['@OData.Type'] ?? null;
|
||||||
|
$configurationType = $policyData['deviceEnrollmentConfigurationType'] ?? null;
|
||||||
|
|
||||||
|
if (is_string($odataType) && $odataType !== '') {
|
||||||
|
$odataTypeKey = strtolower($odataType);
|
||||||
|
|
||||||
|
if (in_array($odataTypeKey, [
|
||||||
|
'#microsoft.graph.deviceenrollmentplatformrestrictionconfiguration',
|
||||||
|
'#microsoft.graph.deviceenrollmentplatformrestrictionsconfiguration',
|
||||||
|
], true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$enrollmentTypes = ['enrollmentRestriction', 'windowsEnrollmentStatusPage'];
|
if (is_string($configurationType) && $configurationType !== '') {
|
||||||
|
$configurationTypeKey = strtolower($configurationType);
|
||||||
|
|
||||||
|
if (in_array($configurationTypeKey, [
|
||||||
|
'deviceenrollmentplatformrestrictionconfiguration',
|
||||||
|
'deviceenrollmentplatformrestrictionsconfiguration',
|
||||||
|
], true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isEnrollmentNotificationItem(array $policyData): bool
|
||||||
|
{
|
||||||
|
$odataType = $policyData['@odata.type'] ?? $policyData['@OData.Type'] ?? null;
|
||||||
|
$configurationType = $policyData['deviceEnrollmentConfigurationType'] ?? null;
|
||||||
|
|
||||||
|
if (is_string($odataType) && strcasecmp($odataType, '#microsoft.graph.deviceEnrollmentNotificationConfiguration') === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! is_string($configurationType) || $configurationType === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return in_array(strtolower($configurationType), [
|
||||||
|
'enrollmentnotificationsconfiguration',
|
||||||
|
'deviceenrollmentnotificationconfiguration',
|
||||||
|
], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function reclassifyEnrollmentConfigurationPoliciesIfNeeded(int $tenantId, string $externalId, string $policyType): void
|
||||||
|
{
|
||||||
|
$enrollmentTypes = [
|
||||||
|
'enrollmentRestriction',
|
||||||
|
'windowsEnrollmentStatusPage',
|
||||||
|
'deviceEnrollmentLimitConfiguration',
|
||||||
|
'deviceEnrollmentPlatformRestrictionsConfiguration',
|
||||||
|
'deviceEnrollmentNotificationConfiguration',
|
||||||
|
];
|
||||||
|
|
||||||
|
if (! in_array($policyType, $enrollmentTypes, true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$existingCorrect = Policy::query()
|
$existingCorrect = Policy::query()
|
||||||
->where('tenant_id', $tenantId)
|
->where('tenant_id', $tenantId)
|
||||||
|
|||||||
@ -69,6 +69,15 @@ protected static function odataTypeMap(): array
|
|||||||
'enrollmentRestriction' => [
|
'enrollmentRestriction' => [
|
||||||
'all' => '#microsoft.graph.deviceEnrollmentConfiguration',
|
'all' => '#microsoft.graph.deviceEnrollmentConfiguration',
|
||||||
],
|
],
|
||||||
|
'deviceEnrollmentLimitConfiguration' => [
|
||||||
|
'all' => '#microsoft.graph.deviceEnrollmentLimitConfiguration',
|
||||||
|
],
|
||||||
|
'deviceEnrollmentPlatformRestrictionsConfiguration' => [
|
||||||
|
'all' => '#microsoft.graph.deviceEnrollmentPlatformRestrictionsConfiguration',
|
||||||
|
],
|
||||||
|
'deviceEnrollmentNotificationConfiguration' => [
|
||||||
|
'all' => '#microsoft.graph.deviceEnrollmentNotificationConfiguration',
|
||||||
|
],
|
||||||
'windowsAutopilotDeploymentProfile' => [
|
'windowsAutopilotDeploymentProfile' => [
|
||||||
'windows' => '#microsoft.graph.windowsAutopilotDeploymentProfile',
|
'windows' => '#microsoft.graph.windowsAutopilotDeploymentProfile',
|
||||||
],
|
],
|
||||||
|
|||||||
@ -518,14 +518,29 @@
|
|||||||
'assignments_delete_path' => '/deviceManagement/deviceHealthScripts/{id}/assignments/{assignmentId}',
|
'assignments_delete_path' => '/deviceManagement/deviceHealthScripts/{id}/assignments/{assignmentId}',
|
||||||
'assignments_delete_method' => 'DELETE',
|
'assignments_delete_method' => 'DELETE',
|
||||||
],
|
],
|
||||||
'enrollmentRestriction' => [
|
'deviceEnrollmentLimitConfiguration' => [
|
||||||
|
'resource' => 'deviceManagement/deviceEnrollmentConfigurations',
|
||||||
|
'allowed_select' => ['id', 'displayName', 'description', '@odata.type', 'version'],
|
||||||
|
'allowed_expand' => [],
|
||||||
|
'type_family' => [
|
||||||
|
'#microsoft.graph.deviceEnrollmentLimitConfiguration',
|
||||||
|
],
|
||||||
|
'create_method' => 'POST',
|
||||||
|
'update_method' => 'PATCH',
|
||||||
|
'id_field' => 'id',
|
||||||
|
'hydration' => 'properties',
|
||||||
|
'assignments_list_path' => '/deviceManagement/deviceEnrollmentConfigurations/{id}/assignments',
|
||||||
|
'assignments_create_path' => '/deviceManagement/deviceEnrollmentConfigurations/{id}/assign',
|
||||||
|
'assignments_create_method' => 'POST',
|
||||||
|
'assignments_payload_key' => 'enrollmentConfigurationAssignments',
|
||||||
|
],
|
||||||
|
'deviceEnrollmentPlatformRestrictionsConfiguration' => [
|
||||||
'resource' => 'deviceManagement/deviceEnrollmentConfigurations',
|
'resource' => 'deviceManagement/deviceEnrollmentConfigurations',
|
||||||
'allowed_select' => ['id', 'displayName', 'description', '@odata.type', 'version'],
|
'allowed_select' => ['id', 'displayName', 'description', '@odata.type', 'version'],
|
||||||
'allowed_expand' => [],
|
'allowed_expand' => [],
|
||||||
'type_family' => [
|
'type_family' => [
|
||||||
'#microsoft.graph.deviceEnrollmentPlatformRestrictionConfiguration',
|
'#microsoft.graph.deviceEnrollmentPlatformRestrictionConfiguration',
|
||||||
'#microsoft.graph.deviceEnrollmentPlatformRestrictionsConfiguration',
|
'#microsoft.graph.deviceEnrollmentPlatformRestrictionsConfiguration',
|
||||||
'#microsoft.graph.deviceEnrollmentLimitConfiguration',
|
|
||||||
],
|
],
|
||||||
'create_method' => 'POST',
|
'create_method' => 'POST',
|
||||||
'update_method' => 'PATCH',
|
'update_method' => 'PATCH',
|
||||||
@ -536,6 +551,36 @@
|
|||||||
'assignments_create_method' => 'POST',
|
'assignments_create_method' => 'POST',
|
||||||
'assignments_payload_key' => 'enrollmentConfigurationAssignments',
|
'assignments_payload_key' => 'enrollmentConfigurationAssignments',
|
||||||
],
|
],
|
||||||
|
'deviceEnrollmentNotificationConfiguration' => [
|
||||||
|
'resource' => 'deviceManagement/deviceEnrollmentConfigurations',
|
||||||
|
'allowed_select' => ['id', 'displayName', 'description', '@odata.type', 'version'],
|
||||||
|
'allowed_expand' => [],
|
||||||
|
'type_family' => [
|
||||||
|
'#microsoft.graph.deviceEnrollmentNotificationConfiguration',
|
||||||
|
],
|
||||||
|
'create_method' => 'POST',
|
||||||
|
'update_method' => 'PATCH',
|
||||||
|
'id_field' => 'id',
|
||||||
|
'hydration' => 'properties',
|
||||||
|
'assignments_list_path' => '/deviceManagement/deviceEnrollmentConfigurations/{id}/assignments',
|
||||||
|
'assignments_create_path' => '/deviceManagement/deviceEnrollmentConfigurations/{id}/assign',
|
||||||
|
'assignments_create_method' => 'POST',
|
||||||
|
'assignments_payload_key' => 'enrollmentConfigurationAssignments',
|
||||||
|
],
|
||||||
|
'enrollmentRestriction' => [
|
||||||
|
'resource' => 'deviceManagement/deviceEnrollmentConfigurations',
|
||||||
|
'allowed_select' => ['id', 'displayName', 'description', '@odata.type', 'version'],
|
||||||
|
'allowed_expand' => [],
|
||||||
|
'type_family' => [],
|
||||||
|
'create_method' => 'POST',
|
||||||
|
'update_method' => 'PATCH',
|
||||||
|
'id_field' => 'id',
|
||||||
|
'hydration' => 'properties',
|
||||||
|
'assignments_list_path' => '/deviceManagement/deviceEnrollmentConfigurations/{id}/assignments',
|
||||||
|
'assignments_create_path' => '/deviceManagement/deviceEnrollmentConfigurations/{id}/assign',
|
||||||
|
'assignments_create_method' => 'POST',
|
||||||
|
'assignments_payload_key' => 'enrollmentConfigurationAssignments',
|
||||||
|
],
|
||||||
'windowsAutopilotDeploymentProfile' => [
|
'windowsAutopilotDeploymentProfile' => [
|
||||||
'resource' => 'deviceManagement/windowsAutopilotDeploymentProfiles',
|
'resource' => 'deviceManagement/windowsAutopilotDeploymentProfiles',
|
||||||
'allowed_select' => ['id', 'displayName', 'description', '@odata.type', 'lastModifiedDateTime'],
|
'allowed_select' => ['id', 'displayName', 'description', '@odata.type', 'lastModifiedDateTime'],
|
||||||
|
|||||||
@ -185,6 +185,37 @@
|
|||||||
'restore' => 'enabled',
|
'restore' => 'enabled',
|
||||||
'risk' => 'medium',
|
'risk' => 'medium',
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'type' => 'deviceEnrollmentLimitConfiguration',
|
||||||
|
'label' => 'Enrollment Limits',
|
||||||
|
'category' => 'Enrollment',
|
||||||
|
'platform' => 'all',
|
||||||
|
'endpoint' => 'deviceManagement/deviceEnrollmentConfigurations',
|
||||||
|
'backup' => 'full',
|
||||||
|
'restore' => 'preview-only',
|
||||||
|
'risk' => 'high',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'type' => 'deviceEnrollmentPlatformRestrictionsConfiguration',
|
||||||
|
'label' => 'Platform Restrictions (Enrollment)',
|
||||||
|
'category' => 'Enrollment',
|
||||||
|
'platform' => 'all',
|
||||||
|
'endpoint' => 'deviceManagement/deviceEnrollmentConfigurations',
|
||||||
|
'backup' => 'full',
|
||||||
|
'restore' => 'preview-only',
|
||||||
|
'risk' => 'high',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'type' => 'deviceEnrollmentNotificationConfiguration',
|
||||||
|
'label' => 'Enrollment Notifications',
|
||||||
|
'category' => 'Enrollment',
|
||||||
|
'platform' => 'all',
|
||||||
|
'endpoint' => 'deviceManagement/deviceEnrollmentConfigurations',
|
||||||
|
'filter' => "deviceEnrollmentConfigurationType eq 'EnrollmentNotificationsConfiguration'",
|
||||||
|
'backup' => 'full',
|
||||||
|
'restore' => 'preview-only',
|
||||||
|
'risk' => 'high',
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'type' => 'enrollmentRestriction',
|
'type' => 'enrollmentRestriction',
|
||||||
'label' => 'Enrollment Restrictions',
|
'label' => 'Enrollment Restrictions',
|
||||||
|
|||||||
@ -12,17 +12,16 @@ ## Phase 2: Research & Design
|
|||||||
- [ ] T003 Decide restore modes and risk levels.
|
- [ ] T003 Decide restore modes and risk levels.
|
||||||
|
|
||||||
## Phase 3: Tests (TDD)
|
## Phase 3: Tests (TDD)
|
||||||
- [ ] T004 Add sync tests ensuring each subtype is classified correctly.
|
- [x] T004 Add sync tests ensuring each subtype is classified correctly.
|
||||||
- [ ] T005 Add snapshot capture test for at least one subtype.
|
- [x] T005 Add snapshot capture test for at least one subtype.
|
||||||
- [ ] T006 Add restore preview test ensuring preview-only behavior.
|
- [x] T006 Add restore preview test ensuring preview-only behavior.
|
||||||
|
|
||||||
## Phase 4: Implementation
|
## Phase 4: Implementation
|
||||||
- [ ] T007 Add new types to `config/tenantpilot.php`.
|
- [x] T007 Add new types to `config/tenantpilot.php`.
|
||||||
- [ ] T008 Add contracts in `config/graph_contracts.php` (resource + type families).
|
- [x] T008 Add contracts in `config/graph_contracts.php` (resource + type families).
|
||||||
- [ ] T009 Update `PolicySyncService` enrollment classification logic.
|
- [x] T009 Update `PolicySyncService` enrollment classification logic.
|
||||||
- [ ] T010 Add normalizer for readable UI output (key fields per subtype).
|
- [x] T010 Add normalizer for readable UI output (key fields per subtype).
|
||||||
|
|
||||||
## Phase 5: Verification
|
## Phase 5: Verification
|
||||||
- [ ] T011 Run targeted tests.
|
- [x] T011 Run targeted tests.
|
||||||
- [ ] T012 Run Pint (`./vendor/bin/pint --dirty`).
|
- [x] T012 Run Pint (`./vendor/bin/pint --dirty`).
|
||||||
|
|
||||||
|
|||||||
@ -109,11 +109,11 @@
|
|||||||
$response->assertSee('app-2');
|
$response->assertSee('app-2');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('policy detail renders normalized settings for enrollment restrictions', function () {
|
test('policy detail renders normalized settings for platform restrictions (enrollment)', function () {
|
||||||
$policy = Policy::create([
|
$policy = Policy::create([
|
||||||
'tenant_id' => $this->tenant->id,
|
'tenant_id' => $this->tenant->id,
|
||||||
'external_id' => 'enroll-restrict-1',
|
'external_id' => 'enroll-restrict-1',
|
||||||
'policy_type' => 'enrollmentRestriction',
|
'policy_type' => 'deviceEnrollmentPlatformRestrictionsConfiguration',
|
||||||
'display_name' => 'Restriction A',
|
'display_name' => 'Restriction A',
|
||||||
'platform' => 'all',
|
'platform' => 'all',
|
||||||
]);
|
]);
|
||||||
@ -143,9 +143,9 @@
|
|||||||
|
|
||||||
$response->assertOk();
|
$response->assertOk();
|
||||||
$response->assertSee('Settings');
|
$response->assertSee('Settings');
|
||||||
$response->assertSee('Enrollment restrictions');
|
$response->assertSee('Platform restrictions (enrollment)');
|
||||||
$response->assertSee('Personal device enrollment blocked');
|
$response->assertSee('Platform: Personal device enrollment blocked');
|
||||||
$response->assertSee('Enabled');
|
$response->assertSee('Enabled');
|
||||||
$response->assertSee('Blocked SKUs');
|
$response->assertSee('Platform: Blocked SKUs');
|
||||||
$response->assertSee('sku-1');
|
$response->assertSee('sku-1');
|
||||||
});
|
});
|
||||||
|
|||||||
@ -109,3 +109,103 @@ public function request(string $method, string $path, array $options = []): Grap
|
|||||||
|
|
||||||
expect($client->applyCalls)->toBe(0);
|
expect($client->applyCalls)->toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('enrollment limit restores are preview-only and skipped on execution', function () {
|
||||||
|
$client = new class implements GraphClientInterface
|
||||||
|
{
|
||||||
|
public int $applyCalls = 0;
|
||||||
|
|
||||||
|
public function listPolicies(string $policyType, array $options = []): GraphResponse
|
||||||
|
{
|
||||||
|
return new GraphResponse(true, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPolicy(string $policyType, string $policyId, array $options = []): GraphResponse
|
||||||
|
{
|
||||||
|
return new GraphResponse(true, ['payload' => []]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOrganization(array $options = []): GraphResponse
|
||||||
|
{
|
||||||
|
return new GraphResponse(true, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function applyPolicy(string $policyType, string $policyId, array $payload, array $options = []): GraphResponse
|
||||||
|
{
|
||||||
|
$this->applyCalls++;
|
||||||
|
|
||||||
|
return new GraphResponse(true, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getServicePrincipalPermissions(array $options = []): GraphResponse
|
||||||
|
{
|
||||||
|
return new GraphResponse(true, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function request(string $method, string $path, array $options = []): GraphResponse
|
||||||
|
{
|
||||||
|
return new GraphResponse(true, []);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
app()->instance(GraphClientInterface::class, $client);
|
||||||
|
|
||||||
|
$tenant = Tenant::create([
|
||||||
|
'tenant_id' => 'tenant-enrollment-limit',
|
||||||
|
'name' => 'Tenant Enrollment Limit',
|
||||||
|
'metadata' => [],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$policy = Policy::create([
|
||||||
|
'tenant_id' => $tenant->id,
|
||||||
|
'external_id' => 'enrollment-limit-1',
|
||||||
|
'policy_type' => 'deviceEnrollmentLimitConfiguration',
|
||||||
|
'display_name' => 'Enrollment Limit',
|
||||||
|
'platform' => 'all',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$backupSet = BackupSet::create([
|
||||||
|
'tenant_id' => $tenant->id,
|
||||||
|
'name' => 'Enrollment Limit Backup',
|
||||||
|
'status' => 'completed',
|
||||||
|
'item_count' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$backupItem = BackupItem::create([
|
||||||
|
'tenant_id' => $tenant->id,
|
||||||
|
'backup_set_id' => $backupSet->id,
|
||||||
|
'policy_id' => $policy->id,
|
||||||
|
'policy_identifier' => $policy->external_id,
|
||||||
|
'policy_type' => $policy->policy_type,
|
||||||
|
'platform' => $policy->platform,
|
||||||
|
'payload' => [
|
||||||
|
'@odata.type' => '#microsoft.graph.deviceEnrollmentLimitConfiguration',
|
||||||
|
'id' => $policy->external_id,
|
||||||
|
'displayName' => $policy->display_name,
|
||||||
|
'limit' => 5,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$service = app(RestoreService::class);
|
||||||
|
$preview = $service->preview($tenant, $backupSet, [$backupItem->id]);
|
||||||
|
|
||||||
|
$previewItem = collect($preview)->first(fn (array $item) => ($item['policy_type'] ?? null) === 'deviceEnrollmentLimitConfiguration');
|
||||||
|
|
||||||
|
expect($previewItem)->not->toBeNull()
|
||||||
|
->and($previewItem['restore_mode'] ?? null)->toBe('preview-only');
|
||||||
|
|
||||||
|
$run = $service->execute(
|
||||||
|
tenant: $tenant,
|
||||||
|
backupSet: $backupSet,
|
||||||
|
selectedItemIds: [$backupItem->id],
|
||||||
|
dryRun: false,
|
||||||
|
actorEmail: 'tester@example.com',
|
||||||
|
actorName: 'Tester',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect($run->results)->toHaveCount(1);
|
||||||
|
expect($run->results[0]['status'])->toBe('skipped');
|
||||||
|
expect($run->results[0]['reason'])->toBe('preview_only');
|
||||||
|
|
||||||
|
expect($client->applyCalls)->toBe(0);
|
||||||
|
});
|
||||||
|
|||||||
@ -106,7 +106,11 @@
|
|||||||
|
|
||||||
$mock->shouldReceive('listPolicies')
|
$mock->shouldReceive('listPolicies')
|
||||||
->andReturnUsing(function (string $policyType) use ($payload) {
|
->andReturnUsing(function (string $policyType) use ($payload) {
|
||||||
if (in_array($policyType, ['enrollmentRestriction', 'windowsEnrollmentStatusPage'], true)) {
|
if (in_array($policyType, [
|
||||||
|
'enrollmentRestriction',
|
||||||
|
'windowsEnrollmentStatusPage',
|
||||||
|
'deviceEnrollmentPlatformRestrictionsConfiguration',
|
||||||
|
], true)) {
|
||||||
return new GraphResponse(true, $payload);
|
return new GraphResponse(true, $payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,6 +126,11 @@
|
|||||||
'platform' => 'all',
|
'platform' => 'all',
|
||||||
'filter' => null,
|
'filter' => null,
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'type' => 'deviceEnrollmentPlatformRestrictionsConfiguration',
|
||||||
|
'platform' => 'all',
|
||||||
|
'filter' => null,
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'type' => 'enrollmentRestriction',
|
'type' => 'enrollmentRestriction',
|
||||||
'platform' => 'all',
|
'platform' => 'all',
|
||||||
@ -142,6 +151,100 @@
|
|||||||
->pluck('external_id')
|
->pluck('external_id')
|
||||||
->all();
|
->all();
|
||||||
|
|
||||||
|
$platformRestrictionIds = Policy::query()
|
||||||
|
->where('tenant_id', $tenant->id)
|
||||||
|
->where('policy_type', 'deviceEnrollmentPlatformRestrictionsConfiguration')
|
||||||
|
->orderBy('external_id')
|
||||||
|
->pluck('external_id')
|
||||||
|
->all();
|
||||||
|
|
||||||
expect($espIds)->toMatchArray(['esp-1']);
|
expect($espIds)->toMatchArray(['esp-1']);
|
||||||
expect($restrictionIds)->toMatchArray(['other-1', 'restriction-1']);
|
expect($platformRestrictionIds)->toMatchArray(['restriction-1']);
|
||||||
|
expect($restrictionIds)->toMatchArray(['other-1']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('policy sync classifies enrollment configuration subtypes separately', function () {
|
||||||
|
$tenant = Tenant::create([
|
||||||
|
'tenant_id' => 'tenant-sync-enrollment-subtypes',
|
||||||
|
'name' => 'Tenant Sync Enrollment Subtypes',
|
||||||
|
'metadata' => [],
|
||||||
|
'is_current' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$tenant->makeCurrent();
|
||||||
|
|
||||||
|
$this->mock(GraphClientInterface::class, function (MockInterface $mock) {
|
||||||
|
$limitPayload = [
|
||||||
|
'id' => 'limit-1',
|
||||||
|
'displayName' => 'Enrollment Limit',
|
||||||
|
'@odata.type' => '#microsoft.graph.deviceEnrollmentLimitConfiguration',
|
||||||
|
'deviceEnrollmentConfigurationType' => 'deviceEnrollmentLimitConfiguration',
|
||||||
|
'limit' => 5,
|
||||||
|
];
|
||||||
|
|
||||||
|
$platformRestrictionsPayload = [
|
||||||
|
'id' => 'platform-1',
|
||||||
|
'displayName' => 'Platform Restrictions',
|
||||||
|
'@odata.type' => '#microsoft.graph.deviceEnrollmentPlatformRestrictionsConfiguration',
|
||||||
|
'deviceEnrollmentConfigurationType' => 'deviceEnrollmentPlatformRestrictionsConfiguration',
|
||||||
|
];
|
||||||
|
|
||||||
|
$notificationPayload = [
|
||||||
|
'id' => 'notify-1',
|
||||||
|
'displayName' => 'Enrollment Notifications',
|
||||||
|
'@odata.type' => '#microsoft.graph.deviceEnrollmentNotificationConfiguration',
|
||||||
|
'deviceEnrollmentConfigurationType' => 'EnrollmentNotificationsConfiguration',
|
||||||
|
];
|
||||||
|
|
||||||
|
$unfilteredPayload = [
|
||||||
|
$limitPayload,
|
||||||
|
$platformRestrictionsPayload,
|
||||||
|
$notificationPayload,
|
||||||
|
];
|
||||||
|
|
||||||
|
$mock->shouldReceive('listPolicies')
|
||||||
|
->andReturnUsing(function (string $policyType) use ($notificationPayload, $unfilteredPayload) {
|
||||||
|
if ($policyType === 'deviceEnrollmentNotificationConfiguration') {
|
||||||
|
return new GraphResponse(true, [$notificationPayload]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($policyType, [
|
||||||
|
'enrollmentRestriction',
|
||||||
|
'deviceEnrollmentLimitConfiguration',
|
||||||
|
'deviceEnrollmentPlatformRestrictionsConfiguration',
|
||||||
|
'windowsEnrollmentStatusPage',
|
||||||
|
], true)) {
|
||||||
|
return new GraphResponse(true, $unfilteredPayload);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new GraphResponse(true, []);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$service = app(PolicySyncService::class);
|
||||||
|
|
||||||
|
$service->syncPolicies($tenant, [
|
||||||
|
['type' => 'deviceEnrollmentLimitConfiguration', 'platform' => 'all', 'filter' => null],
|
||||||
|
['type' => 'deviceEnrollmentPlatformRestrictionsConfiguration', 'platform' => 'all', 'filter' => null],
|
||||||
|
['type' => 'deviceEnrollmentNotificationConfiguration', 'platform' => 'all', 'filter' => null],
|
||||||
|
['type' => 'enrollmentRestriction', 'platform' => 'all', 'filter' => null],
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(Policy::query()
|
||||||
|
->where('tenant_id', $tenant->id)
|
||||||
|
->where('policy_type', 'deviceEnrollmentLimitConfiguration')
|
||||||
|
->pluck('external_id')
|
||||||
|
->all())->toMatchArray(['limit-1']);
|
||||||
|
|
||||||
|
expect(Policy::query()
|
||||||
|
->where('tenant_id', $tenant->id)
|
||||||
|
->where('policy_type', 'deviceEnrollmentPlatformRestrictionsConfiguration')
|
||||||
|
->pluck('external_id')
|
||||||
|
->all())->toMatchArray(['platform-1']);
|
||||||
|
|
||||||
|
expect(Policy::query()
|
||||||
|
->where('tenant_id', $tenant->id)
|
||||||
|
->where('policy_type', 'deviceEnrollmentNotificationConfiguration')
|
||||||
|
->pluck('external_id')
|
||||||
|
->all())->toMatchArray(['notify-1']);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -98,6 +98,76 @@
|
|||||||
expect($version->assignments[0]['target']['assignment_filter_name'])->toBe('Targeted Devices');
|
expect($version->assignments[0]['target']['assignment_filter_name'])->toBe('Targeted Devices');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('captures enrollment limit configuration version with assignments from graph', function () {
|
||||||
|
$this->policy->forceFill([
|
||||||
|
'policy_type' => 'deviceEnrollmentLimitConfiguration',
|
||||||
|
'platform' => 'all',
|
||||||
|
])->save();
|
||||||
|
|
||||||
|
$this->mock(PolicySnapshotService::class, function ($mock) {
|
||||||
|
$mock->shouldReceive('fetch')
|
||||||
|
->once()
|
||||||
|
->andReturn([
|
||||||
|
'payload' => [
|
||||||
|
'@odata.type' => '#microsoft.graph.deviceEnrollmentLimitConfiguration',
|
||||||
|
'id' => 'test-policy-id',
|
||||||
|
'displayName' => 'Enrollment Limit',
|
||||||
|
'limit' => 5,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->mock(AssignmentFetcher::class, function ($mock) {
|
||||||
|
$mock->shouldReceive('fetch')
|
||||||
|
->once()
|
||||||
|
->withArgs(function (string $policyType): bool {
|
||||||
|
return $policyType === 'deviceEnrollmentLimitConfiguration';
|
||||||
|
})
|
||||||
|
->andReturn([
|
||||||
|
[
|
||||||
|
'id' => 'assignment-1',
|
||||||
|
'intent' => 'apply',
|
||||||
|
'target' => [
|
||||||
|
'@odata.type' => '#microsoft.graph.groupAssignmentTarget',
|
||||||
|
'groupId' => 'group-123',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->mock(GroupResolver::class, function ($mock) {
|
||||||
|
$mock->shouldReceive('resolveGroupIds')
|
||||||
|
->once()
|
||||||
|
->andReturn([
|
||||||
|
'group-123' => [
|
||||||
|
'id' => 'group-123',
|
||||||
|
'displayName' => 'Test Group',
|
||||||
|
'orphaned' => false,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->mock(AssignmentFilterResolver::class, function ($mock) {
|
||||||
|
$mock->shouldReceive('resolve')
|
||||||
|
->once()
|
||||||
|
->andReturn([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
$versionService = app(VersionService::class);
|
||||||
|
$version = $versionService->captureFromGraph(
|
||||||
|
$this->tenant,
|
||||||
|
$this->policy,
|
||||||
|
'test@example.com'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect($version)->not->toBeNull()
|
||||||
|
->and($version->policy_type)->toBe('deviceEnrollmentLimitConfiguration')
|
||||||
|
->and($version->snapshot['@odata.type'] ?? null)->toBe('#microsoft.graph.deviceEnrollmentLimitConfiguration')
|
||||||
|
->and($version->snapshot['limit'] ?? null)->toBe(5)
|
||||||
|
->and($version->assignments)->toHaveCount(1)
|
||||||
|
->and($version->metadata['assignments_count'])->toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
it('hydrates assignment filter names when filter data is stored at root', function () {
|
it('hydrates assignment filter names when filter data is stored at root', function () {
|
||||||
$this->mock(PolicySnapshotService::class, function ($mock) {
|
$this->mock(PolicySnapshotService::class, function ($mock) {
|
||||||
$mock->shouldReceive('fetch')
|
$mock->shouldReceive('fetch')
|
||||||
|
|||||||
@ -67,34 +67,30 @@
|
|||||||
expect(collect($result['warnings'])->join(' '))->toContain('@odata.type mismatch');
|
expect(collect($result['warnings'])->join(' '))->toContain('@odata.type mismatch');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes enrollment restrictions platform restriction payload', function () {
|
it('normalizes enrollment platform restriction payload', function () {
|
||||||
$snapshot = [
|
$snapshot = [
|
||||||
'@odata.type' => '#microsoft.graph.deviceEnrollmentPlatformRestrictionConfiguration',
|
'@odata.type' => '#microsoft.graph.deviceEnrollmentPlatformRestrictionConfiguration',
|
||||||
'deviceEnrollmentConfigurationType' => 'deviceEnrollmentPlatformRestrictionConfiguration',
|
'deviceEnrollmentConfigurationType' => 'deviceEnrollmentPlatformRestrictionConfiguration',
|
||||||
'displayName' => 'DeviceTypeRestriction',
|
'displayName' => 'DeviceTypeRestriction',
|
||||||
'version' => 2,
|
'version' => 2,
|
||||||
// Graph uses this singular shape for platform restriction configs.
|
|
||||||
'platformRestriction' => [
|
'platformRestriction' => [
|
||||||
'platformBlocked' => false,
|
'platformBlocked' => false,
|
||||||
'personalDeviceEnrollmentBlocked' => true,
|
'personalDeviceEnrollmentBlocked' => true,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
$result = $this->normalizer->normalize($snapshot, 'enrollmentRestriction', 'all');
|
$result = $this->normalizer->normalize($snapshot, 'deviceEnrollmentPlatformRestrictionsConfiguration', 'all');
|
||||||
|
|
||||||
$block = collect($result['settings'])->firstWhere('title', 'Enrollment restrictions');
|
$block = collect($result['settings'])->firstWhere('title', 'Platform restrictions (enrollment)');
|
||||||
expect($block)->not->toBeNull();
|
expect($block)->not->toBeNull();
|
||||||
|
|
||||||
$platformEntry = collect($block['entries'] ?? [])->firstWhere('key', 'Platform restrictions');
|
expect(collect($block['entries'] ?? [])->firstWhere('key', 'Platform: Platform blocked')['value'] ?? null)->toBe('Disabled');
|
||||||
expect($platformEntry)->toBeNull();
|
expect(collect($block['entries'] ?? [])->firstWhere('key', 'Platform: Personal device enrollment blocked')['value'] ?? null)->toBe('Enabled');
|
||||||
|
|
||||||
expect(collect($block['entries'] ?? [])->firstWhere('key', 'Platform blocked')['value'] ?? null)->toBe('Disabled');
|
expect(collect($block['entries'] ?? [])->firstWhere('key', 'Platform: OS minimum version')['value'] ?? null)->toBe('None');
|
||||||
expect(collect($block['entries'] ?? [])->firstWhere('key', 'Personal device enrollment blocked')['value'] ?? null)->toBe('Enabled');
|
expect(collect($block['entries'] ?? [])->firstWhere('key', 'Platform: OS maximum version')['value'] ?? null)->toBe('None');
|
||||||
|
expect(collect($block['entries'] ?? [])->firstWhere('key', 'Platform: Blocked manufacturers')['value'] ?? null)->toBe(['None']);
|
||||||
expect(collect($block['entries'] ?? [])->firstWhere('key', 'OS minimum version')['value'] ?? null)->toBe('None');
|
expect(collect($block['entries'] ?? [])->firstWhere('key', 'Platform: Blocked SKUs')['value'] ?? null)->toBe(['None']);
|
||||||
expect(collect($block['entries'] ?? [])->firstWhere('key', 'OS maximum version')['value'] ?? null)->toBe('None');
|
|
||||||
expect(collect($block['entries'] ?? [])->firstWhere('key', 'Blocked manufacturers')['value'] ?? null)->toBe(['None']);
|
|
||||||
expect(collect($block['entries'] ?? [])->firstWhere('key', 'Blocked SKUs')['value'] ?? null)->toBe(['None']);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes Autopilot deployment profile key fields', function () {
|
it('normalizes Autopilot deployment profile key fields', function () {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user