new Connect-SnipeitPS command

This commit is contained in:
Petri Asikainen 2021-08-02 08:12:53 +03:00
parent 7b2cffda28
commit 4c0b9b0e85
4 changed files with 164 additions and 35 deletions

View file

@ -1,32 +1,43 @@
function Invoke-SnipeitMethod { <#
<#
.SYNOPSIS .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( [OutputType(
[PSObject] [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")] [ValidateSet("GET", "POST", "PUT", "PATCH", "DELETE")]
[string]$Method = "GET", [string]$Method = "GET",
# Body of the request
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[Hashtable]$Body, [Hashtable]$Body,
[string] $Token,
# GET Parameters
[Hashtable]$GetParameters [Hashtable]$GetParameters
) )
BEGIN { BEGIN {
$Url = $SnipeitPSSession.url
$Token = $SnipeitPSSession.apiKey
# Validation of parameters # Validation of parameters
if (($Method -in ("POST", "PUT", "PATCH")) -and (!($Body))) { if (($Method -in ("POST", "PUT", "PATCH")) -and (!($Body))) {
$message = "The following parameters are required when using the ${Method} parameter: Body." $message = "The following parameters are required when using the ${Method} parameter: Body."
@ -34,18 +45,23 @@
Throw $exception 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 #To support images "image" property have be handled before this
$_headers = @{ $_headers = @{
"Authorization" = "Bearer $($token)" "Authorization" = "Bearer $($Token)"
'Content-Type' = 'application/json; charset=utf-8' 'Content-Type' = 'application/json; charset=utf-8'
"Accept" = "application/json" "Accept" = "application/json"
} }
} }
Process { 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)" Write-Debug "Using `$GetParameters: $($GetParameters | Out-String)"
[string]$URI += (ConvertTo-GetParameter $GetParameters) [string]$URI += (ConvertTo-GetParameter $GetParameters)
# Prevent recursive appends # Prevent recursive appends
@ -54,15 +70,14 @@
# set mandatory parameters # set mandatory parameters
$splatParameters = @{ $splatParameters = @{
Uri = $URi Uri = $apiUri
Method = $Method Method = $Method
Headers = $_headers Headers = $_headers
UseBasicParsing = $true UseBasicParsing = $true
ErrorAction = 'SilentlyContinue' ErrorAction = 'SilentlyContinue'
} }
# Place holder for intended image manipulation # Send image requests as multipart/form-data if supported
# if and when snipe it API gets support for images
if($null -ne $body -and $Body.Keys -contains 'image' ){ if($null -ne $body -and $Body.Keys -contains 'image' ){
if($PSVersionTable.PSVersion -ge '7.0'){ if($PSVersionTable.PSVersion -ge '7.0'){
$Body['image'] = get-item $body['image'] $Body['image'] = get-item $body['image']
@ -72,10 +87,10 @@
$splatParameters["Method"] = 'POST' $splatParameters["Method"] = 'POST'
$splatParameters["Form"] = $Body $splatParameters["Form"] = $Body
} else { } else {
# use base64 encoded images for powershell version < 7 # use base64 encoded images for powershell version < 7
Add-Type -AssemblyName "System.Web" Add-Type -AssemblyName "System.Web"
$mimetype = [System.Web.MimeMapping]::GetMimeMapping($body['image']) $mimetype = [System.Web.MimeMapping]::GetMimeMapping($body['image'])
$Body['image'] = 'data:@'+$mimetype+';base64,'+[Convert]::ToBase64String([IO.File]::ReadAllBytes($Body['image'])) $Body['image'] = 'data:@'+$mimetype+';base64,'+[Convert]::ToBase64String([IO.File]::ReadAllBytes($Body['image']))
} }
} }
@ -106,18 +121,16 @@
if ($webResponse) { if ($webResponse) {
Write-Verbose $webResponse Write-Verbose $webResponse
# API returned a Content: lets work wit it # API returned a Content: lets work with it
try{ try{
if ($webResponse.status -eq "error") { 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: # This could be handled nicely in an function such as:
# ResolveError $response -WriteError # ResolveError $response -WriteError
Write-Error $($webResponse.messages | Out-String) Write-Error $($webResponse.messages | Out-String)
} } else {
else {
#update operations return payload #update operations return payload
if ($webResponse.payload){ if ($webResponse.payload) {
$result = $webResponse.payload $result = $webResponse.payload
} }
#Search operations return rows #Search operations return rows
@ -125,7 +138,7 @@
$result = $webResponse.rows $result = $webResponse.rows
} }
#Remove operations returns status and message #Remove operations returns status and message
elseif ($webResponse.status -eq 'success'){ elseif ($webResponse.status -eq 'success') {
$result = $webResponse.payload $result = $webResponse.payload
} }
#get operations with id returns just one object #get operations with id returns just one object
@ -137,9 +150,6 @@
Write-Verbose "Messages: $($webResponse.messages)" Write-Verbose "Messages: $($webResponse.messages)"
$result $result
} }
} }
catch { catch {
@ -148,7 +158,7 @@
} }
elseif ($webResponse.StatusCode -eq "Unauthorized") { 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 { else {
# No content, although statusCode < 400 # No content, although statusCode < 400
@ -166,3 +176,4 @@
Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function ended" Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function ended"
} }
} }

View file

@ -0,0 +1,14 @@
function Set-SnipeitPSSessionApiKey {
[CmdletBinding(
SupportsShouldProcess = $true,
ConfirmImpact = "Low"
)]
param(
[string]$apiKey
)
process {
if ($PSCmdlet.ShouldProcess("ShouldProcess?")) {
$SnipeitPSSession.apiKey = $apiKey
}
}
}

View file

@ -0,0 +1,14 @@
function Set-SnipeitPSSessionUrl {
[CmdletBinding(
SupportsShouldProcess = $true,
ConfirmImpact = "Low"
)]
param(
$url
)
process {
if ($PSCmdlet.ShouldProcess("ShouldProcess?")) {
$SnipeitPSSession.url = $url
}
}
}

View file

@ -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
}
}
}
}