Public/History/Search-JIMMetaverseObjectChange.ps1
|
# Copyright (c) Tetron Limited. All rights reserved. # Licensed under the Tetron Commercial License. See LICENSE file in the project root. function Search-JIMMetaverseObjectChange { <# .SYNOPSIS Searches changes to Metaverse Objects across every object. .DESCRIPTION Finds changes to Metaverse Objects, newest first: by when they were made, by Metaverse Object Type, by display name, and by how named attributes changed, for example every Person whose Employee Status changed to Disabled this month. Changes to objects since deleted are included. Each changed attribute carries its first ten value changes and, in valueChangeTotal, how many there are; Get-JIMMetaverseObjectChangeValue gets the rest. Give one attribute condition with -Attribute, -Operator and -Value, or several with -Condition. With several, -MatchMode All (the default) requires every condition to be met by the same change, to one Metaverse Object in one Activity; -MatchMode Any requires one. Only changes JIM recorded can be found: none are recorded while Metaverse Object change tracking is turned off, and history retention removes older ones. .PARAMETER Attribute The name of the Metaverse Attribute whose changes to find. .PARAMETER Operator How the attribute changed. ChangedTo finds a value added (a single-valued attribute changed to it), ChangedFrom a value removed, and AnyChange either. .PARAMETER Value The value the attribute changed to or from. Leave it out to match any value. Text and Reference values match case-insensitively, a Reference value against the referenced Metaverse Object's display name, and * matches any run of characters. A date is yyyy-MM-dd, matching the whole day in UTC. .PARAMETER Condition Several attribute conditions, one hashtable each, with the keys Attribute (a name) or AttributeId, Operator (AnyChange when left out) and Value (any value when left out). At most ten. .PARAMETER MatchMode With several conditions, All requires every condition to be met by the same change; Any requires one. .PARAMETER ObjectTypeName Only changes to Metaverse Objects of the Metaverse Object Type with this name. .PARAMETER ObjectTypeId Only changes to Metaverse Objects of the Metaverse Object Type with this id. .PARAMETER DisplayName Only changes to Metaverse Objects whose display name contains this text. .PARAMETER FromDate Only changes made on or after this time. .PARAMETER ToDate Only changes made on or before this time. .PARAMETER All Returns every page of changes rather than one. It stops after 1,000 pages with a warning; -Force reads on. .PARAMETER Force With -All, reads every page, past the 1,000-page limit. .PARAMETER Page The page of changes to return, counting from 1. Ignored with -All. .PARAMETER PageSize How many changes each page holds. .OUTPUTS One object per change, newest first, with the attributes it changed and the values added and removed. .EXAMPLE Search-JIMMetaverseObjectChange -ObjectTypeName 'Person' -Attribute 'Employee Status' -Operator ChangedTo -Value 'Disabled' -FromDate (Get-Date).AddDays(-30) Finds every Person whose Employee Status changed to Disabled in the last 30 days. .EXAMPLE Search-JIMMetaverseObjectChange -Condition @( @{ Attribute = 'Employee Status'; Operator = 'ChangedTo'; Value = 'Disabled' }, @{ Attribute = 'Department'; Operator = 'ChangedTo'; Value = 'Leavers' } ) -All Finds every change that set Employee Status to Disabled and Department to Leavers at the same time. .EXAMPLE Search-JIMMetaverseObjectChange -Attribute 'Department' -Operator ChangedFrom -Value 'Fin*' -All | Select-Object ChangeTime, MetaverseObjectDisplayName Lists when each Metaverse Object moved out of a department starting with "Fin". .LINK Get-JIMMetaverseObjectChangeHistory .LINK Get-JIMMetaverseAttribute #> [CmdletBinding(DefaultParameterSetName = 'Attribute')] [OutputType('JIM.MetaverseObjectChangeSearchItem')] param( [Parameter(ParameterSetName = 'Attribute')] [ValidateNotNullOrEmpty()] [string]$Attribute, [Parameter(ParameterSetName = 'Attribute')] [ValidateSet('AnyChange', 'ChangedTo', 'ChangedFrom')] [string]$Operator = 'AnyChange', [Parameter(ParameterSetName = 'Attribute')] [string]$Value, [Parameter(Mandatory, ParameterSetName = 'Conditions')] [ValidateCount(1, 10)] [hashtable[]]$Condition, [Parameter()] [ValidateSet('All', 'Any')] [string]$MatchMode = 'All', [Parameter()] [ValidateNotNullOrEmpty()] [string]$ObjectTypeName, [Parameter()] [int]$ObjectTypeId, [Parameter()] [string]$DisplayName, [Parameter()] [DateTime]$FromDate, [Parameter()] [DateTime]$ToDate, [Parameter()] [switch]$All, [Parameter()] [switch]$Force, [Parameter()] [ValidateRange(1, [int]::MaxValue)] [int]$Page = 1, [Parameter()] [ValidateRange(1, 100)] [int]$PageSize = 25 ) process { 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 } $conditions = @() if ($PSCmdlet.ParameterSetName -eq 'Conditions') { foreach ($entry in $Condition) { if ($entry.ContainsKey('AttributeId')) { $attributeId = [int]$entry.AttributeId } elseif ($entry.ContainsKey('Attribute')) { $attributeId = (Resolve-JIMMetaverseAttribute -Name $entry.Attribute).id } else { Write-Error "Each -Condition entry needs an Attribute (a name) or an AttributeId." -ErrorAction Stop return } $conditions += @{ attributeId = $attributeId operator = if ($entry.ContainsKey('Operator')) { [string]$entry.Operator } else { 'AnyChange' } value = if ($entry.ContainsKey('Value')) { [string]$entry.Value } else { $null } } } } elseif ($PSBoundParameters.ContainsKey('Attribute')) { $conditions += @{ attributeId = (Resolve-JIMMetaverseAttribute -Name $Attribute).id operator = $Operator value = if ($PSBoundParameters.ContainsKey('Value')) { $Value } else { $null } } } $criteria = @{ conditions = $conditions matchMode = $MatchMode pageSize = $PageSize } if ($PSBoundParameters.ContainsKey('ObjectTypeName')) { $criteria.objectTypeId = (Resolve-JIMMetaverseObjectType -Name $ObjectTypeName).id } elseif ($PSBoundParameters.ContainsKey('ObjectTypeId')) { $criteria.objectTypeId = $ObjectTypeId } if ($PSBoundParameters.ContainsKey('DisplayName')) { $criteria.displayNameSearch = $DisplayName } if ($PSBoundParameters.ContainsKey('FromDate')) { $criteria.fromDate = $FromDate.ToUniversalTime().ToString('o') } if ($PSBoundParameters.ContainsKey('ToDate')) { $criteria.toDate = $ToDate.ToUniversalTime().ToString('o') } # The shared helper owns the -All loop, the page cap and the warnings; a single page is fetched directly. $pageRequest = { param($p) $body = $criteria.Clone() $body.page = $p Write-Verbose "Searching Metaverse Object changes (Page: $p, PageSize: $PageSize)" Invoke-JIMApi -Endpoint '/api/v1/history/metaverse-object-changes/search' -Method 'POST' -Body $body } if ($All) { Invoke-JIMPagedFetch -PageRequest $pageRequest -CmdletName 'Search-JIMMetaverseObjectChange' -PageSize $PageSize -Force:$Force ` -ItemNoun 'changes' } else { $response = & $pageRequest $Page foreach ($item in $response.items) { $item } } } } |