diff --git a/SnipeitPS/Private/Invoke-SnipeitMethod.ps1 b/SnipeitPS/Private/Invoke-SnipeitMethod.ps1 index 4f8f26d..122bfc1 100644 --- a/SnipeitPS/Private/Invoke-SnipeitMethod.ps1 +++ b/SnipeitPS/Private/Invoke-SnipeitMethod.ps1 @@ -1,32 +1,43 @@ -function Invoke-SnipeitMethod { - <# +<# .SYNOPSIS - Extracted invokation of the REST method to own function. - #> + Make api request to Snipe it + + .PARAMETER Api + Api part of url. prefix with slash ie. "/api/v1/hardware" + + .PARAMETER Method + Method of the invokation, one of following "GET", "POST", "PUT", "PATCH" or "DELETE" + + .PARAMETER Body + Request body as hashtable. Needed for post, put and patch + + .PARAMETER GetParameters + Get-Parameters as hastable. +#> + +function Invoke-SnipeitMethod { [OutputType( [PSObject] )] - param ( - # REST API to invoke - [Parameter(Mandatory = $true)] - [Uri]$URi, - # Method of the invokation + param ( + + [Parameter(Mandatory = $true)] + [string]$Api, + [ValidateSet("GET", "POST", "PUT", "PATCH", "DELETE")] [string]$Method = "GET", - # Body of the request [ValidateNotNullOrEmpty()] [Hashtable]$Body, - [string] $Token, - - # GET Parameters [Hashtable]$GetParameters - ) BEGIN { + $Url = $SnipeitPSSession.url + $Token = $SnipeitPSSession.apiKey + # Validation of parameters if (($Method -in ("POST", "PUT", "PATCH")) -and (!($Body))) { $message = "The following parameters are required when using the ${Method} parameter: Body." @@ -34,18 +45,23 @@ Throw $exception } + # Double check those old deprecated -url parameters + $Url = $Url.AbsoluteUri.TrimEnd('/') + + #Build request uri + $apiUri = "$Url$Api" #To support images "image" property have be handled before this $_headers = @{ - "Authorization" = "Bearer $($token)" + "Authorization" = "Bearer $($Token)" 'Content-Type' = 'application/json; charset=utf-8' "Accept" = "application/json" } } Process { - if ($GetParameters -and ($URi -notlike "*\?*")) - { + # This can be done using $Body, maybe some day - PetriAsi + if ($GetParameters -and ($apiUri -notlike "*\?*")){ Write-Debug "Using `$GetParameters: $($GetParameters | Out-String)" [string]$URI += (ConvertTo-GetParameter $GetParameters) # Prevent recursive appends @@ -54,15 +70,14 @@ # set mandatory parameters $splatParameters = @{ - Uri = $URi + Uri = $apiUri Method = $Method Headers = $_headers UseBasicParsing = $true ErrorAction = 'SilentlyContinue' } - # Place holder for intended image manipulation - # if and when snipe it API gets support for images + # Send image requests as multipart/form-data if supported if($null -ne $body -and $Body.Keys -contains 'image' ){ if($PSVersionTable.PSVersion -ge '7.0'){ $Body['image'] = get-item $body['image'] @@ -72,10 +87,10 @@ $splatParameters["Method"] = 'POST' $splatParameters["Form"] = $Body } else { - # use base64 encoded images for powershell version < 7 - Add-Type -AssemblyName "System.Web" - $mimetype = [System.Web.MimeMapping]::GetMimeMapping($body['image']) - $Body['image'] = 'data:@'+$mimetype+';base64,'+[Convert]::ToBase64String([IO.File]::ReadAllBytes($Body['image'])) + # use base64 encoded images for powershell version < 7 + Add-Type -AssemblyName "System.Web" + $mimetype = [System.Web.MimeMapping]::GetMimeMapping($body['image']) + $Body['image'] = 'data:@'+$mimetype+';base64,'+[Convert]::ToBase64String([IO.File]::ReadAllBytes($Body['image'])) } } @@ -106,18 +121,16 @@ if ($webResponse) { Write-Verbose $webResponse - # API returned a Content: lets work wit it + # API returned a Content: lets work with it try{ - if ($webResponse.status -eq "error") { - Write-Verbose "[$($MyInvocation.MyCommand.Name)] An error response was received from; resolving" + Write-Verbose "[$($MyInvocation.MyCommand.Name)] An error response was received ... resolving" # This could be handled nicely in an function such as: # ResolveError $response -WriteError Write-Error $($webResponse.messages | Out-String) - } - else { + } else { #update operations return payload - if ($webResponse.payload){ + if ($webResponse.payload) { $result = $webResponse.payload } #Search operations return rows @@ -125,7 +138,7 @@ $result = $webResponse.rows } #Remove operations returns status and message - elseif ($webResponse.status -eq 'success'){ + elseif ($webResponse.status -eq 'success') { $result = $webResponse.payload } #get operations with id returns just one object @@ -137,9 +150,6 @@ Write-Verbose "Messages: $($webResponse.messages)" $result - - - } } catch { @@ -148,7 +158,7 @@ } elseif ($webResponse.StatusCode -eq "Unauthorized") { - Write-Error "[$($MyInvocation.MyCommand.Name)] You are not Authorized to access the resource, check your token is correct" + Write-Error "[$($MyInvocation.MyCommand.Name)] You are not Authorized to access the resource, check your apiKey is correct" } else { # No content, although statusCode < 400 @@ -166,3 +176,4 @@ Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function ended" } } + diff --git a/SnipeitPS/Private/Set-SnipeitPSSessionApiKey.ps1 b/SnipeitPS/Private/Set-SnipeitPSSessionApiKey.ps1 new file mode 100644 index 0000000..cd3e4da --- /dev/null +++ b/SnipeitPS/Private/Set-SnipeitPSSessionApiKey.ps1 @@ -0,0 +1,14 @@ +function Set-SnipeitPSSessionApiKey { + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = "Low" + )] + param( + [string]$apiKey + ) + process { + if ($PSCmdlet.ShouldProcess("ShouldProcess?")) { + $SnipeitPSSession.apiKey = $apiKey + } + } +} diff --git a/SnipeitPS/Private/Set-SnipeitPSSessionUrl.ps1 b/SnipeitPS/Private/Set-SnipeitPSSessionUrl.ps1 new file mode 100644 index 0000000..b15153d --- /dev/null +++ b/SnipeitPS/Private/Set-SnipeitPSSessionUrl.ps1 @@ -0,0 +1,14 @@ +function Set-SnipeitPSSessionUrl { + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = "Low" + )] + param( + $url + ) + process { + if ($PSCmdlet.ShouldProcess("ShouldProcess?")) { + $SnipeitPSSession.url = $url + } + } +} diff --git a/SnipeitPS/Public/Connect-Snipeit.ps1 b/SnipeitPS/Public/Connect-Snipeit.ps1 new file mode 100644 index 0000000..99f9c98 --- /dev/null +++ b/SnipeitPS/Public/Connect-Snipeit.ps1 @@ -0,0 +1,90 @@ +<# + .SYNOPSIS + Sets authetication information + + .DESCRIPTION + Set and stores apikey and url user to connect Snipe-It system. + Based on Set-SnipeitInfo command, that's now just combatipility wrapper + and calls Connect-SnipeitPS + + .PARAMETER url + URL of Snipeit system. + + .PARAMETER apiKey + User's API Key for Snipeit. + + .PARAMETER DontStore + Don't store connection information just connect to Url + + .EXAMPLE + Connect-SnipeitPS -Url $url -apiKey $myapikey + Connect to Snipe it api and stores connection information. + + .EXAMPLE + Connect-SnipeitPS -Url $url -apiKey $myapikey -DontStore + Just connects to Snipe it api, connection information is not stored. + + .EXAMPLE + Connect-SnipeitPS -Url $url + Connects existing Snipe It Url with stored apiKey + + .EXAMPLE + Connect-SnipeitPS + Connects last used Snipe It Url with stored apikey + + +#> +function Connect-SnipeitPS { + [CmdletBinding( + DefaultParameterSetName = 'Connect to existing connection' + )] + [System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseShouldProcessForStateChangingFunctions', '')] + + param ( + + [Parameter(ParameterSetName='Setup new connection',Mandatory=$true)] + [Parameter(ParameterSetName='Connect to existing connection',Mandatory=$false)] + [Uri]$url, + + [Parameter(ParameterSetName='Setup new connection',Mandatory=$true)] + [String]$apiKey, + + [Parameter(ParameterSetName='Setup new connection')] + [switch]$DontStore + ) + + + PROCESS { + switch ($PsCmdlet.ParameterSetName) { + 'Setup new connection' { + try { + $SnipeitPSSession.url = $url + $SnipeitPSSession.apiKey = $apiKey + + #test connection + $Parameters = @{ + Api = '/api/v1/statuslabels' + Method = 'Get' + GetParameters = @{'limit'=1} + } + Write-Verbose "Testin connection to $url." + + $contest = Invoke-SnipeitMethod @Parameters + if ( $contest) { + Write-Verbose "Connection to $url tested succesfully." + } + + } + catch { + throw "Cannot setup connection to $url. To start troubleshooting, check your url, certificates and apiKey" + } + # TODO: Save connection information safely on disk + + } + + 'Connect to existing connection' { + # TODO: everything + } + } + } +}