Spec 430: Exchange PowerShell adapter contract slice 1. Validation was not rerun during PR creation handoff; branch contains implementation report and tests. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #497
299 lines
16 KiB
PHP
299 lines
16 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services\TenantConfiguration;
|
|
|
|
use App\Models\TenantConfigurationResourceType;
|
|
use App\Support\TenantConfiguration\SourceClass;
|
|
|
|
final class CoverageIdentityStrategyRegistry
|
|
{
|
|
/**
|
|
* @var array<string, array<string, mixed>>
|
|
*/
|
|
private const STRATEGIES = [
|
|
'deviceAndAppManagementAssignmentFilter' => [
|
|
'strategy_identifier' => 'tcm.assignment_filter.v1',
|
|
'preferred_identity_fields' => ['id', 'sourceId', 'assignmentFilterId'],
|
|
'fallback_identity_fields' => ['templateReference.templateId', 'sourceKey'],
|
|
'source_composite_fields' => ['platform', 'assignmentFilterManagementType', 'rule'],
|
|
'derived_composite_fields' => ['platform', 'payloadType', 'source_metadata.source_contract_key'],
|
|
'display_fields' => ['displayName', 'name'],
|
|
'secondary_fields' => ['platform', 'assignmentFilterManagementType', 'source_metadata.source_contract_key', 'source_metadata.source_version'],
|
|
'requires_provider_connection_scope' => true,
|
|
'allows_derived_identity' => true,
|
|
'allows_experimental_identity' => false,
|
|
'derived_claims_allowed' => false,
|
|
],
|
|
'deviceEnrollmentLimitRestriction' => [
|
|
'strategy_identifier' => 'tcm.device_enrollment_limit_restriction.v1',
|
|
'preferred_identity_fields' => ['id', 'sourceId', 'restrictionId'],
|
|
'fallback_identity_fields' => ['settingId', 'sourceKey'],
|
|
'source_composite_fields' => ['platform', 'limit', 'priority'],
|
|
'derived_composite_fields' => ['platform', 'limit', 'source_metadata.source_contract_key'],
|
|
'display_fields' => ['displayName', 'name'],
|
|
'secondary_fields' => ['platform', 'limit', 'priority', 'source_metadata.source_contract_key'],
|
|
'requires_provider_connection_scope' => true,
|
|
'allows_derived_identity' => true,
|
|
'allows_experimental_identity' => false,
|
|
'derived_claims_allowed' => false,
|
|
],
|
|
'deviceEnrollmentPlatformRestriction' => [
|
|
'strategy_identifier' => 'tcm.device_enrollment_platform_restriction.v1',
|
|
'preferred_identity_fields' => ['id', 'sourceId', 'restrictionId'],
|
|
'fallback_identity_fields' => ['platformRestrictionId', 'sourceKey'],
|
|
'source_composite_fields' => ['platform', 'platformType', 'restrictionType'],
|
|
'derived_composite_fields' => ['platform', 'platformType', 'source_metadata.source_contract_key'],
|
|
'display_fields' => ['displayName', 'name'],
|
|
'secondary_fields' => ['platform', 'platformType', 'restrictionType', 'source_metadata.source_contract_key'],
|
|
'requires_provider_connection_scope' => true,
|
|
'allows_derived_identity' => true,
|
|
'allows_experimental_identity' => false,
|
|
'derived_claims_allowed' => false,
|
|
],
|
|
'deviceEnrollmentStatusPageWindows10' => [
|
|
'strategy_identifier' => 'tcm.device_enrollment_status_page_windows10.v1',
|
|
'preferred_identity_fields' => ['id', 'sourceId', 'statusPageId'],
|
|
'fallback_identity_fields' => ['enrollmentStatusPageId', 'sourceKey'],
|
|
'source_composite_fields' => ['platform', 'installProgressTimeoutInMinutes', 'priority'],
|
|
'derived_composite_fields' => ['platform', 'showInstallationProgress', 'source_metadata.source_contract_key'],
|
|
'display_fields' => ['displayName', 'name'],
|
|
'secondary_fields' => ['platform', 'showInstallationProgress', 'installProgressTimeoutInMinutes', 'source_metadata.source_contract_key'],
|
|
'requires_provider_connection_scope' => true,
|
|
'allows_derived_identity' => true,
|
|
'allows_experimental_identity' => false,
|
|
'derived_claims_allowed' => false,
|
|
],
|
|
'appProtectionPolicyAndroid' => [
|
|
'strategy_identifier' => 'tcm.app_protection_policy_android.v1',
|
|
'preferred_identity_fields' => ['id', 'sourceId', 'policyId'],
|
|
'fallback_identity_fields' => ['appProtectionPolicyId', 'sourceKey'],
|
|
'source_composite_fields' => ['platform', 'targetedAppManagementLevels', 'roleScopeTagIds'],
|
|
'derived_composite_fields' => ['platform', 'targetedAppManagementLevels', 'source_metadata.source_contract_key'],
|
|
'display_fields' => ['displayName', 'name'],
|
|
'secondary_fields' => ['platform', 'targetedAppManagementLevels', 'roleScopeTagIds', 'source_metadata.source_contract_key'],
|
|
'requires_provider_connection_scope' => true,
|
|
'allows_derived_identity' => true,
|
|
'allows_experimental_identity' => false,
|
|
'derived_claims_allowed' => false,
|
|
],
|
|
'appProtectionPolicyiOS' => [
|
|
'strategy_identifier' => 'tcm.app_protection_policy_ios.v1',
|
|
'preferred_identity_fields' => ['id', 'sourceId', 'policyId'],
|
|
'fallback_identity_fields' => ['appProtectionPolicyId', 'sourceKey'],
|
|
'source_composite_fields' => ['platform', 'targetedAppManagementLevels', 'roleScopeTagIds'],
|
|
'derived_composite_fields' => ['platform', 'targetedAppManagementLevels', 'source_metadata.source_contract_key'],
|
|
'display_fields' => ['displayName', 'name'],
|
|
'secondary_fields' => ['platform', 'targetedAppManagementLevels', 'roleScopeTagIds', 'source_metadata.source_contract_key'],
|
|
'requires_provider_connection_scope' => true,
|
|
'allows_derived_identity' => true,
|
|
'allows_experimental_identity' => false,
|
|
'derived_claims_allowed' => false,
|
|
],
|
|
'conditionalAccessPolicy' => [
|
|
'strategy_identifier' => 'graph.conditional_access_policy.v1',
|
|
'preferred_identity_fields' => ['id', 'policyId', 'sourceId'],
|
|
'fallback_identity_fields' => ['sourceKey'],
|
|
'source_composite_fields' => [],
|
|
'derived_composite_fields' => [],
|
|
'display_fields' => ['displayName', 'name'],
|
|
'secondary_fields' => ['state', 'source_metadata.source_contract_key', 'source_metadata.source_version'],
|
|
'requires_provider_connection_scope' => true,
|
|
'allows_derived_identity' => false,
|
|
'allows_experimental_identity' => false,
|
|
'derived_claims_allowed' => false,
|
|
'stable_key_kind' => 'graph_object_id',
|
|
],
|
|
'securityDefaults' => [
|
|
'strategy_identifier' => 'graph.security_defaults.v1',
|
|
'preferred_identity_fields' => ['id'],
|
|
'fallback_identity_fields' => [],
|
|
'source_composite_fields' => [],
|
|
'derived_composite_fields' => [],
|
|
'display_fields' => ['displayName', 'name'],
|
|
'secondary_fields' => ['isEnabled', 'source_metadata.source_contract_key', 'source_metadata.source_version'],
|
|
'requires_provider_connection_scope' => true,
|
|
'allows_derived_identity' => false,
|
|
'allows_experimental_identity' => false,
|
|
'derived_claims_allowed' => false,
|
|
'stable_key_kind' => 'graph_object_id',
|
|
],
|
|
'transportRule' => [
|
|
'strategy_identifier' => 'tcm.exchange.transport_rule.v1',
|
|
'preferred_identity_fields' => ['id', 'sourceId', 'Guid', 'RuleId'],
|
|
'fallback_identity_fields' => [],
|
|
'source_composite_fields' => [],
|
|
'derived_composite_fields' => [],
|
|
'display_fields' => ['displayName', 'DisplayName', 'name', 'Name'],
|
|
'secondary_fields' => ['Priority', 'priority', 'Mode', 'mode', 'State', 'state', 'source_metadata.source_contract_key', 'source_metadata.source_version'],
|
|
'requires_provider_connection_scope' => true,
|
|
'allows_derived_identity' => false,
|
|
'allows_experimental_identity' => false,
|
|
'derived_claims_allowed' => false,
|
|
'stable_key_kind' => 'tcm_resource_identifier',
|
|
],
|
|
'remoteDomain' => [
|
|
'strategy_identifier' => 'tcm.exchange.remote_domain.v1',
|
|
'preferred_identity_fields' => ['id', 'sourceId', 'Guid', 'RemoteDomainId', 'Identity'],
|
|
'fallback_identity_fields' => [],
|
|
'source_composite_fields' => [],
|
|
'derived_composite_fields' => ['DomainName', 'domainName'],
|
|
'display_fields' => ['displayName', 'DisplayName', 'name', 'Name', 'DomainName', 'domainName'],
|
|
'secondary_fields' => ['IsDefault', 'isDefault', 'AllowedOOFType', 'allowedOOFType', 'AutoReplyEnabled', 'autoReplyEnabled', 'source_metadata.source_contract_key', 'source_metadata.source_version'],
|
|
'requires_provider_connection_scope' => true,
|
|
'allows_derived_identity' => false,
|
|
'allows_experimental_identity' => false,
|
|
'derived_claims_allowed' => false,
|
|
'stable_key_kind' => 'tcm_resource_identifier',
|
|
],
|
|
'inboundConnector' => [
|
|
'strategy_identifier' => 'tcm.exchange.inbound_connector.v1',
|
|
'preferred_identity_fields' => ['id', 'sourceId', 'Guid', 'ConnectorId', 'Identity'],
|
|
'fallback_identity_fields' => [],
|
|
'source_composite_fields' => [],
|
|
'derived_composite_fields' => [],
|
|
'display_fields' => ['displayName', 'DisplayName', 'name', 'Name'],
|
|
'secondary_fields' => ['ConnectorType', 'connectorType', 'Enabled', 'enabled', 'RequireTls', 'requireTls', 'source_metadata.source_contract_key', 'source_metadata.source_version'],
|
|
'requires_provider_connection_scope' => true,
|
|
'allows_derived_identity' => false,
|
|
'allows_experimental_identity' => false,
|
|
'derived_claims_allowed' => false,
|
|
'stable_key_kind' => 'tcm_resource_identifier',
|
|
],
|
|
'acceptedDomain' => [
|
|
'strategy_identifier' => 'tcm.exchange.accepted_domain.v1',
|
|
'preferred_identity_fields' => ['id', 'sourceId'],
|
|
'fallback_identity_fields' => ['DomainName', 'domainName'],
|
|
'source_composite_fields' => [],
|
|
'derived_composite_fields' => [],
|
|
'display_fields' => ['displayName', 'DisplayName', 'name', 'Name'],
|
|
'secondary_fields' => ['DomainType', 'domainType', 'IsDefault', 'isDefault', 'State', 'state', 'source_metadata.source_contract_key', 'source_metadata.source_version'],
|
|
'requires_provider_connection_scope' => true,
|
|
'allows_derived_identity' => false,
|
|
'allows_experimental_identity' => false,
|
|
'derived_claims_allowed' => false,
|
|
'stable_key_kind' => 'tcm_resource_identifier',
|
|
],
|
|
'appPermissionPolicy' => [
|
|
'strategy_identifier' => 'tcm.teams.app_permission_policy.v1',
|
|
'preferred_identity_fields' => ['id', 'sourceId', 'policyId'],
|
|
'fallback_identity_fields' => [],
|
|
'source_composite_fields' => [],
|
|
'derived_composite_fields' => [],
|
|
'display_fields' => ['displayName', 'DisplayName', 'name', 'Name'],
|
|
'secondary_fields' => ['GlobalCatalogAppsType', 'globalCatalogAppsType', 'PrivateCatalogAppsType', 'privateCatalogAppsType', 'source_metadata.source_contract_key', 'source_metadata.source_version'],
|
|
'requires_provider_connection_scope' => true,
|
|
'allows_derived_identity' => false,
|
|
'allows_experimental_identity' => false,
|
|
'derived_claims_allowed' => false,
|
|
'stable_key_kind' => 'tcm_resource_identifier',
|
|
],
|
|
'meetingPolicy' => [
|
|
'strategy_identifier' => 'tcm.teams.meeting_policy.v1',
|
|
'preferred_identity_fields' => ['id', 'sourceId', 'policyId'],
|
|
'fallback_identity_fields' => [],
|
|
'source_composite_fields' => [],
|
|
'derived_composite_fields' => [],
|
|
'display_fields' => ['displayName', 'DisplayName', 'name', 'Name'],
|
|
'secondary_fields' => ['State', 'state', 'AutoAdmittedUsers', 'autoAdmittedUsers', 'source_metadata.source_contract_key', 'source_metadata.source_version'],
|
|
'requires_provider_connection_scope' => true,
|
|
'allows_derived_identity' => false,
|
|
'allows_experimental_identity' => false,
|
|
'derived_claims_allowed' => false,
|
|
'stable_key_kind' => 'tcm_resource_identifier',
|
|
],
|
|
'notificationMessageTemplate' => [
|
|
'strategy_identifier' => 'graph.notification_message_template.v1',
|
|
'preferred_identity_fields' => ['id', 'templateId', 'sourceId'],
|
|
'fallback_identity_fields' => ['notificationMessageTemplateId', 'sourceKey'],
|
|
'source_composite_fields' => ['brandingOptions', 'source_metadata.source_contract_key'],
|
|
'derived_composite_fields' => ['source_metadata.source_contract_key', 'source_metadata.source_version'],
|
|
'display_fields' => ['displayName', 'name'],
|
|
'secondary_fields' => ['brandingOptions', 'source_metadata.source_contract_key', 'source_metadata.source_version'],
|
|
'requires_provider_connection_scope' => true,
|
|
'allows_derived_identity' => true,
|
|
'allows_experimental_identity' => false,
|
|
'derived_claims_allowed' => false,
|
|
],
|
|
'roleScopeTag' => [
|
|
'strategy_identifier' => 'graph_beta.role_scope_tag.v1',
|
|
'preferred_identity_fields' => ['id', 'roleScopeTagId', 'sourceId'],
|
|
'fallback_identity_fields' => ['sourceKey'],
|
|
'source_composite_fields' => ['source_metadata.source_contract_key', 'source_metadata.source_version'],
|
|
'derived_composite_fields' => ['source_metadata.source_contract_key', 'source_metadata.source_version'],
|
|
'display_fields' => ['displayName', 'name'],
|
|
'secondary_fields' => ['description', 'source_metadata.source_contract_key', 'source_metadata.source_version'],
|
|
'requires_provider_connection_scope' => true,
|
|
'allows_derived_identity' => true,
|
|
'allows_experimental_identity' => true,
|
|
'derived_claims_allowed' => false,
|
|
],
|
|
];
|
|
|
|
/**
|
|
* @return array<string, array<string, mixed>>
|
|
*/
|
|
public function strategies(): array
|
|
{
|
|
return self::STRATEGIES;
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
public function strategyFor(TenantConfigurationResourceType|string $resourceType): array
|
|
{
|
|
$canonicalType = $resourceType instanceof TenantConfigurationResourceType
|
|
? (string) $resourceType->canonical_type
|
|
: $resourceType;
|
|
|
|
$sourceClass = $resourceType instanceof TenantConfigurationResourceType
|
|
? $this->sourceClassValue($resourceType->source_class)
|
|
: null;
|
|
|
|
$strategy = self::STRATEGIES[$canonicalType] ?? null;
|
|
|
|
if ($strategy === null) {
|
|
return [
|
|
'strategy_identifier' => 'unsupported.'.$canonicalType,
|
|
'canonical_type' => $canonicalType,
|
|
'source_class' => $sourceClass,
|
|
'preferred_identity_fields' => [],
|
|
'fallback_identity_fields' => [],
|
|
'source_composite_fields' => [],
|
|
'derived_composite_fields' => [],
|
|
'display_fields' => ['displayName', 'name'],
|
|
'secondary_fields' => [],
|
|
'requires_provider_connection_scope' => true,
|
|
'allows_derived_identity' => false,
|
|
'allows_experimental_identity' => false,
|
|
'derived_claims_allowed' => false,
|
|
'supported' => false,
|
|
];
|
|
}
|
|
|
|
return [
|
|
...$strategy,
|
|
'canonical_type' => $canonicalType,
|
|
'source_class' => $sourceClass,
|
|
'supported' => true,
|
|
];
|
|
}
|
|
|
|
private function sourceClassValue(mixed $sourceClass): ?string
|
|
{
|
|
if ($sourceClass instanceof SourceClass) {
|
|
return $sourceClass->value;
|
|
}
|
|
|
|
if (is_scalar($sourceClass)) {
|
|
$sourceClass = trim((string) $sourceClass);
|
|
|
|
return $sourceClass !== '' ? $sourceClass : null;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|