public/public-functions.ps1



function Connect-Pps {
    <#
    .Synopsis
       Connect to Pleasant Password Server
    .DESCRIPTION
       Connect to Pleasant Password Server
    .PARAMETER Uri
       The full server url
    .PARAMETER Credential
       Credential object to connect to Pleasant
    .PARAMETER Username
       The username to connect to Pleasant
    .PARAMETER Password
       The password to connect to Pleasant
    .EXAMPLE
       Connect-Pps -Uri https://server.local:443 -Credential $cred
    .EXAMPLE
       Connect-Pps -Uri https://server.local:443 -Username "MyUser" -Password "MyPassword"
    #>


    [CmdletBinding()]
    [Alias()]
    [OutputType([PSCustomObject])]
    Param(
        # Param1 help description
        [Parameter(Mandatory=$true, Position=0)]
        [ValidateNotNullOrEmpty()]
        $Uri,

        [Parameter(ParameterSetName='Credential', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
        [pscredential]
        $Credential,

        [Parameter(ParameterSetName='Username', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
        [string]
        $Username,

        [Parameter(ParameterSetName='Username', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
        [securestring]
        $Password
    )

    begin{
        $currentErrAction = $ErrorActionPreference
        $ErrorActionPreference = "Stop"
    }
    process{
        if ($PSBoundParameters.ContainsKey("Credential")){
            Write-Verbose "Using credential object for authentication"
            $body = "grant_type=password&username=$($Credential.UserName)&password=$($Credential.GetNetworkCredential().password)"
        } else {
            Write-Verbose "Using username & password for authentication"
            $body = "grant_type=password&username=$($Username)&password=$($Password)"
        }

        $tokenResponse = Invoke-RestMethod -Uri ($Uri.Trim('/') + "/OAuth2/Token") -Method POST -Body $body -ContentType "application/x-www-form-urlencoded"
        $tokenResponse | Add-Member -NotePropertyName expires_at -NotePropertyValue (Get-Date).AddSeconds($tokenResponse.expires_in)
        $tokenResponse | Add-Member -NotePropertyName Server -NotePropertyValue ($Uri.Trim('/'))
        $script:PleasantConnection = $tokenResponse
    }
    end{
        $ErrorActionPreference = $currentErrAction
        return $script:PleasantConnection | Select-Object -Property "Server","token_type","expires_at"        
    }
}

function Get-PpsChildItem {
    [CmdletBinding()]
    param (
        # The folder Id to query
        [Parameter(Mandatory=$false)]
        [ValidateNotNullOrEmpty()]
        [guid]$FolderId

        # How many levels to query
        # [Parameter(Mandatory=$false)]
        # [int]$RecurseLevel
    )
    
    $endPoint = "/api/v6/rest/folders"
    if ($PSBoundParameters.ContainsKey("FolderId")){
        $endPoint += "/$($FolderId)"
    }

    # if ($PSBoundParameters.ContainsKey("RecurseLevel")){
    # $endPoint += "/$($RecurseLevel)"
    # }


    Invoke-PpsRestMethod -Method "Get" -EndPoint $endPoint
}

function Get-PpsEntry {
    [CmdletBinding()]
    param (
        # The credential / entry Id to query
        [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
        [Alias("EntryId")]
        [guid]$Id,

        [Parameter(Mandatory=$false)]
        [switch]$ShowPassword
    )
    
    $endPoint = "/api/v6/rest/entries/$($Id)"

    if ($PSBoundParameters.ContainsKey('ShowPassword') -AND $PSBoundParameters['ShowPassword'] -eq $true) {
        $endPoint += "/password"
    }

    $response = Invoke-PpsRestMethod -Method "Get" -EndPoint $endPoint

    return $response
}

function Set-PpsEntry {
    [CmdletBinding()]
    param (
        # The credential / entry Id to update
        [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
        [Alias("EntryId")]
        [guid]$Id,

        # The new Name
        [Parameter(Mandatory=$false)]
        [string]$Name,

        # The new Username
        [Parameter(Mandatory=$false)]
        [string]$Username,

        # the new Password
        [Parameter(Mandatory=$false)]
        [string]$Password,

        # the new group / folder this entry falls under
        [Parameter(Mandatory=$false)]
        [guid]$GroupId,

        # the new Url of the entry
        [Parameter(Mandatory=$false)]
        [string]$Url,

        # new notes of the entry
        [Parameter(Mandatory=$false)]
        [string]$Notes,

        # new Tags of the entry
        [Parameter(Mandatory=$false)]
        [array]$Tags,

        # optional CustomFields of the entry
        [Parameter(Mandatory=$false)]
        [hashtable]$CustomUserFields
    )
    
    $endPoint = "/api/v6/rest/entries/$($Id)"

    $body =  @{}
    foreach ( $prop in @("Name","Username","Password","GroupId","Url","Notes","Tags","CustomUserFields") ){
        if ($PSBoundParameters.ContainsKey($prop)){
            $body[$prop] = (Get-Variable -Name $prop -ValueOnly)
        }
    }

    $body = $body | ConvertTo-Json
    $response = Invoke-PpsRestMethod -Method "PATCH" -EndPoint $endPoint -Body $body
    #return $null
}

function New-PpsEntry {
    [CmdletBinding()]
    param (
        # The name of the new entry
        [Parameter(Mandatory=$true)]
        [string]$Name,

        # The Username of the new entry
        [Parameter(Mandatory=$false)]
        [string]$Username,

        # the new password
        [Parameter(Mandatory=$false)]
        [string]$Password,

        # the group / folder this entry falls under
        [Parameter(Mandatory=$true)]
        [guid]$GroupId,

        # optional Url of the entry
        [Parameter(Mandatory=$false)]
        [string]$Url,

        # optional notes of the entry
        [Parameter(Mandatory=$false)]
        [string]$Notes,

        # optional Tags of the entry
        [Parameter(Mandatory=$false)]
        [array]$Tags,

        # optional CustomFields of the entry
        [Parameter(Mandatory=$false)]
        [hashtable]$CustomUserFields
    )
    
    $endPoint = "/api/v6/rest/entries"

    $body = @{
        Name = $Name
        GroupId = $GroupId
    }

    # Append to body hashtable based on input
    foreach ( $prop in @("Username","Password","Url","Notes","Tags","CustomUserFields") ){
        if ($PSBoundParameters.ContainsKey($prop)){
            $body[$prop] = (Get-Variable -Name $prop -ValueOnly)
        }
    }

    $body = $body | ConvertTo-Json
    Write-Verbose "Method: POST, Endpoint: $($endPoint), Body: $($body)"
    $response = Invoke-PpsRestMethod -Method "POST" -EndPoint $endPoint -Body $body
    #return $null
}

function Disconnect-Pps {
    [CmdletBinding()]
    Param()

    if ($null -eq $script:PleasantConnection){
        Write-Verbose "Not connected"
    }
    else {
        Write-Verbose "Disconnecting pleasant server: $($script:PleasantConnection.Server)"
        Remove-Variable -Name "PleasantConnection" -Scope "Script" -ErrorAction "Ignore"
    }
}