Public/ConnectedSystems/Set-JIMConnectedSystemAttribute.ps1
|
# Copyright (c) Tetron Limited. All rights reserved. # Licensed under the Tetron Commercial License. See LICENSE file in the project root. function Set-JIMConnectedSystemAttribute { <# .SYNOPSIS Changes attributes of a Connected System Object Type. .DESCRIPTION Changes one attribute, or in bulk several at once with -AttributeUpdates: whether JIM manages it, whether it identifies objects, whether its values are case-exact, the step of time a date is held to, and where the Connector allows it, its data type and whether it holds one value or several. .PARAMETER ConnectedSystemId The ID of the Connected System. .PARAMETER ObjectTypeId The ID of the Object Type the attributes belong to. .PARAMETER AttributeId The ID of the attribute to change. .PARAMETER AttributeUpdates The attributes to change, as a hashtable keyed by attribute ID whose values are hashtables of the settings to change (selected, isExternalId, isSecondaryExternalId, caseExact, dateTimeResolution); the examples show one. .PARAMETER Selected Whether JIM imports and exports the attribute. .PARAMETER IsExternalId Whether the attribute uniquely and permanently identifies an object of this type, such as objectGUID or an employee ID. .PARAMETER IsSecondaryExternalId Whether the Connected System also identifies an object by the attribute, as an LDAP directory does by distinguished name. .PARAMETER Type Replaces the data type inferred from the schema. Accepted only where the Connector says its schema cannot state a type for certain: a delimited file names no types, and Oracle has one numeric type, so a NUMBER column may be a whole number, a counter or a fractional figure. Refused once a Synchronisation Rule uses the attribute or it holds values. Integer is the Number data type, as in New-JIMMetaverseAttribute. A Boolean holds one value, so Boolean also makes the attribute single-valued. Cannot be set with -AttributeUpdates. .PARAMETER Plurality Whether the attribute holds one value or several. Accepted only where the Connector cannot read it from the Connected System's schema: a delimited file's header names columns and nothing more, so its columns are discovered single-valued, and a MultiValued column holds its values separated by the Multi-Value Delimiter. Setting it makes the plurality the administrator's, so a schema refresh keeps it. Refused once a Synchronisation Rule uses the attribute or it holds values, and for a Boolean, which holds one value. Cannot be set with -AttributeUpdates. .PARAMETER CaseExact Whether the attribute's values are case-exact: $true when values differing only in case identify different things, $false when they are the same value. Only a Text attribute can be declared case-exact. Setting it makes the declaration the administrator's, so a schema refresh keeps it. Offered on every Connector. .PARAMETER DateTimeResolution The finest step of time the Connected System holds this DateTime attribute's values to. JIM sends each date floored to it and compares at it, so a difference the Connected System cannot hold is never exported again and again. Discovered by the Connector (Second for Active Directory and SCIM, a SQL column's own precision); setting it makes the resolution the administrator's, so a schema refresh keeps it. Only a DateTime attribute has one. .PARAMETER PassThru Returns the attribute as changed, or with -AttributeUpdates, the outcome of the change. .OUTPUTS With -PassThru, the attribute as changed, or with -AttributeUpdates, what was changed and what failed; otherwise nothing. An attribute -AttributeUpdates could not change is written to the warning stream. .EXAMPLE Set-JIMConnectedSystemAttribute -ConnectedSystemId 1 -ObjectTypeId 5 -AttributeId 10 -Selected $true Marks a single attribute as selected for management by JIM. .EXAMPLE Set-JIMConnectedSystemAttribute -ConnectedSystemId 1 -ObjectTypeId 5 -AttributeId 10 -IsExternalId $true Marks an attribute as the primary external identifier. .EXAMPLE Set-JIMConnectedSystemAttribute -ConnectedSystemId 1 -ObjectTypeId 5 -AttributeId 15 -IsSecondaryExternalId $true -PassThru Marks an attribute as a secondary identifier (e.g., DN) and returns the updated object. .EXAMPLE $updates = @{ 10 = @{ selected = $true } 11 = @{ selected = $true } 12 = @{ selected = $true; isExternalId = $true } } Set-JIMConnectedSystemAttribute -ConnectedSystemId 1 -ObjectTypeId 5 -AttributeUpdates $updates Bulk updates multiple attributes in a single operation, creating only one Activity record. .EXAMPLE # Get all attributes and select them all in one operation $cs = Get-JIMConnectedSystem -Id 1 $objectType = $cs.objectTypes | Where-Object { $_.name -eq 'user' } $updates = @{} foreach ($attr in $objectType.attributes) { $updates[$attr.id] = @{ selected = $true } } Set-JIMConnectedSystemAttribute -ConnectedSystemId 1 -ObjectTypeId $objectType.id -AttributeUpdates $updates -PassThru Selects all attributes on an object type using the bulk update API. .EXAMPLE Set-JIMConnectedSystemAttribute -ConnectedSystemId 1 -ObjectTypeId 5 -AttributeId 10 -Type Integer Corrects an Oracle NUMBER column that schema discovery read as a Decimal, so it can flow into a built-in whole-number Metaverse Attribute such as Employee Number without an expression. .EXAMPLE Set-JIMConnectedSystemAttribute -ConnectedSystemId 2 -ObjectTypeId 6 -AttributeId 30 -Plurality MultiValued Tells JIM that a delimited file's member column holds several values, separated by the Multi-Value Delimiter, so an import reads each one and an export writes the whole set. .EXAMPLE Set-JIMConnectedSystemAttribute -ConnectedSystemId 1 -ObjectTypeId 5 -AttributeId 12 -CaseExact $true Declares that an attribute's values are case-exact, so JBloggs and jbloggs are different values. A schema refresh keeps this declaration rather than restating what the Connected System's schema says. .EXAMPLE Set-JIMConnectedSystemAttribute -ConnectedSystemId 3 -ObjectTypeId 8 -AttributeId 41 -DateTimeResolution Millisecond Tells JIM that a SCIM service provider keeps this date attribute's milliseconds, so JIM sends them rather than the whole seconds SCIM discovery assumes. .LINK Get-JIMConnectedSystem Set-JIMConnectedSystemObjectType #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium', DefaultParameterSetName = 'Single')] [OutputType('JIM.ConnectedSystemAttributeDto', ParameterSetName = 'Single')] [OutputType('JIM.BulkUpdateConnectedSystemAttributesResponse', ParameterSetName = 'Bulk')] param( [Parameter(Mandatory, ParameterSetName = 'Single')] [Parameter(Mandatory, ParameterSetName = 'Bulk')] [int]$ConnectedSystemId, [Parameter(Mandatory, ParameterSetName = 'Single')] [Parameter(Mandatory, ParameterSetName = 'Bulk')] [int]$ObjectTypeId, [Parameter(Mandatory, ParameterSetName = 'Single', ValueFromPipelineByPropertyName)] [Alias('Id')] [int]$AttributeId, [Parameter(Mandatory, ParameterSetName = 'Bulk')] [hashtable]$AttributeUpdates, [Parameter(ParameterSetName = 'Single')] [bool]$Selected, [Parameter(ParameterSetName = 'Single')] [bool]$IsExternalId, [Parameter(ParameterSetName = 'Single')] [bool]$IsSecondaryExternalId, [Parameter(ParameterSetName = 'Single')] [ValidateSet('Text', 'Integer', 'LongNumber', 'Decimal', 'DateTime', 'Boolean', 'Reference', 'Guid', 'Binary')] [string]$Type, [Parameter(ParameterSetName = 'Single')] [ValidateSet('SingleValued', 'MultiValued')] [string]$Plurality, [Parameter(ParameterSetName = 'Single')] [bool]$CaseExact, [Parameter(ParameterSetName = 'Single')] [ValidateSet('Microsecond', 'TenMicroseconds', 'HundredMicroseconds', 'Millisecond', 'TenMilliseconds', 'HundredMilliseconds', 'Second', 'Minute', 'Day')] [string]$DateTimeResolution, [switch]$PassThru ) 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 } if ($PSCmdlet.ParameterSetName -eq 'Bulk') { # Bulk update mode if ($AttributeUpdates.Count -eq 0) { Write-Warning "No attribute updates specified." return } if ($PSCmdlet.ShouldProcess("$($AttributeUpdates.Count) attributes in Object Type $ObjectTypeId", "Bulk Update")) { Write-Verbose "Bulk updating $($AttributeUpdates.Count) attributes in Object Type: $ObjectTypeId" try { # Convert the hashtable to use string keys for JSON serialization # PowerShell's ConvertTo-Json doesn't support integer keys in hashtables $attributesWithStringKeys = @{} foreach ($key in $AttributeUpdates.Keys) { $attributesWithStringKeys[[string]$key] = $AttributeUpdates[$key] } $body = @{ attributes = $attributesWithStringKeys } $result = Invoke-JIMApi -Endpoint "/api/v1/synchronisation/connected-systems/$ConnectedSystemId/object-types/$ObjectTypeId/attributes" -Method 'PUT' -Body $body Write-Verbose "Bulk update completed: $($result.updatedCount) attributes updated" if ($result.errors) { foreach ($updateError in $result.errors) { Write-Warning "Failed to update attribute $($updateError.attributeId): $($updateError.errorMessage)" } } if ($PassThru) { $result } } catch { Write-Error "Failed to bulk update attributes: $_" } } } else { # Single attribute update mode (existing behaviour) $body = @{} if ($PSBoundParameters.ContainsKey('Selected')) { $body.selected = $Selected } if ($PSBoundParameters.ContainsKey('IsExternalId')) { $body.isExternalId = $IsExternalId } if ($PSBoundParameters.ContainsKey('IsSecondaryExternalId')) { $body.isSecondaryExternalId = $IsSecondaryExternalId } if ($PSBoundParameters.ContainsKey('Type')) { # The ValidateSet exposes 'Integer' as a friendly alias for the AttributeDataType member # 'Number'; the API takes the enum member name. $body.type = if ($Type -eq 'Integer') { 'Number' } else { $Type } } if ($PSBoundParameters.ContainsKey('Plurality')) { $body.plurality = $Plurality } if ($PSBoundParameters.ContainsKey('CaseExact')) { $body.caseExact = $CaseExact } if ($PSBoundParameters.ContainsKey('DateTimeResolution')) { $body.dateTimeResolution = $DateTimeResolution } if ($body.Count -eq 0) { Write-Warning "No updates specified." return } if ($PSCmdlet.ShouldProcess("Attribute $AttributeId in Object Type $ObjectTypeId", "Update")) { Write-Verbose "Updating Attribute: $AttributeId in Object Type: $ObjectTypeId" try { $result = Invoke-JIMApi -Endpoint "/api/v1/synchronisation/connected-systems/$ConnectedSystemId/object-types/$ObjectTypeId/attributes/$AttributeId" -Method 'PUT' -Body $body Write-Verbose "Updated Attribute: $AttributeId" if ($PassThru) { $result } } catch { Write-Error "Failed to update Attribute: $_" } } } } } |