Private/ConvertTo-WindowsDeviceLinkTenantCatalog.ps1
|
function ConvertTo-WindowsDeviceLinkTenantCatalog { [CmdletBinding()] param( [Parameter(Mandatory)][ValidateNotNull()][object]$InputObject, [Parameter(Mandatory)][ValidateNotNullOrEmpty()][string]$Source ) function Assert-Fields { param($Object,[string[]]$Allowed,[string]$Location) if ($Object -isnot [pscustomobject]) { throw "$Location must be a JSON object." } foreach ($field in $Object.PSObject.Properties.Name) { if ($field -cnotin $Allowed) { throw "$Location contains an unsupported field. Only $($Allowed -join ', ') are allowed; do not include secrets." } } } function Get-ConfigurationGuid { param($Value,[string]$Field) $parsed = [guid]::Empty if ($Value -isnot [string] -or -not [guid]::TryParse($Value,[ref]$parsed) -or $parsed -eq [guid]::Empty) { throw "$Field must be a non-empty GUID string." } $parsed.ToString().ToLowerInvariant() } Assert-Fields $InputObject @('schemaVersion','mode','clientId','tenants') 'Configuration' if ($InputObject.schemaVersion -isnot [int] -and $InputObject.schemaVersion -isnot [long]) { throw 'schemaVersion must be the integer 1.' } if ($InputObject.schemaVersion -ne 1) { throw 'Unsupported configuration schemaVersion. Expected 1.' } if ($InputObject.mode -isnot [string] -or $InputObject.mode -cne 'Direct') { throw 'Configuration mode must be Direct. Backend obtains its catalog from the API.' } if ($InputObject.tenants -isnot [array] -or $InputObject.tenants.Count -eq 0) { throw 'tenants must be a non-empty JSON array.' } $sharedClientId = $null if ('clientId' -in $InputObject.PSObject.Properties.Name) { $sharedClientId = Get-ConfigurationGuid $InputObject.clientId 'clientId' } $seenNames = @{} $seenIds = @{} $entries = foreach ($tenant in $InputObject.tenants) { Assert-Fields $tenant @('name','tenantId','clientId') 'Tenant entry' if ($tenant.name -isnot [string] -or [string]::IsNullOrWhiteSpace($tenant.name) -or $tenant.name.Trim().Length -gt 128 -or $tenant.name -match '[\x00-\x1f\x7f]') { throw 'Each tenant name must contain 1 to 128 characters without control characters.' } $name = $tenant.name.Trim() $id = Get-ConfigurationGuid $tenant.tenantId 'tenantId' if ($seenNames.ContainsKey($name)) { throw 'Tenant names must be unique (case-insensitive).' } if ($seenIds.ContainsKey($id)) { throw 'Tenant IDs must be unique.' } $seenNames[$name] = $true $seenIds[$id] = $true $clientId = $sharedClientId if ('clientId' -in $tenant.PSObject.Properties.Name) { $clientId = Get-ConfigurationGuid $tenant.clientId 'Tenant clientId' } [pscustomobject]@{ PSTypeName='Windows.DeviceLink.TenantCatalogEntry' Name=$name TenantId=$id ClientId=$clientId Source=$Source OperationMode='Direct' Enabled=$true Capabilities=@('Lookup','Register') } } $entries | Sort-Object Name } |