Public/DataFlow/Get-JIMDataFlow.ps1
|
# Copyright (c) Tetron Limited. All rights reserved. # Licensed under the Tetron Commercial License. See LICENSE file in the project root. function Get-JIMDataFlow { <# .SYNOPSIS Gets attribute data flows from JIM. .DESCRIPTION Retrieves a system-wide map of every attribute data flow, in both directions: what contributes each Metaverse Attribute, and what each Connected System attribute is written from. One flow per Synchronisation Rule Attribute Flow mapping. An Import flow reads Connected System attributes and writes a single Metaverse Attribute, so it carries a priority and a "Null is a value" flag. An Export flow reads Metaverse Attributes and writes a single Connected System attribute, so it carries the owning rule's Enforce State. The properties that do not apply to a flow's direction are null rather than defaulted, so you never have to guess which are meaningful. Import flows also carry contributorCount: how many flows contribute to the same Metaverse Attribute, counted across the whole configuration rather than the filtered results, so filtering to one Connected System does not make a shared attribute look like a sole contributor. The filters combine with AND. -SyncRuleName narrows whatever the other filters left, so removing it returns those results. .PARAMETER Direction Only flows in this direction: Import for flows into the Metaverse, Export for flows out of it. Both when omitted. .PARAMETER ConnectedSystemId Only flows on this Connected System. .PARAMETER ConnectedSystemName Only flows on the Connected System with exactly this name. .PARAMETER InputObject A Connected System from the pipeline, for example from Get-JIMConnectedSystem. Its Id filters the flows, as -ConnectedSystemId would. .PARAMETER MetaverseObjectTypeId Only flows on this Metaverse Object Type. .PARAMETER ConnectedSystemObjectTypeId Only flows on this Connected System Object Type. .PARAMETER MetaverseAttributeId Only flows that read or write this Metaverse Attribute, whichever side it sits on. A flow whose Metaverse side is an expression cannot match, because an expression's attribute references live in its text; use -Search for those. .PARAMETER ConnectedSystemAttributeId Only flows that read or write this Connected System attribute, with the same expression limitation as -MetaverseAttributeId. .PARAMETER MultipleContributorsOnly Only Import flows whose target Metaverse Attribute has more than one contributor: the flows whose priority order decides anything. .PARAMETER Search Text matched, ignoring case, against the Synchronisation Rule, the Connected System, both object types, every attribute named on either side, and expression text. .PARAMETER SyncRuleName Only flows on Synchronisation Rules with this name, applied after the other filters. .OUTPUTS One object per flow. The cmdlet pages through the whole result set itself. .EXAMPLE Get-JIMDataFlow Gets every attribute data flow, in both directions. .EXAMPLE Get-JIMDataFlow -Direction Import -MultipleContributorsOnly Gets the inbound flows whose target Metaverse Attribute has more than one contributor: the attributes whose priority order decides which value wins. .EXAMPLE Get-JIMDataFlow -Search 'department' Answers "what touches department?" across both directions, including any expression that mentions it. .EXAMPLE Get-JIMDataFlow -ConnectedSystemName 'Contoso AD' -Direction Export Answers "what does JIM write to Contoso AD, and from where?". .EXAMPLE Get-JIMDataFlow -Direction Import | Where-Object { $_.nullIsValue } | Select-Object targetMetaverseAttributeName, syncRuleName, priority Lists every contribution that asserts an authoritative "no value", which is the setting most worth reviewing deliberately. .EXAMPLE Get-JIMConnectedSystem -Name "HR*" | Get-JIMDataFlow Gets the flows for Connected Systems with names starting with "HR". .LINK Get-JIMSyncRule Get-JIMSyncRuleMapping Get-JIMMetaverseAttributePriority #> [CmdletBinding(DefaultParameterSetName = 'List')] [OutputType('JIM.DataFlowHeader')] param( [Parameter(ParameterSetName = 'List')] [Parameter(ParameterSetName = 'ByConnectedSystemName')] [ValidateSet('Import', 'Export')] [string]$Direction, [Parameter(ParameterSetName = 'List', ValueFromPipelineByPropertyName)] [int]$ConnectedSystemId, [Parameter(Mandatory, ParameterSetName = 'ByConnectedSystemName')] [string]$ConnectedSystemName, # A Connected System object (e.g. from Get-JIMConnectedSystem) exposes Id, not # ConnectedSystemId, so it cannot bind to -ConnectedSystemId by property name. Binding the # whole object here and reading its Id below is the fix, the same shape and reasoning as # Get-JIMSyncRule. [Parameter(ParameterSetName = 'List', ValueFromPipeline)] [PSCustomObject]$InputObject, [Parameter(ParameterSetName = 'List')] [Parameter(ParameterSetName = 'ByConnectedSystemName')] [int]$MetaverseObjectTypeId, [Parameter(ParameterSetName = 'List')] [Parameter(ParameterSetName = 'ByConnectedSystemName')] [int]$ConnectedSystemObjectTypeId, [Parameter(ParameterSetName = 'List')] [Parameter(ParameterSetName = 'ByConnectedSystemName')] [int]$MetaverseAttributeId, [Parameter(ParameterSetName = 'List')] [Parameter(ParameterSetName = 'ByConnectedSystemName')] [int]$ConnectedSystemAttributeId, [Parameter(ParameterSetName = 'List')] [Parameter(ParameterSetName = 'ByConnectedSystemName')] [switch]$MultipleContributorsOnly, [Parameter(ParameterSetName = 'List')] [Parameter(ParameterSetName = 'ByConnectedSystemName')] [string]$Search, [Parameter(ParameterSetName = 'List')] [Parameter(ParameterSetName = 'ByConnectedSystemName')] [SupportsWildcards()] [string]$SyncRuleName ) process { # Check connection first if (-not $script:JIMConnection) { Write-Error "You are not connected to JIM. Run Connect-JIM -Url <your JIM URL> to authenticate, then try again." return } # Resolve ConnectedSystemName to ConnectedSystemId if specified if ($PSBoundParameters.ContainsKey('ConnectedSystemName')) { $connectedSystem = Resolve-JIMConnectedSystem -Name $ConnectedSystemName $ConnectedSystemId = $connectedSystem.id } # -ConnectedSystemId (direct or bound by property name) takes precedence; otherwise fall # back to the piped Connected System object's Id (see -InputObject above). $filterByConnectedSystem = $ConnectedSystemId -gt 0 if (-not $filterByConnectedSystem -and $InputObject -and $InputObject.PSObject.Properties['Id']) { $ConnectedSystemId = [int]$InputObject.Id $filterByConnectedSystem = $ConnectedSystemId -gt 0 } # The filters are evaluated by the API, so this cmdlet and the portal's Data Flow page return # the same flows for the same filters. -SyncRuleName stays client-side because it supports # PowerShell wildcards. $baseQueryParams = @('pageSize=100') if ($Direction) { $baseQueryParams += "direction=$Direction" } if ($filterByConnectedSystem) { $baseQueryParams += "connectedSystemId=$ConnectedSystemId" } if ($MetaverseObjectTypeId -gt 0) { $baseQueryParams += "metaverseObjectTypeId=$MetaverseObjectTypeId" } if ($ConnectedSystemObjectTypeId -gt 0) { $baseQueryParams += "connectedSystemObjectTypeId=$ConnectedSystemObjectTypeId" } if ($MetaverseAttributeId -gt 0) { $baseQueryParams += "metaverseAttributeId=$MetaverseAttributeId" } if ($ConnectedSystemAttributeId -gt 0) { $baseQueryParams += "connectedSystemAttributeId=$ConnectedSystemAttributeId" } if ($MultipleContributorsOnly) { $baseQueryParams += 'multipleContributorsOnly=true' } if ($Search) { $baseQueryParams += "search=$([System.Uri]::EscapeDataString($Search))" } Write-Verbose "Getting attribute data flows" # Page through the whole result set. Data flows are configuration rather than object data, so # the set is small, but stopping at the first page would silently truncate the map and make # the filters look as though they had excluded flows they did not. $currentPage = 1 $pagesFetched = 0 do { $queryString = (@("page=$currentPage") + $baseQueryParams) -join '&' $response = Invoke-JIMApi -Endpoint "/api/v1/synchronisation/data-flows?$queryString" $pagesFetched++ # Handle paginated response - check if 'items' property exists (not if it's truthy) $flows = if ($null -ne $response.items) { $response.items } else { $response } # Output each flow individually for pipeline support foreach ($flow in $flows) { if (-not $SyncRuleName -or $flow.syncRuleName -like $SyncRuleName) { $flow } } $hasMore = $response.hasNextPage -eq $true if ($hasMore -and $pagesFetched -ge $script:JIMMaxAllPages) { Write-Warning "Get-JIMDataFlow stopped after $script:JIMMaxAllPages pages; more results remain (total pages: $($response.totalPages)). Narrow the query with -Direction, -ConnectedSystemId, -MetaverseObjectTypeId or -Search." break } if ($hasMore) { $currentPage++ Write-Verbose "Fetching page $currentPage of $($response.totalPages)..." } } while ($hasMore) } } |