JiraPS.psm1
#region Dependencies # Load the ConfluencePS namespace from C# # if (!("" -as [Type])) { # Add-Type -Path (Join-Path $PSScriptRoot JiraPS.Types.cs) -ReferencedAssemblies Microsoft.CSharp, Microsoft.PowerShell.Commands.Utility, System.Management.Automation # } # if ($PSVersionTable.PSVersion.Major -lt 5) { # Add-Type -Path (Join-Path $PSScriptRoot JiraPS.Attributes.cs) -ReferencedAssemblies Microsoft.CSharp, Microsoft.PowerShell.Commands.Utility, System.Management.Automation # } # Load Web assembly when needed # PowerShell Core has the assembly preloaded if (!("System.Web.HttpUtility" -as [Type])) { Add-Type -AssemblyName "System.Web" } # Load System.Net.Http when needed # PowerShell Core has the assembly preloaded if (!("System.Net.Http.HttpRequestException" -as [Type])) { Add-Type -AssemblyName "System.Net.Http" } if (!("System.Net.Http" -as [Type])) { Add-Type -Assembly System.Net.Http } #region Configuration $script:serverConfig = ("{0}/AtlassianPS/JiraPS/server_config" -f [Environment]::GetFolderPath('ApplicationData')) if (-not (Test-Path $script:serverConfig)) { $null = New-Item -Path $script:serverConfig -ItemType File -Force } $script:JiraServerUrl = [Uri](Get-Content $script:serverConfig) $script:DefaultContentType = "application/json; charset=utf-8" $script:DefaultPageSize = 25 $script:DefaultHeaders = @{ "Accept-Charset" = "utf-8" } # Bug in PSv3's .Net API if ($PSVersionTable.PSVersion.Major -gt 3) { $script:DefaultHeaders["Accept"] = "application/json" } $script:PagingContainers = @( "comments" "dashboards" "groups" "issues" "values" "worklogs" ) $script:SessionTransformationMethod = "ConvertTo-JiraSession" function Add-JiraFilterPermission { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( SupportsShouldProcess, DefaultParameterSetName = 'ByInputObject' )] # [OutputType( [JiraPS.FilterPermission] )] param( [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = 'ByInputObject' )] [ValidateNotNullOrEmpty()] [PSTypeName('JiraPS.Filter')] $Filter, [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = 'ById')] [ValidateNotNullOrEmpty()] [UInt32[]] $Id, [Parameter( Mandatory )] [ValidateNotNullOrEmpty()] [ValidateSet('Group', 'Project', 'ProjectRole', 'Authenticated', 'Global')] [String]$Type, [Parameter()] [String]$Value, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) 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)" if ($PSCmdlet.ParameterSetName -eq 'ById') { $Filter = Get-JiraFilter -Id $Id } $body = @{ type = $Type.ToLower() } switch ($Type) { "Group" { $body["groupname"] = $Value } "Project" { $body["projectId"] = $Value } "ProjectRole" { $body["projectRoleId"] = $Value } "Authenticated" { } "Global" { } } 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-JiraFilter -InputObject $_filter -FilterPermissions $result) } } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Add-JiraGroupMember { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( SupportsShouldProcess )] param( [Parameter( Mandatory, ValueFromPipeline )] [Alias('GroupName')] [ValidateNotNullOrEmpty()] [Object[]] $Group, [Parameter( Mandatory )] [ValidateNotNullOrEmpty()] [Object[]] $UserName, <# #ToDo:CustomClass Once we have custom classes, this can also accept ValueFromPipeline #> [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Switch] $PassThru ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2/group/user?groupname={0}" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" foreach ($_group in $Group) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$_group]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$_group [$_group]" $groupObj = Get-JiraGroup -GroupName $_group -Credential $Credential -ErrorAction Stop $groupMembers = (Get-JiraGroupMember -Group $_group -Credential $Credential -ErrorAction Stop).Name # At present, it looks like this REST method doesn't support arrays in the Name property... # in other words, a single REST call can only add a single group member to a single group. # That's kind of annoying. # Anyway, this builds a bunch of individual JSON strings with each username in its own Web # request, which we'll loop through again in the Process block. $users = Resolve-JiraUser -InputObject $UserName -Exact -Credential $Credential foreach ($user in $users) { if ($groupMembers -notcontains $user.Name) { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] User [$($user.Name)] is not already in group [$_group]. Adding user." $parameter = @{ URI = $resourceURi -f $groupObj.Name Method = "POST" Body = ConvertTo-Json -InputObject @{ 'name' = $user.Name } Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" if ($PSCmdlet.ShouldProcess($GroupName, "Adding user '$($user.Name)'.")) { $result = Invoke-JiraMethod @parameter } } else { $errorMessage = @{ Category = "ResourceExists" ErrorId = "Adding [$user] to [$_group]" Message = "User [$user] is already a member of group [$_group]" } WriteError @errorMessage } } if ($PassThru) { Write-Output (ConvertTo-JiraGroup -InputObject $result) } } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Add-JiraIssueAttachment { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( SupportsShouldProcess )] param( [Parameter( Mandatory )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.Issue" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraIssue' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Issue. Expected [JiraPS.Issue] or [String], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Alias('Key')] [Object] $Issue, <# #ToDo:CustomClass Once we have custom classes, this can also accept ValueFromPipeline #> [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [ValidateScript( { if (-not (Test-Path $_ -PathType Leaf)) { $exception = ([System.ArgumentException]"File not found") #fix code highlighting] $errorId = 'ParameterValue.FileNotFound' $errorCategory = 'ObjectNotFound' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "No file could be found with the provided path '$_'." $PSCmdlet.ThrowTerminatingError($errorItem) } else { return $true } } )] [Alias('InFile', 'FullName', 'Path')] [String[]] $FilePath, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Switch] $PassThru ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $resourceURi = "{0}/attachments" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" if (@($Issue).Count -ne 1) { $exception = ([System.ArgumentException]"invalid Issue provided") $errorId = 'ParameterValue.JiraIssue' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Only one Issue can be provided at a time." $PSCmdlet.ThrowTerminatingError($errorItem) } # Find the proper object for the Issue $issueObj = Resolve-JiraIssueObject -InputObject $Issue -Credential $Credential foreach ($file in $FilePath) { $file = Resolve-FilePath -Path $file $enc = [System.Text.Encoding]::GetEncoding("iso-8859-1") $boundary = [System.Guid]::NewGuid().ToString() $fileName = Split-Path -Path $file -Leaf $readFile = [System.IO.File]::ReadAllBytes($file) $fileEnc = $enc.GetString($readFile) $bodyLines = @' --{0} Content-Disposition: form-data; name="file"; filename="{1}" Content-Type: application/octet-stream {2} --{0}-- '@ -f $boundary, $fileName, $fileEnc $headers = @{ 'X-Atlassian-Token' = 'nocheck' 'Content-Type' = "multipart/form-data; boundary=`"$boundary`"" } $parameter = @{ URI = $resourceURi -f $issueObj.RestURL Method = "POST" Body = $bodyLines Headers = $headers RawBody = $true Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" if ($PSCmdlet.ShouldProcess($IssueObj.Key, "Adding attachment '$($fileName)'.")) { $rawResult = Invoke-JiraMethod @parameter if ($PassThru) { Write-Output (ConvertTo-JiraAttachment -InputObject $rawResult) } } } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Add-JiraIssueComment { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( SupportsShouldProcess )] param( [Parameter( Mandatory )] [ValidateNotNullOrEmpty()] [String] $Comment, [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.Issue" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraIssue' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Issue. Expected [JiraPS.Issue] or [String], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Alias('Key')] [Object] $Issue, [ValidateSet('All Users', 'Developers', 'Administrators')] [String] $VisibleRole = 'All Users', [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $resourceURi = "{0}/comment" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" # Find the proper object for the Issue $issueObj = Resolve-JiraIssueObject -InputObject $Issue -Credential $Credential $requestBody = @{ 'body' = $Comment } # If the visible role should be all users, the visibility block shouldn't be passed at # all. JIRA returns a 500 Internal Server Error if you try to pass this block with a # value of "All Users". if ($VisibleRole -ne 'All Users') { $requestBody.visibility = @{ 'type' = 'role' 'value' = $VisibleRole } } $parameter = @{ URI = $resourceURi -f $issueObj.RestURL Method = "POST" Body = ConvertTo-Json -InputObject $requestBody Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" if ($PSCmdlet.ShouldProcess($issueObj.Key)) { $rawResult = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraComment -InputObject $rawResult) } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Add-JiraIssueLink { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( SupportsShouldProcess )] param( [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.Issue" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraIssue' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Issue. Expected [JiraPS.Issue] or [String], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Alias('Key')] [Object[]] $Issue, [Parameter( Mandatory )] [ValidateScript( { $objectProperties = Get-Member -InputObject $_ -MemberType *Property if (-not( ($objectProperties.Name -contains "type") -and (($objectProperties.Name -contains "outwardIssue") -or ($objectProperties.Name -contains "inwardIssue")) )) { $exception = ([System.ArgumentException]"Invalid Parameter") #fix code highlighting] $errorId = 'ParameterProperties.Incomplete' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "The IssueLink provided does not contain the information needed." $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Object[]] $IssueLink, [String] $Comment, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2/issueLink" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" foreach ($_issue in $Issue) { # Find the proper object for the Issue $issueObj = Resolve-JiraIssueObject -InputObject $_issue -Credential $Credential foreach ($_issueLink in $IssueLink) { if ($_issueLink.inwardIssue) { $inwardIssue = @{ key = $_issueLink.inwardIssue.key } } else { $inwardIssue = @{ key = $issueObj.key } } if ($_issueLink.outwardIssue) { $outwardIssue = @{ key = $_issueLink.outwardIssue.key } } else { $outwardIssue = @{ key = $issueObj.key } } $body = @{ type = @{ name = $_issueLink.type.name } inwardIssue = $inwardIssue outwardIssue = $outwardIssue } if ($Comment) { $body.comment = @{ body = $Comment } } $parameter = @{ URI = $resourceURi Method = "POST" Body = ConvertTo-Json -InputObject $body Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" if ($PSCmdlet.ShouldProcess($issueObj.Key)) { Invoke-JiraMethod @parameter } } } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Add-JiraIssueWatcher { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( SupportsShouldProcess )] param( [Parameter( Mandatory )] [String[]] $Watcher, <# #ToDo:CustomClass Once we have custom classes, this can also accept ValueFromPipeline #> [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.Issue" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraIssue' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Issue. Expected [JiraPS.Issue] or [String], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Alias('Key')] [Object] $Issue, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $resourceURi = "{0}/watchers" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" # Find the proper object for the Issue $issueObj = Resolve-JiraIssueObject -InputObject $Issue -Credential $Credential foreach ($_watcher in $Watcher) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$_watcher]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$_watcher [$_watcher]" $parameter = @{ URI = $resourceURi -f $issueObj.RestURL Method = "POST" Body = '"{0}"' -f $_watcher Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" if ($PSCmdlet.ShouldProcess($issueObj.Key, "Adding user '$_watcher' as watcher.")) { Invoke-JiraMethod @parameter } } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Add-JiraIssueWorklog { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( SupportsShouldProcess )] param( [Parameter( Mandatory )] [ValidateNotNullOrEmpty()] [String] $Comment, [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.Issue" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraIssue' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Issue. Expected [JiraPS.Issue] or [String], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Alias('Key')] [Object] $Issue, [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [TimeSpan] $TimeSpent, [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [DateTime] $DateStarted, [ValidateSet('All Users', 'Developers', 'Administrators')] [String] $VisibleRole = 'All Users', [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $resourceURi = "{0}/worklog" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" # Find the proper object for the Issue $issueObj = Resolve-JiraIssueObject -InputObject $Issue -Credential $Credential if (-not $issueObj) { $errorMessage = @{ Category = "ObjectNotFound" CategoryActivity = "Searching for Issue" Message = "Invalid Issue provided." } Write-Error @errorMessage } # Harmonize DateStarted: # `Get-Date -Date "01.01.2000"` does not return the local timezone # which is required by the API $DateStarted = [DateTime]::new($DateStarted.Ticks, 'Local') $requestBody = @{ 'comment' = $Comment # We need to fix the date with a RegEx replace because the API does not like: # * miliseconds with more than 3 digits # * `:` in the TimeZone 'started' = $DateStarted.ToString("o") -replace "\.(\d{3})\d*([\+\-]\d{2}):", ".`$1`$2" 'timeSpentSeconds' = $TimeSpent.TotalSeconds.ToString() } # If the visible role should be all users, the visibility block shouldn't be passed at # all. JIRA returns a 500 Internal Server Error if you try to pass this block with a # value of "All Users". if ($VisibleRole -ne 'All Users') { $requestBody.visibility = @{ 'type' = 'role' 'value' = $VisibleRole } } $parameter = @{ URI = $resourceURi -f $issueObj.RestURL Method = "POST" Body = ConvertTo-Json -InputObject $requestBody Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" if ($PSCmdlet.ShouldProcess($issueObj.Key)) { $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraWorklogitem -InputObject $result) } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Find-JiraFilter { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( DefaultParameterSetName='ByAccountId', SupportsPaging )] param( [Parameter(ValueFromPipeline,ValueFromPipelineByPropertyName)] [string[]]$Name, [Parameter(ParameterSetName='ByAccountId',ValueFromPipelineByPropertyName)] [string]$AccountId, [Parameter(ParameterSetName='ByOwner',ValueFromPipelineByPropertyName)] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.User" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraUser' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Owner. Expected [JiraPS.User] or [String], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Alias('UserName')] [Object] $Owner, [Parameter(ValueFromPipelineByPropertyName)] [string]$GroupName, [Parameter(ValueFromPipelineByPropertyName)] [ValidateScript( { if (("JiraPS.Project" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraProject' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Project. Expected [JiraPS.Project] or [String], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Object] $Project, [Validateset('description','favourite','favouritedCount','jql','owner','searchUrl','sharePermissions','subscriptions','viewUrl')] [String[]] $Fields = @('description','favourite','favouritedCount','jql','owner','searchUrl','sharePermissions','subscriptions','viewUrl'), [Validateset('description','favourite_count','is_favourite','id','name','owner')] [string]$Sort, [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $searchURi = "$server/rest/api/2/filter/search" [String]$Fields = $Fields -join ',' } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" $parameter = @{ URI = $searchURi Method = 'GET' GetParameter = @{ expand = $Fields } Paging = $true Credential = $Credential } if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('AccountId')) { $parameter['GetParameter']['accountId'] = $AccountId } elseif ($PSCmdlet.ParameterSetName -eq 'ByOwner') { $userObj = Get-JiraUser -InputObject $Owner -Credential $Credential -ErrorAction Stop $parameter['GetParameter']['accountId'] = $userObj.AccountId } if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('GroupName')) { $parameter['GetParameter']['groupName'] = $GroupName } if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('Project')) { $projectObj = Get-JiraProject -Project $Project -Credential $Credential -ErrorAction Stop $parameter['GetParameter']['projectId'] = $projectObj.Id } if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('Sort')) { $parameter['GetParameter']['orderBy'] = $Sort } # Paging ($PSCmdlet.PagingParameters | Get-Member -MemberType Property).Name | ForEach-Object { $parameter[$_] = $PSCmdlet.PagingParameters.$_ } if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('Name')) { foreach($_name in $Name) { $parameter['GetParameter']['filterName'] = $_name Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" Write-Output (Invoke-JiraMethod @parameter | ConvertTo-JiraFilter) } } else { Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" Write-Output (Invoke-JiraMethod @parameter | ConvertTo-JiraFilter) } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Format-Jira { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding()] [OutputType([System.String])] param( [Parameter( Mandatory, ValueFromPipeline, ValueFromRemainingArguments )] [ValidateNotNull()] [PSObject[]] $InputObject, [Object[]] $Property ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $headers = New-Object -TypeName System.Collections.ArrayList $thisLine = New-Object -TypeName System.Text.StringBuilder $allText = New-Object -TypeName System.Text.StringBuilder $headerDefined = $false $n = [System.Environment]::NewLine if ($Property) { if ($Property -eq '*') { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] -Property * was passed. Adding all properties." } else { foreach ($p in $Property) { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Adding header [$p]" [void] $headers.Add($p.ToString()) } $headerString = "||$(($headers.ToArray()) -join '||')||" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Full header: [$headerString]" [void] $allText.Append($headerString) $headerDefined = $true } } else { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Property parameter was not specified. Checking first InputObject for property names." } } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" foreach ($i in $InputObject) { if (-not ($headerDefined)) { # This should only be called if Property was not supplied and this is the first object in the InputObject array. if ($Property -and $Property -eq '*') { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Adding all properties from object [$i]" $allProperties = Get-Member -InputObject $i -MemberType '*Property' foreach ($a in $allProperties) { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Adding header [$($a.Name)]" [void] $headers.Add($a.Name) } } else { # TODO: find a way to format output objects based on PowerShell's own Format-Table # Identify default table properties if possible and use them to create a Jira table if ($i.PSStandardMembers.DefaultDisplayPropertySet) { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Identifying default properties for object [$i]" $propertyNames = $i.PSStandardMembers.DefaultDisplayPropertySet.ReferencedPropertyNames foreach ($p in $propertyNames) { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Adding header [$p]" [void] $headers.Add($p) } } else { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] No default format data exists for object [$i] (type=[$($i.GetType())]). All properties will be used." $allProperties = Get-Member -InputObject $i -MemberType '*Property' foreach ($a in $allProperties) { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Adding header [$($a.Name)]" [void] $headers.Add($a.Name) } } } $headerString = "||$(($headers.ToArray()) -join '||')||" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Full header: [$headerString]" [void] $allText.Append($headerString) $headerDefined = $true } Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Processing object [$i]" [void] $thisLine.Clear() [void] $thisLine.Append("$n|") foreach ($h in $headers) { $value = $InputObject.$h if ($value) { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Adding property (name=[$h], value=[$value])" [void] $thisLine.Append("$value|") } else { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Property [$h] does not exist on this object." [void] $thisLine.Append(' |') } } $thisLineString = $thisLine.ToString() Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Completed line: [$thisLineString]" [void] $allText.Append($thisLineString) } } end { Write-Output $allText.ToString() Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraComponent { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding(DefaultParameterSetName = 'ByID')] param( [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = 'ByProject' )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.Project" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraProject' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Issue. Expected [JiraPS.Project] or [String], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Object[]] $Project, <# #ToDo:CustomClass Once we have custom classes, these two parameters can be one #> [Parameter( Position = 0, Mandatory, ParameterSetName = 'ByID' )] [Alias("Id")] [Int[]] $ComponentId, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2{0}" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" switch ($PSCmdlet.ParameterSetName) { "ByProject" { foreach ($_project in $Project) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$_project]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$_project [$_project]" if ($_project -isnot [string]) { $_project = $_project.Key } $parameter = @{ URI = $resourceURi -f "/project/$_project/components" Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraComponent -InputObject $result) } } "ByID" { foreach ($_id in $ComponentId) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$_id]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$_id [$_id]" $parameter = @{ URI = $resourceURi -f "/component/$_id" Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraComponent -InputObject $result) } } } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraConfigServer { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding()] [OutputType([System.String])] param() 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)" return ($script:JiraServerUrl -replace "\/$", "") } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraField { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( DefaultParameterSetName = '_All' )] param( [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = '_Search' )] [String[]] $Field, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2/field" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" switch ($PSCmdlet.ParameterSetName) { '_All' { $parameter = @{ URI = $resourceURi Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraField -InputObject $result) } '_Search' { foreach ($_field in $Field) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$_field]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$_field [$_field]" $allFields = Get-JiraField -Credential $Credential Write-Output ($allFields | Where-Object -FilterScript {($_.Id -eq $_field) -or ($_.Name -like $_field)}) } } } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraFilter { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding(DefaultParameterSetName = 'ByFilterID')] param( [Parameter( Position = 0, Mandatory, ParameterSetName = 'ByFilterID' )] [String[]] $Id, <# #ToDo:CustomClass Once we have custom classes for the module, this can use ValueFromPipelineByPropertyName and we will no longer need the InputObject #> [Parameter( Mandatory, ValueFromPipeline, ParameterSetName = 'ByInputObject' )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.Filter" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraFilter' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Filter. Expected [JiraPS.Filter] or [String], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Object[]] $InputObject, [Parameter( Mandatory, ParameterSetName = 'MyFavorite' )] [Alias('Favourite')] [Switch] $Favorite, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2/filter/{0}" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" switch ($PSCmdlet.ParameterSetName) { "ByFilterID" { foreach ($_id in $Id) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$_id]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$_id [$_id]" $parameter = @{ URI = $resourceURi -f $_id Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraFilter -InputObject $result) } } "ByInputObject" { foreach ($object in $InputObject) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$object]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$object [$object]" if ((Get-Member -InputObject $object).TypeName -eq 'JiraPS.Filter') { $thisId = $object.ID } else { $thisId = $object.ToString() Write-Verbose "[$($MyInvocation.MyCommand.Name)] ID is assumed to be [$thisId] via ToString()" } Write-Output (Get-JiraFilter -Id $thisId -Credential $Credential) } } "MyFavorite" { $parameter = @{ URI = $resourceURi -f "favourite" Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraFilter -InputObject $result) } } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraFilterPermission { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( DefaultParameterSetName = 'ById' )] # [OutputType( [JiraPS.FilterPermission] )] param( [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = 'ByInputObject' )] [ValidateNotNullOrEmpty()] [PSTypeName('JiraPS.Filter')] $Filter, [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 { 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)" if ($PSCmdlet.ParameterSetName -eq 'ById') { $Filter = Get-JiraFilter -Id $Id } 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 { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraGroup { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding()] param( [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [Alias('Name')] [String[]] $GroupName, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2/group?groupname={0}" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" foreach ($group in $GroupName) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$group]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$group [$group]" $escapedGroupName = ConvertTo-URLEncoded $group $parameter = @{ URI = $resourceURi -f $escapedGroupName Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraGroup -InputObject $result) } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraGroupMember { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( SupportsPaging )] param( [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.Group" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraGroup' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Group. Expected [JiraPS.Group] or [String], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Object[]] $Group, [Switch] $IncludeInactive, [UInt32] $StartIndex = 0, [UInt32] $MaxResults, [UInt32] $PageSize = $script:DefaultPageSize, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2/group/member" if ($PageSize -gt 50) { Write-Warning "JIRA's API may not properly support MaxResults values higher than 50 for this method. If you receive inconsistent results, do not pass the MaxResults parameter to this function to return all results." } } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" $groupObj = Get-JiraGroup -GroupName $Group -Credential $Credential -ErrorAction Stop foreach ($_group in $groupObj) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$_group]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$_group [$_group]" $parameter = @{ URI = $resourceURi Method = "GET" GetParameter = @{ groupname = $_group.Name maxResults = $PageSize } OutputType = "JiraUser" Paging = $true Credential = $Credential } if ($IncludeInactive) { $parameter["includeInactiveUsers"] = $true } # Paging ($PSCmdlet.PagingParameters | Get-Member -MemberType Property).Name | ForEach-Object { $parameter[$_] = $PSCmdlet.PagingParameters.$_ } # Make `SupportsPaging` be backwards compatible if ($StartIndex) { Write-Warning "[$($MyInvocation.MyCommand.Name)] The parameter '-StartIndex' has been marked as deprecated. For more information, plase read the help." $parameter["Skip"] = $StartIndex } if ($MaxResults) { Write-Warning "[$($MyInvocation.MyCommand.Name)] The parameter '-MaxResults' has been marked as deprecated. For more information, plase read the help." $parameter["First"] = $MaxResults } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" Invoke-JiraMethod @parameter } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraIssue { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( SupportsPaging, DefaultParameterSetName = 'ByIssueKey' )] param( [Parameter( Position = 0, Mandatory, ParameterSetName = 'ByIssueKey' )] [ValidateNotNullOrEmpty()] [Alias('Issue')] [String[]] $Key, [Parameter( Position = 0, Mandatory, ParameterSetName = 'ByInputObject' )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.Issue" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraIssue' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Issue. Expected [JiraPS.Issue] or [String], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) } else { return $true } } )] [Object[]] $InputObject, <# #ToDo:Deprecate This is not necessary if $Key uses ValueFromPipelineByPropertyName #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> [Parameter( Mandatory, ParameterSetName = 'ByJQL' )] [Alias('JQL')] [String] $Query, [Parameter( Mandatory, ParameterSetName = 'ByFilter' )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.Filter" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraFilter' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Filter. Expected [JiraPS.Filter] or [String], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Object] $Filter, [Parameter()] [ValidateNotNullOrEmpty()] [String[]] $Fields = "*all", [Parameter( ParameterSetName = 'ByJQL' )] [Parameter( ParameterSetName = 'ByFilter' )] [UInt32] $StartIndex = 0, [Parameter( ParameterSetName = 'ByJQL' )] [Parameter( ParameterSetName = 'ByFilter' )] [UInt32] $MaxResults = 0, [Parameter( ParameterSetName = 'ByJQL' )] [Parameter( ParameterSetName = 'ByFilter' )] [UInt32] $PageSize = $script:DefaultPageSize, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $searchURi = "$server/rest/api/2/search" $resourceURi = "$server/rest/api/2/issue/{0}" [String]$Fields = $Fields -join "," } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" switch ($PSCmdlet.ParameterSetName) { 'ByIssueKey' { foreach ($_key in $Key) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$_key]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$_key [$_key]" $getParameter = @{ expand = "transitions" } if ($Fields) { $getParameter["fields"] = $Fields } $parameter = @{ URI = $resourceURi -f $_key Method = "GET" GetParameter = $getParameter Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraIssue -InputObject $result) } } 'ByInputObject' { # Write-Warning "[$($MyInvocation.MyCommand.Name)] The parameter '-InputObject' has been marked as deprecated." foreach ($_issue in $InputObject) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$_issue]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$_issue [$_issue]" Write-Output (Get-JiraIssue -Key $_issue.Key -Fields $Fields -Credential $Credential) } } 'ByJQL' { $parameter = @{ URI = $searchURi Method = "GET" GetParameter = @{ jql = (ConvertTo-URLEncoded $Query) validateQuery = $true expand = "transitions" maxResults = $PageSize } OutputType = "JiraIssue" Paging = $true Credential = $Credential } if ($Fields) { $parameter["GetParameter"]["fields"] = $Fields } # Paging ($PSCmdlet.PagingParameters | Get-Member -MemberType Property).Name | ForEach-Object { $parameter[$_] = $PSCmdlet.PagingParameters.$_ } # Make `SupportsPaging` be backwards compatible if ($StartIndex) { Write-Warning "[$($MyInvocation.MyCommand.Name)] The parameter '-StartIndex' has been marked as deprecated. For more information, plase read the help." $parameter["Skip"] = $StartIndex } if ($MaxResults) { Write-Warning "[$($MyInvocation.MyCommand.Name)] The parameter '-MaxResults' has been marked as deprecated. For more information, plase read the help." $parameter["First"] = $MaxResults } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" Invoke-JiraMethod @parameter } 'ByFilter' { $filterObj = (Get-JiraFilter -InputObject $Filter -Credential $Credential -ErrorAction Stop).searchurl <# #ToDo:CustomClass Once we have custom classes, this will no longer be necessary #> $parameter = @{ URI = $filterObj Method = "GET" GetParameter = @{ validateQuery = $true expand = "transitions" maxResults = $PageSize } OutputType = "JiraIssue" Paging = $true Credential = $Credential } if ($Fields) { $parameter["GetParameter"]["fields"] = $Fields } # Paging ($PSCmdlet.PagingParameters | Get-Member -MemberType Property).Name | ForEach-Object { $parameter[$_] = $PSCmdlet.PagingParameters.$_ } # Make `SupportsPaging` be backwards compatible if ($StartIndex) { Write-Warning "[$($MyInvocation.MyCommand.Name)] The parameter '-StartIndex' has been marked as deprecated. For more information, plase read the help." $parameter["Skip"] = $StartIndex } if ($MaxResults) { Write-Warning "[$($MyInvocation.MyCommand.Name)] The parameter '-MaxResults' has been marked as deprecated. For more information, plase read the help." $parameter["First"] = $MaxResults } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" Invoke-JiraMethod @parameter } } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraIssueAttachment { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding()] param( [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.Issue" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraIssue' $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidArgument $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Issue. Expected [JiraPS.Issue] or [String], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Alias('Key')] [Object] $Issue, [String] $FileName, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) 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)" # Find the proper object for the Issue $issueObj = Resolve-JiraIssueObject -InputObject $Issue -Credential $Credential if ($issueObj.Attachment) { Write-Debug "[$($MyInvocation.MyCommand.Name)] Found Attachments on the Issue." if ($FileName) { $attachments = $issueObj.Attachment | Where-Object {$_.Filename -like $FileName} } else { $attachments = $issueObj.Attachment } ConvertTo-JiraAttachment -InputObject $attachments } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraIssueAttachmentFile { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding()] [OutputType([Bool])] param ( [Parameter( Mandatory, ValueFromPipeline )] [PSTypeName('JiraPS.Attachment')] $Attachment, [ValidateScript( { if (-not (Test-Path $_)) { $errorItem = [System.Management.Automation.ErrorRecord]::new( ([System.ArgumentException]"Path not found"), 'ParameterValue.FileNotFound', [System.Management.Automation.ErrorCategory]::ObjectNotFound, $_ ) $errorItem.ErrorDetails = "Invalid path '$_'." $PSCmdlet.ThrowTerminatingError($errorItem) } else { return $true } } )] [String] $Path, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) 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)" foreach ($_Attachment in $Attachment) { if ($Path) { $filename = Join-Path $Path $_Attachment.Filename } else { $filename = $_Attachment.Filename } $iwParameters = @{ Uri = $_Attachment.Content Method = 'Get' Headers = @{"Accept" = $_Attachment.MimeType} OutFile = $filename Credential = $Credential } $result = Invoke-JiraMethod @iwParameters (-not $result) } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function ended" } } function Get-JiraIssueComment { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding()] param( [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.Issue" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraIssue' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Issue. Expected [JiraPS.Issue] or [String], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Alias('Key')] [Object] $Issue, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) 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)" # Find the proper object for the Issue $issueObj = Resolve-JiraIssueObject -InputObject $Issue -Credential $Credential $parameter = @{ URI = "{0}/comment" -f $issueObj.RestURL Method = "GET" GetParameter = @{ maxResults = $PageSize } OutputType = "JiraComment" Paging = $true Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" Invoke-JiraMethod @parameter } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraIssueCreateMetadata { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding()] param( [Parameter( Mandatory )] [String] $Project, [Parameter( Mandatory )] [String] $IssueType, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2/issue/createmeta?projectIds={0}&issuetypeIds={1}&expand=projects.issuetypes.fields" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" $projectObj = Get-JiraProject -Project $Project -Credential $Credential -ErrorAction Stop $issueTypeObj = $projectObj.IssueTypes | Where-Object -FilterScript {$_.Id -eq $IssueType -or $_.Name -eq $IssueType} if ($null -eq $issueTypeObj.Id) { $errorMessage = @{ Category = "InvalidResult" CategoryActivity = "Validating parameters" Message = "No issue types were found in the project [$Project] for the given issue type [$IssueType]. Use Get-JiraIssueType for more details." } Write-Error @errorMessage } $parameter = @{ URI = $resourceURi -f $projectObj.Id, $issueTypeObj.Id Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter if ($result) { if (@($result.projects).Count -eq 0) { $errorMessage = @{ Category = "InvalidResult" CategoryActivity = "Validating response" Message = "No projects were found for the given project [$Project]. Use Get-JiraProject for more details." } Write-Error @errorMessage } elseif (@($result.projects).Count -gt 1) { $errorMessage = @{ Category = "InvalidResult" CategoryActivity = "Validating response" Message = "Multiple projects were found for the given project [$Project]. Refine the parameters to return only one project." } Write-Error @errorMessage } if (@($result.projects.issuetypes) -eq 0) { $errorMessage = @{ Category = "InvalidResult" CategoryActivity = "Validating response" Message = "No issue types were found for the given issue type [$IssueType]. Use Get-JiraIssueType for more details." } Write-Error @errorMessage } elseif (@($result.projects.issuetypes).Count -gt 1) { $errorMessage = @{ Category = "InvalidResult" CategoryActivity = "Validating response" Message = "Multiple issue types were found for the given issue type [$IssueType]. Refine the parameters to return only one issue type." } Write-Error @errorMessage } Write-Output (ConvertTo-JiraCreateMetaField -InputObject $result) } else { $exception = ([System.ArgumentException]"No results") $errorId = 'IssueMetadata.ObjectNotFound' $errorCategory = 'ObjectNotFound' $errorTarget = $Project $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "No metadata found for project $Project and issueType $IssueType." Throw $errorItem } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraIssueEditMetadata { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding()] param( [Parameter( Mandatory )] [String] $Issue, <# #ToDo:CustomClass Once we have custom classes, this should be a JiraPS.Issue #> [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2/issue/{0}/editmeta" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" $parameter = @{ URI = $resourceURi -f $Issue <# #ToDo:CustomClass When the Input is typecasted to a JiraPS.Issue, the `self` of the issue can be used #> Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Debug ($result | Out-String) if ($result) { if (@($result.fields.projects).Count -eq 0) { $errorMessage = @{ Category = "InvalidResult" CategoryActivity = "Validating response" Message = "No projects were found for the given project [$Project]. Use Get-JiraProject for more details." } Write-Error @errorMessage } elseif (@($result.fields.projects).Count -gt 1) { $errorMessage = @{ Category = "InvalidResult" CategoryActivity = "Validating response" Message = "Multiple projects were found for the given project [$Project]. Refine the parameters to return only one project." } Write-Error @errorMessage } if (@($result.fields.projects.issuetypes) -eq 0) { $errorMessage = @{ Category = "InvalidResult" CategoryActivity = "Validating response" Message = "No issue types were found for the given issue type [$IssueType]. Use Get-JiraIssueType for more details." } Write-Error @errorMessage } elseif (@($result.fields.projects.issuetypes).Count -gt 1) { $errorMessage = @{ Category = "InvalidResult" CategoryActivity = "Validating response" Message = "Multiple issue types were found for the given issue type [$IssueType]. Refine the parameters to return only one issue type." } Write-Error @errorMessage } Write-Output (ConvertTo-JiraEditMetaField -InputObject $result) } else { $exception = ([System.ArgumentException]"No results") $errorId = 'IssueMetadata.ObjectNotFound' $errorCategory = 'ObjectNotFound' $errorTarget = $Project $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "No metadata found for project $Project and issueType $IssueType." Throw $errorItem } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraIssueLink { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding()] param( [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [Int[]] $Id, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2/issueLink/{0}" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" # Validate input object from Pipeline if (($_) -and ("JiraPS.IssueLink" -notin $_.PSObject.TypeNames)) { $exception = ([System.ArgumentException]"Invalid Parameter") $errorId = 'ParameterProperties.WrongObjectType' $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidArgument $errorTarget = $Id $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "The IssueLink provided did not match the constraints." $PSCmdlet.ThrowTerminatingError($errorItem) } foreach ($_id in $Id) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$_id]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$_id [$_id]" $parameter = @{ URI = $resourceURi -f $_id Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraIssueLink -InputObject $result) } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraIssueLinkType { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( DefaultParameterSetName = '_All' )] param( [Parameter( Position = 0, Mandatory, ParameterSetName = '_Search' )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.IssueLinkType" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String])) -and (($_ -isnot [Int]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraIssueLinkType' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for IssueLinkType. Expected [JiraPS.IssueLinkType], [String] or [Int], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Object] $LinkType, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2/issueLinkType{0}" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" switch ($PSCmdlet.ParameterSetName) { '_All' { $parameter = @{ URI = $resourceURi -f "" Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraIssueLinkType -InputObject $result.issueLinkTypes) } '_Search' { # If the link type provided is an int, we can assume it's an ID number. # If it's a String, it's probably a name, though, and there isn't an API call to look up a link type by name. if ($LinkType -is [Int]) { $parameter = @{ URI = $resourceURi -f "/$LinkType" Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraIssueLinkType -InputObject $result) } else { Write-Output (Get-JiraIssueLinkType -Credential $Credential | Where-Object { $_.Name -like $LinkType }) } } } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraIssueType { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( DefaultParameterSetName = '_All' )] param( [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = '_Search' )] [String[]] $IssueType, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2/issuetype" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" switch ($PSCmdlet.ParameterSetName) { '_All' { $parameter = @{ URI = $resourceURi Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraIssueType -InputObject $result) } '_Search' { foreach ($_issueType in $IssueType) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$_issueType]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$_issueType [$_issueType]" $allIssueTypes = Get-JiraIssueType -Credential $Credential Write-Output ($allIssueTypes | Where-Object -FilterScript {$_.Id -eq $_issueType}) Write-Output ($allIssueTypes | Where-Object -FilterScript {$_.Name -like $_issueType}) } } } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraIssueWatcher { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding()] param( [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.Issue" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlight] $errorId = 'ParameterType.NotJiraIssue' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Issue. Expected [JiraPS.Issue] or [String], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Alias('Key')] [Object] $Issue, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) 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)" # Find the proper object for the Issue $issueObj = Resolve-JiraIssueObject -InputObject $Issue -Credential $Credential foreach ($issue in $issueObj) { $parameter = @{ URI = "{0}/watchers" -f $issue.RestURL Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" if ($result = Invoke-JiraMethod @parameter) { Write-Output $result.watchers # TODO: are these users? } } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraPriority { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( DefaultParameterSetName = '_All' )] param( [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = '_Search' )] [Int[]] $Id, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2/priority{0}" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" switch ($PSCmdlet.ParameterSetName) { '_All' { $parameter = @{ URI = $resourceURi -f "" Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraPriority -InputObject $result) } '_Search' { foreach ($_id in $Id) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$_id]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$_id [$_id]" $parameter = @{ URI = $resourceURi -f "/$_id" Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraPriority -InputObject $result) } } } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraProject { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( DefaultParameterSetName = '_All' )] param( [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = '_Search' )] [String[]] $Project, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2/project{0}?expand=description,lead,issueTypes,url,projectKeys" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" switch ($PSCmdlet.ParameterSetName) { '_All' { $parameter = @{ URI = $resourceURi -f "" Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraProject -InputObject $result) } '_Search' { foreach ($_project in $Project) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$_project]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$_project [$_project]" $parameter = @{ URI = $resourceURi -f "/$($_project)" Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraProject -InputObject $result) } } } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraRemoteLink { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding()] param( [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.Issue" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraIssue' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Issue. Expected [JiraPS.Issue] or [String], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Alias("Key")] [Object] $Issue, [Int] $LinkId, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) 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)" foreach ($_issue in $Issue) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$_issue]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$_issue [$_issue]" # Find the proper object for the Issue $issueObj = Resolve-JiraIssueObject -InputObject $_issue -Credential $Credential $urlAppendix = "" if ($LinkId) { $urlAppendix = "/$LinkId" } $parameter = @{ URI = "{0}/remotelink{1}" -f $issueObj.RestUrl, $urlAppendix Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraLink -InputObject $result) } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraServerInformation { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding()] param( [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2/serverInfo" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" $parameter = @{ URI = $resourceURi Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraServerInfo -InputObject $result) } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } New-Alias -Name "Get-JiraServerInfo" -Value "Get-JiraServerInformation" -ErrorAction SilentlyContinue function Get-JiraSession { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding()] param() 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)" if ($MyInvocation.MyCommand.Module.PrivateData -and $MyInvocation.MyCommand.Module.PrivateData.Session) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Using Session saved in PrivateData" Write-Output $MyInvocation.MyCommand.Module.PrivateData.Session } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraUser { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( DefaultParameterSetName = 'Self' )] param( [Parameter( Position = 0, Mandatory, ValueFromPipelineByPropertyName, ParameterSetName = 'ByUserName' )] [AllowEmptyString()] [Alias('User', 'Name')] [String[]] $UserName, [Parameter( Position = 0, Mandatory, ParameterSetName = 'ByInputObject' )] [Object[]] $InputObject, [Parameter( ParameterSetName = 'ByInputObject' )] [Parameter( ParameterSetName = 'ByUserName' )] [Switch]$Exact, [Switch] $IncludeInactive, [Parameter( ParameterSetName = 'ByUserName' )] [ValidateRange(1, 1000)] [UInt32] $MaxResults = 50, [Parameter( ParameterSetName = 'ByUserName' )] [ValidateNotNullOrEmpty()] [UInt64] $Skip = 0, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $selfResourceUri = "$server/rest/api/2/myself" $searchResourceUri = "$server/rest/api/2/user/search?username={0}" $exactResourceUri = "$server/rest/api/2/user?username={0}" if ($IncludeInactive) { $searchResourceUri += "&includeInactive=true" } if ($MaxResults) { $searchResourceUri += "&maxResults=$MaxResults" } if ($Skip) { $searchResourceUri += "&startAt=$Skip" } } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" $ParameterSetName = '' switch ($PsCmdlet.ParameterSetName) { 'ByInputObject' { $UserName = $InputObject.Name; $ParameterSetName = 'ByUserName'; $Exact = $true } 'ByUserName' { $ParameterSetName = 'ByUserName' } 'Self' { $ParameterSetName = 'Self' } } switch ($ParameterSetName) { "Self" { $resourceURi = $selfResourceUri $parameter = @{ URI = $resourceURi Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Get-JiraUser -UserName $result.Name -Exact } "ByInputObject" { $UserName = $InputObject.Name $PsCmdlet.ParameterSetName = "ByUserName" } "ByUserName" { $resourceURi = if ($Exact) { $exactResourceUri } else { $searchResourceUri } foreach ($user in $UserName) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$user]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$user [$user]" $parameter = @{ URI = $resourceURi -f $user Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" if ($users = Invoke-JiraMethod @parameter) { foreach ($item in $users) { $parameter = @{ URI = "{0}&expand=groups" -f $item.self Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraUser -InputObject $result) } } else { $errorMessage = @{ Category = "ObjectNotFound" CategoryActivity = "Searching for user" Message = "No results when searching for user $user" } Write-Error @errorMessage } } } } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Get-JiraVersion { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( SupportsPaging, DefaultParameterSetName = 'byId' )] param( [Parameter( Mandatory, ParameterSetName = 'byId' )] [Int[]] $Id, [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = 'byInputVersion' )] [PSTypeName('JiraPS.Version')] $InputVersion, [Parameter( Position = 0, Mandatory , ParameterSetName = 'byProject' )] [Alias('Key')] [String[]] $Project, [Parameter( Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = 'byInputProject' )] [PSTypeName('JiraPS.Project')] $InputProject, [Parameter( ParameterSetName = 'byProject' )] [Parameter( ParameterSetName = 'byInputProject' )] [Alias('Versions')] [String[]] $Name = "*", [Parameter( ParameterSetName = 'byProject')] [Parameter( ParameterSetName = 'byInputProject')] [ValidateSet("sequence", "name", "startDate", "releaseDate" )] [String] $Sort = "name", [UInt32] $PageSize = $script:DefaultPageSize, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2/{0}" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" $ParameterSetName = '' switch ($PsCmdlet.ParameterSetName) { 'byInputProject' { $Project = $InputProject.Key; $ParameterSetName = 'byProject' } 'byInputVersion' { $Id = $InputVersion.Id; $ParameterSetName = 'byId' } 'byProject' { $ParameterSetName = 'byProject' } 'byId' { $ParameterSetName = 'byId' } } switch ($ParameterSetName) { "byId" { foreach ($_id in $ID) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$_id]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$_id [$_id]" $parameter = @{ URI = $resourceURi -f "version/$_id" Method = "GET" Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraVersion -InputObject $result) } } "byProject" { foreach ($_project in $Project) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$_project]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$_project [$_project]" $projectData = Get-JiraProject -Project $_project -Credential $Credential $parameter = @{ URI = $resourceURi -f "project/$($projectData.key)/version" Method = "GET" GetParameter = @{ orderBy = $Sort maxResults = $PageSize } Paging = $true OutputType = "JiraVersion" Credential = $Credential } # Paging ($PSCmdlet.PagingParameters | Get-Member -MemberType Property).Name | ForEach-Object { $parameter[$_] = $PSCmdlet.PagingParameters.$_ } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" if ($result = Invoke-JiraMethod @parameter) { $result | Where-Object { $__ = $_.Name Write-DebugMessage ($__ | Out-String) $Name | Foreach-Object { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Matching $_ against $($__)" $__ -like $_ } } } } } } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Invoke-JiraIssueTransition { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding()] param( [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.Issue" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraIssue' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Issue. Expected [JiraPS.Issue] or [String], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Alias('Key')] [Object] $Issue, [Parameter( Mandatory )] $Transition, [PSCustomObject] $Fields, [Object] $Assignee, [String] $Comment, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Switch] $Passthru ) 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)" # Find the proper object for the Issue $issueObj = Resolve-JiraIssueObject -InputObject $Issue -Credential $Credential if ("JiraPS.Transition" -in $Transition.PSObject.TypeNames) { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Transition parameter is a JiraPS.Transition object" $transitionId = $Transition.Id } else { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Attempting to cast Transition parameter [$Transition] as int for transition ID" try { $transitionId = [Int]"$Transition" } catch { $exception = ([System.ArgumentException]"Invalid Type for Parameter") $errorId = 'ParameterType.NotJiraTransition' $errorCategory = 'InvalidArgument' $errorTarget = $Transition $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTargetError $errorItem.ErrorDetails = "Wrong object type provided for Transition. Expected [JiraPS.Transition] or [Int], but was $($Transition.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) } } Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Checking that the issue can perform the given transition" if (($issueObj.Transition.Id) -notcontains $transitionId) { $exception = ([System.ArgumentException]"Invalid value for Parameter") $errorId = 'ParameterValue.InvalidTransition' $errorCategory = 'InvalidArgument' $errorTarget = $Issue $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "The specified Jira issue cannot perform transition [$transitionId]. Check the issue's Transition property and provide a transition valid for its current state." $PSCmdlet.ThrowTerminatingError($errorItem) } $requestBody = @{ 'transition' = @{ 'id' = $transitionId } } if ($Assignee) { if ($Assignee -eq 'Unassigned') { <# #ToDo:Deprecated This behavior should be deprecated #> Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] 'Unassigned' String passed. Issue will be assigned to no one." $assigneeString = "" $validAssignee = $true } else { if ($assigneeObj = Resolve-JiraUser -InputObject $Assignee -Credential $Credential -Exact) { Write-Debug "[$($MyInvocation.MyCommand.Name)] User found (name=[$($assigneeObj.Name)],RestUrl=[$($assigneeObj.RestUrl)])" $assigneeString = $assigneeObj.Name $validAssignee = $true } else { $exception = ([System.ArgumentException]"Invalid value for Parameter") $errorId = 'ParameterValue.InvalidAssignee' $errorCategory = 'InvalidArgument' $errorTarget = $Assignee $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Unable to validate Jira user [$Assignee]. Use Get-JiraUser for more details." $PSCmdlet.ThrowTerminatingError($errorItem) } } } if ($validAssignee) { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Updating Assignee" $requestBody += @{ 'fields' = @{ 'assignee' = @{ 'name' = $assigneeString } } } } $requestBody += @{ 'update' = @{} } if ($Fields) { Write-Debug "[$($MyInvocation.MyCommand.Name)] Resolving `$Fields" foreach ($key in $Fields.Keys) { $name = $key $value = $Fields.$key Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Attempting to identify field (name=[$name], value=[$value])" if ($field = Get-JiraField -Field $name -Credential $Credential) { # For some reason, this was coming through as a hashtable instead of a String, # which was causing ConvertTo-Json to crash later. # Not sure why, but this forces $id to be a String and not a hashtable. $id = "$($field.ID)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Field [$name] was identified as ID [$id]" $requestBody.update.$id = @( @{ 'set' = $value }) } else { $exception = ([System.ArgumentException]"Invalid value for Parameter") $errorId = 'ParameterValue.InvalidFields' $errorCategory = 'InvalidArgument' $errorTarget = $Fields $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Unable to identify field [$name] from -Fields hashtable. Use Get-JiraField for more information." $PSCmdlet.ThrowTerminatingError($errorItem) } } } if ($Comment) { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Adding comment" $requestBody.update.comment += , @{ 'add' = @{ 'body' = $Comment } } } $parameter = @{ URI = "{0}/transitions" -f $issueObj.RestURL Method = "POST" Body = ConvertTo-Json -InputObject $requestBody -Depth 5 Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" Invoke-JiraMethod @parameter if ($Passthru) { Get-JiraIssue $issueObj } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function Invoke-JiraMethod { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( SupportsPaging )] param( [Parameter( Mandatory )] [Uri] $URI, [Microsoft.PowerShell.Commands.WebRequestMethod] $Method = "GET", [String] $Body, [Switch] $RawBody, [Hashtable] $Headers = @{}, [Hashtable] $GetParameter = @{}, [Switch] $Paging, [String] $InFile, [String] $OutFile, [Switch] $StoreSession, [ValidateSet( "JiraComment", "JiraIssue", "JiraUser", "JiraVersion" )] [String] $OutputType, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, # [Parameter( DontShow )] [ValidateNotNullOrEmpty()] [System.Management.Automation.PSCmdlet] $Cmdlet = $PSCmdlet ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" Set-TlsLevel -Tls12 Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" # load DefaultParameters for Invoke-WebRequest # as the global PSDefaultParameterValues is not used $PSDefaultParameterValues = Resolve-DefaultParameterValue -Reference $global:PSDefaultParameterValues -CommandName 'Invoke-WebRequest' #region Headers # Construct the Headers with the folling priority: # - Headers passes as parameters # - User's Headers in $PSDefaultParameterValues # - Module's default Headers $_headers = Join-Hashtable -Hashtable $script:DefaultHeaders, $PSDefaultParameterValues["Invoke-WebRequest:Headers"], $Headers #endregion Headers #region Manage URI # Amend query from URI with GetParameter $uriQuery = ConvertTo-ParameterHash -Uri $Uri $internalGetParameter = Join-Hashtable $uriQuery, $GetParameter # And remove it from URI [Uri]$Uri = $Uri.GetLeftPart("Path") $PaginatedUri = $Uri # Use default PageSize if (-not $internalGetParameter.ContainsKey("maxResults")) { $internalGetParameter["maxResults"] = $script:DefaultPageSize } # Append GET parameters to URi $offset = 0 if ($PSCmdlet.PagingParameters) { if ($PSCmdlet.PagingParameters.Skip) { $internalGetParameter["startAt"] = $PSCmdlet.PagingParameters.Skip $offset = $PSCmdlet.PagingParameters.Skip } if ($PSCmdlet.PagingParameters.First -lt $internalGetParameter["maxResults"]) { $internalGetParameter["maxResults"] = $PSCmdlet.PagingParameters.First } } [Uri]$PaginatedUri = "{0}{1}" -f $PaginatedUri, (ConvertTo-GetParameter $internalGetParameter) #endregion Manage URI #region Constructe IWR Parameter $splatParameters = @{ Uri = $PaginatedUri Method = $Method Headers = $_headers ContentType = $script:DefaultContentType UseBasicParsing = $true Credential = $Credential ErrorAction = "Stop" Verbose = $false } if ($_headers.ContainsKey("Content-Type")) { $splatParameters["ContentType"] = $_headers["Content-Type"] $splatParameters["Headers"].Remove("Content-Type") $_headers.Remove("Content-Type") } if ($Body) { if ($RawBody) { $splatParameters["Body"] = $Body } else { # Encode Body to preserve special chars # http://stackoverflow.com/questions/15290185/invoke-webrequest-issue-with-special-characters-in-json $splatParameters["Body"] = [System.Text.Encoding]::UTF8.GetBytes($Body) } } if ((-not $Credential) -or ($Credential -eq [System.Management.Automation.PSCredential]::Empty)) { $splatParameters.Remove("Credential") if ($session = Get-JiraSession -ErrorAction SilentlyContinue) { $splatParameters["WebSession"] = $session.WebSession } } if ($StoreSession) { $splatParameters["SessionVariable"] = "newSessionVar" $splatParameters.Remove("WebSession") } if ($InFile) { $splatParameters["InFile"] = $InFile } if ($OutFile) { $splatParameters["OutFile"] = $OutFile } #endregion Constructe IWR Parameter #region Execute the actual query # Normal ProgressPreference really slows down invoke-webrequest as it tries to update the screen for bytes received. # By setting ProgressPreference to silentlyContinue it doesn't try to update the screen and speeds up the downloads. # See https://stackoverflow.com/a/43477248/2641196 $oldProgressPreference = $progressPreference $progressPreference = 'silentlyContinue' try { Write-Verbose "[$($MyInvocation.MyCommand.Name)] $($splatParameters.Method) $($splatParameters.Uri)" Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoke-WebRequest with `$splatParameters: $($splatParameters | Out-String)" # Invoke the API $webResponse = Invoke-WebRequest @splatParameters } catch { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Failed to get an answer from the server" $exception = $_ $webResponse = $exception.Exception.Response } # Reset the progressPreference to the value it was before the Invoke-WebRequest $progressPreference = $oldProgressPreference Write-Debug "[$($MyInvocation.MyCommand.Name)] Executed WebRequest. Access `$webResponse to see details" Test-ServerResponse -InputObject $webResponse -Cmdlet $Cmdlet #endregion Execute the actual query } process { if ($webResponse) { # In PowerShellCore (v6+) the StatusCode of an exception is somewhere else if (-not ($statusCode = $webResponse.StatusCode)) { $statusCode = $webResponse.Exception.Response.StatusCode } Write-Verbose "[$($MyInvocation.MyCommand.Name)] Status code: $($statusCode)" #region Code 400+ if ($statusCode.value__ -ge 400) { Resolve-ErrorWebResponse -Exception $exception -StatusCode $statusCode -Cmdlet $Cmdlet } #endregion Code 400+ #region Code 399- else { if ($StoreSession) { return & $script:SessionTransformationMethod -Session $newSessionVar -Username $Credential.UserName } if ($webResponse.Content) { $response = ConvertFrom-Json ([Text.Encoding]::UTF8.GetString($webResponse.RawContentStream.ToArray())) if ($Paging) { # Remove Parameters that don't need propagation $script:PSDefaultParameterValues.Remove("$($MyInvocation.MyCommand.Name):IncludeTotalCount") $null = $PSBoundParameters.Remove("Paging") $null = $PSBoundParameters.Remove("Skip") if (-not $PSBoundParameters["GetParameter"]) { $PSBoundParameters["GetParameter"] = $internalGetParameter } $total = 0 do { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Invoking pagination [currentTotal: $total]" $result = Expand-Result -InputObject $response $total += @($result).Count $pageSize = $response.maxResults if ($total -gt $PSCmdlet.PagingParameters.First) { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Only output the first $($PSCmdlet.PagingParameters.First % $pageSize) of page" $result = $result | Select-Object -First ($PSCmdlet.PagingParameters.First % $pageSize) } Convert-Result -InputObject $result -OutputType $OutputType Write-DebugMessage ($result | Out-String) if (@($result).Count -lt $response.maxResults) { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Stopping paging, as page had less entries than $($response.maxResults)" break } if ($total -ge $PSCmdlet.PagingParameters.First) { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Stopping paging, as $total reached $($PSCmdlet.PagingParameters.First)" break } # calculate the size of the next page $PSBoundParameters["GetParameter"]["startAt"] = $total + $offset $expectedTotal = $PSBoundParameters["GetParameter"]["startAt"] + $pageSize if ($expectedTotal -gt $PSCmdlet.PagingParameters.First) { $reduceBy = $expectedTotal - $PSCmdlet.PagingParameters.First $PSBoundParameters["GetParameter"]["maxResults"] = $pageSize - $reduceBy } # Inquire the next page $response = Invoke-JiraMethod @PSBoundParameters $result = Expand-Result -InputObject $response } while (@($result).Count -gt 0) if ($PSCmdlet.PagingParameters.IncludeTotalCount) { [double]$Accuracy = 1.0 $PSCmdlet.PagingParameters.NewTotalCount($total, $Accuracy) } } else { $response } } else { # No content, although statusCode < 400 # This could be wanted behavior of the API Write-Verbose "[$($MyInvocation.MyCommand.Name)] No content was returned from." } } #endregion Code 399- } else { Write-Verbose "[$($MyInvocation.MyCommand.Name)] No Web result object was returned from. This is unusual!" } } end { Set-TlsLevel -Revert Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function ended" } } function Move-JiraVersion { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( DefaultParameterSetName = 'ByAfter' )] param( [Parameter( Mandatory, ValueFromPipeline )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.Version" -notin $_.PSObject.TypeNames) -and (($_ -isnot [Int]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraVersion' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Version. Expected [JiraPS.Version] or [Int], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Object] $Version, [Parameter( Mandatory, ParameterSetName = 'ByPosition' )] [ValidateSet('First', 'Last', 'Earlier', 'Later')] [String]$Position, [Parameter( Mandatory, ParameterSetName = 'ByAfter' )] [ValidateNotNullOrEmpty()] [ValidateScript( { if (("JiraPS.Version" -notin $_.PSObject.TypeNames) -and (($_ -isnot [Int]))) { $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] $errorId = 'ParameterType.NotJiraVersion' $errorCategory = 'InvalidArgument' $errorTarget = $_ $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget $errorItem.ErrorDetails = "Wrong object type provided for Version. Expected [JiraPS.Version] or [Int], but was $($_.GetType().Name)" $PSCmdlet.ThrowTerminatingError($errorItem) <# #ToDo:CustomClass Once we have custom classes, this check can be done with Type declaration #> } else { return $true } } )] [Object] $After, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $versionResourceUri = "$server/rest/api/2/version/{0}/move" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" $requestBody = @{ } switch ($PsCmdlet.ParameterSetName) { 'ByPosition' { $requestBody["position"] = $Position } 'ByAfter' { $afterSelfUri = '' if ($After -is [Int]) { $versionObj = Get-JiraVersion -Id $After -Credential $Credential -ErrorAction Stop $afterSelfUri = $versionObj.RestUrl } else { $afterSelfUri = $After.RestUrl } $requestBody["after"] = $afterSelfUri } } if ($Version.Id) { $versionId = $Version.Id } else { $versionId = $Version } $parameter = @{ URI = $versionResourceUri -f $versionId Method = "POST" Body = ConvertTo-Json $requestBody Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" Invoke-JiraMethod @parameter } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function New-JiraFilter { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( SupportsShouldProcess )] param( [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [String] $Name, [Parameter( ValueFromPipelineByPropertyName )] [String] $Description, [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [String] $JQL, [Parameter( ValueFromPipelineByPropertyName )] [Alias('Favourite')] [Switch] $Favorite, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2/filter" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" $requestBody = @{ name = $Name jql = $JQL } if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey("Description")) { $requestBody["description"] = $Description } $requestBody["favourite"] = [Bool]$Favorite $parameter = @{ URI = $resourceURi Method = "POST" Body = ConvertTo-Json -InputObject $requestBody Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" if ($PSCmdlet.ShouldProcess($Name, "Creating new Filter")) { $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraFilter -InputObject $result) } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function New-JiraGroup { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( SupportsShouldProcess )] param( [Parameter( Mandatory )] [Alias('Name')] [String[]] $GroupName, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" $server = Get-JiraConfigServer -ErrorAction Stop $resourceURi = "$server/rest/api/2/group" } process { Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" foreach ($_group in $GroupName) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Processing [$_group]" Write-Debug "[$($MyInvocation.MyCommand.Name)] Processing `$_group [$_group]" $requestBody = @{ "name" = $_group } $parameter = @{ URI = $resourceURi Method = "POST" Body = ConvertTo-Json -InputObject $requestBody Credential = $Credential } Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" if ($PSCmdlet.ShouldProcess($GroupName, "Creating group [$GroupName] to JIRA")) { $result = Invoke-JiraMethod @parameter Write-Output (ConvertTo-JiraGroup -InputObject $result) } } } end { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" } } function New-JiraIssue { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( SupportsShouldProcess )] param( [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [String] $Project, [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [String] $IssueType, [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [String] $Summary, [Parameter( ValueFromPipelineByPropertyName )] [Int] $Priority, [Parameter( ValueFromPipelineByPropertyName )] [String] $Description, [Parameter( ValueFromPipelineByPropertyName )] [AllowNull()] [AllowEmptyString()] [String] $Reporter, [Parameter( ValueFromPipelineByPropertyName )] [String[]] $Labels, [Parameter( ValueFromPipelineByPropertyName )] [String] $Parent, [Parameter( ValueFromPipelineByPropertyName )] [Alias('FixVersions')] [String[]] $FixVersion, [Parameter( ValueFromPipelineByPropertyName )] [PSCustomObject] $Fields, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" } process { $server = Get-JiraConfigServer -ErrorAction Stop -Debug:$false $createmeta = Get-JiraIssueCreateMetadata -Project $Project -IssueType $IssueType -Credential $Credential -ErrorAction Stop -Debug:$false $resourceURi = "$server/rest/api/2/issue" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)"   |