diff --git a/PwshZendesk.psm1 b/PwshZendesk.psm1 index 2165532..1d7e3d6 100644 --- a/PwshZendesk.psm1 +++ b/PwshZendesk.psm1 @@ -6,5 +6,10 @@ Get-ChildItem -Path "$PSScriptRoot\functions" -Filter '*.ps1' -Recurse | ForEach Export-ModuleMember -Function $_.BaseName } +Get-ChildItem -Path "$PSScriptRoot\internal" -Filter '*.ps1' -Recurse | ForEach-Object { + . $_.FullName +} + $Script:NotConnectedMessage = 'No connection supplied or stored. Please either call `Connect-Zendesk` or call `Get-ZendeskConnection` and pass the result to all additional calls.' $Script:InvalidConnection = 'Provided connection is invalid.' +$Script:InvalidRoleMessage = 'Authenticated user must have role `{0}`, but instead has role `{1}`.' diff --git a/functions/Connect-.ps1 b/functions/Connect-.ps1 index 790f046..bfe33cd 100644 --- a/functions/Connect-.ps1 +++ b/functions/Connect-.ps1 @@ -1,5 +1,15 @@  function Connect- { + <# + .SYNOPSIS + Connects to a Zendesk instance. + .DESCRIPTION + Connects to a Zendesk instance. Overriding any existing connection established previously with this function. + .EXAMPLE + PS C:\> Connect-Zendesk -Organization 'company' -Username 'name@company.net' -ApiKey $ApiKey + + Connects to the 'company' Zendesk instance as the user 'name@company.net' + #> [OutputType([Boolean])] [CmdletBinding()] Param ( @@ -23,13 +33,7 @@ function Connect- { $ApiKey ) - $context = Get-Connection @PSBoundParameters - - if (Test-Connection -context $context) { - $Script:Context = $context - } else { - throw $Script:InvalidConnection - } + $Script:Context = Get-Connection @PSBoundParameters $true diff --git a/functions/Get-Connection.ps1 b/functions/Get-Connection.ps1 index e3cf2a0..2bd5845 100644 --- a/functions/Get-Connection.ps1 +++ b/functions/Get-Connection.ps1 @@ -1,6 +1,15 @@ function Get-Connection { + <# + .SYNOPSIS + Returns a Zendesk connection context + .DESCRIPTION + Returns an object describing a connection to a Zendesk instance + .EXAMPLE + PS C:\> $context = Get-ZendeskConnection -Organization 'company' -Username 'name@company.net' -ApiKey $ApiKey + Sets $context to a connection context for the 'company' Zendesk instance as the user 'name@company.net' + #> [OutputType([PSCustomObject])] [CMDletBinding()] Param ( @@ -27,9 +36,15 @@ function Get-Connection { Organization = $Organization BaseUrl = "https://$Organization.zendesk.com" Credential = [System.Management.Automation.PSCredential]::New("$Username/token", $ApiKey) + User = $null } $context | Add-Member -TypeName 'ZendeskContext' + + if (-not (Test-Connection -context $context)) { + throw $Script:InvalidConnection + } + $context } diff --git a/functions/Test-Connection.ps1 b/functions/Test-Connection.ps1 index f42251d..01bf505 100644 --- a/functions/Test-Connection.ps1 +++ b/functions/Test-Connection.ps1 @@ -2,13 +2,15 @@ function Test-Connection { <# .Synopsis - Checks that api credentials have been stored. + Tests the validity of a supplied or stored Zendesk connection. .DESCRIPTION - Checks that api credentials have been stored. + Tests the validity of a supplied or stored Zendesk connection. Updating the stored information on the current user. .EXAMPLE - if (Test-ZendeskConnection) { - Search-Zendesk @searchParams - } + if (Test-ZendeskConnection -Context $Context) { + Search-Zendesk @searchParams + } + + Tests the connection to Zendesk before making a call to `Search-Zendesk` #> [OutputType([Boolean])] [CmdletBinding()] @@ -20,7 +22,7 @@ function Test-Connection { $Context = $null ) - $null = Get-AuthenticatedUser -Context $Context + $Context.User = Get-AuthenticatedUser -Context $Context $true } diff --git a/internal/Assert-IsAdmin.ps1 b/internal/Assert-IsAdmin.ps1 new file mode 100644 index 0000000..0e59fd1 --- /dev/null +++ b/internal/Assert-IsAdmin.ps1 @@ -0,0 +1,25 @@ +function Assert-IsAdmin { + <# + .SYNOPSIS + Asserts that the current user is an admin. + .DESCRIPTION + Asserts that the current user is an admin. + .EXAMPLE + PS C:\> Assert-IsAdmin -Context $Context + + Raises and exception if current user is not an admin + #> + [CmdletBinding()] + Param ( + # Zendesk Connection Context from `Get-ZendeskConnection` + [Parameter(Mandatory = $false)] + [PSTypeName('ZendeskContext')] + [PSCustomObject] + $Context = $null + ) + + if (-not (Test-IsAdmin -Context $Context)) { + throw ($Script:InvalidRoleMessage -f 'admin', $Context.User.Role) + } + +} diff --git a/internal/Assert-IsAgent.ps1 b/internal/Assert-IsAgent.ps1 new file mode 100644 index 0000000..dc9321f --- /dev/null +++ b/internal/Assert-IsAgent.ps1 @@ -0,0 +1,25 @@ +function Assert-IsAgent { + <# + .SYNOPSIS + Asserts that the current user is an agent or admin. + .DESCRIPTION + Asserts that the current user is an agent or admin. + .EXAMPLE + PS C:\> Assert-IsAgent -Context $Context + + Raises and exception if current user is not an agent or an admin + #> + [CmdletBinding()] + Param ( + # Zendesk Connection Context from `Get-ZendeskConnection` + [Parameter(Mandatory = $false)] + [PSTypeName('ZendeskContext')] + [PSCustomObject] + $Context = $null + ) + + if (-not (Test-IsAgent -Context $Context) -and -not (Test-IsAdmin -Context $Context)) { + throw ($Script:InvalidRoleMessage -f 'agent/admin', $Context.User.Role) + } + +} diff --git a/internal/Assert-IsEndUser.ps1 b/internal/Assert-IsEndUser.ps1 new file mode 100644 index 0000000..57d5a58 --- /dev/null +++ b/internal/Assert-IsEndUser.ps1 @@ -0,0 +1,25 @@ +function Assert-IsEndUser { + <# + .SYNOPSIS + Asserts that the current user is an end user. + .DESCRIPTION + Asserts that the current user is an end user. + .EXAMPLE + PS C:\> Assert-IsEndUSer -Context $Context + + Raises and exception if current user is not an end user + #> + [CmdletBinding()] + Param ( + # Zendesk Connection Context from `Get-ZendeskConnection` + [Parameter(Mandatory = $false)] + [PSTypeName('ZendeskContext')] + [PSCustomObject] + $Context = $null + ) + + if (-not (Test-IsEndUser -Context $Context)) { + throw ($Script:InvalidRoleMessage -f 'end-user', $Context.User.Role) + } + +} diff --git a/internal/Test-IsAdmin.ps1 b/internal/Test-IsAdmin.ps1 new file mode 100644 index 0000000..90a748e --- /dev/null +++ b/internal/Test-IsAdmin.ps1 @@ -0,0 +1,32 @@ +function Test-IsAdmin { + <# + .SYNOPSIS + Tests if the current user is an admin. + .DESCRIPTION + Tests if the current user is an admin. + .EXAMPLE + PS C:\> Test-IsAdmin -Context $Context + + Returns `$true` if the current user is an admin or `$false` otherwise. + #> + [CmdletBinding()] + Param ( + # Zendesk Connection Context from `Get-ZendeskConnection` + [Parameter(Mandatory = $false)] + [PSTypeName('ZendeskContext')] + [PSCustomObject] + $Context = $null + ) + + # Determine the context + if ($null -eq $Context) { + if (Test-Path Variable:\Script:Context) { + $Context = $Script:Context + } else { + throw $Script:NotConnectedMessage + } + } + + $Context.User.Role -eq 'admin' + +} diff --git a/internal/Test-IsAgent.ps1 b/internal/Test-IsAgent.ps1 new file mode 100644 index 0000000..910c6b7 --- /dev/null +++ b/internal/Test-IsAgent.ps1 @@ -0,0 +1,32 @@ +function Test-IsAgent { + <# + .SYNOPSIS + Tests if the current user is an agent. + .DESCRIPTION + Tests if the current user is an agent. + .EXAMPLE + PS C:\> Test-IsAgent -Context $Context + + Returns `$true` if the current user is an agent or `$false` otherwise. + #> + [CmdletBinding()] + Param ( + # Zendesk Connection Context from `Get-ZendeskConnection` + [Parameter(Mandatory = $false)] + [PSTypeName('ZendeskContext')] + [PSCustomObject] + $Context = $null + ) + + # Determine the context + if ($null -eq $Context) { + if (Test-Path Variable:\Script:Context) { + $Context = $Script:Context + } else { + throw $Script:NotConnectedMessage + } + } + + $Context.User.Role -eq 'agent' + +} diff --git a/internal/Test-IsEndUser.ps1 b/internal/Test-IsEndUser.ps1 new file mode 100644 index 0000000..d89a118 --- /dev/null +++ b/internal/Test-IsEndUser.ps1 @@ -0,0 +1,32 @@ +function Test-IsEndUser { + <# + .SYNOPSIS + Tests if the current user is an end user. + .DESCRIPTION + Tests if the current user is an end user. + .EXAMPLE + PS C:\> Test-IsEndUser -Context $Context + + Returns `$true` if the current user is an end user or `$false` otherwise. + #> + [CmdletBinding()] + Param ( + # Zendesk Connection Context from `Get-ZendeskConnection` + [Parameter(Mandatory = $false)] + [PSTypeName('ZendeskContext')] + [PSCustomObject] + $Context = $null + ) + + # Determine the context + if ($null -eq $Context) { + if (Test-Path Variable:\Script:Context) { + $Context = $Script:Context + } else { + throw $Script:NotConnectedMessage + } + } + + $Context.User.Role -eq 'end-user' + +} diff --git a/tests/Assertions.tests.ps1 b/tests/Assertions.tests.ps1 new file mode 100644 index 0000000..d24d7ce --- /dev/null +++ b/tests/Assertions.tests.ps1 @@ -0,0 +1,110 @@ +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '')] +Param() + +Import-Module "$PSScriptRoot/../PwshZendesk.psm1" -Force + +Describe 'Users Routes' { + + InModuleScope PwshZendesk { + + $context = @{ + Organization = 'company' + BaseUrl = 'https://company.testdesk.com' + Credential = [System.Management.Automation.PSCredential]::New('email', ('api-key' | ConvertTo-SecureString -AsPlainText -Force)) + User = [PSCustomObject]@{ role = '' } + } + $context | Add-Member -TypeName 'ZendeskContext' + + Context 'Admin' { + + $context.User.role = 'admin' + + It 'Test-IsAdmin => $true' { + Test-IsAdmin -Context $context | Should -Be $true + } + + It 'Test-IsAgent => $false' { + Test-IsAgent -Context $context | Should -Be $false + } + + It 'Test-IsEndUser => $false' { + Test-IsEndUser -Context $context | Should -Be $false + } + + It 'Assert-IsAdmin passes' { + { Assert-IsAdmin -Context $context } | Should -Not -Throw + } + + It 'Assert-IsAgent passes' { + { Assert-IsAgent -Context $context } | Should -Not -Throw + } + + It 'Assert-IsEndUser throws' { + { Assert-IsEndUser -Context $context } | Should -Throw + } + + } + + Context 'Agent' { + + $context.User.role = 'agent' + + It 'Test-IsAdmin => $false' { + Test-IsAdmin -Context $context | Should -Be $false + } + + It 'Test-IsAgent => $true' { + Test-IsAgent -Context $context | Should -Be $true + } + + It 'Test-IsEndUser => $false' { + Test-IsEndUser -Context $context | Should -Be $false + } + + It 'Assert-IsAdmin throw' { + { Assert-IsAdmin -Context $context } | Should -Throw + } + + It 'Assert-IsAgent passes' { + { Assert-IsAgent -Context $context } | Should -Not -Throw + } + + It 'Assert-IsEndUser throws' { + { Assert-IsEndUser -Context $context } | Should -Throw + } + + } + + Context 'End User' { + + $context.User.role = 'end-user' + + It 'Test-IsAdmin => $false' { + Test-IsAdmin -Context $context | Should -Be $false + } + + It 'Test-IsAgent => $false' { + Test-IsAgent -Context $context | Should -Be $false + } + + It 'Test-IsEndUser => $true' { + Test-IsEndUser -Context $context | Should -Be $true + } + + It 'Assert-IsAdmin throws' { + { Assert-IsAdmin -Context $context } | Should -Throw + } + + It 'Assert-IsAgent throws' { + { Assert-IsAgent -Context $context } | Should -Throw + } + + It 'Assert-IsEndUser passes' { + { Assert-IsEndUser -Context $context } | Should -Not -Throw + } + + } + + } + +} diff --git a/tests/Get-UserIdentity.tests.ps1 b/tests/Get-UserIdentity.tests.ps1 index 4c6d8c8..5555144 100644 --- a/tests/Get-UserIdentity.tests.ps1 +++ b/tests/Get-UserIdentity.tests.ps1 @@ -14,6 +14,7 @@ Describe 'Get-UserIdentity' { Organization = 'company' BaseUrl = 'https://company.testdesk.com' Credential = [System.Management.Automation.PSCredential]::New("email", ('api-key' | ConvertTo-SecureString -AsPlainText -Force)) + User = [PSCustomObject]@{ role = 'admin' } } $context | Add-Member -TypeName 'ZendeskContext' diff --git a/tests/New-UserIdentity.tests.ps1 b/tests/New-UserIdentity.tests.ps1 index 0cdc2b0..bc90fe5 100644 --- a/tests/New-UserIdentity.tests.ps1 +++ b/tests/New-UserIdentity.tests.ps1 @@ -14,6 +14,7 @@ Describe 'New-UserIdentity' { Organization = 'company' BaseUrl = 'https://company.testdesk.com' Credential = [System.Management.Automation.PSCredential]::New("email", ('api-key' | ConvertTo-SecureString -AsPlainText -Force)) + User = [PSCustomObject]@{ role = 'admin' } } $context | Add-Member -TypeName 'ZendeskContext' @@ -116,7 +117,7 @@ Describe 'New-UserIdentity' { } It 'Does nothing in WhatIf' { - Remove-UserIdentity -UserId 1 -Id 1 -WhatIf + New-UserIdentity -Context $context -UserId 1 -Type 'email' -Value 'name@company.com' -WhatIf Assert-MockCalled Invoke-Method -Exactly 0 -Scope It } } diff --git a/tests/Remove-UserIdentity.tests.ps1 b/tests/Remove-UserIdentity.tests.ps1 index a28a09e..b3abf63 100644 --- a/tests/Remove-UserIdentity.tests.ps1 +++ b/tests/Remove-UserIdentity.tests.ps1 @@ -14,6 +14,7 @@ Describe 'Remove-UserIdentity' { Organization = 'company' BaseUrl = 'https://company.testdesk.com' Credential = [System.Management.Automation.PSCredential]::New("email", ('api-key' | ConvertTo-SecureString -AsPlainText -Force)) + User = [PSCustomObject]@{ role = 'admin' } } $context | Add-Member -TypeName 'ZendeskContext' diff --git a/tests/Send-UserIdentityVerification.tests.ps1 b/tests/Send-UserIdentityVerification.tests.ps1 index 6528ea7..a096efc 100644 --- a/tests/Send-UserIdentityVerification.tests.ps1 +++ b/tests/Send-UserIdentityVerification.tests.ps1 @@ -14,6 +14,7 @@ Describe 'Send-UserIdentityVerification' { Organization = 'company' BaseUrl = 'https://company.testdesk.com' Credential = [System.Management.Automation.PSCredential]::New("email", ('api-key' | ConvertTo-SecureString -AsPlainText -Force)) + User = [PSCustomObject]@{ role = 'admin' } } $context | Add-Member -TypeName 'ZendeskContext' diff --git a/tests/Set-UserIdentityAsPrimary.tests.ps1 b/tests/Set-UserIdentityAsPrimary.tests.ps1 index 957f4c0..70d190f 100644 --- a/tests/Set-UserIdentityAsPrimary.tests.ps1 +++ b/tests/Set-UserIdentityAsPrimary.tests.ps1 @@ -14,6 +14,7 @@ Describe 'Set-UserIdentityAsPrimary' { Organization = 'company' BaseUrl = 'https://company.testdesk.com' Credential = [System.Management.Automation.PSCredential]::New("email", ('api-key' | ConvertTo-SecureString -AsPlainText -Force)) + User = [PSCustomObject]@{ role = 'admin' } } $context | Add-Member -TypeName 'ZendeskContext' diff --git a/tests/Set-UserIdentityAsVerified.tests.ps1 b/tests/Set-UserIdentityAsVerified.tests.ps1 index 5c697b2..e0734b1 100644 --- a/tests/Set-UserIdentityAsVerified.tests.ps1 +++ b/tests/Set-UserIdentityAsVerified.tests.ps1 @@ -14,6 +14,7 @@ Describe 'Set-UserIdentityAsVerified' { Organization = 'company' BaseUrl = 'https://company.testdesk.com' Credential = [System.Management.Automation.PSCredential]::New("email", ('api-key' | ConvertTo-SecureString -AsPlainText -Force)) + User = [PSCustomObject]@{ role = 'admin' } } $context | Add-Member -TypeName 'ZendeskContext' @@ -51,18 +52,13 @@ Describe 'Set-UserIdentityAsVerified' { { Set-UserIdentityAsVerified -UserId 'a' -Id 1 } | Should -Throw } - It 'Hits the correct endpoint' { - Set-UserIdentityAsVerified -UserId 1 -Id 1 -Confirm:$false - Assert-MockCalled Invoke-Method -Exactly 1 -ParameterFilter { $Path -match '/api/v2/users/\d+/identities/\d+/verify' -and $Method -eq 'Put' } -Scope It - } - It 'Passes on the UserId' { - Set-UserIdentityAsVerified -UserId 736088406 -Id 1 -Confirm:$false + Set-UserIdentityAsVerified -Context $context -UserId 736088406 -Id 1 -Confirm:$false Assert-MockCalled Invoke-Method -Exactly 1 -ParameterFilter { $Path -match '736088406' } -Scope It } It 'Passes on the Id' { - Set-UserIdentityAsVerified -UserId 1 -Id 736088406 -Confirm:$false + Set-UserIdentityAsVerified -Context $context -UserId 1 -Id 736088406 -Confirm:$false Assert-MockCalled Invoke-Method -Exactly 1 -ParameterFilter { $Path -match '736088406' } -Scope It } @@ -72,7 +68,7 @@ Describe 'Set-UserIdentityAsVerified' { } It 'Does nothing in WhatIf' { - Set-UserIdentityAsVerified -UserId 1 -Id 1 -WhatIf + Set-UserIdentityAsVerified -Context $context -UserId 1 -Id 1 -WhatIf Assert-MockCalled Invoke-Method -Exactly 0 -Scope It } }