nerm/src/PSSailpoint.NERM/Private/NERMApiClient.ps1

#
# NERM API
# The NERM API accesss and modifies resources in your environment.
# Version: 1.0.0
# Generated by OpenAPI Generator: https://openapi-generator.tech
#

function Invoke-NERMApiClient {
    [OutputType('System.Collections.Hashtable')]
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory)]
        [string]$Uri,
        [Parameter(Mandatory)]
        [AllowEmptyCollection()]
        [string[]]$Accepts,
        [Parameter(Mandatory)]
        [AllowEmptyCollection()]
        [string[]]$ContentTypes,
        [Parameter(Mandatory)]
        [hashtable]$HeaderParameters,
        [Parameter(Mandatory)]
        [hashtable]$FormParameters,
        [Parameter(Mandatory)]
        [hashtable]$QueryParameters,
        [Parameter(Mandatory)]
        [hashtable]$CookieParameters,
        [Parameter(Mandatory)]
        [AllowEmptyString()]
        [string]$Body,
        [Parameter(Mandatory)]
        [string]$Method,
        [Parameter(Mandatory)]
        [AllowEmptyString()]
        [string]$ReturnType,
        [Parameter(Mandatory)]
        [bool]$IsBodyNullable
    )

    'Calling method: Invoke-NERMApiClient' | Write-Debug
    $PSBoundParameters | Out-DebugParameter | Write-Debug

    $Configuration = Get-DefaultConfiguration
    $RequestUri = $Configuration["NermBaseUrl"] + $Uri

    Write-Debug "Calling Endpoint: $RequestUri"

    $DefaultHeaders = $Configuration["DefaultHeaders"]
    # should make sure that SkipCertificateCheck is not set for PowerShell 5
    $SkipCertificateCheck = $Configuration["SkipCertificateCheck"]
    $Proxy = $Configuration["Proxy"]

    # cookie parameters
    foreach ($Parameter in $CookieParameters.GetEnumerator()) {
        if ($Parameter.Name -eq "cookieAuth") {
            $HeaderParameters["Cookie"] = $Parameter.Value
        } else {
            $HeaderParameters[$Parameter.Name] = $Parameter.Value
        }
    }
    if ($CookieParameters -and $CookieParameters.Count -gt 1) {
        Write-Warning "Multiple cookie parameters found. Currently only the first one is supported/used"
    }

    # accept, content-type headers
    $Accept = SelectHeaders -Headers $Accepts
    if ($Accept) {
        $HeaderParameters['Accept'] = $Accept
    }

    try {
        $Token = Get-IDNAccessToken
        $HeaderParameters['Authorization'] = "Bearer $Token"
    } catch {
        Write-Host $_ -ForegroundColor Red
        break
    }

    # Build User-Agent header
    $UserAgent = "SailPoint-SDK-PowerShell/2.0.7"
    if ($Configuration["ConsumerIdentifier"] -and $Configuration["ConsumerVersion"]) {
        $UserAgent = "$UserAgent ($($Configuration["ConsumerIdentifier"])/$($Configuration["ConsumerVersion"]))"
    }
    if ($IsWindows) { $OSPlatform = "windows" } elseif ($IsLinux) { $OSPlatform = "linux" } elseif ($IsMacOS) { $OSPlatform = "darwin" } else { $OSPlatform = "unknown" }
    $OSArch = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString().ToLower()
    $UserAgent = "$UserAgent ($OSPlatform; $OSArch) PowerShell/$($PSVersionTable.PSVersion.ToString()) (openapi-generator/7.12.0)"
    $HeaderParameters['User-Agent'] = $UserAgent


    $HasFormData = $False

    # Content-Type and multipart handling
    $ContentType = SelectHeaders -Headers $ContentTypes
    if ($ContentType) {
        $HeaderParameters['Content-Type'] = $ContentType
        if ($ContentType -eq 'multipart/form-data') {
            $HasFormData = $True
        }
    }

    # if no content type is specified, use application/json as default
    if (-not $ContentType -and -not $HasFormData) {
        $HeaderParameters['Content-Type'] = 'application/json'
    }

    # add default headers if any
    foreach ($header in $DefaultHeaders.GetEnumerator()) {
        $HeaderParameters[$header.Name] = $header.Value
    }

    # construct URL query string
    $HttpValues = [System.Web.HttpUtility]::ParseQueryString([String]::Empty)
    foreach ($Parameter in $QueryParameters.GetEnumerator()) {
        if ($Parameter.Value.Count -gt 1) { // array
            foreach ($Value in $Parameter.Value) {
                $HttpValues.Add($Parameter.Key + '[]', $Value)
            }
        } else {
            $HttpValues.Add($Parameter.Key,$Parameter.Value)
        }
    }
    # Build the request and load it with the query string.
    $UriBuilder = [System.UriBuilder]($RequestUri)
    $UriBuilder.Query = $HttpValues.ToString()

    # include form parameters in the request body
    if ($FormParameters -and $FormParameters.Count -gt 0) {
        if ($HasFormData) {
            $multipartContent = [System.Net.Http.MultipartFormDataContent]::new()

            $FormParameters.Keys | ForEach-Object {
                $value = $FormParameters[$_]
                $isFile = $value.GetType().FullName -eq "System.IO.FileInfo"
                if($isFile) {
                    $FileStream = [System.IO.FileStream]::new($value.FullName, [System.IO.FileMode]::Open)
                    $fileHeader = [System.Net.Http.Headers.ContentDispositionHeaderValue]::new("form-data")
                    $fileHeader.Name = $_
                    $fileHeader.FileName = $value.Name
                    $fileContent = [System.Net.Http.StreamContent]::new($FileStream)
                    $fileContent.Headers.ContentDisposition = $fileHeader
                    $multipartContent.Add($fileContent)
                } else {
                    $stringHeader = [System.Net.Http.Headers.ContentDispositionHeaderValue]::new("form-data")
                    $stringHeader.Name = $_
                    $stringContent = [System.Net.Http.StringContent]::new([string]$value)
                    $stringContent.Headers.ContentDisposition = $stringHeader
                    $multipartContent.Add($stringContent)
                }
            }

            $RequestBody = $multipartContent
        } else {
            $RequestBody = $FormParameters
        }
    }

    if(($ContentType -eq 'multipart/form-data') -and -not ($FormParameters -and $FormParameters.Count -gt 0))
    {
        $HeaderParameters.Remove('Content-Type')
    }


    if ($Body -or $IsBodyNullable) {
        $RequestBody = $Body
        if ([string]::IsNullOrEmpty($RequestBody) -and $IsBodyNullable -eq $true) {
            $RequestBody = "null"
        }
    }

    
    Write-Verbose ("Request Headers: {0}" -f ($HeaderParameters | Out-String))
    Write-Verbose "Request Body: $RequestBody"
    
    if ($SkipCertificateCheck -eq $true) {
        if ($null -eq $Configuration["Proxy"]) {
            # skip certification check, no proxy
            $Response = Invoke-WebRequest -Uri $UriBuilder.Uri `
                                      -Method $Method `
                                      -Headers $HeaderParameters `
                                      -Body $RequestBody `
                                      -ErrorAction Stop `
                                      -UseBasicParsing `
                                      -SkipHeaderValidation `
                                      -MaximumRetryCount $Configuration["MaximumRetryCount"] `
                                      -RetryIntervalSec $Configuration["RetryIntervalSeconds"] `
                                      -SkipCertificateCheck
        } else {
            # skip certification check, use proxy
            $Response = Invoke-WebRequest -Uri $UriBuilder.Uri `
                                      -Method $Method `
                                      -Headers $HeaderParameters `
                                      -Body $RequestBody `
                                      -ErrorAction Stop `
                                      -UseBasicParsing `
                                      -SkipHeaderValidation `
                                      -MaximumRetryCount $Configuration["MaximumRetryCount"] `
                                      -RetryIntervalSec $Configuration["RetryIntervalSeconds"] `
                                      -SkipCertificateCheck `
                                      -Proxy $Configuration["Proxy"].GetProxy($UriBuilder.Uri) `
                                      -ProxyUseDefaultCredentials
        }
    } else {
        if ($null -eq $Configuration["Proxy"]) {
            # perform certification check, no proxy
            $Response = Invoke-WebRequest -Uri $UriBuilder.Uri `
                                      -Method $Method `
                                      -Headers $HeaderParameters `
                                      -Body $RequestBody `
                                      -ErrorAction Stop `
                                      -UseBasicParsing `
                                      -SkipHeaderValidation `
                                      -MaximumRetryCount $Configuration["MaximumRetryCount"] `
                                      -RetryIntervalSec $Configuration["RetryIntervalSeconds"]
        } else {
            # perform certification check, use proxy
            $Response = Invoke-WebRequest -Uri $UriBuilder.Uri `
                                      -Method $Method `
                                      -Headers $HeaderParameters `
                                      -Body $RequestBody `
                                      -ErrorAction Stop `
                                      -UseBasicParsing `
                                      -SkipHeaderValidation `
                                      -MaximumRetryCount $Configuration["MaximumRetryCount"] `
                                      -RetryIntervalSec $Configuration["RetryIntervalSeconds"] `
                                      -Proxy $Configuration["Proxy"].GetProxy($UriBuilder.Uri) `
                                      -ProxyUseDefaultCredentials
        }
    }

    return @{
        Response = if ($Response.Content -is [string]) {
            # If the content is a string, deserialize it
            DeserializeResponse -Response $Response.Content -ReturnType $ReturnType -ContentTypes $Response.Headers["Content-Type"]
        } elseif ($Response.Headers["Content-Type"] -eq "application/zip") {
            # Remove the leading slash using -replace
            $fileName = $Uri -replace '^/', ''

            # If you want to remove any further slashes or problematic characters, use the following
            $fileName = $fileName -replace '/', '-'  # Replace slashes with dashes if you need a cleaner file name

            # Append .zip to the file name
            $zipFileName = "$fileName.zip"
    
            # Get the current working directory (base directory)
            $currentDir = Get-Location
    
            # Combine the current directory with the file name to get the full path
            $zipFilePath = Join-Path $currentDir $zipFileName
    
            # Write the zip file content (in byte array format) to the file
            [System.IO.File]::WriteAllBytes($zipFilePath, $Response.Content)
            Write-Host "Zip file has been saved to: $zipFilePath"
            $null  # Since we saved the zip file, return null as the response
        } else {
            # Otherwise, deserialize the full response object
            DeserializeResponse -Response $Response -ReturnType $ReturnType -ContentTypes $Response.Headers["Content-Type"]
        }
        StatusCode = $Response.StatusCode
        Headers = $Response.Headers
    }
}

# Select JSON MIME if present, otherwise choose the first one if available
function SelectHeaders {
    Param(
        [Parameter(Mandatory)]
        [AllowEmptyCollection()]
        [String[]]$Headers
    )

    foreach ($Header in $Headers) {
        if (-not(IsJsonMIME -MIME $Header)) {
            return $Header
        }
    }

    if (!($Headers) -or $Headers.Count -eq 0) {
        return $null
    } else {
        return $Headers[0] # return the first one
    }
}

function IsJsonMIME {
    Param(
        [Parameter(Mandatory)]
        [string]$MIME
    )

    if ($MIME -match "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$") {
        return $true
    } else {
        return $false
    }
}

function DeserializeResponse {
    Param(
        [Parameter(Mandatory)]
        [AllowEmptyString()]
        [string]$ReturnType,
        [Parameter(Mandatory)]
        [AllowEmptyString()]
        [string]$Response,
        [Parameter(Mandatory)]
        [AllowNull()]
        [AllowEmptyCollection()]
        [string[]]$ContentTypes
    )

    If ($null -eq $ContentTypes) {
        $ContentTypes = [string[]]@()
    }

    If ([string]::IsNullOrEmpty($ReturnType) -and $ContentTypes.Count -eq 0) { # void response
        return $Response
    } Elseif ($ReturnType -match '\[\]$') { # array
        return ConvertFrom-Json $Response -AsHashtable
    } Elseif (@("String", "Boolean", "System.DateTime") -contains $ReturnType) { # string, boolean ,datetime
        return $Response
    } Else { # others (e.g. model, file)
        if ($ContentTypes) {
            $ContentType = $null
            if ($ContentTypes.Count -gt 1) {
                $ContentType = SelectHeaders -Headers $ContentTypes
            } else {
                $ContentType = $ContentTypes[0]
            }

            if (IsJsonMIME -MIME $ContentType) { # JSON
                return ConvertFrom-Json $Response -AsHashtable
            } else { # XML, file, etc
                return $Response
            }
        } else { # no content type in response header, returning raw response
            return $Response
        }
    }
}