Public/Set-TMTaskAction.ps1


Function Set-TMTaskAction {
    param(

        ## TMD Callback Options
        [Parameter(Mandatory = $false)][PSObject]$TMDCallbackOptions,
        [Parameter(Mandatory = $false)][PSObject]$ActionRequest,

        ## The selected Task State drives the APU URI generation
        [Parameter(Mandatory = $true)]
        [ValidateSet('started', 'progress', 'success', 'error')]
        [String]$State,

        ## Extra Features / Data Values
        [Parameter(Mandatory = $false)][String]$Message,

        [Parameter(Mandatory = $false)]
        [ValidateRange(0, 100)]
        [int]$Progress,

        [Parameter(Mandatory = $false)][String]$Stdout,
        [Parameter(Mandatory = $false)][String]$Stderr,
        [Parameter(Mandatory = $false)][PSObject]$Data,
        [Parameter(Mandatory = $false)][String]$DataFile,
        [Parameter(Mandatory = $false)][Boolean]$AllowInsecureSSL = $false
    )

    ## Create a Callback Options object to know what Server to use
    if (-not $TMDCallbackOptions -and $ActionRequest) {
        ## Create the TM Session Callback options for the Task Update functions
        $TMDCallbackOptions = @{
            SiteURL     = $ActionRequest.options.callback.siteUrl;
            BearerToken = $ActionRequest.options.callback.token;
            ProjectID   = $ActionRequest.options.projectId;
            TaskID      = $ActionRequest.task.id;
        }
    }

    ## Don't make a call if Callback options were not present
    if (-not $TMDCallbackOptions) {
        return
    }

    #Honor SSL Settings
    if ($TMSessionConfig.AllowInsecureSSL -or $AllowInsecureSSL) {
        $TMCertSettings = @{SkipCertificateCheck = $true }
    } else {
        $TMCertSettings = @{SkipCertificateCheck = $false }
    }
    $uriPaths = @{
        started  = 'actionStarted'
        progress = 'actionProgress'
        success  = 'actionDone'
        error    = 'actionError'
    }

    $MPBoundary = '--------------------------314159265358979323846264'

    ## Headers
    $RequestHeaders = @{
        "Accept-Version" = "1.0";
        "Content-Type"   = "multipart/form-data; boundary=" + $MPBoundary;
        "Accept"         = "application/json";
        "Authorization"  = 'Bearer ' + $TMDCallbackOptions.BearerToken;
        "Cache-Control"  = "no-cache";
    }

    # Body Creation
    $Body = [System.Text.StringBuilder]::new()

    ## Add Project
    [void]$Body.Append( '--' + $MPBoundary )
    [void]$Body.Append($CRLF)
    [void]$Body.Append( 'Content-Disposition: form-data; name="project.id"' )
    [void]$Body.Append($CRLF)
    [void]$Body.Append( '' )
    [void]$Body.Append($CRLF)
    [void]$Body.Append( $TMDCallbackOptions.ProjectID )
    [void]$Body.Append($CRLF)

    ## Add Progress
    if ($Progress) {
        [void]$Body.Append( '--' + $MPBoundary )
        [void]$Body.Append($CRLF)
        [void]$Body.Append( 'Content-Disposition: form-data; name="progress"' )
        [void]$Body.Append($CRLF)
        [void]$Body.Append( 'Content-Type: application/x-www-form-urlencoded' )
        [void]$Body.Append($CRLF)
        [void]$Body.Append( '' )
        [void]$Body.Append($CRLF)
        [void]$Body.Append( $Progress )
        [void]$Body.Append($CRLF)
    }

    ## Add Message
    if ($Message) {
        [void]$Body.Append( '--' + $MPBoundary )
        [void]$Body.Append($CRLF)
        [void]$Body.Append( 'Content-Disposition: form-data; name="message"' )
        [void]$Body.Append($CRLF)
        [void]$Body.Append( '' )
        [void]$Body.Append($CRLF)
        [void]$Body.Append( $Message )
        [void]$Body.Append($CRLF)
    }

    #Standard Out
    if ($Stdout) {
        [void]$Body.Append( '--' + $MPBoundary )
        [void]$Body.Append($CRLF)
        [void]$Body.Append( 'Content-Disposition: form-data; name="stdout"' )
        [void]$Body.Append($CRLF)
        [void]$Body.Append( '' )
        [void]$Body.Append($CRLF)
        [void]$Body.Append( $Stdout )
        [void]$Body.Append($CRLF)
    }

    #Standard Err
    if ($Stderr) {
        [void]$Body.Append( '--' + $MPBoundary )
        [void]$Body.Append($CRLF)
        [void]$Body.Append( 'Content-Disposition: form-data; name="stderr"' )
        [void]$Body.Append($CRLF)
        [void]$Body.Append( '' )
        [void]$Body.Append($CRLF)
        [void]$Body.Append( $Stderr )
        [void]$Body.Append($CRLF)
    }

    #Data
    if ($Data) {
        [void]$Body.Append( '--' + $MPBoundary )
        [void]$Body.Append($CRLF)
        [void]$Body.Append( 'Content-Disposition: form-data; name="data"' )
        [void]$Body.Append($CRLF)
        [void]$Body.Append( 'Content-Type: application/json;' )
        [void]$Body.Append($CRLF)
        [void]$Body.Append( '' )
        [void]$Body.Append($CRLF)
        [void]$Body.Append( ($Data | ConvertTo-Json -Depth 100 -Compress ) )
        [void]$Body.Append($CRLF)
    }

    # #Data File
    # if($DataFile){
    # [void]$Body.Append( '--' + $MPBoundary )
    # [void]$Body.Append( 'Content-Disposition: form-data; name="datafile"' )
    # [void]$Body.Append( '' )
    # [void]$Body.Append( $DataFile )
    # }

    ## End the Body and save it to a string
    [void]$Body.Append( "--" + $MPBoundary + "--" )
    [void]$Body.Append($CRLF)
    $PostBody = $Body.ToString()

    # API
    $uri = $TMDCallbackOptions.SiteURL
    $uri += "/api/task/" + $TMDCallbackOptions.TaskID + "/"
    $uri += $uriPaths.$State

    ## Invoke the HTTP Request and handle the response
    try {
        # Perform actual web request
        $Response = Invoke-WebRequest -Method Post -Uri $uri -Headers $RequestHeaders -Body $PostBody @TMCertSettings
        if ($Response.StatusCode -eq 200) {
            $ResponseJson = $response.Content | ConvertFrom-Json -Depth 100

            if ($ResponseJson.status -eq 'error') {
                throw $ResponseJson.errors
            }
        }

        ## TM 5.0+ returns a 204 (OK, but no content)
        elseif ($Response.StatusCode -eq 204) {
            return
        } else {
            Throw ('Error while setting task to ' + $State)
        }

    } catch {
        throw $_
    }
}