From 9777e7216e2c645183ee2b91254cd4391a9428f8 Mon Sep 17 00:00:00 2001 From: Oliver Lipkau Date: Sun, 27 May 2018 21:17:28 +0200 Subject: [PATCH 1/9] WIP --- .../ConvertTo-JiraFilterPermission.ps1 | 39 +++++ JiraPS/Private/ConvertTo-JiraProjectRole.ps1 | 29 ++++ JiraPS/Private/Resolve-FullPath.ps1 | 35 +++++ JiraPS/Public/Add-JiraFilterPermission.ps1 | 81 ++++++++++ JiraPS/Public/Get-JiraFilterPermission.ps1 | 41 +++++ JiraPS/Public/Remove-JiraFilterPermission.ps1 | 39 +++++ .../commands/Add-JiraFilterPermission.md | 141 ++++++++++++++++++ .../commands/Get-JiraFilterPermission.md | 78 ++++++++++ .../commands/Remove-JiraFilterPermission.md | 110 ++++++++++++++ 9 files changed, 593 insertions(+) create mode 100644 JiraPS/Private/ConvertTo-JiraFilterPermission.ps1 create mode 100644 JiraPS/Private/ConvertTo-JiraProjectRole.ps1 create mode 100644 JiraPS/Private/Resolve-FullPath.ps1 create mode 100644 JiraPS/Public/Add-JiraFilterPermission.ps1 create mode 100644 JiraPS/Public/Get-JiraFilterPermission.ps1 create mode 100644 JiraPS/Public/Remove-JiraFilterPermission.ps1 create mode 100644 docs/en-US/commands/Add-JiraFilterPermission.md create mode 100644 docs/en-US/commands/Get-JiraFilterPermission.md create mode 100644 docs/en-US/commands/Remove-JiraFilterPermission.md diff --git a/JiraPS/Private/ConvertTo-JiraFilterPermission.ps1 b/JiraPS/Private/ConvertTo-JiraFilterPermission.ps1 new file mode 100644 index 00000000..bdc9b0c6 --- /dev/null +++ b/JiraPS/Private/ConvertTo-JiraFilterPermission.ps1 @@ -0,0 +1,39 @@ +function ConvertTo-JiraFilterPermission { + [CmdletBinding()] + param( + [Parameter( ValueFromPipeline )] + [PSObject[]] + $InputObject + ) + + process { + foreach ($i in $InputObject) { + Write-Debug "[$($MyInvocation.MyCommand.Name)] Converting `$InputObject to custom object" + + $props = @{ + 'ID' = $i.id + 'Type' = $i.type + 'Group' = $null + 'Project' = $null + 'Role' = $null + } + if ($i.group) { + $props["Group"] = ConvertTo-JiraGroup $i.group + } + if ($i.project) { + $props["Project"] = ConvertTo-JiraProject $i.project + } + if ($i.role) { + $props["Role"] = ConvertTo-JiraProjectRole $i.role + } + + $result = New-Object -TypeName PSObject -Property $props + $result.PSObject.TypeNames.Insert(0, 'JiraPS.FilterPermission') + $result | Add-Member -MemberType ScriptMethod -Name 'ToString' -Force -Value { + Write-Output "$($this.Id)" + } + + Write-Output $result + } + } +} diff --git a/JiraPS/Private/ConvertTo-JiraProjectRole.ps1 b/JiraPS/Private/ConvertTo-JiraProjectRole.ps1 new file mode 100644 index 00000000..685dfea9 --- /dev/null +++ b/JiraPS/Private/ConvertTo-JiraProjectRole.ps1 @@ -0,0 +1,29 @@ +function ConvertTo-JiraProjectRole { + [CmdletBinding()] + param( + [Parameter( ValueFromPipeline )] + [PSObject[]] + $InputObject + ) + + process { + foreach ($i in $InputObject) { + Write-Debug "[$($MyInvocation.MyCommand.Name)] Converting `$InputObject to custom object" + + $props = @{ + 'ID' = $i.id + 'Name' = $i.name + 'RestUrl' = $i.self + 'ProjectId' = $i.projectId + } + + $result = New-Object -TypeName PSObject -Property $props + $result.PSObject.TypeNames.Insert(0, 'JiraPS.ProjectRole') + $result | Add-Member -MemberType ScriptMethod -Name "ToString" -Force -Value { + Write-Output "$($this.Name)" + } + + Write-Output $result + } + } +} diff --git a/JiraPS/Private/Resolve-FullPath.ps1 b/JiraPS/Private/Resolve-FullPath.ps1 new file mode 100644 index 00000000..75e4af72 --- /dev/null +++ b/JiraPS/Private/Resolve-FullPath.ps1 @@ -0,0 +1,35 @@ +function Resolve-FullPath { + [CmdletBinding()] + param ( + # Path to be resolved. + # Can be realtive or absolute. + # Resolves PSDrives + [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] + [ValidateNotNullOrEmpty()] + [ValidateScript( + { + if (-not (Test-Path $_ -PathType Leaf)) { + $errorItem = [System.Management.Automation.ErrorRecord]::new( + ([System.ArgumentException]"File not found"), + 'ParameterValue.FileNotFound', + [System.Management.Automation.ErrorCategory]::ObjectNotFound, + $_ + ) + $errorItem.ErrorDetails = "No file could be found with the provided path '$_'." + $PSCmdlet.ThrowTerminatingError($errorItem) + } + else { + return $true + } + } + )] + [Alias( 'FullName', 'PSPath' )] + [String] + $Path + ) + + process { + Write-Verbose "[$($MyInvocation.MyCommand.Name)] Resolving path $Path" + $PSCmdlet.GetUnresolvedProviderPathFromPSPath($Path) + } +} diff --git a/JiraPS/Public/Add-JiraFilterPermission.ps1 b/JiraPS/Public/Add-JiraFilterPermission.ps1 new file mode 100644 index 00000000..e21bbb6f --- /dev/null +++ b/JiraPS/Public/Add-JiraFilterPermission.ps1 @@ -0,0 +1,81 @@ +function Add-JiraFilterPermission { + [CmdletBinding( SupportsShouldProcess )] + param( + # Filter object to which the permission should be applied + [Parameter( Mandatory, ValueFromPipeline )] + [ValidateNotNullOrEmpty()] + [PSTypeName('JiraPS.Filter')] + $Filter, + + # Type of the permission to add + [Parameter( Mandatory )] + [ValidateNotNullOrEmpty()] + [ValidateSet('Group', 'Project', 'ProjectRole', 'Authenticated', 'Global')] + [String]$Type, + + # Value for the Type of the permission + # + # The Value differs per Type of the permission. + # Here is a table to know what Value to provide: + # + # |Type |Value |Source | + # |-------------|---------------------|----------------------------------------------------| + # |Group |Name of the Group |Can be retrieved with `(Get-JiraGroup ...).Name` | + # |Project |Id of the Project |Can be retrieved with `(Get-JiraProject ...).Id` | + # |ProjectRole |Id of the ProjectRole|Can be retrieved with `(Get-JiraProjectRole ...).Id`| + # |Authenticated| **must be null** | | + # |Global | **must be null** | | + [String]$Value, + + # Credentials to use to connect to JIRA. + # + # If not specified, this function will use anonymous access. + [PSCredential] + $Credential + ) + + begin { + Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" + + $resourceURi = "{0}/permission" + } + + process { + Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" + Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" + + $body = @{ + type = $Type.ToLower() + } + switch ($Type) { + "Group" { + $body["groupname"] = $Value + } + "Project" { + $body["projectId"] = $Value + } + "ProjectRole" { + $body["projectRoleId"] = $Value + } + "Authenticated" { } + "Global" { } + } + + $parameter = @{ + URI = $resourceURi -f $Filter.RestURL + Method = "POST" + Body = ConvertTo-Json $body + Credential = $Credential + } + Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" + if ($PSCmdlet.ShouldProcess($Filter.Name, "Add Permission [$Type - $Value]")) { + $result = Invoke-JiraMethod @parameter + + Write-Output (ConvertTo-JiraFilterPermission -InputObject $result) + } + } + + end { + Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" + } +} diff --git a/JiraPS/Public/Get-JiraFilterPermission.ps1 b/JiraPS/Public/Get-JiraFilterPermission.ps1 new file mode 100644 index 00000000..8c3a992a --- /dev/null +++ b/JiraPS/Public/Get-JiraFilterPermission.ps1 @@ -0,0 +1,41 @@ +function Get-JiraFilterPermission { + [CmdletBinding()] + param( + # Filter object from which to retrieve the permissions + [Parameter( Mandatory, ValueFromPipeline )] + [ValidateNotNullOrEmpty()] + [PSTypeName('JiraPS.Filter')] + $Filter, + + # Credentials to use to connect to JIRA. + # + # If not specified, this function will use anonymous access. + [PSCredential] + $Credential + ) + + begin { + Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" + + $resourceURi = "{0}/permission" + } + + process { + Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" + Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" + + $parameter = @{ + URI = $resourceURi -f $Filter.RestURL + Method = "GET" + Credential = $Credential + } + Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" + $result = Invoke-JiraMethod @parameter + + Write-Output (ConvertTo-JiraFilterPermission -InputObject $result) + } + + end { + Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" + } +} diff --git a/JiraPS/Public/Remove-JiraFilterPermission.ps1 b/JiraPS/Public/Remove-JiraFilterPermission.ps1 new file mode 100644 index 00000000..d0313502 --- /dev/null +++ b/JiraPS/Public/Remove-JiraFilterPermission.ps1 @@ -0,0 +1,39 @@ +function Remove-JiraFilterPermission { + [CmdletBinding( SupportsShouldProcess )] + param( + # Filter object to which the permission should be applied + [Parameter( Mandatory, ValueFromPipeline )] + [ValidateNotNullOrEmpty()] + [PSTypeName('JiraPS.FilterPermission')] + $InputObject, + + # Credentials to use to connect to JIRA. + # + # If not specified, this function will use anonymous access. + [PSCredential] + $Credential + ) + + begin { + Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" + } + + process { + Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" + Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" + + $parameter = @{ + URI = $InputObject.RestURL + Method = "DELETE" + Credential = $Credential + } + Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" + if ($PSCmdlet.ShouldProcess($InputObject.Type, "Remove Permission")) { + Invoke-JiraMethod @parameter + } + } + + end { + Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" + } +} diff --git a/docs/en-US/commands/Add-JiraFilterPermission.md b/docs/en-US/commands/Add-JiraFilterPermission.md new file mode 100644 index 00000000..4ef07c0f --- /dev/null +++ b/docs/en-US/commands/Add-JiraFilterPermission.md @@ -0,0 +1,141 @@ +--- +external help file: JiraPS-help.xml +Module Name: JiraPS +online version: +schema: 2.0.0 +--- + +# Add-JiraFilterPermission + +## SYNOPSIS +{{Fill in the Synopsis}} + +## SYNTAX + +``` +Add-JiraFilterPermission [-Filter] [-Type] [[-Value] ] [[-Credential] ] + [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +{{Fill in the Description}} + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> {{ Add example code here }} +``` + +{{ Add example description here }} + +## PARAMETERS + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Credential +{{Fill Credential Description}} + +```yaml +Type: PSCredential +Parameter Sets: (All) +Aliases: + +Required: False +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Filter +{{Fill Filter Description}} + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Type +{{Fill Type Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: +Accepted values: Group, Project, ProjectRole, Authenticated, Global + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Value +{{Fill Value Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.Object + + +## OUTPUTS + +### System.Object + +## NOTES + +## RELATED LINKS diff --git a/docs/en-US/commands/Get-JiraFilterPermission.md b/docs/en-US/commands/Get-JiraFilterPermission.md new file mode 100644 index 00000000..98eb689e --- /dev/null +++ b/docs/en-US/commands/Get-JiraFilterPermission.md @@ -0,0 +1,78 @@ +--- +external help file: JiraPS-help.xml +Module Name: JiraPS +online version: https://atlassianps.org/docs/JiraPS/commands/Get-JiraFilter/ +schema: 2.0.0 +--- + +# Get-JiraFilterPermission + +## SYNOPSIS +{{Fill in the Synopsis}} + +## SYNTAX + +``` +Get-JiraFilterPermission [-Filter] [[-Credential] ] [] +``` + +## DESCRIPTION +{{Fill in the Description}} + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> {{ Add example code here }} +``` + +{{ Add example description here }} + +## PARAMETERS + +### -Credential +{{Fill Credential Description}} + +```yaml +Type: PSCredential +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Filter +{{Fill Filter Description}} + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.Object + + +## OUTPUTS + +### System.Object + +## NOTES + +## RELATED LINKS diff --git a/docs/en-US/commands/Remove-JiraFilterPermission.md b/docs/en-US/commands/Remove-JiraFilterPermission.md new file mode 100644 index 00000000..aaf802cb --- /dev/null +++ b/docs/en-US/commands/Remove-JiraFilterPermission.md @@ -0,0 +1,110 @@ +--- +external help file: JiraPS-help.xml +Module Name: JiraPS +online version: https://atlassianps.org/docs/JiraPS/commands/New-JiraVersion/ +schema: 2.0.0 +--- + +# Remove-JiraFilterPermission + +## SYNOPSIS +{{Fill in the Synopsis}} + +## SYNTAX + +``` +Remove-JiraFilterPermission [-InputObject] [[-Credential] ] [-WhatIf] [-Confirm] + [] +``` + +## DESCRIPTION +{{Fill in the Description}} + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> {{ Add example code here }} +``` + +{{ Add example description here }} + +## PARAMETERS + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Credential +{{Fill Credential Description}} + +```yaml +Type: PSCredential +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -InputObject +{{Fill InputObject Description}} + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.Object + + +## OUTPUTS + +### System.Object + +## NOTES + +## RELATED LINKS From 6f76a61cef9f96e84c286d45e18f44abb1caf7c9 Mon Sep 17 00:00:00 2001 From: Oliver Lipkau Date: Thu, 14 Jun 2018 20:22:17 +0200 Subject: [PATCH 2/9] Updated documentation on Add-JiraFilterPermission * added tests (WIP) * added external help * added -Id parameterSet * changed documentation on other functions (WIP) --- JiraPS/Public/Add-JiraFilterPermission.ps1 | 40 +++--- Tests/Add-JiraFilterPermission.Tests.ps1 | 125 +++++++++++++++++ .../commands/Add-JiraFilterPermission.md | 131 ++++++++++++------ docs/en-US/commands/Remove-JiraFilter.md | 2 +- .../commands/Remove-JiraFilterPermission.md | 2 +- 5 files changed, 237 insertions(+), 63 deletions(-) create mode 100644 Tests/Add-JiraFilterPermission.Tests.ps1 diff --git a/JiraPS/Public/Add-JiraFilterPermission.ps1 b/JiraPS/Public/Add-JiraFilterPermission.ps1 index e21bbb6f..b0fa88c0 100644 --- a/JiraPS/Public/Add-JiraFilterPermission.ps1 +++ b/JiraPS/Public/Add-JiraFilterPermission.ps1 @@ -1,37 +1,27 @@ function Add-JiraFilterPermission { - [CmdletBinding( SupportsShouldProcess )] + [CmdletBinding( SupportsShouldProcess, DefaultParameterSetName = 'ByInputObject' )] + [OutputType( [JiraPS.FilterPermission] )] param( - # Filter object to which the permission should be applied - [Parameter( Mandatory, ValueFromPipeline )] + [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = 'ByInputObject' )] [ValidateNotNullOrEmpty()] [PSTypeName('JiraPS.Filter')] $Filter, - # Type of the permission to add - [Parameter( Mandatory )] + [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = 'ById')] + [UInt32[]] + $Id, + + [Parameter( Position = 1, Mandatory )] [ValidateNotNullOrEmpty()] [ValidateSet('Group', 'Project', 'ProjectRole', 'Authenticated', 'Global')] [String]$Type, - # Value for the Type of the permission - # - # The Value differs per Type of the permission. - # Here is a table to know what Value to provide: - # - # |Type |Value |Source | - # |-------------|---------------------|----------------------------------------------------| - # |Group |Name of the Group |Can be retrieved with `(Get-JiraGroup ...).Name` | - # |Project |Id of the Project |Can be retrieved with `(Get-JiraProject ...).Id` | - # |ProjectRole |Id of the ProjectRole|Can be retrieved with `(Get-JiraProjectRole ...).Id`| - # |Authenticated| **must be null** | | - # |Global | **must be null** | | [String]$Value, - # Credentials to use to connect to JIRA. - # - # If not specified, this function will use anonymous access. - [PSCredential] - $Credential + [Parameter()] + [System.Management.Automation.PSCredential] + [System.Management.Automation.Credential()] + $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { @@ -44,6 +34,12 @@ Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" + if ($PSCmdlet.ParameterSetName -eq 'ById') { + $InputObject = foreach ($_id in $Id) { + Get-JiraFilter -Id $_id + } + } + $body = @{ type = $Type.ToLower() } diff --git a/Tests/Add-JiraFilterPermission.Tests.ps1 b/Tests/Add-JiraFilterPermission.Tests.ps1 new file mode 100644 index 00000000..1d56300e --- /dev/null +++ b/Tests/Add-JiraFilterPermission.Tests.ps1 @@ -0,0 +1,125 @@ +Describe 'Add-JiraFilterPermission' { + BeforeAll { + Remove-Module JiraPS -ErrorAction SilentlyContinue + Import-Module "$PSScriptRoot/../JiraPS" -Force -ErrorAction Stop + } + + InModuleScope JiraPS { + + . "$PSScriptRoot/Shared.ps1" + + #region Definitions + $jiraServer = "https://jira.example.com" + + $responseFilter = @" +{ + "self": "$jiraServer/rest/api/latest/filter/12844", + "id": "12844", + "name": "{0}", + "jql": "{1}", + "favourite": false +} +"@ + #endregion Definitions + + #region Mocks + Mock Get-JiraConfigServer -ModuleName JiraPS { + $jiraServer + } + + Mock ConvertTo-JiraFilterPermission -ModuleName JiraPS { + $i = (ConvertFrom-Json $responseFilter) + $i.PSObject.TypeNames.Insert(0, 'JiraPS.FilterPermission') + $i + } + + Mock Get-JiraFilter -ModuleName JiraPS { + ConvertTo-JiraFilter + } + + Mock Invoke-JiraMethod -ModuleName JiraPS -ParameterFilter {$Method -eq 'Post' -and $URI -like "$jiraServer/rest/api/*/filter"} { + ShowMockInfo 'Invoke-JiraMethod' 'Method', 'Uri', 'Body' + ConvertFrom-Json $responseFilter + } + + Mock Invoke-JiraMethod -ModuleName JiraPS { + ShowMockInfo 'Invoke-JiraMethod' 'Method', 'Uri' + throw "Unidentified call to Invoke-JiraMethod" + } + #endregion Mocks + + Context "Sanity checking" { + $command = Get-Command -Name Add-JiraFilterPermission + + defParam $command 'Filter' + defParam $command 'Type' + defParam $command 'Value' + defParam $command 'Credential' + } + + Context "Behavior testing" { + It "Invokes the Jira API to create a filter" { + { + $newData = @{ + Name = "myName" + Description = "myDescription" + JQL = "myJQL" + Favorite = $true + } + New-JiraFilter @newData + } | Should Not Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It -ParameterFilter { + $Method -eq 'Post' -and + $URI -like '*/rest/api/*/filter' -and + $Body -match "`"name`":\s*`"myName`"" -and + $Body -match "`"description`":\s*`"myDescription`"" -and + $Body -match "`"jql`":\s*`"myJQL`"" -and + $Body -match "`"favourite`":\s*true" + } + } + } + + Context "Input testing" { + It "-Name and -JQL" { + { + $parameter = @{ + Name = "newName" + JQL = "newJQL" + } + New-JiraFilter @parameter + } | Should Not Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It + } + It "-Name and -Description and -JQL" { + { + $parameter = @{ + Name = "newName" + Description = "newDescription" + JQL = "newJQL" + } + New-JiraFilter @parameter + } | Should Not Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It + } + It "-Name and -Description and -JQL and -Favorite" { + { + $parameter = @{ + Name = "newName" + Description = "newDescription" + JQL = "newJQL" + Favorite = $true + } + New-JiraFilter @parameter + } | Should Not Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It + } + It "maps the properties of an object to the parameters" { + { Get-JiraFilter "12345" | New-JiraFilter } | Should Not Throw + } + } + } +} diff --git a/docs/en-US/commands/Add-JiraFilterPermission.md b/docs/en-US/commands/Add-JiraFilterPermission.md index 4ef07c0f..ea354d97 100644 --- a/docs/en-US/commands/Add-JiraFilterPermission.md +++ b/docs/en-US/commands/Add-JiraFilterPermission.md @@ -1,68 +1,74 @@ --- external help file: JiraPS-help.xml Module Name: JiraPS -online version: +online version: https://atlassianps.org/docs/JiraPS/commands/Add-JiraFilterPermission/ +locale: en-US schema: 2.0.0 +layout: documentation +permalink: /docs/JiraPS/commands/Add-JiraFilterPermission/ --- - # Add-JiraFilterPermission ## SYNOPSIS -{{Fill in the Synopsis}} + +Share a Filter with other users. ## SYNTAX +### ByInputObject (Default) + +```powershell +Add-JiraFilterPermission [-Filter] [-Type] [[-Value] ] + [[-Credential] ] [-WhatIf] [-Confirm] [] ``` -Add-JiraFilterPermission [-Filter] [-Type] [[-Value] ] [[-Credential] ] - [-WhatIf] [-Confirm] [] + +### ById + +```powershell +Add-JiraFilterPermission [-Id] [-Type] [[-Value] ] + [[-Credential] ] [-WhatIf] [-Confirm] [] ``` ## DESCRIPTION -{{Fill in the Description}} + +Share a Filter with other users, such as "Group", "Project", "ProjectRole", +"Authenticated" or "Global". ## EXAMPLES ### Example 1 + ```powershell -PS C:\> {{ Add example code here }} +Add-JiraFilterPermission -Filter (Get-JiraFilter 12345) -Type "Global" +#------- +Add-JiraFilterPermission -Id 12345 -Type "Global" ``` -{{ Add example description here }} - -## PARAMETERS +Two methods of sharing Filter 12345 with everyone. -### -Confirm -Prompts you for confirmation before running the cmdlet. - -```yaml -Type: SwitchParameter -Parameter Sets: (All) -Aliases: cf +### Example 2 -Required: False -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False +```powershell +12345 | Add-JiraFilterPermission -Type "Authenticated" ``` -### -Credential -{{Fill Credential Description}} +Share Filter 12345 with authenticated users. -```yaml -Type: PSCredential -Parameter Sets: (All) -Aliases: +_The Id could be read from a file._ -Required: False -Position: 3 -Default value: None -Accept pipeline input: False -Accept wildcard characters: False +### Example 3 + +```powershell +Get-JiraFilter 12345 | Add-JiraFilterPermission -Type "Group" -Value "administrators" ``` +Share Filter 12345 only with users in the administrators groups. + +## PARAMETERS + ### -Filter -{{Fill Filter Description}} + +Filter object to which the permission should be applied ```yaml Type: Object @@ -77,7 +83,8 @@ Accept wildcard characters: False ``` ### -Type -{{Fill Type Description}} + +Type of the permission to add ```yaml Type: String @@ -93,7 +100,19 @@ Accept wildcard characters: False ``` ### -Value -{{Fill Value Description}} + +Value for the Type of the permission. + +The Value differs per Type of the permission. + +Here is a table to know what Value to provide: +|Type |Value |Source | +|-------------|---------------------|----------------------------------------------------| +|Group |Name of the Group |Can be retrieved with `(Get-JiraGroup ...).Name` | +|Project |Id of the Project |Can be retrieved with `(Get-JiraProject ...).Id` | +|ProjectRole |Id of the ProjectRole|Can be retrieved with `(Get-JiraProjectRole ...).Id`| +|Authenticated| **must be null** | | +|Global | **must be null** | | ```yaml Type: String @@ -107,7 +126,25 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -Credential + +Credentials to use to connect to JIRA. +If not specified, this function will use anonymous access. + +```yaml +Type: PSCredential +Parameter Sets: (All) +Aliases: + +Required: False +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -WhatIf + Shows what would happen if the cmdlet runs. The cmdlet is not run. @@ -123,18 +160,34 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -Confirm + +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### CommonParameters + This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). ## INPUTS -### System.Object - +### [JiraPS.Filter] ## OUTPUTS -### System.Object +### [JiraPS.FilterPermission] ## NOTES diff --git a/docs/en-US/commands/Remove-JiraFilter.md b/docs/en-US/commands/Remove-JiraFilter.md index be4fbf57..b86af168 100644 --- a/docs/en-US/commands/Remove-JiraFilter.md +++ b/docs/en-US/commands/Remove-JiraFilter.md @@ -16,7 +16,7 @@ Removes an existing filter. ## SYNTAX ```powershell -Remove-JiraFilter [-InputObject] [-WhatIf] [-Confirm] [] +Remove-JiraFilter [-InputObject] [-WhatIf] [-Confirm] [] ``` ## DESCRIPTION diff --git a/docs/en-US/commands/Remove-JiraFilterPermission.md b/docs/en-US/commands/Remove-JiraFilterPermission.md index aaf802cb..41afe8c5 100644 --- a/docs/en-US/commands/Remove-JiraFilterPermission.md +++ b/docs/en-US/commands/Remove-JiraFilterPermission.md @@ -13,7 +13,7 @@ schema: 2.0.0 ## SYNTAX ``` -Remove-JiraFilterPermission [-InputObject] [[-Credential] ] [-WhatIf] [-Confirm] +Remove-JiraFilterPermission [-InputObject] [[-Credential] ] [-WhatIf] [-Confirm] [] ``` From 82f6a631567f89a1a8e6b5a19c14db33f2d357ed Mon Sep 17 00:00:00 2001 From: Oliver Lipkau Date: Thu, 21 Jun 2018 13:59:55 +0200 Subject: [PATCH 3/9] Implemented Remove-JiraFilterPermission --- JiraPS/Public/Remove-JiraFilterPermission.ps1 | 82 +++++++--- Tests/Remove-JiraFilterPermission.Tests.ps1 | 151 ++++++++++++++++++ .../commands/Remove-JiraFilterPermission.md | 135 ++++++++++++---- 3 files changed, 319 insertions(+), 49 deletions(-) create mode 100644 Tests/Remove-JiraFilterPermission.Tests.ps1 diff --git a/JiraPS/Public/Remove-JiraFilterPermission.ps1 b/JiraPS/Public/Remove-JiraFilterPermission.ps1 index d0313502..be5affac 100644 --- a/JiraPS/Public/Remove-JiraFilterPermission.ps1 +++ b/JiraPS/Public/Remove-JiraFilterPermission.ps1 @@ -1,17 +1,52 @@ function Remove-JiraFilterPermission { - [CmdletBinding( SupportsShouldProcess )] + [CmdletBinding( SupportsShouldProcess, DefaultParameterSetName = 'ByFilterId' )] param( - # Filter object to which the permission should be applied - [Parameter( Mandatory, ValueFromPipeline )] + [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = 'ByFilterObject' )] [ValidateNotNullOrEmpty()] - [PSTypeName('JiraPS.FilterPermission')] - $InputObject, - - # Credentials to use to connect to JIRA. - # - # If not specified, this function will use anonymous access. - [PSCredential] - $Credential + [ValidateScript( + { + if (@($Filter).Count -gt 1) { + $exception = ([System.ArgumentException]"Invalid Parameter") + $errorId = 'ParameterType.TooManyFilters' + $errorCategory = 'InvalidArgument' + $errorTarget = $_ + $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget + $errorItem.ErrorDetails = "Only one Filter can be passed at a time." + $PSCmdlet.ThrowTerminatingError($errorItem) + } + elseif (@($_.FilterPermissions).Count -lt 1) { + $exception = ([System.ArgumentException]"Invalid Type for Parameter") + $errorId = 'ParameterType.FilterWithoutPermission' + $errorCategory = 'InvalidArgument' + $errorTarget = $_ + $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget + $errorItem.ErrorDetails = "The Filter provided does not contain any Permission to delete." + $PSCmdlet.ThrowTerminatingError($errorItem) + } + else { + return $true + } + } + )] + [PSTypeName('JiraPS.Filter')] + $Filter, + + [Parameter( Position = 0, Mandatory, ParameterSetName = 'ByFilterId' )] + [ValidateNotNullOrEmpty()] + [Alias('Id')] + [UInt32] + $FilterId, + + # TODO: [Parameter( Position = 1, ParameterSetName = 'ByFilterObject')] + [Parameter( Position = 1, Mandatory, ParameterSetName = 'ByFilterId')] + [ValidateNotNullOrEmpty()] + [UInt32[]] + $PermissionId, + + [Parameter()] + [System.Management.Automation.PSCredential] + [System.Management.Automation.Credential()] + $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { @@ -22,14 +57,25 @@ Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" - $parameter = @{ - URI = $InputObject.RestURL - Method = "DELETE" - Credential = $Credential + switch ($PSCmdlet.ParameterSetName) { + "ByFilterObject" { + $PermissionId = $Filter.FilterPermissions.Id + } + "ByFilterId" { + $Filter = Get-JiraFilter -Id $FilterId + } } - Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" - if ($PSCmdlet.ShouldProcess($InputObject.Type, "Remove Permission")) { - Invoke-JiraMethod @parameter + + foreach ($_permissionId in $PermissionId) { + $parameter = @{ + URI = "{0}/permission/{1}" -f $Filter.RestURL, $_permissionId + Method = "DELETE" + Credential = $Credential + } + Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" + if ($PSCmdlet.ShouldProcess($InputObject.Type, "Remove Permission")) { + Invoke-JiraMethod @parameter + } } } diff --git a/Tests/Remove-JiraFilterPermission.Tests.ps1 b/Tests/Remove-JiraFilterPermission.Tests.ps1 new file mode 100644 index 00000000..8d34ed47 --- /dev/null +++ b/Tests/Remove-JiraFilterPermission.Tests.ps1 @@ -0,0 +1,151 @@ +Describe 'Remove-JiraFilterPermission' { + BeforeAll { + Remove-Module JiraPS -ErrorAction SilentlyContinue + Import-Module "$PSScriptRoot/../JiraPS" -Force -ErrorAction Stop + } + + InModuleScope JiraPS { + + . "$PSScriptRoot/Shared.ps1" + + #region Definitions + $jiraServer = "https://jira.example.com" + + $filterPermission1 = New-Object -TypeName PSCustomObject -Property @{ Id = 1111 } + $filterPermission1.PSObject.TypeNames.Insert(0, 'JiraPS.FilterPermission') + $filterPermission2 = New-Object -TypeName PSCustomObject -Property @{ Id = 2222 } + $filterPermission2.Id = 2222 + $fullFilter = New-Object -TypeName PSCustomObject -Property @{ + Id = 12345 + RestUrl = "$jiraServer/rest/api/2/filter/12345" + FilterPermissions = @( + $filterPermission1 + $filterPermission2 + ) + } + $fullFilter.PSObject.TypeNames.Insert(0, 'JiraPS.Filter') + $basicFilter = New-Object -TypeName PSCustomObject -Property @{ + Id = 23456 + RestUrl = "$jiraServer/rest/api/2/filter/23456" + } + $basicFilter.PSObject.TypeNames.Insert(0, 'JiraPS.Filter') + + #endregion Definitions + + #region Mocks + Mock Get-JiraConfigServer -ModuleName JiraPS { + $jiraServer + } + + Mock Get-JiraFilter -ModuleName JiraPS { + $basicFilter + } + + Mock Get-JiraFilterPermission -ModuleName JiraPS { + $fullFilter + } + + Mock Invoke-JiraMethod -ModuleName JiraPS -ParameterFilter {$Method -eq 'Delete' -and $URI -like "$jiraServer/rest/api/*/filter/*/permission*"} { + ShowMockInfo 'Invoke-JiraMethod' 'Method', 'Uri' + } + + Mock Invoke-JiraMethod -ModuleName JiraPS { + ShowMockInfo 'Invoke-JiraMethod' 'Method', 'Uri' + throw "Unidentified call to Invoke-JiraMethod" + } + #endregion Mocks + + Context "Sanity checking" { + $command = Get-Command -Name Remove-JiraFilterPermission + + defParam $command 'Filter' + defParam $command 'FilterId' + defParam $command 'PermissionId' + defParam $command 'Credential' + } + + Context "Behavior testing" { + It "Deletes Permission from Filter Object" { + { + Get-JiraFilterPermission -Id 1 | Remove-JiraFilterPermission + } | Should Not Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It -ParameterFilter { + $Method -eq 'Delete' -and + $URI -like '*/rest/api/*/filter/12345/permission/1111' + } + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It -ParameterFilter { + $Method -eq 'Delete' -and + $URI -like '*/rest/api/*/filter/12345/permission/2222' + } + } + + It "Deletes Permission from FilterId + PermissionId" { + { + Remove-JiraFilterPermission -FilterId 1 -PermissionId 3333, 4444 + } | Should Not Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It -ParameterFilter { + $Method -eq 'Delete' -and + $URI -like '*/rest/api/*/filter/23456/permission/3333' + } + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It -ParameterFilter { + $Method -eq 'Delete' -and + $URI -like '*/rest/api/*/filter/23456/permission/4444' + } + } + } + + Context "Input testing" { + It "validates the -Filter to ensure FilterPermissions" { + { Remove-JiraFilterPermission -Filter (Get-JiraFilter -Id 1) } | Should -Throw + { Remove-JiraFilterPermission -Filter (Get-JiraFilterPermission -Id 1) } | Should -Not -Throw + } + + It "finds the filter by FilterId" { + { Remove-JiraFilterPermission -FilterId 1 -PermissionId 1111 } | Should -Not -Throw + + Assert-MockCalled -CommandName Get-JiraFilter -ModuleName JiraPS -Exactly -Times 1 -Scope It + } + + It "does not accept negative FilterIds" { + { Remove-JiraFilterPermission -FilterId -1 -PermissionId 1111 } | Should -Throw + } + + It "does not accept negative PermissionIds" { + { Remove-JiraFilterPermission -FilterId 1 -PermissionId -1111 } | Should -Throw + } + + It "can only process one FilterId" { + { Remove-JiraFilterPermission -FilterId 1, 2 -PermissionId 1111 } | Should -Throw + } + + It "can process multiple PermissionIds" { + { Remove-JiraFilterPermission -FilterId 1 -PermissionId 1111, 2222 } | Should -Not -Throw + } + + It "allows for the filter to be passed over the pipeline" { + { Get-JiraFilterPermission -Id 1 | Remove-JiraFilterPermission } | Should -Not -Throw + } + + It "can ony process one Filter objects" { + $filter = @() + $filter += Get-JiraFilterPermission -Id 1 + $filter += Get-JiraFilterPermission -Id 1 + + { Remove-JiraFilterPermission -Filter $filter } | Should -Throw + } + + It "resolves positional parameters" { + { Remove-JiraFilterPermission 12345 1111 } | Should -Not -Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It + + $filter = Get-JiraFilterPermission -Id 1 + { Remove-JiraFilterPermission $filter } | Should -Not -Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 3 -Scope It + } + } + } +} diff --git a/docs/en-US/commands/Remove-JiraFilterPermission.md b/docs/en-US/commands/Remove-JiraFilterPermission.md index 41afe8c5..f60384b7 100644 --- a/docs/en-US/commands/Remove-JiraFilterPermission.md +++ b/docs/en-US/commands/Remove-JiraFilterPermission.md @@ -1,82 +1,125 @@ --- external help file: JiraPS-help.xml Module Name: JiraPS -online version: https://atlassianps.org/docs/JiraPS/commands/New-JiraVersion/ +online version: https://atlassianps.org/docs/JiraPS/commands/Remove-JiraFilterPermission/ +locale: en-US schema: 2.0.0 +layout: documentation +permalink: /docs/JiraPS/commands/Remove-JiraFilterPermission/ --- - # Remove-JiraFilterPermission ## SYNOPSIS -{{Fill in the Synopsis}} + +Remove a permission of a Filter ## SYNTAX +### ByFilterId (Default) + +```powershell +Remove-JiraFilterPermission [-Filter] [[-Credential] ] + [-WhatIf] [-Confirm] [] ``` -Remove-JiraFilterPermission [-InputObject] [[-Credential] ] [-WhatIf] [-Confirm] - [] + +### ByFilterObject + +```powershell +Remove-JiraFilterPermission [-FilterId] [-PermissionId] + [[-Credential] ] [-WhatIf] [-Confirm] [] ``` ## DESCRIPTION -{{Fill in the Description}} + +Remove a sharing permission of a Filter. ## EXAMPLES ### Example 1 + +```powershell +Remove-JiraFilterPermission -FilterId 11822 -PermissionId 1111, 2222 +``` + +Remove two share permissions of Filter with ID '11822' + +### Example 1 + ```powershell -PS C:\> {{ Add example code here }} +Get-JiraFilter 11822 | Get-JiraFilterPermission | Remove-JiraFilterPermission ``` -{{ Add example description here }} +Remove all permissions of Filter 11822 ## PARAMETERS -### -Confirm -Prompts you for confirmation before running the cmdlet. +### -Filter + +Object of the Filter from which to remove a permission. ```yaml -Type: SwitchParameter -Parameter Sets: (All) -Aliases: cf +Type: JiraPS.Filter +Parameter Sets: ByFilterObject +Aliases: -Required: False -Position: Named +Required: True +Position: 0 Default value: None -Accept pipeline input: False +Accept pipeline input: True (ByValue) Accept wildcard characters: False ``` -### -Credential -{{Fill Credential Description}} +### -FilterId + +Id of the Filter from which to remove a permission. ```yaml -Type: PSCredential -Parameter Sets: (All) +Type: UInt32 +Parameter Sets: ByFilterId Aliases: -Required: False -Position: 1 +Required: True +Position: 0 Default value: None -Accept pipeline input: False +Accept pipeline input: True (ByValue) Accept wildcard characters: False ``` -### -InputObject -{{Fill InputObject Description}} +### -PermissionId + +List of id's of the permissions to remove. ```yaml -Type: Object -Parameter Sets: (All) +Type: UInt32[] +Parameter Sets: ByFilterId Aliases: Required: True -Position: 0 +Position: 1 Default value: None Accept pipeline input: True (ByValue) Accept wildcard characters: False ``` +### -Credential + +Credentials to use to connect to JIRA. +If not specified, this function will use anonymous access. + +```yaml +Type: PSCredential +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -WhatIf + Shows what would happen if the cmdlet runs. The cmdlet is not run. @@ -92,19 +135,49 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -Confirm + +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### CommonParameters -This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. -For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +This cmdlet supports the common parameters: -Debug, -ErrorAction, +-ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, +-OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters +(). ## INPUTS ### System.Object - ## OUTPUTS ### System.Object ## NOTES +This function requires either the `-Credential` parameter to be passed or +a persistent JIRA session. +See `New-JiraSession` for more details. +If neither are supplied, this function will run with anonymous access to JIRA. + ## RELATED LINKS + +[Get-JiraFilter](../Get-JiraFilter/) + +[Add-JiraFilterPermission](../Add-JiraFilterPermission/) + +[Get-JiraFilterPermission](../Get-JiraFilterPermission/) From 9283dbc5c3ccf17d69abc305bb3801707e363995 Mon Sep 17 00:00:00 2001 From: Oliver Lipkau Date: Thu, 21 Jun 2018 14:00:58 +0200 Subject: [PATCH 4/9] Improved implementation of Get-JiraFilterPermission added Unit tests --- JiraPS/Public/Get-JiraFilterPermission.ps1 | 40 +++--- Tests/Get-JiraFilterPermission.Tests.ps1 | 125 ++++++++++++++++++ .../commands/Get-JiraFilterPermission.md | 108 +++++++++++---- 3 files changed, 235 insertions(+), 38 deletions(-) create mode 100644 Tests/Get-JiraFilterPermission.Tests.ps1 diff --git a/JiraPS/Public/Get-JiraFilterPermission.ps1 b/JiraPS/Public/Get-JiraFilterPermission.ps1 index 8c3a992a..bc8fc4f6 100644 --- a/JiraPS/Public/Get-JiraFilterPermission.ps1 +++ b/JiraPS/Public/Get-JiraFilterPermission.ps1 @@ -1,17 +1,21 @@ function Get-JiraFilterPermission { - [CmdletBinding()] + [CmdletBinding( DefaultParameterSetName = 'ById' )] + # [OutputType( [JiraPS.FilterPermission] )] param( - # Filter object from which to retrieve the permissions - [Parameter( Mandatory, ValueFromPipeline )] + [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = 'ByInputObject' )] [ValidateNotNullOrEmpty()] [PSTypeName('JiraPS.Filter')] $Filter, - # Credentials to use to connect to JIRA. - # - # If not specified, this function will use anonymous access. - [PSCredential] - $Credential + [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = 'ById')] + [ValidateNotNullOrEmpty()] + [UInt32[]] + $Id, + + [Parameter()] + [System.Management.Automation.PSCredential] + [System.Management.Automation.Credential()] + $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { @@ -24,15 +28,21 @@ function Get-JiraFilterPermission { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" - $parameter = @{ - URI = $resourceURi -f $Filter.RestURL - Method = "GET" - Credential = $Credential + if ($PSCmdlet.ParameterSetName -eq 'ById') { + $Filter = Get-JiraFilter -Id $Id } - Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" - $result = Invoke-JiraMethod @parameter - Write-Output (ConvertTo-JiraFilterPermission -InputObject $result) + foreach ($_filter in $Filter) { + $parameter = @{ + URI = $resourceURi -f $_filter.RestURL + Method = "GET" + Credential = $Credential + } + Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" + $result = Invoke-JiraMethod @parameter + + Write-Output (ConvertTo-JiraFilter -InputObject $_filter -FilterPermissions $result) + } } end { diff --git a/Tests/Get-JiraFilterPermission.Tests.ps1 b/Tests/Get-JiraFilterPermission.Tests.ps1 new file mode 100644 index 00000000..71ff2533 --- /dev/null +++ b/Tests/Get-JiraFilterPermission.Tests.ps1 @@ -0,0 +1,125 @@ +Describe 'Get-JiraFilterPermission' { + BeforeAll { + Remove-Module JiraPS -ErrorAction SilentlyContinue + Import-Module "$PSScriptRoot/../JiraPS" -Force -ErrorAction Stop + } + + InModuleScope JiraPS { + + . "$PSScriptRoot/Shared.ps1" + + #region Definitions + $jiraServer = "https://jira.example.com" + + $sampleResponse = @" +{ + "id": 10000, + "type": "global" +} +"@ + #endregion Definitions + + #region Mocks + Mock Get-JiraConfigServer -ModuleName JiraPS { + $jiraServer + } + + Mock ConvertTo-JiraFilter -ModuleName JiraPS { } + + Mock Get-JiraFilter -ModuleName JiraPS { + foreach ($_id in $Id) { + $basicFilter = New-Object -TypeName PSCustomObject -Property @{ + Id = $Id + RestUrl = "$jiraServer/rest/api/2/filter/$Id" + } + $basicFilter.PSObject.TypeNames.Insert(0, 'JiraPS.Filter') + $basicFilter + } + } + + Mock Invoke-JiraMethod -ModuleName JiraPS -ParameterFilter {$Method -eq 'Get' -and $URI -like "$jiraServer/rest/api/*/filter/*/permission"} { + ShowMockInfo 'Invoke-JiraMethod' 'Method', 'Uri' + ConvertFrom-Json $sampleResponse + } + + Mock Invoke-JiraMethod -ModuleName JiraPS { + ShowMockInfo 'Invoke-JiraMethod' 'Method', 'Uri' + throw "Unidentified call to Invoke-JiraMethod" + } + #endregion Mocks + + Context "Sanity checking" { + $command = Get-Command -Name Get-JiraFilterPermission + + defParam $command 'Filter' + defParam $command 'Id' + defParam $command 'Credential' + } + + Context "Behavior testing" { + It "Retrieves the permissions of a Filter by Object" { + { Get-JiraFilter -Id 23456 | Get-JiraFilterPermission } | Should -Not -Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It -ParameterFilter { + $Method -eq 'Get' -and + $URI -like '*/rest/api/*/filter/23456/permission' + } + } + + It "Retrieves the permissions of a Filter by Id" { + { 23456 | Get-JiraFilterPermission } | Should -Not -Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It -ParameterFilter { + $Method -eq 'Get' -and + $URI -like '*/rest/api/*/filter/23456/permission' + } + } + } + + Context "Input testing" { + It "finds the filter by Id" { + { Get-JiraFilterPermission -Id 23456 } | Should -Not -Throw + + Assert-MockCalled -CommandName Get-JiraFilter -ModuleName JiraPS -Exactly -Times 1 -Scope It + } + + It "does not accept negative Ids" { + { Get-JiraFilterPermission -Id -1 } | Should -Throw + } + + It "can process multiple Ids" { + { Get-JiraFilterPermission -Id 23456, 23456 } | Should -Not -Throw + + Assert-MockCalled -CommandName Get-JiraFilter -ModuleName JiraPS -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 2 -Scope It + } + + It "allows for the filter to be passed over the pipeline" { + { Get-JiraFilter -Id 23456 | Get-JiraFilterPermission } | Should -Not -Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It + } + + It "can ony process one Filter objects" { + $filter = @() + $filter += Get-JiraFilter -Id 23456 + $filter += Get-JiraFilter -Id 23456 + + { Get-JiraFilterPermission -Filter $filter } | Should -Not -Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 2 -Scope It + } + + It "resolves positional parameters" { + { Get-JiraFilterPermission 23456 } | Should -Not -Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It + + $filter = Get-JiraFilter -Id 23456 + { Get-JiraFilterPermission $filter } | Should -Not -Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 2 -Scope It + } + } + } +} diff --git a/docs/en-US/commands/Get-JiraFilterPermission.md b/docs/en-US/commands/Get-JiraFilterPermission.md index 98eb689e..b9878f71 100644 --- a/docs/en-US/commands/Get-JiraFilterPermission.md +++ b/docs/en-US/commands/Get-JiraFilterPermission.md @@ -1,56 +1,87 @@ --- external help file: JiraPS-help.xml Module Name: JiraPS -online version: https://atlassianps.org/docs/JiraPS/commands/Get-JiraFilter/ +online version: https://atlassianps.org/docs/JiraPS/commands/Get-JiraFilterPermission/ +locale: en-US schema: 2.0.0 +layout: documentation +permalink: /docs/JiraPS/commands/Get-JiraFilterPermission/ --- - # Get-JiraFilterPermission ## SYNOPSIS -{{Fill in the Synopsis}} + +Fetch the permissions of a specific Filter. ## SYNTAX +### ByInputObject (Default) + +```powershell +Get-JiraFilterPermission [-Filter] [[-Credential] ] + [] ``` -Get-JiraFilterPermission [-Filter] [[-Credential] ] [] + +### ById + +```powershell +Get-JiraFilterPermission [-Id] [[-Credential] ] + [] ``` ## DESCRIPTION -{{Fill in the Description}} + +This allows the user to retrieve all the sharing permissions set for a Filter. ## EXAMPLES ### Example 1 + ```powershell -PS C:\> {{ Add example code here }} +Get-JiraFilterPermission -Filter (Get-JiraFilter 12345) +#------- +Get-JiraFilterPermission -Id 12345 ``` -{{ Add example description here }} +Two methods for retrieving the permissions set for Filter 12345. + +### Example 2 + +```powershell +12345 | Get-JiraFilterPermission +#------- +Get-JiraFilter 12345 | Add-JiraFilterPermission +``` + +Two methods for retrieve the permissions set for Filter 12345 by using the pipeline. + +_The Id could be read from a file._ ## PARAMETERS -### -Credential -{{Fill Credential Description}} +### -Filter + +Filter object from which to retrieve the permissions ```yaml -Type: PSCredential -Parameter Sets: (All) +Type: JiraPS.Filter +Parameter Sets: ByInputObject Aliases: -Required: False -Position: 1 +Required: True +Position: 0 Default value: None -Accept pipeline input: False +Accept pipeline input: True (ByValue) Accept wildcard characters: False ``` -### -Filter -{{Fill Filter Description}} +### -Id + +Id of the Filter from which to retrieve the permissions ```yaml -Type: Object -Parameter Sets: (All) +Type: UInt32[] +Parameter Sets: ById Aliases: Required: True @@ -60,19 +91,50 @@ Accept pipeline input: True (ByValue) Accept wildcard characters: False ``` +### -Credential + +Credentials to use to connect to JIRA. +If not specified, this function will use anonymous access. + +```yaml +Type: PSCredential +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### CommonParameters -This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. -For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). -## INPUTS +This cmdlet supports the common parameters: -Debug, -ErrorAction, +-ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, +-OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters +(). -### System.Object +## INPUTS +### [JiraPS.Filter] ## OUTPUTS -### System.Object +### [JiraPS.Filter] ## NOTES +This function requires either the `-Credential` parameter to be passed or +a persistent JIRA session. +See `New-JiraSession` for more details. +If neither are supplied, this function will run with anonymous access to JIRA. + ## RELATED LINKS + +[Get-JiraFilter](../Get-JiraFilter/) + +[Add-JiraFilterPermission](../Add-JiraFilterPermission/) + +[Remove-JiraFilterPermission](../Remove-JiraFilterPermission/) From 376e8919e0f22e6f1ae70133f63d0427592a14b3 Mon Sep 17 00:00:00 2001 From: Oliver Lipkau Date: Thu, 21 Jun 2018 14:02:02 +0200 Subject: [PATCH 5/9] Improved implementation of Add-JiraFilterPermission added proper tests --- JiraPS/Public/Add-JiraFilterPermission.ps1 | 32 +- Tests/Add-JiraFilterPermission.Tests.ps1 | 280 ++++++++++++++---- .../commands/Add-JiraFilterPermission.md | 51 +++- 3 files changed, 284 insertions(+), 79 deletions(-) diff --git a/JiraPS/Public/Add-JiraFilterPermission.ps1 b/JiraPS/Public/Add-JiraFilterPermission.ps1 index b0fa88c0..6e2ca439 100644 --- a/JiraPS/Public/Add-JiraFilterPermission.ps1 +++ b/JiraPS/Public/Add-JiraFilterPermission.ps1 @@ -1,6 +1,6 @@ function Add-JiraFilterPermission { [CmdletBinding( SupportsShouldProcess, DefaultParameterSetName = 'ByInputObject' )] - [OutputType( [JiraPS.FilterPermission] )] + # [OutputType( [JiraPS.FilterPermission] )] param( [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = 'ByInputObject' )] [ValidateNotNullOrEmpty()] @@ -8,14 +8,16 @@ $Filter, [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = 'ById')] + [ValidateNotNullOrEmpty()] [UInt32[]] $Id, - [Parameter( Position = 1, Mandatory )] + [Parameter( Mandatory )] [ValidateNotNullOrEmpty()] [ValidateSet('Group', 'Project', 'ProjectRole', 'Authenticated', 'Global')] [String]$Type, + [Parameter()] [String]$Value, [Parameter()] @@ -35,9 +37,7 @@ Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" if ($PSCmdlet.ParameterSetName -eq 'ById') { - $InputObject = foreach ($_id in $Id) { - Get-JiraFilter -Id $_id - } + $Filter = Get-JiraFilter -Id $Id } $body = @{ @@ -57,17 +57,19 @@ "Global" { } } - $parameter = @{ - URI = $resourceURi -f $Filter.RestURL - Method = "POST" - Body = ConvertTo-Json $body - Credential = $Credential - } - Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" - if ($PSCmdlet.ShouldProcess($Filter.Name, "Add Permission [$Type - $Value]")) { - $result = Invoke-JiraMethod @parameter + foreach ($_filter in $Filter) { + $parameter = @{ + URI = $resourceURi -f $_filter.RestURL + Method = "POST" + Body = ConvertTo-Json $body + Credential = $Credential + } + Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" + if ($PSCmdlet.ShouldProcess($_filter.Name, "Add Permission [$Type - $Value]")) { + $result = Invoke-JiraMethod @parameter - Write-Output (ConvertTo-JiraFilterPermission -InputObject $result) + Write-Output (ConvertTo-JiraFilter -InputObject $_filter -FilterPermissions $result) + } } } diff --git a/Tests/Add-JiraFilterPermission.Tests.ps1 b/Tests/Add-JiraFilterPermission.Tests.ps1 index 1d56300e..d1f947c5 100644 --- a/Tests/Add-JiraFilterPermission.Tests.ps1 +++ b/Tests/Add-JiraFilterPermission.Tests.ps1 @@ -11,14 +11,87 @@ Describe 'Add-JiraFilterPermission' { #region Definitions $jiraServer = "https://jira.example.com" - $responseFilter = @" -{ - "self": "$jiraServer/rest/api/latest/filter/12844", - "id": "12844", - "name": "{0}", - "jql": "{1}", - "favourite": false -} + $permissionJSON = @" +[ + { + "id": 10000, + "type": "global" + }, + { + "id": 10010, + "type": "project", + "project": { + "self": "$jiraServer/jira/rest/api/2/project/EX", + "id": "10000", + "key": "EX", + "name": "Example", + "avatarUrls": { + "48x48": "$jiraServer/jira/secure/projectavatar?size=large&pid=10000", + "24x24": "$jiraServer/jira/secure/projectavatar?size=small&pid=10000", + "16x16": "$jiraServer/jira/secure/projectavatar?size=xsmall&pid=10000", + "32x32": "$jiraServer/jira/secure/projectavatar?size=medium&pid=10000" + }, + "projectCategory": { + "self": "$jiraServer/jira/rest/api/2/projectCategory/10000", + "id": "10000", + "name": "FIRST", + "description": "First Project Category" + }, + "simplified": false + } + }, + { + "id": 10010, + "type": "project", + "project": { + "self": "$jiraServer/jira/rest/api/2/project/MKY", + "id": "10002", + "key": "MKY", + "name": "Example", + "avatarUrls": { + "48x48": "$jiraServer/jira/secure/projectavatar?size=large&pid=10002", + "24x24": "$jiraServer/jira/secure/projectavatar?size=small&pid=10002", + "16x16": "$jiraServer/jira/secure/projectavatar?size=xsmall&pid=10002", + "32x32": "$jiraServer/jira/secure/projectavatar?size=medium&pid=10002" + }, + "projectCategory": { + "self": "$jiraServer/jira/rest/api/2/projectCategory/10000", + "id": "10000", + "name": "FIRST", + "description": "First Project Category" + }, + "simplified": false + }, + "role": { + "self": "$jiraServer/jira/rest/api/2/project/MKY/role/10360", + "name": "Developers", + "id": 10360, + "description": "A project role that represents developers in a project", + "actors": [ + { + "id": 10240, + "displayName": "jira-developers", + "type": "atlassian-group-role-actor", + "name": "jira-developers" + }, + { + "id": 10241, + "displayName": "Fred F. User", + "type": "atlassian-user-role-actor", + "name": "fred" + } + ] + } + }, + { + "id": 10010, + "type": "group", + "group": { + "name": "jira-administrators", + "self": "$jiraServer/jira/rest/api/2/group?groupname=jira-administrators" + } + } +] "@ #endregion Definitions @@ -27,19 +100,32 @@ Describe 'Add-JiraFilterPermission' { $jiraServer } + Mock ConvertTo-JiraFilter -ModuleName JiraPS { + $i = New-Object -TypeName PSCustomObject + $i.PSObject.TypeNames.Insert(0, 'JiraPS.Filter') + $i + } + Mock ConvertTo-JiraFilterPermission -ModuleName JiraPS { - $i = (ConvertFrom-Json $responseFilter) + $i = (ConvertFrom-Json $permissionJSON) $i.PSObject.TypeNames.Insert(0, 'JiraPS.FilterPermission') $i } Mock Get-JiraFilter -ModuleName JiraPS { - ConvertTo-JiraFilter + foreach ($_id in $Id) { + $object = New-Object -TypeName PSCustomObject -Property @{ + id = $_id + RestUrl = "$jiraServer/rest/api/latest/filter/$_id" + } + $object.PSObject.TypeNames.Insert(0, 'JiraPS.Filter') + $object + } } - Mock Invoke-JiraMethod -ModuleName JiraPS -ParameterFilter {$Method -eq 'Post' -and $URI -like "$jiraServer/rest/api/*/filter"} { + Mock Invoke-JiraMethod -ModuleName JiraPS -ParameterFilter {$Method -eq 'Post' -and $URI -like "$jiraServer/rest/api/*/filter/*/permission"} { ShowMockInfo 'Invoke-JiraMethod' 'Method', 'Uri', 'Body' - ConvertFrom-Json $responseFilter + ConvertFrom-Json $permissionJSON } Mock Invoke-JiraMethod -ModuleName JiraPS { @@ -52,73 +138,153 @@ Describe 'Add-JiraFilterPermission' { $command = Get-Command -Name Add-JiraFilterPermission defParam $command 'Filter' + defParam $command 'Id' defParam $command 'Type' defParam $command 'Value' defParam $command 'Credential' } Context "Behavior testing" { - It "Invokes the Jira API to create a filter" { + It "Adds share permission to Filter Object" { { - $newData = @{ - Name = "myName" - Description = "myDescription" - JQL = "myJQL" - Favorite = $true - } - New-JiraFilter @newData + Add-JiraFilterPermission -Filter (Get-JiraFilter -Id 12844) -Type "Global" } | Should Not Throw Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It -ParameterFilter { $Method -eq 'Post' -and - $URI -like '*/rest/api/*/filter' -and - $Body -match "`"name`":\s*`"myName`"" -and - $Body -match "`"description`":\s*`"myDescription`"" -and - $Body -match "`"jql`":\s*`"myJQL`"" -and - $Body -match "`"favourite`":\s*true" + $URI -like '*/rest/api/*/filter/12844/permission' } + + Assert-MockCalled -CommandName ConvertTo-JiraFilter -ModuleName JiraPS -Exactly -Times 1 -Scope It } - } - Context "Input testing" { - It "-Name and -JQL" { + It "Adds share permission to FilterId" { { - $parameter = @{ - Name = "newName" - JQL = "newJQL" - } - New-JiraFilter @parameter + Add-JiraFilterPermission -Id 12844 -Type "Global" } | Should Not Throw - Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It -ParameterFilter { + $Method -eq 'Post' -and + $URI -like '*/rest/api/*/filter/12844/permission' + } + + Assert-MockCalled -CommandName ConvertTo-JiraFilter -ModuleName JiraPS -Exactly -Times 1 -Scope It } - It "-Name and -Description and -JQL" { - { - $parameter = @{ - Name = "newName" - Description = "newDescription" - JQL = "newJQL" - } - New-JiraFilter @parameter - } | Should Not Throw + } - Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It + Context "Input testing" { + It "requires -Filter to be a JiraPS.Filter" { + { Add-JiraFilterPermission -Filter 1 -Type "Global" } | Should -Throw + { Add-JiraFilterPermission -Filter "lorem" -Type "Global" } | Should -Throw + { Add-JiraFilterPermission -Filter (Get-Date) -Type "Global" } | Should -Throw + + { Add-JiraFilterPermission -Filter (Get-JiraFilter -Id 1) -Type "Global" } | Should -Not -Throw } - It "-Name and -Description and -JQL and -Favorite" { - { - $parameter = @{ - Name = "newName" - Description = "newDescription" - JQL = "newJQL" - Favorite = $true - } - New-JiraFilter @parameter - } | Should Not Throw - Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It + It "allows a JiraPS.Filter to be passed over the pipeline" { + { Get-JiraFilter -Id 1 | Add-JiraFilterPermission -Type "Global" } | Should -Not -Throw + } + + It "can process multiple Filters" { + $filters = 1..5 | ForEach-Object { Get-JiraFilter -Id 1 } + $filters.Count | Should -Be 5 + + { Add-JiraFilterPermission -Filter $filters -Type "Global" } | Should -Not -Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 5 -Scope It } - It "maps the properties of an object to the parameters" { - { Get-JiraFilter "12345" | New-JiraFilter } | Should Not Throw + + It "can find a filter by it's Id" { + { Add-JiraFilterPermission -Id 1 -Type "Global" } | Should -Not -Throw + + Assert-MockCalled -CommandName Get-JiraFilter -ModuleName JiraPS -Exactly -Times 1 -Scope It + } + + It "allows for the filter's Id to be passed over the pipeline" { + { 1,2 | Add-JiraFilterPermission -Type "Global" } | Should -Not -Throw + + Assert-MockCalled -CommandName Get-JiraFilter -ModuleName JiraPS -Exactly -Times 2 -Scope It + } + + It "can process mutiple FilterIds" { + { Add-JiraFilterPermission -Id 1,2,3,4,5 -Type "Global" } | Should -Not -Throw + + Assert-MockCalled -CommandName Get-JiraFilter -ModuleName JiraPS -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 5 -Scope It + } + + It "accepts the 5 known permission types" { + { Add-JiraFilterPermission -Id 1 -Type "lorem" } | Should -Throw + { Add-JiraFilterPermission -Id 1 -Type "Invalid" } | Should -Throw + + { Add-JiraFilterPermission -Id 1 -Type "Global" } | Should -Not -Throw + { Add-JiraFilterPermission -Id 1 -Type "Group" } | Should -Not -Throw + { Add-JiraFilterPermission -Id 1 -Type "Project" } | Should -Not -Throw + { Add-JiraFilterPermission -Id 1 -Type "ProjectRole" } | Should -Not -Throw + { Add-JiraFilterPermission -Id 1 -Type "Authenticated" } | Should -Not -Throw + } + + It "does not validate -Value" { + { Add-JiraFilterPermission -Id 1 -Type "Global" -Value "invalid" } | Should -Not -Throw + { Add-JiraFilterPermission -Id 1 -Type "Group" -Value "not a group" } | Should -Not -Throw + { Add-JiraFilterPermission -Id 1 -Type "Project" -Value "not a project" } | Should -Not -Throw + { Add-JiraFilterPermission -Id 1 -Type "ProjectRole" -Value "not a Role" } | Should -Not -Throw + { Add-JiraFilterPermission -Id 1 -Type "Authenticated" -Value "invalid" } | Should -Not -Throw + } + + It "constructs a valid request Body for type 'Global'" { + { Add-JiraFilterPermission -Id 12844 -Type "Global" } | Should -Not -Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It -ParameterFilter { + $Method -eq 'Post' -and + $URI -like '*/rest/api/*/filter/12844/permission' -and + $Body -match '"type":\s*"global"' -and + $Body -notmatch ',' + } + } + + It "constructs a valid request Body for type 'Authenticated'" { + { Add-JiraFilterPermission -Id 12844 -Type "Authenticated" } | Should -Not -Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It -ParameterFilter { + $Method -eq 'Post' -and + $URI -like '*/rest/api/*/filter/12844/permission' -and + $Body -match '"type":\s*"authenticated"' -and + $Body -notmatch "," + } + } + + It "constructs a valid request Body for type 'Group'" { + { Add-JiraFilterPermission -Id 12844 -Type "Group" -Value "administrators" } | Should -Not -Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It -ParameterFilter { + $Method -eq 'Post' -and + $URI -like '*/rest/api/*/filter/12844/permission' -and + $Body -match '"type":\s*"group"' -and + $Body -match '"groupname":\s*"administrators"' + } + } + + It "constructs a valid request Body for type 'Project'" { + { Add-JiraFilterPermission -Id 12844 -Type "Project" -Value "11822" } | Should -Not -Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It -ParameterFilter { + $Method -eq 'Post' -and + $URI -like '*/rest/api/*/filter/12844/permission' -and + $Body -match '"type":\s*"project"' -and + $Body -match '"projectId":\s*"11822"' + } + } + + It "constructs a valid request Body for type 'ProjectRole'" { + { Add-JiraFilterPermission -Id 12844 -Type "ProjectRole" -Value "11822" } | Should -Not -Throw + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It -ParameterFilter { + $Method -eq 'Post' -and + $URI -like '*/rest/api/*/filter/12844/permission' -and + $Body -match '"type":\s*"projectRole"' -and + $Body -match '"projectRoleId":\s*"11822"' + } } } } diff --git a/docs/en-US/commands/Add-JiraFilterPermission.md b/docs/en-US/commands/Add-JiraFilterPermission.md index ea354d97..ddfa6661 100644 --- a/docs/en-US/commands/Add-JiraFilterPermission.md +++ b/docs/en-US/commands/Add-JiraFilterPermission.md @@ -18,8 +18,9 @@ Share a Filter with other users. ### ByInputObject (Default) ```powershell -Add-JiraFilterPermission [-Filter] [-Type] [[-Value] ] - [[-Credential] ] [-WhatIf] [-Confirm] [] +Add-JiraFilterPermission [-Filter] [-Type] + [[-Value] ] [[-Credential] ] [-WhatIf] [-Confirm] + [] ``` ### ById @@ -71,8 +72,26 @@ Share Filter 12345 only with users in the administrators groups. Filter object to which the permission should be applied ```yaml -Type: Object -Parameter Sets: (All) +Type: JiraPS.Filter +Parameter Sets: ByInputObject +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Id + +Id of the Filter to which the permission should be applied + +_Id can be passed over the pipeline when reading from a file._ + +```yaml +Type: UInt32[] +Parameter Sets: ById Aliases: Required: True @@ -178,8 +197,11 @@ Accept wildcard characters: False ### CommonParameters -This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. -For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). +This cmdlet supports the common parameters: -Debug, -ErrorAction, +-ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, +-OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters +(). ## INPUTS @@ -187,8 +209,23 @@ For more information, see about_CommonParameters (http://go.microsoft.com/fwlink ## OUTPUTS -### [JiraPS.FilterPermission] +### [JiraPS.Filter] ## NOTES +This functions does not validate the input for `-Value`. +In case the value is invalid, unexpected or missing, the API will response with +an error. + +This function requires either the `-Credential` parameter to be passed or +a persistent JIRA session. +See `New-JiraSession` for more details. +If neither are supplied, this function will run with anonymous access to JIRA. + ## RELATED LINKS + +[Get-JiraFilter](../Get-JiraFilter/) + +[Get-JiraFilterPermission](../Get-JiraFilterPermission/) + +[Remove-JiraFilterPermission](../Remove-JiraFilterPermission/) From bc73ac58bb0a9ad13423f0a751efd6e7d4df236e Mon Sep 17 00:00:00 2001 From: Oliver Lipkau Date: Thu, 21 Jun 2018 14:03:14 +0200 Subject: [PATCH 6/9] Implemented custom objects for FilterPermission --- JiraPS/Private/ConvertTo-JiraFilter.ps1 | 32 +++-- .../ConvertTo-JiraFilterPermission.ps1 | 2 +- JiraPS/Private/ConvertTo-JiraProjectRole.ps1 | 9 +- Tests/ConvertTo-JiraFilter.Tests.ps1 | 103 ++++++++++++++- .../ConvertTo-JiraFilterPermission.Tests.ps1 | 117 ++++++++++++++++++ Tests/ConvertTo-JiraProjectRole.Tests.ps1 | 49 ++++++++ 6 files changed, 293 insertions(+), 19 deletions(-) create mode 100644 Tests/ConvertTo-JiraFilterPermission.Tests.ps1 create mode 100644 Tests/ConvertTo-JiraProjectRole.Tests.ps1 diff --git a/JiraPS/Private/ConvertTo-JiraFilter.ps1 b/JiraPS/Private/ConvertTo-JiraFilter.ps1 index 6eb2be6f..15f1b635 100644 --- a/JiraPS/Private/ConvertTo-JiraFilter.ps1 +++ b/JiraPS/Private/ConvertTo-JiraFilter.ps1 @@ -3,7 +3,10 @@ function ConvertTo-JiraFilter { param( [Parameter( ValueFromPipeline )] [PSObject[]] - $InputObject + $InputObject, + + [PSObject[]] + $FilterPermissions ) process { @@ -11,17 +14,22 @@ function ConvertTo-JiraFilter { Write-Debug "[$($MyInvocation.MyCommand.Name)] Converting `$InputObject to custom object" $props = @{ - 'ID' = $i.id - 'Name' = $i.name - 'JQL' = $i.jql - 'RestUrl' = $i.self - 'ViewUrl' = $i.viewUrl - 'SearchUrl' = $i.searchUrl - 'Favourite' = $i.favourite - - 'SharePermission' = $i.sharePermissions - 'SharedUser' = $i.sharedUsers - 'Subscription' = $i.subscriptions + 'ID' = $i.id + 'Name' = $i.name + 'JQL' = $i.jql + 'RestUrl' = $i.self + 'ViewUrl' = $i.viewUrl + 'SearchUrl' = $i.searchUrl + 'Favourite' = $i.favourite + 'FilterPermissions' = @() + + 'SharePermission' = $i.sharePermissions + 'SharedUser' = $i.sharedUsers + 'Subscription' = $i.subscriptions + } + + if ($FilterPermissions) { + $props.FilterPermissions = @(ConvertTo-JiraFilterPermission ($FilterPermissions)) } if ($i.description) { diff --git a/JiraPS/Private/ConvertTo-JiraFilterPermission.ps1 b/JiraPS/Private/ConvertTo-JiraFilterPermission.ps1 index bdc9b0c6..95cd1225 100644 --- a/JiraPS/Private/ConvertTo-JiraFilterPermission.ps1 +++ b/JiraPS/Private/ConvertTo-JiraFilterPermission.ps1 @@ -30,7 +30,7 @@ function ConvertTo-JiraFilterPermission { $result = New-Object -TypeName PSObject -Property $props $result.PSObject.TypeNames.Insert(0, 'JiraPS.FilterPermission') $result | Add-Member -MemberType ScriptMethod -Name 'ToString' -Force -Value { - Write-Output "$($this.Id)" + Write-Output "$($this.Type)" } Write-Output $result diff --git a/JiraPS/Private/ConvertTo-JiraProjectRole.ps1 b/JiraPS/Private/ConvertTo-JiraProjectRole.ps1 index 685dfea9..aef189f7 100644 --- a/JiraPS/Private/ConvertTo-JiraProjectRole.ps1 +++ b/JiraPS/Private/ConvertTo-JiraProjectRole.ps1 @@ -11,10 +11,11 @@ function ConvertTo-JiraProjectRole { Write-Debug "[$($MyInvocation.MyCommand.Name)] Converting `$InputObject to custom object" $props = @{ - 'ID' = $i.id - 'Name' = $i.name - 'RestUrl' = $i.self - 'ProjectId' = $i.projectId + 'ID' = $i.id + 'Name' = $i.name + 'Description' = $i.description + 'Actors' = $i.actors + 'RestUrl' = $i.self } $result = New-Object -TypeName PSObject -Property $props diff --git a/Tests/ConvertTo-JiraFilter.Tests.ps1 b/Tests/ConvertTo-JiraFilter.Tests.ps1 index c53fc172..0aa7e6a4 100644 --- a/Tests/ConvertTo-JiraFilter.Tests.ps1 +++ b/Tests/ConvertTo-JiraFilter.Tests.ps1 @@ -52,8 +52,97 @@ Describe "ConvertTo-JiraFilter" { } '@ + $samplePermission = @" +[ + { + "id": 10000, + "type": "global" + }, + { + "id": 10010, + "type": "project", + "project": { + "self": "$jiraServer/jira/rest/api/2/project/EX", + "id": "10000", + "key": "EX", + "name": "Example", + "avatarUrls": { + "48x48": "$jiraServer/jira/secure/projectavatar?size=large&pid=10000", + "24x24": "$jiraServer/jira/secure/projectavatar?size=small&pid=10000", + "16x16": "$jiraServer/jira/secure/projectavatar?size=xsmall&pid=10000", + "32x32": "$jiraServer/jira/secure/projectavatar?size=medium&pid=10000" + }, + "projectCategory": { + "self": "$jiraServer/jira/rest/api/2/projectCategory/10000", + "id": "10000", + "name": "FIRST", + "description": "First Project Category" + }, + "simplified": false + } + }, + { + "id": 10010, + "type": "project", + "project": { + "self": "$jiraServer/jira/rest/api/2/project/MKY", + "id": "10002", + "key": "MKY", + "name": "Example", + "avatarUrls": { + "48x48": "$jiraServer/jira/secure/projectavatar?size=large&pid=10002", + "24x24": "$jiraServer/jira/secure/projectavatar?size=small&pid=10002", + "16x16": "$jiraServer/jira/secure/projectavatar?size=xsmall&pid=10002", + "32x32": "$jiraServer/jira/secure/projectavatar?size=medium&pid=10002" + }, + "projectCategory": { + "self": "$jiraServer/jira/rest/api/2/projectCategory/10000", + "id": "10000", + "name": "FIRST", + "description": "First Project Category" + }, + "simplified": false + }, + "role": { + "self": "$jiraServer/jira/rest/api/2/project/MKY/role/10360", + "name": "Developers", + "id": 10360, + "description": "A project role that represents developers in a project", + "actors": [ + { + "id": 10240, + "displayName": "jira-developers", + "type": "atlassian-group-role-actor", + "name": "jira-developers" + }, + { + "id": 10241, + "displayName": "Fred F. User", + "type": "atlassian-user-role-actor", + "name": "fred" + } + ] + } + }, + { + "id": 10010, + "type": "group", + "group": { + "name": "jira-administrators", + "self": "$jiraServer/jira/rest/api/2/group?groupname=jira-administrators" + } + } +] +"@ + + Mock ConvertTo-JiraFilterPermission -ModuleName JiraPS { + $i = New-Object -TypeName PSCustomObject -Property @{ Id = 1111 } + $i.PSObject.TypeNames.Insert(0, 'JiraPS.FilterPermission') + $i + } + $sampleObject = ConvertFrom-Json -InputObject $sampleJson - $r = ConvertTo-JiraFilter -InputObject $sampleObject + $r = ConvertTo-JiraFilter -InputObject $sampleObject -FilterPermission $samplePermission It "Creates a PSObject out of JSON input" { $r | Should Not BeNullOrEmpty @@ -67,7 +156,17 @@ Describe "ConvertTo-JiraFilter" { defProp $r 'RestUrl' 'https://jira.atlassian.com/rest/api/latest/filter/12844' defProp $r 'ViewUrl' 'https://jira.atlassian.com/secure/IssueNavigator.jspa?mode=hide&requestId=12844' defProp $r 'SearchUrl' 'https://jira.atlassian.com/rest/api/latest/search?jql=project+%3D+10240+AND+issuetype+%3D+1+ORDER+BY+key+DESC' - defProp $r 'Favorite' $false + defProp $r 'Favourite' $false + It "Defines the 'Favorite' property as an alias of 'Favourite'" { + ($r | Get-Member -Name Favorite).MemberType | Should -Be "AliasProperty" + } + It "Uses output type of 'JiraPS.FilterPermission' for property 'FilterPermissions'" { + checkType $r.FilterPermissions 'JiraPS.FilterPermission' + } + + It "uses ConvertTo-JiraFilterPermission" { + Assert-MockCalled -CommandName ConvertTo-JiraFilterPermission -Module JiraPS -Exactly -Times 1 -Scope Describe + } } } diff --git a/Tests/ConvertTo-JiraFilterPermission.Tests.ps1 b/Tests/ConvertTo-JiraFilterPermission.Tests.ps1 new file mode 100644 index 00000000..2c4f1475 --- /dev/null +++ b/Tests/ConvertTo-JiraFilterPermission.Tests.ps1 @@ -0,0 +1,117 @@ +Describe "ConvertTo-JiraFilterPermission" { + + Import-Module "$PSScriptRoot/../JiraPS" -Force -ErrorAction Stop + + InModuleScope JiraPS { + + . "$PSScriptRoot/Shared.ps1" + + $sampleJson = @" +[ + { + "id": 10000, + "type": "global" + }, + { + "id": 10010, + "type": "project", + "project": { + "self": "$jiraServer/jira/rest/api/2/project/EX", + "id": "10000", + "key": "EX", + "name": "Example", + "avatarUrls": { + "48x48": "$jiraServer/jira/secure/projectavatar?size=large&pid=10000", + "24x24": "$jiraServer/jira/secure/projectavatar?size=small&pid=10000", + "16x16": "$jiraServer/jira/secure/projectavatar?size=xsmall&pid=10000", + "32x32": "$jiraServer/jira/secure/projectavatar?size=medium&pid=10000" + }, + "projectCategory": { + "self": "$jiraServer/jira/rest/api/2/projectCategory/10000", + "id": "10000", + "name": "FIRST", + "description": "First Project Category" + }, + "simplified": false + } + }, + { + "id": 10010, + "type": "project", + "project": { + "self": "$jiraServer/jira/rest/api/2/project/MKY", + "id": "10002", + "key": "MKY", + "name": "Example", + "avatarUrls": { + "48x48": "$jiraServer/jira/secure/projectavatar?size=large&pid=10002", + "24x24": "$jiraServer/jira/secure/projectavatar?size=small&pid=10002", + "16x16": "$jiraServer/jira/secure/projectavatar?size=xsmall&pid=10002", + "32x32": "$jiraServer/jira/secure/projectavatar?size=medium&pid=10002" + }, + "projectCategory": { + "self": "$jiraServer/jira/rest/api/2/projectCategory/10000", + "id": "10000", + "name": "FIRST", + "description": "First Project Category" + }, + "simplified": false + }, + "role": { + "self": "$jiraServer/jira/rest/api/2/project/MKY/role/10360", + "name": "Developers", + "id": 10360, + "description": "A project role that represents developers in a project", + "actors": [ + { + "id": 10240, + "displayName": "jira-developers", + "type": "atlassian-group-role-actor", + "name": "jira-developers" + }, + { + "id": 10241, + "displayName": "Fred F. User", + "type": "atlassian-user-role-actor", + "name": "fred" + } + ] + } + }, + { + "id": 10010, + "type": "group", + "group": { + "name": "jira-administrators", + "self": "$jiraServer/jira/rest/api/2/group?groupname=jira-administrators" + } + } +] +"@ + + $sampleObject = ConvertFrom-Json -InputObject $sampleJson + $r = ConvertTo-JiraFilterPermission -InputObject $sampleObject + + It "Creates a PSObject out of JSON input" { + $r | Should -Not -BeNullOrEmpty + } + + checkPsType $r 'JiraPS.FilterPermission' + + defProp $r 'Id' @(10000, 10010, 10010, 10010) + defProp $r 'Type' @('global', 'project', 'project', 'group') + It "Defines the 'Group' property of type 'JiraPS.Group'" { + checkType $r[3].Group 'JiraPS.Group' + $r.Group.Name | Should -Be 'jira-administrators' + } + It "Defines the 'Project' property of type 'JiraPS.Project'" { + checkType $r[1].Project 'JiraPS.Project' + $r.Project.Name | Should -Be @('Example', 'Example') + } + + It "Defines the 'Role' property of type 'JiraPS.ProjectRole'" { + checkType $r[2].Role 'JiraPS.ProjectRole' + $r.Role.Name | Should -Be 'Developers' + } + } +} diff --git a/Tests/ConvertTo-JiraProjectRole.Tests.ps1 b/Tests/ConvertTo-JiraProjectRole.Tests.ps1 new file mode 100644 index 00000000..acee0c95 --- /dev/null +++ b/Tests/ConvertTo-JiraProjectRole.Tests.ps1 @@ -0,0 +1,49 @@ +Describe "ConvertTo-JiraProjectRole" { + + Import-Module "$PSScriptRoot/../JiraPS" -Force -ErrorAction Stop + + InModuleScope JiraPS { + + . "$PSScriptRoot/Shared.ps1" + + $sampleJson = @" +[ + { + "self": "http://www.example.com/jira/rest/api/2/project/MKY/role/10360", + "name": "Developers", + "id": 10360, + "description": "A project role that represents developers in a project", + "actors": [ + { + "id": 10240, + "displayName": "jira-developers", + "type": "atlassian-group-role-actor", + "name": "jira-developers" + }, + { + "id": 10241, + "displayName": "Fred F. User", + "type": "atlassian-user-role-actor", + "name": "fred" + } + ] + } +] +"@ + + $sampleObject = ConvertFrom-Json -InputObject $sampleJson + $r = ConvertTo-JiraProjectRole -InputObject $sampleObject + + It "Creates a PSObject out of JSON input" { + $r | Should -Not -BeNullOrEmpty + } + + checkPsType $r 'JiraPS.ProjectRole' + + defProp $r 'Id' 10360 + defProp $r 'Name' "Developers" + defProp $r 'Description' "A project role that represents developers in a project" + hasProp $r 'Actors' + defProp $r 'RestUrl' "http://www.example.com/jira/rest/api/2/project/MKY/role/10360" + } +} From e1884e9acd19ef704e2c829392933b9eae07ff73 Mon Sep 17 00:00:00 2001 From: Oliver Lipkau Date: Thu, 21 Jun 2018 14:03:57 +0200 Subject: [PATCH 7/9] Improved documentation of Filter functions --- JiraPS/Public/Remove-JiraFilter.ps1 | 1 + docs/en-US/commands/Get-JiraFilter.md | 28 +++++++++++++++++------- docs/en-US/commands/Remove-JiraFilter.md | 17 +++++++++----- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/JiraPS/Public/Remove-JiraFilter.ps1 b/JiraPS/Public/Remove-JiraFilter.ps1 index 8a892bdf..886a7709 100644 --- a/JiraPS/Public/Remove-JiraFilter.ps1 +++ b/JiraPS/Public/Remove-JiraFilter.ps1 @@ -7,6 +7,7 @@ function Remove-JiraFilter { $InputObject, [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = 'ById')] + [ValidateNotNullOrEmpty()] [UInt32[]] $Id, diff --git a/docs/en-US/commands/Get-JiraFilter.md b/docs/en-US/commands/Get-JiraFilter.md index 7ff88bf8..47d95c19 100644 --- a/docs/en-US/commands/Get-JiraFilter.md +++ b/docs/en-US/commands/Get-JiraFilter.md @@ -24,7 +24,8 @@ Get-JiraFilter [-Id] [-Credential ] [ ### ByInputObject ```powershell -Get-JiraFilter -InputObject [-Credential ] [] +Get-JiraFilter -InputObject [-Credential ] + [] ``` ### MyFavorite @@ -35,13 +36,14 @@ Get-JiraFilter -Favorite [-Credential ] [] ## DESCRIPTION -This function returns information about a filter in JIRA, including the JQL syntax of the filter, its owner, and sharing status. +This function returns information about a filter in JIRA, including the JQL +syntax of the filter, its owner, and sharing status. This function is only capable of returning filters by their Filter ID. This is a limitation of JIRA's REST API. -The easiest way to obtain the ID of a filter is to load the filter in the "regular" Web view of JIRA, -then copy the ID from the URL of the page. +The easiest way to obtain the ID of a filter is to load the filter in the +"regular" Web view of JIRA, then copy the ID from the URL of the page. ## EXAMPLES @@ -139,12 +141,15 @@ Accept wildcard characters: False ### CommonParameters -This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. -For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). +This cmdlet supports the common parameters: -Debug, -ErrorAction, +-ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, +-OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters +(). ## INPUTS -### [JiraPS.Filter[]] / [String[]] +### [JiraPS.Filter] / [String] The filter to look up in JIRA. This can be a String (filter ID) or a JiraPS.Filter object. @@ -154,7 +159,8 @@ The filter to look up in JIRA. This can be a String (filter ID) or a JiraPS.Filt ## NOTES -This function requires either the `-Credential` parameter to be passed or a persistent JIRA session. +This function requires either the `-Credential` parameter to be passed or +a persistent JIRA session. See `New-JiraSession` for more details. If neither are supplied, this function will run with anonymous access to JIRA. @@ -165,3 +171,9 @@ If neither are supplied, this function will run with anonymous access to JIRA. [Set-JiraFilter](../Set-JiraFilter/) [Remove-JiraFilter](../Remove-JiraFilter/) + +[Add-JiraFilterPermission](../Add-JiraFilterPermission/) + +[Get-JiraFilterPermission](../Get-JiraFilterPermission/) + +[Remove-JiraFilterPermission](../Remove-JiraFilterPermission/) diff --git a/docs/en-US/commands/Remove-JiraFilter.md b/docs/en-US/commands/Remove-JiraFilter.md index b5fbc5a2..66dd3b5c 100644 --- a/docs/en-US/commands/Remove-JiraFilter.md +++ b/docs/en-US/commands/Remove-JiraFilter.md @@ -18,7 +18,8 @@ Removes an existing filter. ### byInputObject (Default) ```powershell -Remove-JiraFilter [-InputObject] [-WhatIf] [-Confirm] [] +Remove-JiraFilter [-InputObject] [-WhatIf] [-Confirm] + [] ``` ### byId (Default) @@ -76,8 +77,8 @@ $listOfFilters | Remove-JiraFilter Remove filters with id "1", "2", "3" and "4". -This input allows for the ID of the filters to be stored in an array and passed to -the command. (eg: `Get-Content` from a file with the ids) +This input allows for the ID of the filters to be stored in an array and passed +to the command. (eg: `Get-Content` from a file with the ids) ## PARAMETERS @@ -169,8 +170,11 @@ Accept wildcard characters: False ### CommonParameters -This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. -For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). +This cmdlet supports the common parameters: -Debug, -ErrorAction, +-ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, +-OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters +(). ## INPUTS @@ -180,7 +184,8 @@ For more information, see about_CommonParameters (http://go.microsoft.com/fwlink ## NOTES -This function requires either the `-Credential` parameter to be passed or a persistent JIRA session. +This function requires either the `-Credential` parameter to be passed or +a persistent JIRA session. See `New-JiraSession` for more details. If neither are supplied, this function will run with anonymous access to JIRA. From 7a5c2fdcf9674271267a12bd779cd0b458edbe6a Mon Sep 17 00:00:00 2001 From: Oliver Lipkau Date: Thu, 21 Jun 2018 14:04:28 +0200 Subject: [PATCH 8/9] Updated Tests for the Help-engine --- Tests/JiraPS.Help.Tests.ps1 | 397 ++++++++++++++++++++---------------- 1 file changed, 226 insertions(+), 171 deletions(-) diff --git a/Tests/JiraPS.Help.Tests.ps1 b/Tests/JiraPS.Help.Tests.ps1 index 46bf7d6d..08cc814e 100644 --- a/Tests/JiraPS.Help.Tests.ps1 +++ b/Tests/JiraPS.Help.Tests.ps1 @@ -1,205 +1,260 @@ -<# - .NOTES - =========================================================================== - Created with: SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.119 - Created on: 4/12/2016 1:11 PM - Created by: June Blender - Organization: SAPIEN Technologies, Inc - Filename: *.Help.Tests.ps1 - =========================================================================== - .DESCRIPTION - To test help for the commands in a module, place this file in the module folder. - To test any module from any path, use https://github.com/juneb/PesterTDD/Module.Help.Tests.ps1 -#> - -<# -.SYNOPSIS -Gets command parameters; one per name. Prefers default parameter set. - -.DESCRIPTION -Gets one CommandParameterInfo object for each parameter in the specified -command. If a command has more than one parameter with the same name, this -function gets the parameters in the default parameter set, if one is specified. - -For example, if a command has two parameter sets: - Name, ID (default) - Name, Path -This function returns: - Name (default), ID Path - -This function is used to get parameters for help and for help testing. - -.PARAMETER Command -Enter a CommandInfo object, such as the object that Get-Command returns. You -can also pipe a CommandInfo object to the function. - -This parameter takes a CommandInfo object, instead of a command name, so -you can use the parameters of Get-Command to specify the module and version -of the command. - -.EXAMPLE -PS C:\> Get-ParametersDefaultFirst -Command (Get-Command New-Guid) -This command uses the Command parameter to specify the command to -Get-ParametersDefaultFirst - -.EXAMPLE -PS C:\> Get-Command New-Guid | Get-ParametersDefaultFirst -You can also pipe a CommandInfo object to Get-ParametersDefaultFirst - -.EXAMPLE -PS C:\> Get-ParametersDefaultFirst -Command (Get-Command BetterCredentials\Get-Credential) -You can use the Command parameter to specify the CommandInfo object. This -command runs Get-Command module-qualified name value. - -.EXAMPLE -PS C:\> $ModuleSpec = @{ModuleName='BetterCredentials';RequiredVersion=4.3} -PS C:\> Get-Command -FullyQualifiedName $ModuleSpec | Get-ParametersDefaultFirst -This command uses a Microsoft.PowerShell.Commands.ModuleSpecification object to -specify the module and version. You can also use it to specify the module GUID. -Then, it pipes the CommandInfo object to Get-ParametersDefaultFirst. -#> -function Get-ParametersDefaultFirst { - param - ( - [Parameter(Mandatory = $true, - ValueFromPipeline = $true)] - [System.Management.Automation.CommandInfo] - $Command - ) +#requires -modules BuildHelpers +#requires -modules Pester - BEGIN { - $Common = 'Debug', 'ErrorAction', 'ErrorVariable', 'InformationAction', 'InformationVariable', 'OutBuffer', 'OutVariable', 'PipelineVariable', 'Verbose', 'WarningAction', 'WarningVariable' - $parameters = @() - } - PROCESS { - if ($defaultPSetName = $Command.DefaultParameterSet) { - $defaultParameters = ($Command.ParameterSets | Where-Object Name -eq $defaultPSetName).parameters | Where-Object Name -NotIn $common - $otherParameters = ($Command.ParameterSets | Where-Object Name -ne $defaultPSetName).parameters | Where-Object Name -NotIn $common - - $parameters += $defaultParameters - if ($parameters -and $otherParameters) { - $otherParameters | ForEach-Object { - if ($_.Name -notin $parameters.Name) { - $parameters += $_ - } - } - $parameters = $parameters | Sort-Object Name - } +Describe "Help tests" -Tag Documentation { + + BeforeAll { + Import-Module BuildHelpers + Remove-Item -Path Env:\BH* + + $projectRoot = (Resolve-Path "$PSScriptRoot/..").Path + if ($projectRoot -like "*Release") { + $projectRoot = (Resolve-Path "$projectRoot/..").Path } - else { - $parameters = $Command.ParameterSets.Parameters | Where-Object Name -NotIn $common | Sort-Object Name -Unique + Set-BuildEnvironment -BuildOutput '$ProjectPath/Release' -Path $projectRoot -ErrorAction SilentlyContinue + $env:BHManifestToTest = $env:BHPSModuleManifest + $isBuild = $PSScriptRoot -like "$env:BHBuildOutput*" + if ($isBuild) { + $Pattern = [regex]::Escape($env:BHProjectPath) + + $env:BHBuildModuleManifest = $env:BHPSModuleManifest -replace $Pattern, $env:BHBuildOutput + $env:BHManifestToTest = $env:BHBuildModuleManifest } - return $parameters + Remove-Module $env:BHProjectName -ErrorAction SilentlyContinue + Import-Module $env:BHManifestToTest + } + AfterAll { + Remove-Module $env:BHProjectName -ErrorAction SilentlyContinue + Remove-Module BuildHelpers -ErrorAction SilentlyContinue + Remove-Item -Path Env:\BH* } - END { } -} -$ModuleBase = "$PSScriptRoot\..\JiraPS" + $DefaultParams = @( + 'Verbose' + 'Debug' + 'ErrorAction' + 'WarningAction' + 'InformationAction' + 'ErrorVariable' + 'WarningVariable' + 'InformationVariable' + 'OutVariable' + 'OutBuffer' + 'PipelineVariable' + 'WhatIf' + 'Confirm' + ) -# Handles modules in version directories -$leaf = Split-Path $ModuleBase -Leaf -$parent = Split-Path $ModuleBase -Parent -$parsedVersion = $null -if ([System.Version]::TryParse($leaf, [ref]$parsedVersion)) { - $ModuleName = Split-Path $parent -Leaf -} -else { - $ModuleName = $leaf -} + $module = Get-Module $env:BHProjectName + $commands = Get-Command -Module $module -CommandType Cmdlet, Function, Workflow # Not alias + $classes = Get-ChildItem "$env:BHProjectPath/docs/en-US/classes/*" -ErrorAction SilentlyContinue + $enums = Get-ChildItem "$env:BHProjectPath/docs/en-US/enumerations/*" -ErrorAction SilentlyContinue -# Removes all versions of the module from the session before importing -Get-Module $moduleName | Remove-Module + #region Public Functions + foreach ($command in $commands) { + $commandName = $command.Name -replace $module.Prefix, '' + $markdownFile = Resolve-Path "$env:BHProjectPath/docs/en-US/commands/$commandName.md" -$Module = Import-Module $ModuleBase\$ModuleName.psd1 -PassThru -ErrorAction Stop -$commands = Get-Command -Module $module -CommandType Cmdlet, Function, Workflow # Not alias + # The module-qualified command fails on Microsoft.PowerShell.Archive cmdlets + $help = Get-Help $command.Name -ErrorAction Stop -## When testing help, remember that help is cached at the beginning of each session. -## To test, restart session. + Context "Function $commandName's Help" { -foreach ($command in $commands) { - $commandName = $command.Name + #region PlatyPS external Help + It "is described in a markdown file" { + $markdownFile | Should -Not -BeNullOrEmpty + Test-Path $markdownFile | Should -Be $true + } - # The module-qualified command fails on Microsoft.PowerShell.Archive cmdlets - $Help = Get-Help $commandName -ErrorAction Stop + It "does not have Comment-Based Help" { + # We use .EXAMPLE, as we test this extensivly and it is never auto-generated + $command.Definition | Should -Not -BeNullOrEmpty + $Pattern = [regex]::Escape(".EXAMPLE") - Describe "Test help for $commandName" -Tag "CommandHelp" { + $command.Definition | Should -Not -Match "^\s*$Pattern" + } - # If help is not found, synopsis in auto-generated help is the syntax diagram - It "should not be auto-generated" { - $Help.Synopsis | Should Not BeLike '*`[``]*' - } + It "has no platyPS template artifacts" { + $markdownFile | Should -Not -BeNullOrEmpty + $markdownFile | Should -Not -FileContentMatch '{{.*}}' + } - # Should be a synopsis for every function - It "gets synopsis for $commandName" { - $Help.Synopsis | Should Not beNullOrEmpty - } + It "has a link to the 'Online Version'" { + [Uri]$onlineLink = ($help.relatedLinks.navigationLink | Where-Object linkText -eq "Online Version:").Uri - # Should be a description for every function - It "gets description for $commandName" { - $Help.Description | Should Not BeNullOrEmpty - } + $onlineLink.Authority | Should -Be "atlassianps.org" + $onlineLink.Scheme | Should -Be "https" + $onlineLink.PathAndQuery | Should -Be "/docs/$env:BHProjectName/commands/$commandName/" + } - # Should be at least one example - It "gets example code from $commandName" { - ($Help.Examples.Example | Select-Object -First 1).Code | Should Not BeNullOrEmpty - } + it "has a valid HelpUri" { + $command.HelpUri | Should -Not -BeNullOrEmpty + $Pattern = [regex]::Escape("https://atlassianps.org/docs/$env:BHProjectName/commands/$commandName") - # Should be at least one example description - It "gets example help from $commandName" { - ($Help.Examples.Example.Remarks | Select-Object -First 1).Text | Should Not BeNullOrEmpty - } + $command.HelpUri | Should -Match $Pattern + } - It "has at least as many examples as ParameterSets" { - ($Help.Examples.Example | Measure-Object).Count | Should Not BeLessThan $command.ParameterSets.Count - } + It "defines the frontmatter for the homepage" { + $markdownFile | Should -Not -BeNullOrEmpty + $markdownFile | Should -FileContentMatch "Module Name: $env:BHProjectName" + $markdownFile | Should -FileContentMatchExactly "layout: documentation" + $markdownFile | Should -FileContentMatch "permalink: /docs/$env:BHProjectName/commands/$commandName/" + } + #endregion PlatyPS external Help + + #region Help Content + It "has a synopsis" { + $help.Synopsis | Should -Not -BeNullOrEmpty + } + + It "has a description" { + $help.Description.Text -join '' | Should -Not -BeNullOrEmpty + } + + It "has examples" { + ($help.Examples.Example | Select-Object -First 1).Code | Should -Not -BeNullOrEmpty + } + + It "has desciptions for all examples" { + foreach ($example in ($help.Examples.Example)) { + $example.remarks.Text | Should -Not -BeNullOrEmpty + } + } + + It "has at least as many examples as ParameterSets" { + ($help.Examples.Example | Measure-Object).Count | Should -BeGreaterOrEqual $command.ParameterSets.Count + } + #endregion Help Content + + #region Consistency with Code + # It "does not define parameter position for functions with only one ParameterSet" { + # if ($command.ParameterSets.Count -eq 1) { + # $command.Parameters.Keys | Foreach-Object { + # $command.Parameters[$_].ParameterSets.Values.Position | Should -BeLessThan 0 + # } + # } + # } + + It "has all ParameterSets in the Help" { + # @($command.ParameterSets).Count | Should -Be @($help.Syntax.SyntaxItem).Count + } - Context "Test parameter help for $commandName" { - # Get parameters. When >1 parameter with same name, - # get parameter from the default parameter set, if any. - if ($parameters = Get-ParametersDefaultFirst -Command $command) { - $parameterNames = $parameters.Name - $HelpParameterNames = $Help.Parameters.Parameter.Name | Sort-Object -Unique - - foreach ($parameter in $parameters) { - $parameterName = $parameter.Name - $parameterHelp = $Help.parameters.parameter | Where-Object Name -EQ $parameterName - - # Should be a description for every parameter - if ($parameterName -notmatch 'Confirm|WhatIf') { - It "gets help for parameter: $parameterName : in $commandName" { - $parameterHelp.Description.Text | Should Not BeNullOrEmpty + #region Parameters + foreach ($parameterName in $command.Parameters.Keys) { + $parameterCode = $command.Parameters[$parameterName] + + if ($help.Parameters | Get-Member -Name Parameter) { + $parameterHelp = $help.Parameters.Parameter | Where-Object Name -EQ $parameterName + + if ($parameterName -notin $DefaultParams) { + It "has a description for parameter [-$parameterName] in $commandName" { + $parameterHelp.Description.Text | Should -Not -BeNullOrEmpty } - } - # Required value in Help should match IsMandatory property of parameter - It "help for $parameterName parameter in $commandName has correct Mandatory value" { - $codeMandatory = $parameter.IsMandatory.toString() - $parameterHelp.Required | Should Be $codeMandatory - } + It "has a mandatory flag for parameter [-$parameterName] in $commandName" { + $isMandatory = $parameterCode.ParameterSets.Values.IsMandatory -contains "True" - # Parameter type in Help should match code - It "help for $commandName has correct parameter type for $parameterName" { - $codeType = $parameter.ParameterType.Name - if ($codeType -eq "Object") { - if (($parameter.Attributes) -and ($parameter.Attributes | Get-Member -Name PSTypeName)) { - $codeType = $parameter.Attributes[0].PSTypeName + $parameterHelp.Required | Should -BeLike $isMandatory.ToString() + } + + It "matches the type of the parameter [-$parameterName] in code and help of $commandName" { + $codeType = $parameterCode.ParameterType.Name + if ($codeType -eq "Object") { + if (($parameterCode.Attributes) -and ($parameterCode.Attributes | Get-Member -Name PSTypeName)) { + $codeType = $parameterCode.Attributes[0].PSTypeName + } } + # To avoid calling Trim method on a null object. + $helpType = if ($parameterHelp.parameterValue) { $parameterHelp.parameterValue.Trim() } + if ($helpType -eq "PSCustomObject") { $helpType = "PSObject" } + + $helpType | Should -Be $codeType } - # To avoid calling Trim method on a null object. - $helpType = if ($parameterHelp.parameterValue) { $parameterHelp.parameterValue.Trim() } - if ($helpType -eq "PSCustomObject") { $helpType = "PSObject" } - $helpType | Should be $codeType } } - foreach ($helpParm in $HelpParameterNames) { - # Shouldn't find extra parameters in help. - It "finds help parameter in code: $helpParm" { - $helpParm -in $parameterNames | Should Be $true + It "does not have parameters that are not in the code" { + $parameter = @() + if ($help.Parameters | Get-Member -Name Parameter) { + $parameter = $help.Parameters.Parameter.Name | Sort-Object -Unique } + foreach ($helpParm in $parameter) { + $command.Parameters.Keys | Should -Contain $helpParm + } + } + } + #endregion Parameters + #endregion Consistency with Code + } + } + #endregion Public Functions + + #region Classes + if ($classes) { + foreach ($class in $classes) { + Context "Classes $($class.BaseName) Help" { + + It "is described in a markdown file" { + $class.FullName | Should -Not -BeNullOrEmpty + Test-Path $class.FullName | Should -Be $true + } + + It "has no platyPS template artifacts" { + $class.FullName | Should -Not -BeNullOrEmpty + $class.FullName | Should -Not -FileContentMatch '{{.*}}' + } + + It "defines the frontmatter for the homepage" { + $class.FullName | Should -Not -BeNullOrEmpty + $class.FullName | Should -FileContentMatch "Module Name: $env:BHProjectName" + $class.FullName | Should -FileContentMatchExactly "layout: documentation" + $class.FullName | Should -FileContentMatch "permalink: /docs/$env:BHProjectName/classes/$commandName/" + } + } + } + + Context "Missing classes" { + It "has a documentation file for every class" { + foreach ($class in ([AtlassianPS.ServerData].Assembly.GetTypes() | Where-Object IsClass)) { + $classes.BaseName | Should -Contain $class.FullName + } + } + } + } + #endregion Classes + + #region Enumerations + if ($enums) { + foreach ($enum in $enums) { + Context "Enumeration $($enum.BaseName) Help" { + + It "is described in a markdown file" { + $enum.FullName | Should -Not -BeNullOrEmpty + Test-Path $enum.FullName | Should -Be $true + } + + It "has no platyPS template artifacts" { + $enum.FullName | Should -Not -BeNullOrEmpty + $enum.FullName | Should -Not -FileContentMatch '{{.*}}' + } + + It "defines the frontmatter for the homepage" { + $enum.FullName | Should -Not -BeNullOrEmpty + $enum.FullName | Should -FileContentMatch "Module Name: $env:BHProjectName" + $enum.FullName | Should -FileContentMatchExactly "layout: documentation" + $enum.FullName | Should -FileContentMatch "permalink: /docs/$env:BHProjectName/enumerations/$commandName/" + } + } + } + + Context "Missing classes" { + It "has a documentation file for every class" { + foreach ($enum in ([AtlassianPS.ServerData].Assembly.GetTypes() | Where-Object IsEnum)) { + $enums.BaseName | Should -Contain $enum.FullName } } } } + #endregion Enumerations } From 6f25903e5e9bb42aef5819292317336785e2b660 Mon Sep 17 00:00:00 2001 From: Oliver Lipkau Date: Thu, 21 Jun 2018 14:16:19 +0200 Subject: [PATCH 9/9] Upgraded Pester to 4.3.1 --- Tools/build.requirements.psd1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/build.requirements.psd1 b/Tools/build.requirements.psd1 index 7c0668f0..48501742 100644 --- a/Tools/build.requirements.psd1 +++ b/Tools/build.requirements.psd1 @@ -14,7 +14,7 @@ Parameters = @{ SkipPublisherCheck = $true } - Version = "4.1.1" + Version = "4.3.1" } platyPS = "latest" PSScriptAnalyzer = @{