Public/Remove-midPointShadow.ps1

function Remove-midPointShadow {
    <#
    .SYNOPSIS
    Deletes an account on its resource (not only midPoint's shadow).

    .DESCRIPTION
    Deletes the shadow with DELETE /shadows/<oid>, like "delete projection" in the midPoint GUI: midPoint
    deletes the account on the resource (the connector's delete operation runs) and unlinks it from its owner.
    On a manual resource midPoint opens a case instead; the account is gone when the case is completed.

    Takes shadow objects from Get-midPointShadow or shadow OIDs. Other objects (e.g. a user piped by
    mistake) and names are refused before anything is sent, because a shadow name is only unique per resource.
    Before the delete the cmdlet reads the shadow without contacting the resource (noFetch) to check that the
    OID is a shadow and to show its name and resource in the confirmation.

    A shadow that no longer exists (HTTP 404) or is dead (the account was already deleted; midPoint keeps such
    shadows for a while) gives a warning, not an error, and nothing is sent: deleting a dead shadow again would
    open another case on a manual resource (run 18). midPoint refuses to delete an
    account that is still assigned when the resource enforces assignments (HTTP 409, "... violates an
    assignment policy"); that and every other error stops the cmdlet. Remove the assignment instead.
    Asks for confirmation; use -Confirm:$false in scripts.

    .PARAMETER Shadow
    The shadow: an object from Get-midPointShadow or a shadow OID.

    .EXAMPLE
    Get-midPointShadow jack -Resource 'Some Resource' -NoFetch | Remove-midPointShadow -Confirm:$false

    .EXAMPLE
    Remove-midPointShadow 33333333-3333-3333-3333-333333333333
    #>

    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
    param(
        [Parameter(Mandatory, Position = 0, ValueFromPipeline)]
        [Alias('Oid')]
        [object] $Shadow
    )

    process {
        $oid = $null
        if ($Shadow -is [string]) {
            if ($Shadow -match $script:midPointOidPattern) { $oid = $Shadow }
        }
        elseif ($Shadow.PSObject.TypeNames -contains 'midPointTools.Shadow') {
            $oid = [string]$Shadow.Oid
        }
        if (-not $oid) {
            $what = if ($Shadow -is [string]) { "'$Shadow' is not an OID" } else { "a $(@($Shadow.PSObject.TypeNames)[0]) object is not a shadow" }
            $record = [System.Management.Automation.ErrorRecord]::new(
                [System.ArgumentException]::new("Remove-midPointShadow takes shadows from Get-midPointShadow or shadow OIDs; $what."),
                'midPointNotAShadow', [System.Management.Automation.ErrorCategory]::InvalidArgument, $Shadow)
            $PSCmdlet.ThrowTerminatingError($record)
        }

        $path = 'shadows/{0}' -f [uri]::EscapeDataString($oid)
        try {
            $raw = Get-midPointObjectByOid -Type shadows -Oid $oid -Options 'noFetch', 'resolveNames'
        }
        catch {
            if ($_.Exception.Data['StatusCode'] -eq 404) {
                Write-Warning "Shadow $oid no longer exists (already deleted)."
                return
            }
            throw
        }
        $resourceRef = Get-midPointProperty $raw 'resourceRef'
        if (-not $resourceRef) {
            throw [System.ArgumentException]::new("Object $oid is not a shadow (no resourceRef).")
        }
        if (Get-midPointProperty $raw 'dead') {
            Write-Warning "Shadow $oid is dead: the account was already deleted."
            return
        }
        $name = ConvertFrom-midPointPolyString (Get-midPointProperty $raw 'name')
        $resource = ConvertFrom-midPointPolyString (Get-midPointProperty $resourceRef 'targetName')
        if (-not $resource) { $resource = [string](Get-midPointProperty $resourceRef 'oid') }
        if (-not $PSCmdlet.ShouldProcess("$name on $resource ($oid)", 'Delete the account on the resource')) { return }

        try {
            $null = Invoke-midPointRestMethod -Method DELETE -Path $path
        }
        catch {
            if ($_.Exception.Data['StatusCode'] -eq 404) {
                Write-Warning "Shadow $oid no longer exists (already deleted)."
                return
            }
            throw
        }
    }
}