Public/Update-GuacUser.ps1
|
function Update-GuacUser { <# .SYNOPSIS Updates an existing Guacamole user. .DESCRIPTION Two mutation modes, exactly one of which must be supplied: - -Patch (the canonical form): a JSON Patch operations array applied via the collection PATCH endpoint (DirectoryResource.patchObjects). A single operation or an array of operations is accepted. Supported operations: add (create), replace (update, path "/{username}"), and remove (path "/{username}"). - -Replace: a replacement of the user via DirectoryObjectResource.updateObject (PUT /users/{username}). User update semantics differ from connections and groups: the server translator (UserObjectTranslator.applyExternalChanges) updates the password only when one is present in the body (a body without a "password" leaves the existing password unchanged), and replaces the "disabled" and "attributes" fields. The username is the user's identifier and cannot be changed through this endpoint; to rename a user, create a new one and remove the old. As with all Update-* cmdlets, omitted fields have a defined effect: here, omitting "password" preserves it, while "disabled" and "attributes" are replaced (an omitted "attributes" map is nulled). The target user is addressed by -Id (a username), or by piping a user object (as returned by Get-GuacUser) into the cmdlet (bound to -InputObject); the piped object's Identifier is used when -Id is not given. -Id takes precedence over the piped identifier. A user may not change their own password through this endpoint; the server rejects it (UserResource.updateObject). Use Set-GuacUserPassword for that case. Reference (Apache Guacamole 1.6.0): - guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryResource.java (patchObjects: @PATCH with List<APIPatch<ExternalType>>) - guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryObjectResource.java (updateObject: @PUT) - guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java (updateObject override: self password change is rejected) - guacamole/src/main/java/org/apache/guacamole/rest/user/UserObjectTranslator.java (applyExternalChanges: password conditional; disabled, attributes replaced) - guacamole/src/main/java/org/apache/guacamole/rest/user/APIUser.java .EXAMPLE $user = Get-GuacUser -Id 'jdoe' $user.Disabled = $true Update-GuacUser -Id 'jdoe' -Replace $user .EXAMPLE Update-GuacUser -Id 'jdoe' -Patch ( @{ op = 'replace'; path = '/jdoe'; value = $fullUser } ) .EXAMPLE Update-GuacUser -Id 'jdoe' -Replace @{ disabled = $false attributes = @{ 'guac-email-address' = 'jdoe@example.com' } } #> [CmdletBinding(SupportsShouldProcess = $true)] [OutputType([PSCustomObject])] param ( [Parameter(Mandatory = $false)] [AllowNull()] [N2C_GuacAdmin_GuacSession] $Session, [Parameter(Mandatory = $false)] [AllowEmptyString()] [string] $Server = [string]::Empty, [Parameter(Mandatory = $false)] [AllowEmptyString()] [string] $DataSource = [string]::Empty, [Parameter(Mandatory = $false, Position = 0)] [AllowEmptyString()] [string] $Id = [string]::Empty, [Parameter(Mandatory = $false)] [AllowNull()] [object] $Patch, [Parameter(Mandatory = $false)] [AllowNull()] [object] $Replace, [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [AllowNull()] [object] $InputObject ) begin { $pendingId = [string]::Empty } process { if ($null -ne $InputObject) { $pendingId = Get-GuacIdentifier -Object $InputObject # DataSource resolution priority: explicit param > piped object > session default if ([string]::IsNullOrWhiteSpace($DataSource)) { $pipedDs = Get-GuacDataSourceFromObject -Object $InputObject if (-not [string]::IsNullOrWhiteSpace($pipedDs)) { $DataSource = $pipedDs } } } } end { $hasPatch = ($null -ne $Patch) $hasReplace = ($null -ne $Replace) if ($hasPatch -and $hasReplace) { throw ($script:GuacRestExceptionType::new( 'Update-GuacUser: supply exactly one of -Patch or -Replace, not both.' )) } if (-not $hasPatch -and -not $hasReplace) { throw ($script:GuacRestExceptionType::new( 'Update-GuacUser: supply -Patch (a JSON Patch operations array) or -Replace (a user object), or pipe a user object with one of them.' )) } $targetId = $Id if ([string]::IsNullOrWhiteSpace($targetId)) { $targetId = $pendingId } if ($hasReplace -and [string]::IsNullOrWhiteSpace($targetId)) { throw ($script:GuacRestExceptionType::new( 'Update-GuacUser -Replace requires the username: supply -Id or pipe a user object carrying an Identifier.' )) } $ctx = Resolve-GuacSessionContext -Session $Session -Server $Server -DataSource $DataSource -CmdletName 'Update-GuacUser' if ($hasPatch) { if (-not [string]::IsNullOrWhiteSpace($targetId)) { $whatIfTarget = ('user {0}' -f $targetId) } else { $whatIfTarget = 'user (patch)' } if (-not ($PSCmdlet.ShouldProcess($whatIfTarget, 'Update Guacamole user (PATCH users)'))) { return } Invoke-GuacEntityPatch -Context $ctx -Collection 'users' ` -TargetLabel ('user {0}' -f $targetId) -Patch $Patch | Out-Null return } # Replacement via PUT. The username is the identifier and is not part # of the mutable body; drop it so it cannot be "changed". $body = ConvertTo-GuacEntityBody -Object $Replace -ExcludeProperty @('identifier', 'Identifier', 'username', 'lastActive') if (-not ($PSCmdlet.ShouldProcess(('user {0}' -f $targetId), 'Replace Guacamole user (PUT users/{username})'))) { return } return (Invoke-GuacDirectory -Context $ctx -Collection 'users' -Action 'Update' -Id $targetId -Body $body) } } |