lib/Settings.ps1

function New-TMSetting {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false, Position = 0)]
        [String]$TMSession = "Default",

        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('Key')]
        [String]$Name,

        [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
        [AllowNull()]
        [Alias('Project')]
        [Object]$ProjectId,

        [ArgumentCompleter({ [TMSetting]::ValidCategories })]
        [ValidateScript( { $_ -in [TMSetting]::ValidCategories } )]
        [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
        [String]$Category = 'SCRIPT_SETTING',

        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [Object]$Value,

        [Parameter(Mandatory = $false)]
        [Switch]$Passthru
    )

    begin {
        # Get the session configuration
        Write-Verbose "Checking for cached TMSession"
        $TMSessionConfig = $global:TMSessions[$TMSession]
        Write-Debug "TMSessionConfig:"
        Write-Debug ($TMSessionConfig | ConvertTo-Json -Depth 5)
        if (-not $TMSessionConfig) {
            throw "TMSession '$TMSession' not found. Use New-TMSession command before using features."
        }

        # Make sure we have a bearer token for the REST endpoint
        Write-Verbose "Checking for TMRestSession with bearer token"
        if (-not $TMSessionConfig.TMRestSession) {
            throw "TMSession '$TMSession' is not logged into the TransitionManager API. Use New-TMSession -Api `$true command to connect to a compatible server."
        }

        # Make sure the TM instance is v5.0.4 or greater
        Write-Verbose "Checking for compatible TransitionManager instance"
        Write-Debug "TM Version: $($TMSessionConfig.TMVersion)"
        if ($TMSessionConfig.TMVersion -lt '5.0.4') {
            throw "The Settings endpoints are not available on TransitionManager versions below 5.0.4"
        }
    }

    process {

        ## Check for an existing setting
        $GetSettingSplat = @{
            TMSession = $TMSession
            Name      = $Name
            ProjectId = $ProjectId
            Category  = $Category
        }
        $ExistingSetting = Get-TMSetting @GetSettingSplat
        if ($ExistingSetting) {
            throw "Setting named [$Name] already exists, use Get-TMSetting and Set-TMSetting to update it."
        }

        if ($ProjectId -is [TMReference]) {
            $ProjectId = $ProjectId.Id
        }
        else {
            $ProjectId = $TMSessionConfig.Project.Id
        }
        Write-Verbose "Forming web request parameters"
        $RestSplat = @{
            Uri                = "https://$($TMSessionConfig.TMServer)/tdstm/api/setting"
            Method             = 'POST'
            WebSession         = $TMSessionConfig.TMRestSession
            Body               = (@{
                    project  = $ProjectId
                    category = $Category
                    key      = $Name
                    type     = $Value -is [String] ? 'text' : 'json'
                    value    = $Value
                } | ConvertTo-Json -Compress)
            SkipHttpErrorCheck = $true
            StatusCodeVariable = 'StatusCode'
        }
        Write-Debug "Web Request Parameters:"
        Write-Debug ($RestSplat | ConvertTo-Json -Depth 10)
        Write-Verbose "Invoking REST method"
        try {
            $Response = Invoke-RestMethod @RestSplat

            if ($StatusCode -in 200, 204) {
                if ($Passthru) {
                    ## Workaround for 5.0.4 bug identified
                    $Response.project = $TMSessionConfig.UserContext.Project

                    [TMSetting]::new($Response)
                }
            }
            else {
                throw $Response
            }
        }
        catch {
            throw "Error while creating setting: $($_.Exception.Message)"
        }
    }
}
function Set-TMSetting {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false, Position = 0)]
        [String]$TMSession = "Default",

        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [Object]$Id,

        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('Key')]
        [String]$Name,

        [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
        [AllowNull()]
        [Alias('Project')]
        [Object]$ProjectId,

        [ArgumentCompleter({ [TMSetting]::ValidCategories })]
        [ValidateScript( { $_ -in [TMSetting]::ValidCategories } )]
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [String]$Category = 'SCRIPT_SETTING',

        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [Object]$Value,

        [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
        [ValidateSet('json', 'text')]
        [String]$Format = 'json',

        [Parameter(Mandatory = $false)]
        [Switch]$Passthru
    )

    begin {
        # Get the session configuration
        Write-Verbose "Checking for cached TMSession"
        $TMSessionConfig = $global:TMSessions[$TMSession]
        Write-Debug "TMSessionConfig:"
        Write-Debug ($TMSessionConfig | ConvertTo-Json -Depth 5)
        if (-not $TMSessionConfig) {
            throw "TMSession '$TMSession' not found. Use New-TMSession command before using features."
        }

        # Make sure we have a bearer token for the REST endpoint
        Write-Verbose "Checking for TMRestSession with bearer token"
        if (-not $TMSessionConfig.TMRestSession) {
            throw "TMSession '$TMSession' is not logged into the TransitionManager API. Use New-TMSession -Api `$true command to connect to a compatible server."
        }

        # Make sure the TM instance is v5.0.4 or greater
        Write-Verbose "Checking for compatible TransitionManager instance"
        Write-Debug "TM Version: $($TMSessionConfig.TMVersion)"
        if ($TMSessionConfig.TMVersion -lt '5.0.4') {
            throw "The Settings endpoints are not available on TransitionManager versions below 5.0.4"
        }
    }

    process {
        if ($ProjectId -is [TMReference]) {
            $ProjectId = $ProjectId.Id
        }
        else {
            $ProjectId = $TMSessionConfig.Project.Id
        }
        Write-Verbose "Forming web request parameters"
        $RestSplat = @{
            Uri                = "https://$($TMSessionConfig.TMServer)/tdstm/api/setting/$Id.$Format?project=$ProjectId"
            Method             = 'PUT'
            WebSession         = $TMSessionConfig.TMRestSession
            Body               = (@{
                    id       = $Id
                    project  = $ProjectId
                    category = $Category
                    key      = $Name
                    type     = $Value -is [String] ? 'text' : 'json'
                    value    = $Value
                } | ConvertTo-Json -Compress)
            SkipHttpErrorCheck = $true
            StatusCodeVariable = 'StatusCode'
        }
        Write-Debug "Web Request Parameters:"
        Write-Debug ($RestSplat | ConvertTo-Json -Depth 10)
        Write-Verbose "Invoking REST method"
        try {
            $Response = Invoke-RestMethod @RestSplat
            if ($StatusCode -in 200, 204) {
                if ($Passthru) {
                    [TMSetting]::new($Response)
                }
            }
            else {
                throw $Response
            }
        }
        catch {
            throw "Error while creating setting: $($_.Exception.Message)"
        }
    }
}


function Get-TMSetting {
    [CmdletBinding(DefaultParameterSetName = 'ByProperty')]
    param (
        [Parameter(Mandatory = $false, Position = 0)]
        [String]$TMSession = "Default",

        [Parameter(Mandatory = $true,
            ParameterSetName = 'ById',
            ValueFromPipelineByPropertyName = $true)]
        [Int]$Id,

        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('Key')]
        [String]$Name,

        [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
        [ArgumentCompleter({ [TMSetting]::ValidCategories })]
        [ValidateScript( { $_ -in [TMSetting]::ValidCategories } )]
        [String]$Category = 'SCRIPT_SETTING',

        [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
        [AllowNull()]
        [Alias('Project')]
        [Object]$ProjectId = $TMSessions[$TMSession].UserContext.Project.id,

        [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
        [ValidateSet('json', 'text')]
        [String]$Format = 'json',

        [Parameter(Mandatory = $false)]
        [Switch]$ValueOnly
    )

    begin {
        # Get the session configuration
        Write-Verbose "Checking for cached TMSession"
        $TMSessionConfig = $global:TMSessions[$TMSession]
        Write-Debug "TMSessionConfig:"
        Write-Debug ($TMSessionConfig | ConvertTo-Json -Depth 5)
        if (-not $TMSessionConfig) {
            throw "TMSession '$TMSession' not found. Use New-TMSession command before using features."
        }

        # Make sure we have a bearer token for the REST endpoint
        Write-Verbose "Checking for TMRestSession with bearer token"
        if (-not $TMSessionConfig.TMRestSession) {
            throw "TMSession '$TMSession' is not logged into the TransitionManager API. Use New-TMSession -Api `$true command to connect to a compatible server."
        }

        # Make sure the TM instance is v5.0.4 or greater
        Write-Verbose "Checking for compatible TransitionManager instance"
        Write-Debug "TM Version: $($TMSessionConfig.TMVersion)"
        if ($TMSessionConfig.TMVersion -lt '5.0.4') {
            throw "The Settings endpoints are not available on TransitionManager versions below 5.0.4"
        }
    }

    process {
        Write-Verbose "Forming the URI"

        ## Configure the root Uri
        $Uri = "https://$($TMSessionConfig.TMServer)/tdstm/api/setting"

        ## Add the Name/Key
        if ($Name) {
            $Uri += "/$Category/$([System.Web.HTTPUtility]::UrlEncode($Name.ToUpper())).$Format"
        }

        if ($PSCmdlet.ParameterSetName -eq 'ById') {
            $Uri += "/$Id"
        }

        ## Get the Project ID and append to the request
        if ($ProjectId -is [TMReference]) {
            $ProjectId = $ProjectId.Id
        }
        $Uri += "?project=$ProjectId"

        Write-Debug "URI: $Uri"
        Write-Verbose "Forming web request parameters"
        $RestSplat = @{
            Uri                = $Uri
            Method             = 'GET'
            WebSession         = $TMSessionConfig.TMRestSession
            SkipHttpErrorCheck = $true
            StatusCodeVariable = 'StatusCode'
        }
        Write-Debug "Web Request Parameters:"
        Write-Debug ($RestSplat | ConvertTo-Json -Depth 10)
        try {

            Write-Verbose "Invoking REST method"
            $Response = Invoke-RestMethod @RestSplat

            ## Handle an array of messages
            if ($Response.GetType().Name -eq 'Object[]') {
                $Response = $Response
            }

            ## Handle something that is not a PS Custom Object
            elseif ($Response.GetType().Name -ne 'PSCustomObject') {
                $ResponseHash = $Response | ConvertFrom-Json -AsHashtable -ErrorAction 'SilentlyContinue'
                if ($ResponseHash) {
                    $Response = $ResponseHash
                }
            }

            if ($StatusCode -in 200, 204) {
                $Setting = [TMSetting]::new($Response)
                $ValueOnly.IsPresent ? $Setting.Value : $Setting
            }
            else {

                ## Handle what should be interpereted as an Empty/Null value on the name
                if ($Response[0] -eq 'Requested information was not found') {
                    $Response = $Null
                }

                ## Return the Response
                $Response
            }
        }
        catch {
            throw "Error while creating setting: $($_.Exception.Message)"
        }
    }
}

function Remove-TMSetting {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false, Position = 0)]
        [String]$TMSession = "Default",

        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [Object]$Id,

        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('Key')]
        [String]$Name,

        [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
        [AllowNull()]
        [Alias('Project')]
        [Object]$ProjectId,

        [ArgumentCompleter({ [TMSetting]::ValidCategories })]
        [ValidateScript( { $_ -in [TMSetting]::ValidCategories } )]
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [String]$Category,

        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [Object]$Value

    )

    begin {
        # Get the session configuration
        Write-Verbose "Checking for cached TMSession"
        $TMSessionConfig = $global:TMSessions[$TMSession]
        Write-Debug "TMSessionConfig:"
        Write-Debug ($TMSessionConfig | ConvertTo-Json -Depth 5)
        if (-not $TMSessionConfig) {
            throw "TMSession '$TMSession' not found. Use New-TMSession command before using features."
        }

        # Make sure we have a bearer token for the REST endpoint
        Write-Verbose "Checking for TMRestSession with bearer token"
        if (-not $TMSessionConfig.TMRestSession) {
            throw "TMSession '$TMSession' is not logged into the TransitionManager API. Use New-TMSession -Api `$true command to connect to a compatible server."
        }

        # Make sure the TM instance is v5.0.4 or greater
        Write-Verbose "Checking for compatible TransitionManager instance"
        Write-Debug "TM Version: $($TMSessionConfig.TMVersion)"
        if ($TMSessionConfig.TMVersion -lt '5.0.4') {
            throw "The Settings endpoints are not available on TransitionManager versions below 5.0.4"
        }
    }

    process {
        if ($ProjectId -is [TMReference]) {
            $ProjectId = $ProjectId.Id
        }
        else {
            $ProjectId = $TMSessionConfig.Project.Id
        }
        Write-Verbose "Forming web request parameters"
        $RestSplat = @{
            Uri                = "https://$($TMSessionConfig.TMServer)/tdstm/api/setting/$Id"
            Method             = 'DELETE'
            WebSession         = $TMSessionConfig.TMRestSession
            Body               = (@{
                    id       = $Id
                    project  = $ProjectId
                    category = $Category
                    key      = $Name
                    type     = $Value -is [String] ? 'text' : 'json'
                    value    = $Value
                } | ConvertTo-Json -Compress)
            SkipHttpErrorCheck = $true
            StatusCodeVariable = 'StatusCode'
        }
        Write-Debug "Web Request Parameters:"
        Write-Debug ($RestSplat | ConvertTo-Json -Depth 10)
        Write-Verbose "Invoking REST method"
        try {
            $Response = Invoke-RestMethod @RestSplat
            if (($StatusCode -in 200, 204) -and ($Response.deleted -eq 1)) {
                return
            }
            else {
                throw $Response
            }
        }
        catch {
            throw "Error while creating setting: $($_.Exception.Message)"
        }
    }
}