Functions/Accounts/Set-PASAccount.ps1

# .ExternalHelp psPAS-help.xml
function Set-PASAccount {
    [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = "Gen2SingleOp")]
    param(

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateNotNullOrEmpty()]
        [Alias("id")]
        [string]$AccountID,

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "Gen2SingleOp"
        )]
        [ValidateSet("add", "replace", "remove")]
        [Alias("Operation")]
        [string]$op,

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "Gen2SingleOp"
        )]
        [string]$path,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "Gen2SingleOp"
        )]
        [string]$value,

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "Gen2MultiOp"
        )]
        [hashtable[]]$operations,

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "Gen1"
        )]
        [string]$Folder,

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "Gen1"
        )]
        [Alias("Name")]
        [string]$AccountName,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "Gen1"
        )]
        [string]$DeviceType,

        [Alias("PolicyID")]
        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "Gen1"
        )]
        [string]$PlatformID,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "Gen1"
        )]
        [string]$Address,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "Gen1"
        )]
        [string]$UserName,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "Gen1"
        )]
        [string]$GroupName,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "Gen1"
        )]
        [string]$GroupPlatformID,

        [parameter(
            Mandatory = $false,
            ValueFromPipelineByPropertyName = $false,
            ParameterSetName = "Gen1"
        )]
        [hashtable]$Properties = @{ },

        [parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ParameterSetName = "Gen2SingleOp"
        )]
        [parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ParameterSetName = "Gen2MultiOp"
        )]
        [parameter(
            Mandatory = $false,
            ValueFromPipeline = $true,
            ParameterSetName = "Gen1"
        )]
        [PSObject]$InputObject
    )

    BEGIN {

    }#begin

    PROCESS {

        #Get all parameters that will be sent in the request
        $boundParameters = $PSBoundParameters | Get-PASParameter -ParametersToRemove InputObject, AccountID

        switch ($PSCmdlet.ParameterSetName) {

            { $PSItem -match "Gen2" } {

                Assert-VersionRequirement -RequiredVersion 10.4

                #Create URL for Request
                $URI = "$Script:BaseURI/api/Accounts/$AccountID"

                #Define method for request
                $Method = "PATCH"

                #Define type of output object
                $Type = "psPAS.CyberArk.Vault.Account.V10"

                if ($PSCmdlet.ParameterSetName -match "Gen2MultiOp") {

                    $boundParameters = $boundParameters["operations"]

                }

                #Do Not Pipe into ConvertTo-JSON.
                #Correct JSON Format is only achieved when the array is not sent along the pipe
                $body = ConvertTo-Json @($boundParameters)

            }

            "Gen1" {

                #Create URL for Request
                $URI = "$Script:BaseURI/WebServices/PIMServices.svc/Accounts/$AccountID"

                #Define method for request
                $Method = "PUT"

                #Define type of output object
                $Type = "psPAS.CyberArk.Vault.Account"

                if ($PSBoundParameters.ContainsKey("Properties")) {

                    #Format "Properties" parameter value.
                    #Array of key=value pairs required for JSON convertion
                    $boundParameters["Properties"] = [Collections.Generic.List[String]]@($boundParameters["Properties"].getenumerator() |

                            ForEach-Object { $_ })

                }

                If (($InputObject) -and (($InputObject | Get-Member).TypeName -eq "psPAS.CyberArk.Vault.Account")) {

                    #If InputObject is psPAS.CyberArk.Vault.Account
                    #*i.e. receiving pipeline from Get-PASAccount

                    #Get all existing properties as defined by input object:
                    #Process Pipeline input object properties
                    $InputObject |

                        #exclude properties output by get-pasaccount not applicable to set-pasaccount request
                        Select-Object -Property * -ExcludeProperty Name, PolicyID, Safe |

                            #get all remaining noteproperties
                            Get-Member -MemberType "NoteProperty" |

                                #For each property
                                ForEach-Object {

                                    #Initialise hashtable
                                    $ExistingProperty = @{ }

                                    #if property is not bound to function parameter by name,
                                    if (!(($PSBoundParameters.ContainsKey($($_.Name))) -or (

                                                #if not being explicitly updated.
                                                $($Properties).ContainsKey($($_.Name))))) {

                                        [hashtable]$ExistingProperty.Add($($_.Name), $($InputObject.$($_.Name)))

                                        #Add to Properties node of request data
                                        [array]$boundParameters["Properties"] += $ExistingProperty.GetEnumerator() | ForEach-Object { $_ }
                                        #*any existing properties of an account not sent in a "set" request will be cleared on the account.
                                        #*This ensures correctly formatted request with all existing account properties included
                                        #*when function is sent data via the pipeline.

                                    }

                                }

                }

                #Create body of request
                $body = @{

                    "Accounts" = $boundParameters

                    #ensure nodes at all required depths are included in the JSON object
                } | ConvertTo-Json -Depth 3

                break

            }
        }

        if ($PSCmdlet.ShouldProcess($AccountID, "Update Account Properties")) {

            #send request to PAS web service
            $Result = Invoke-PASRestMethod -Uri $URI -Method $Method -Body $Body -WebSession $Script:WebSession

            If ($null -ne $result) {

                switch ($PSCmdlet.ParameterSetName) {

                    "Gen1" { $Return = $Result.UpdateAccountResult ; break }

                    default { $Return = $Result }

                }

                $Return | Add-ObjectDetail -typename $Type -PropertyToAdd @{

                    "AccountID" = $AccountID

                }

            }

        }

    }#process

    END { }#end

}