Public/Get-ConnectorSyncSessionOperation.ps1
|
<# .SYNOPSIS Generates Create, Update, and Delete operations by comparing the sync session objects to existing API data. .DESCRIPTION Fetches the current connector objects from the API and compares them against the objects accumulated in the active sync session (via Add-ConnectorSyncSessionObject). Emits Build-ConnectorOperation hashtables for each required change: - Create: objects present in the session but not in the API. - Update: objects present in both but with differing Data payloads. - Delete: objects present in the API but not in the session. The resulting operations can be piped directly to Complete-ConnectorSyncSessionOperation. .OUTPUTS System.Collections.Hashtable .EXAMPLE Get-ConnectorSyncSessionOperation | Complete-ConnectorSyncSessionOperation .EXAMPLE $ops = Get-ConnectorSyncSessionOperation $ops | Where-Object { $_.OperationType -eq "Delete" } | Complete-ConnectorSyncSessionOperation -WhatIf #> function Get-ConnectorSyncSessionOperation { [CmdletBinding()] param ( [Switch] $AllowEmptySession ) process { if ([String]::IsNullOrEmpty($Script:APIRoot)) { throw "Please connect first" } $GetExistingConnectorObjectsWebResult = Invoke-WebRequest -Uri "$($Script:APIRoot)data" -Headers (Get-EntraIDAccessTokenHeader -Profile $Script:AccessTokenProfile) -Method Get -SkipHttpErrorCheck if ($GetExistingConnectorObjectsWebResult.StatusCode -ge 400) { throw "Unable to get connector objects. HTTP Status: $($GetExistingConnectorObjectsWebResult.StatusCode). Response: $($GetExistingConnectorObjectsWebResult.Content)" } $GetExistingConnectorObjectsResult = $GetExistingConnectorObjectsWebResult.Content | ConvertFrom-Json -AsHashtable -Depth 20 if (!$GetExistingConnectorObjectsResult.isSuccess) { throw "Unable to get connector objects" } $ExistingConnectorObjects = @{} if ($GetExistingConnectorObjectsResult.data) { $GetExistingConnectorObjectsResult.data | ForEach-Object { $ExistingConnectorObjects[$_.externalId] = $_ } } Write-Verbose "Found $($ExistingConnectorObjects.Count) existing objects" if ($Script:SyncSessionObjects.Count -gt 0) { $Script:SyncSessionObjects.GetEnumerator() | ForEach-Object { if ($ExistingConnectorObjects.ContainsKey($_.Key)) { Write-Debug "Object $($_.Key) already exists, checking for diff" $ExistingConnectorObject = $ExistingConnectorObjects[$_.Key] # FUNKY JSON WORKAROUND FOR HANDLING FLOATING POINT PRECISION AND OTHER JSON SERIALIZATION INCONSISTENCIES: $ExistingJSONstep1 = ($ExistingConnectorObject.data | ConvertTo-Json -Compress -Depth 20 | ConvertFrom-Json -Depth 20 | ConvertTo-Json -Compress -Depth 20).Replace(".0,", ",").Replace(".0}", "}") $ExistingJSON = $ExistingJSONstep1.ToCharArray() $SyncJSONstep1 = ($_.Value.data | ConvertTo-Json -Depth 20 -Compress | ConvertFrom-Json -Depth 20 | ConvertTo-Json -Compress -Depth 20).Replace(".0,", ",").Replace(".0}", "}") $SyncJSON = $SyncJSONstep1.ToCharArray() $IsDifferent = $ExistingJSON.Length -ne $SyncJSON.Length if (!$IsDifferent) { Write-Debug "Length is the same ($($ExistingJSON.Length) and $($SyncJSON.Length)), doing character comparison using the 'JSON to char array and sort method'" $IsDifferent = (($SyncJSON | Sort-Object) -join "") -cne (($ExistingJSON | Sort-Object) -join "") } if ($IsDifferent) { Write-Debug "Object $($_.Key) is different, emitting update operation" Write-Debug " EXISTING: $ExistingJSONstep1" Write-Debug " NEW: $SyncJSONstep1" Build-ConnectorOperation -OperationType Update -ConnectorObject $_.Value -Id $ExistingConnectorObject.id } else { Write-Debug "Object $($_.Key) is identical, skipping" } } else { Write-Debug "Object $($_.Key) is new, emitting create operation" Build-ConnectorOperation -OperationType Create -ConnectorObject $_.Value } } } else { if (-not $AllowEmptySession) { throw "No objects in sync session. Use -AllowEmptySession to emit delete operations for all existing objects." } } $ExistingConnectorObjects.GetEnumerator() | ForEach-Object { if (-not $Script:SyncSessionObjects.ContainsKey($_.Key)) { Build-ConnectorOperation -OperationType Delete -ConnectorObject $_.Value -Id $_.Value.id } } } } |