Public/Import-TMDActionRequest.ps1


Function Import-TMDActionRequest {
    param(
        [Parameter(Mandatory = $false)][String]$FromB64,
        [Parameter(Mandatory = $false)][String]$SerializedActionRequestObject,
        [Parameter(Mandatory = $false)][PSObject]$PSObjectActionRequest,
        [Parameter(Mandatory = $false)][String]$FromFile,
        [Parameter(Mandatory = $false)][Switch]$PassThru,
        [Parameter(Mandatory = $false)][Switch]$SkipProviderLoad
    )
    if ($FromFile) {
        $actionRequest = (Get-Content -Path $FromFile | ConvertFrom-Json)
    } elseif ($SerializedActionRequestObject) {
        $actionRequest = [System.Management.Automation.PSSerializer]::Deserialize($SerializedActionRequestObject)
    } elseif ($PSObjectActionRequest) {
        $actionRequest = $PSObjectActionRequest
    } elseif ($FromB64) {
        $actionRequest = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($FromB64)) | ConvertFrom-Json
    } else {
        throw 'Unable to create Action Request Object.'
    }


    ## Make sure we created a new actionRequest,
    ## use it as a container to populate the runspace with some variables
    if ($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;
        }

        ## Handle Credential Creation for items passed from Credentials
        if ($null -ne $actionRequest.options.credentials) {

            ## Extract the Username and and Encrypt the password
            $Username = $actionRequest.options.credentials.username
            $EncryptedPassword = ConvertTo-SecureString $actionRequest.options.credentials.password -AsPlainText -Force

            ## Remove the credentials object from the $actionRequest
            $actionRequest.options.credentials = $null

            ## Create a new Credential and assign it to the $Credential variable in the current scope (session)
            $PSCredential = New-Object System.Management.Automation.PSCredential ($Username, $EncryptedPassword)
            $ActionRequest | Add-Member -NotePropertyName 'PSCredential' -NotePropertyValue $PSCredential | Out-Null
            New-Variable -Name 'Credential' -Value $PSCredential -Force -Scope Global
        }



        ## Handle Credential Creation within any Parameters that defined a credential
        $suppliedCredentials = $actionRequest.params.PSObject.Properties | Where-Object { $_.Name -like 'supplied_credential_*' }

        ## Convert any 'supplied_credential_' objects into their appropriate PSObject format.
        if ($suppliedCredentials.count -gt 0) {

            $suppliedCredentials | ForEach-Object {
                $suppliedCredential = $_

                ## Remove the credentials object from the parameter
                $actionRequest.params.PSObject.Properties.Remove($suppliedCredential.Name)

                ## Extract the Username and and Encrypt the password
                $Username = $suppliedCredential.value.username
                $EncryptedPassword = ConvertTo-SecureString $suppliedCredential.value.password -AsPlainText -Force
                $ConvertedCredential = New-Object System.Management.Automation.PSCredential ($Username, $EncryptedPassword)

                ## Add the converted credential to the Params
                $actionRequest.params | Add-Member -NotePropertyName ($suppliedCredential.Name -replace 'supplied_credential_', '' ) -NotePropertyValue $ConvertedCredential -Force
            }
        }

        ## Handle Credential Creation within any Parameters that defined a credential
        $storedCredentials = $actionRequest.params.PSObject.Properties | Where-Object { $_.Name -like 'use_storedcredential_*' }

        ## Retrieve any 'use_stored_credential_' objects from local storage into their appropriate PSObject format.
        if ($storedCredentials.count -gt 0) {

            $storedCredentials | ForEach-Object {
                $storedCredential = $_

                ## Remove the credentials object from the parameter
                $actionRequest.params.PSObject.Properties.Remove($storedCredential.Name)

                $RetrievedCredential = Get-StoredCredential -CredentialName $storedCredential.Value

                ## Add the converted credential to the Params
                $actionRequest.params | Add-Member -NotePropertyName ($storedCredential.Name -replace 'use_storedcredential_', '' ) -NotePropertyValue $RetrievedCredential -Force
            }
        }

        ## Allow Required Modules to be imported automatically
        $PSModuleAutoloadingPreference = 'All'
        $Global:PSModuleAutoloadingPreference = 'All'

        ## Add the ProviderSetup to the ActionRequest
        if ($ProviderSetup) {

            ## Always add the ProviderSetup to the Action Request
            $actionRequest | Add-Member -NotePropertyName ProviderSetup -NotePropertyValue $ProviderSetup -Force

            ## Only import the Modules if it's not supposed to skip (This only occurs when a script is being bootstrapped to connect to the Session)
            if (-not $SkipProviderLoad) {

                ## Display the Startup/Import Message
                if ($ProviderSetup.StartupMessage) {
                    Write-Host $ProviderSetup.StartupMessage
                }

                ## Import Each Declared Module
                foreach ($Module in $ProviderSetup.ModulesToImport) {
                    # . Import-PublicGalleryModule $Module
                    . Import-Module $Module -ErrorAction 'SilentlyContinue' -SkipEditionCheck -Scope Global
                }
                foreach ($Module in $ProviderSetup.WinPSModulesToImport) {
                    # . Import-PublicGalleryModule $Module
                    # . Import-Module $Module -ErrorAction 'SilentlyContinue' -SkipEditionCheck -Scope Global
                    . Import-Module $Module -UseWindowsPowerShell
                }

                ## If the ProviderSetup has a StartupScript Run the ScriptBlock
                if ($ProviderSetup.StartupScript) {
                    . Invoke-Command -ScriptBlock $ProviderSetup.StartupScript -NoNewScope -ErrorAction 'SilentlyContinue'
                }
            }
        }

        ## Import the remaining Variables
        New-Variable -Name 'ActionRequest' -Value $actionRequest -Force -Scope Global
        New-Variable -Name 'Params' -Value $actionRequest.params -Force -Scope Global
        New-Variable -Name 'TMDCallbackOptions' -Value $TMDCallbackOptions -Force -Scope Global

    } else {
        ## The result of the script didn't produce an actionRequest object
        throw 'Unable to create an $actionRequest object'
    }
    if ($PassThru) { $ActionRequest }
}