GitHubProjects.ps1
# Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. @{ GitHubProjectTypeName = 'GitHub.Project' }.GetEnumerator() | ForEach-Object { Set-Variable -Scope Script -Option ReadOnly -Name $_.Key -Value $_.Value } filter Get-GitHubProject { <# .DESCRIPTION Get the projects for a given GitHub user, repository or organization. The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub .PARAMETER OwnerName Owner of the repository. If not supplied here, the DefaultOwnerName configuration property value will be used. .PARAMETER RepositoryName Name of the repository. If not supplied here, the DefaultRepositoryName configuration property value will be used. .PARAMETER Uri Uri for the repository. The OwnerName and RepositoryName will be extracted from here instead of needing to provide them individually. .PARAMETER OrganizationName The name of the organization to get projects for. .PARAMETER UserName The name of the user to get projects for. .PARAMETER Project ID of the project to retrieve. .PARAMETER State Only projects with this state are returned. .PARAMETER AccessToken If provided, this will be used as the AccessToken for authentication with the REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. .INPUTS GitHub.Branch GitHub.Content GitHub.Event GitHub.Issue GitHub.IssueComment GitHub.Label GitHub.Milestone GitHub.PullRequest GitHub.Project GitHub.ProjectCard GitHub.ProjectColumn GitHub.Reaction GitHub.Release GitHub.ReleaseAsset GitHub.Repository .OUTPUTS GitHub.Project .EXAMPLE Get-GitHubProject -OwnerName microsoft -RepositoryName PowerShellForGitHub Get the projects for the microsoft\PowerShellForGitHub repository. .EXAMPLE Get-GitHubProject -OrganizationName Microsoft Get the projects for the Microsoft organization. .EXAMPLE Get-GitHubProject -Uri https://github.com/Microsoft/PowerShellForGitHub Get the projects for the microsoft\PowerShellForGitHub repository using the Uri. .EXAMPLE Get-GitHubProject -UserName GitHubUser Get the projects for the user GitHubUser. .EXAMPLE Get-GitHubProject -OwnerName microsoft -RepositoryName PowerShellForGitHub -State Closed Get closed projects from the microsoft\PowerShellForGitHub repo. .EXAMPLE Get-GitHubProject -Project 4378613 Get a project by id, with this parameter you don't need any other information. #> [CmdletBinding(DefaultParameterSetName = 'Elements')] [OutputType({$script:GitHubPullRequestTypeName})] param( [Parameter( Mandatory, ParameterSetName = 'Elements')] [string] $OwnerName, [Parameter( Mandatory, ParameterSetName = 'Elements')] [string] $RepositoryName, [Parameter( Mandatory, ValueFromPipelineByPropertyName, ParameterSetName='Uri')] [Parameter( Mandatory, ValueFromPipelineByPropertyName, ParameterSetName='ProjectObject')] [Alias('RepositoryUrl')] [string] $Uri, [Parameter( Mandatory, ParameterSetName = 'Organization')] [string] $OrganizationName, [Parameter( Mandatory, ParameterSetName = 'User')] [string] $UserName, [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = 'Project')] [Parameter( Mandatory, ValueFromPipelineByPropertyName, ParameterSetName='ProjectObject')] [Alias('ProjectId')] [int64] $Project, [ValidateSet('Open', 'Closed', 'All')] [string] $State, [string] $AccessToken ) Write-InvocationLog $telemetryProperties = @{} $uriFragment = [String]::Empty $description = [String]::Empty if ($PSCmdlet.ParameterSetName -in @('Project', 'ProjectObject')) { $telemetryProperties['Project'] = Get-PiiSafeString -PlainText $Project $uriFragment = "/projects/$Project" $description = "Getting project $project" } elseif ($PSCmdlet.ParameterSetName -in ('Elements', 'Uri')) { $elements = Resolve-RepositoryElements $OwnerName = $elements.ownerName $RepositoryName = $elements.repositoryName $telemetryProperties['OwnerName'] = Get-PiiSafeString -PlainText $OwnerName $telemetryProperties['RepositoryName'] = Get-PiiSafeString -PlainText $RepositoryName $uriFragment = "/repos/$OwnerName/$RepositoryName/projects" $description = "Getting projects for $RepositoryName" } elseif ($PSCmdlet.ParameterSetName -eq 'Organization') { $telemetryProperties['OrganizationName'] = Get-PiiSafeString -PlainText $OrganizationName $uriFragment = "/orgs/$OrganizationName/projects" $description = "Getting projects for $OrganizationName" } elseif ($PSCmdlet.ParameterSetName -eq 'User') { $telemetryProperties['UserName'] = Get-PiiSafeString -PlainText $UserName $uriFragment = "/users/$UserName/projects" $description = "Getting projects for $UserName" } if ($PSBoundParameters.ContainsKey('State')) { $getParams = @() $State = $State.ToLower() $getParams += "state=$State" $uriFragment = "$uriFragment`?" + ($getParams -join '&') $description += " with state '$state'" } $params = @{ 'UriFragment' = $uriFragment 'Description' = $description 'AccessToken' = $AccessToken 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties 'AcceptHeader' = $script:inertiaAcceptHeader } return (Invoke-GHRestMethodMultipleResult @params | Add-GitHubProjectAdditionalProperties) } filter New-GitHubProject { <# .DESCRIPTION Creates a new GitHub project for the given repository The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub .PARAMETER OwnerName Owner of the repository. If not supplied here, the DefaultOwnerName configuration property value will be used. .PARAMETER RepositoryName Name of the repository. If not supplied here, the DefaultRepositoryName configuration property value will be used. .PARAMETER Uri Uri for the repository. The OwnerName and RepositoryName will be extracted from here instead of needing to provide them individually. .PARAMETER OrganizationName The name of the organization to create the project under. .PARAMETER UserProject If this switch is specified creates a project for your user. .PARAMETER Name The name of the project to create. .PARAMETER Description Short description for the new project. .PARAMETER AccessToken If provided, this will be used as the AccessToken for authentication with the REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. .INPUTS GitHub.Branch GitHub.Content GitHub.Event GitHub.Issue GitHub.IssueComment GitHub.Label GitHub.Milestone GitHub.PullRequest GitHub.Project GitHub.ProjectCard GitHub.ProjectColumn GitHub.Reaction GitHub.Release GitHub.ReleaseAsset GitHub.Repository .OUTPUTS GitHub.Project .EXAMPLE New-GitHubProject -OwnerName microsoft -RepositoryName PowerShellForGitHub -ProjectName TestProject Creates a project called 'TestProject' for the microsoft\PowerShellForGitHub repository. .EXAMPLE New-GitHubProject -OrganizationName Microsoft -ProjectName TestProject -Description 'This is just a test project' Create a project for the Microsoft organization called 'TestProject' with a description. .EXAMPLE New-GitHubProject -Uri https://github.com/Microsoft/PowerShellForGitHub -ProjectName TestProject Create a project for the microsoft\PowerShellForGitHub repository using the Uri called 'TestProject'. .EXAMPLE New-GitHubProject -UserProject -ProjectName 'TestProject' Creates a project for the signed in user called 'TestProject'. #> [CmdletBinding( SupportsShouldProcess, DefaultParameterSetName = 'Elements')] [OutputType({$script:GitHubPullRequestTypeName})] param( [Parameter( Mandatory, ParameterSetName = 'Elements')] [string] $OwnerName, [Parameter( Mandatory, ParameterSetName = 'Elements')] [string] $RepositoryName, [Parameter( Mandatory, ValueFromPipelineByPropertyName, ParameterSetName='Uri')] [Alias('RepositoryUrl')] [string] $Uri, [Parameter( Mandatory, ParameterSetName = 'Organization')] [string] $OrganizationName, [Parameter( Mandatory, ParameterSetName = 'User')] [switch] $UserProject, [Parameter( Mandatory, ValueFromPipeline)] [Alias('Name')] [string] $ProjectName, [string] $Description, [string] $AccessToken ) Write-InvocationLog $telemetryProperties = @{} $telemetryProperties['ProjectName'] = Get-PiiSafeString -PlainText $ProjectName $uriFragment = [String]::Empty $apiDescription = [String]::Empty if ($PSCmdlet.ParameterSetName -in ('Elements', 'Uri')) { $elements = Resolve-RepositoryElements $OwnerName = $elements.ownerName $RepositoryName = $elements.repositoryName $telemetryProperties['OwnerName'] = Get-PiiSafeString -PlainText $OwnerName $telemetryProperties['RepositoryName'] = Get-PiiSafeString -PlainText $RepositoryName $uriFragment = "/repos/$OwnerName/$RepositoryName/projects" $apiDescription = "Creating project for $RepositoryName" } elseif ($PSCmdlet.ParameterSetName -eq 'Organization') { $telemetryProperties['OrganizationName'] = Get-PiiSafeString -PlainText $OrganizationName $uriFragment = "/orgs/$OrganizationName/projects" $apiDescription = "Creating project for $OrganizationName" } elseif ($PSCmdlet.ParameterSetName -eq 'User') { $telemetryProperties['User'] = $true $uriFragment = "/user/projects" $apiDescription = "Creating project for user" } $hashBody = @{ 'name' = $ProjectName } if ($PSBoundParameters.ContainsKey('Description')) { $hashBody.add('body', $Description) } if (-not $PSCmdlet.ShouldProcess($ProjectName, 'Create GitHub Project')) { return } $params = @{ 'UriFragment' = $uriFragment 'Body' = (ConvertTo-Json -InputObject $hashBody) 'Method' = 'Post' 'Description' = $apiDescription 'AccessToken' = $AccessToken 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties 'AcceptHeader' = $script:inertiaAcceptHeader } return (Invoke-GHRestMethod @params | Add-GitHubProjectAdditionalProperties) } filter Set-GitHubProject { <# .DESCRIPTION Modify a GitHub Project. The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub .PARAMETER Project ID of the project to modify. .PARAMETER Description Short description for the project. .PARAMETER State Set the state of the project. .PARAMETER OrganizationPermission Set the permission level that determines whether all members of the project's organization can see and/or make changes to the project. Only available for organization projects. .PARAMETER Private Sets the visibility of a project board. Only available for organization and user projects. Note: Updating a project's visibility requires admin access to the project. .PARAMETER PassThru Returns the updated Project. By default, this cmdlet does not generate any output. You can use "Set-GitHubConfiguration -DefaultPassThru" to control the default behavior of this switch. .PARAMETER AccessToken If provided, this will be used as the AccessToken for authentication with the REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. .INPUTS GitHub.Branch GitHub.Content GitHub.Event GitHub.Issue GitHub.IssueComment GitHub.Label GitHub.Milestone GitHub.PullRequest GitHub.Project GitHub.ProjectCard GitHub.ProjectColumn GitHub.Release GitHub.ReleaseAsset GitHub.Repository .OUTPUTS GitHub.Project .EXAMPLE Set-GitHubProject -Project 999999 -State Closed Set the project with ID '999999' to closed. .EXAMPLE $project = Get-GitHubProject -OwnerName microsoft -RepositoryName PowerShellForGitHub | Where-Object Name -eq 'TestProject' Set-GitHubProject -Project $project.id -State Closed Get the ID for the 'TestProject' project for the microsoft\PowerShellForGitHub repository and set state to closed. #> [CmdletBinding(SupportsShouldProcess)] [OutputType({$script:GitHubPullRequestTypeName})] param( [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [Alias('ProjectId')] [int64] $Project, [string] $Description, [ValidateSet('Open', 'Closed')] [string] $State, [ValidateSet('Read', 'Write', 'Admin', 'None')] [string] $OrganizationPermission, [switch] $Private, [switch] $PassThru, [string] $AccessToken ) Write-InvocationLog $telemetryProperties = @{} $uriFragment = "projects/$Project" $apiDescription = "Updating project $Project" $hashBody = @{} if ($PSBoundParameters.ContainsKey('Description')) { $hashBody.add('body', $Description) $apiDescription += " description" } if ($PSBoundParameters.ContainsKey('State')) { $hashBody.add('state', $State) $apiDescription += ", state to '$State'" } if ($PSBoundParameters.ContainsKey('Private')) { $hashBody.add('private', $Private.ToBool()) $apiDescription += ", private to '$Private'" } if ($PSBoundParameters.ContainsKey('OrganizationPermission')) { $hashBody.add('organization_permission', $OrganizationPermission.ToLower()) $apiDescription += ", organization_permission to '$OrganizationPermission'" } if (-not $PSCmdlet.ShouldProcess($Project, 'Set GitHub Project')) { return } $params = @{ 'UriFragment' = $uriFragment 'Description' = $apiDescription 'Body' = (ConvertTo-Json -InputObject $hashBody) 'AccessToken' = $AccessToken 'Method' = 'Patch' 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties 'AcceptHeader' = $script:inertiaAcceptHeader } $result = (Invoke-GHRestMethod @params | Add-GitHubProjectAdditionalProperties) if (Resolve-ParameterWithDefaultConfigurationValue -Name PassThru -ConfigValueName DefaultPassThru) { return $result } } filter Remove-GitHubProject { <# .DESCRIPTION Removes the projects for a given GitHub repository. The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub .PARAMETER Project ID of the project to remove. .PARAMETER Force If this switch is specified, you will not be prompted for confirmation of command execution. .PARAMETER AccessToken If provided, this will be used as the AccessToken for authentication with the REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. .INPUTS GitHub.Branch GitHub.Content GitHub.Event GitHub.Issue GitHub.IssueComment GitHub.Label GitHub.Milestone GitHub.PullRequest GitHub.Project GitHub.ProjectCard GitHub.ProjectColumn GitHub.Release GitHub.ReleaseAsset GitHub.Repository .EXAMPLE Remove-GitHubProject -Project 4387531 Remove project with ID '4387531'. .EXAMPLE Remove-GitHubProject -Project 4387531 -Confirm:$false Remove project with ID '4387531' without prompting for confirmation. .EXAMPLE Remove-GitHubProject -Project 4387531 -Force Remove project with ID '4387531' without prompting for confirmation. .EXAMPLE $project = Get-GitHubProject -OwnerName microsoft -RepositoryName PowerShellForGitHub | Where-Object Name -eq 'TestProject' Remove-GitHubProject -Project $project.id Get the ID for the 'TestProject' project for the microsoft\PowerShellForGitHub repository and then remove the project. #> [CmdletBinding( SupportsShouldProcess, ConfirmImpact = 'High')] [Alias('Delete-GitHubProject')] param( [Parameter( Mandatory, ValueFromPipelineByPropertyName)] [Alias('ProjectId')] [int64] $Project, [switch] $Force, [string] $AccessToken ) Write-InvocationLog $telemetryProperties = @{} $uriFragment = "projects/$Project" $description = "Deleting project $Project" if ($Force -and (-not $Confirm)) { $ConfirmPreference = 'None' } if (-not $PSCmdlet.ShouldProcess($Project, 'Remove GitHub Project')) { return } $params = @{ 'UriFragment' = $uriFragment 'Description' = $description 'AccessToken' = $AccessToken 'Method' = 'Delete' 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties 'AcceptHeader' = $script:inertiaAcceptHeader } return Invoke-GHRestMethod @params } filter Add-GitHubProjectAdditionalProperties { <# .SYNOPSIS Adds type name and additional properties to ease pipelining to GitHub Project objects. .PARAMETER InputObject The GitHub object to add additional properties to. .PARAMETER TypeName The type that should be assigned to the object. .INPUTS [PSCustomObject] .OUTPUTS GitHub.Project #> [CmdletBinding()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="Internal helper that is definitely adding more than one property.")] param( [Parameter( Mandatory, ValueFromPipeline)] [AllowNull()] [AllowEmptyCollection()] [PSCustomObject[]] $InputObject, [ValidateNotNullOrEmpty()] [string] $TypeName = $script:GitHubProjectTypeName ) foreach ($item in $InputObject) { $item.PSObject.TypeNames.Insert(0, $TypeName) if (-not (Get-GitHubConfiguration -Name DisablePipelineSupport)) { $elements = Split-GitHubUri -Uri $item.html_url $repositoryUrl = Join-GitHubUri @elements # A "user" project has no associated repository, and adding this in that scenario # would cause API-level errors with piping further on, if ($elements.OwnerName -ne 'users') { Add-Member -InputObject $item -Name 'RepositoryUrl' -Value $repositoryUrl -MemberType NoteProperty -Force } Add-Member -InputObject $item -Name 'ProjectId' -Value $item.id -MemberType NoteProperty -Force if ($null -ne $item.creator) { $null = Add-GitHubUserAdditionalProperties -InputObject $item.creator } } Write-Output $item } } # SIG # Begin signature block # MIIjkQYJKoZIhvcNAQcCoIIjgjCCI34CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAQDjtl/FSZEwxw # tSYm3zedm6K28y5wjDDpgh+r5U3P5qCCDYEwggX/MIID56ADAgECAhMzAAABh3IX # chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB # znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH # sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d # weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ # itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV # Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw # UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 # ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu # ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu # bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w # Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3 # Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx # MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy # S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K # NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV # BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr # qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx # zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe # yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g # yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf # AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI # 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5 # GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea # jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS # AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 # IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0 # ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla # MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT # H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB # AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG # OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S # 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz # y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7 # 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u # M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33 # X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl # XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP # 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB # l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF # RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM # CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ # BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud # DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO # 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0 # LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y # Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p # Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y # Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB # FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw # cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA # XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY # 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj # 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd # d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ # Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf # wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ # aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j # NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B # xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96 # eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7 # r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I # RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVZjCCFWICAQEwgZUwfjELMAkG # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z # b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN # BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor # BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgwZD2Ikmb # rSeupJp6v8NUrq2F6hsZtYzub8jSmUU2rxgwQgYKKwYBBAGCNwIBDDE0MDKgFIAS # AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN # BgkqhkiG9w0BAQEFAASCAQCPeXA2Hs+W4hVGtLBI5Ixs/DXo/2jHGQxR3U0dDTZ/ # 2JG81Nm2xm2TXUJKrb+uhreXPABNynMymB6RCssWhFrb7cKTIrOCMos6Ztnrqw2q # RAZFUP580fGd3E8noUDTkzJmw7QtTyGRqF05XjocqiVAXmo4xwuJXEk5Zm87BSd2 # KYYkd/G/pCc3LVidGBVQx8mx7Zhzlg33hQUqIFet3wTIAXA0spd+jHnQm5okp8kI # dHA2nQqEFREg5zciB/X/rU2zFsh2QQWbu9GCCCyxUURZp9RmyKS6m6eR01lLFlY+ # F9ORECkl+Q+k3fEhmr29jLDmomZztiWTGGAFUGlR7WKSoYIS8DCCEuwGCisGAQQB # gjcDAwExghLcMIIS2AYJKoZIhvcNAQcCoIISyTCCEsUCAQMxDzANBglghkgBZQME # AgEFADCCAVQGCyqGSIb3DQEJEAEEoIIBQwSCAT8wggE7AgEBBgorBgEEAYRZCgMB # MDEwDQYJYIZIAWUDBAIBBQAEIGr7gUqElrkAAfpftmESt5dZRpftGSSBV26vnu3v # zcSdAgZfFxEtm04YEjIwMjAwODE4MDMxNDMwLjE2WjAEgAIB9KCB1KSB0TCBzjEL # MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v # bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEpMCcGA1UECxMgTWlj # cm9zb2Z0IE9wZXJhdGlvbnMgUHVlcnRvIFJpY28xJjAkBgNVBAsTHVRoYWxlcyBU # U1MgRVNOOkM0QkQtRTM3Ri01RkZDMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1T # dGFtcCBTZXJ2aWNloIIORDCCBPUwggPdoAMCAQICEzMAAAEjOLDkrdhakJ0AAAAA # ASMwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp # bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw # b3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAw # HhcNMTkxMjE5MDExNDU2WhcNMjEwMzE3MDExNDU2WjCBzjELMAkGA1UEBhMCVVMx # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEpMCcGA1UECxMgTWljcm9zb2Z0IE9wZXJh # dGlvbnMgUHVlcnRvIFJpY28xJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOkM0QkQt # RTM3Ri01RkZDMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNl # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnbzQybBkpdwBLvHZm8Dh # M44LPD7rdez1QsZa11kM3dWX5oZASwzASsiSDNCLR9M7Sw4P03eE7UdpNYehLzQ3 # 9BvqgtHZYJmS/9UzhYWdOE6/fIDnNK36+4o3CuMQcULSOUwMImppTtK3pYluX+QA # /myAzSq2kQRCHG1Vp/wihXmWry+Awk2vfQ7iuotgSL9hlZBljBAcCJUy6cJikmJx # yc041FF2DYPdPK7bZ4QnA9A/oOR4SKgzL16EyYGuSMANU6BBX5PiaKv6EAl4g3Ky # mzrCBE7mqO5Xn6O9zM1BrVabuPGyoG/TgYKUink0e+tdCZn2all2PeuPEW5lsqN3 # cQIDAQABo4IBGzCCARcwHQYDVR0OBBYEFIHUbBSA040b+RHCsGjeGRX4DJ4eMB8G # A1UdIwQYMBaAFNVjOlyKMZDzQ3t8RhvFM2hahW1VMFYGA1UdHwRPME0wS6BJoEeG # RWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Rp # bVN0YVBDQV8yMDEwLTA3LTAxLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUH # MAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljVGltU3Rh # UENBXzIwMTAtMDctMDEuY3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYB # BQUHAwgwDQYJKoZIhvcNAQELBQADggEBAFvlAbeqV+hbqvVXiVP6Q7wtTMXfZLd9 # R+Cf9LVBAE/M5Gz/q6OPT3K0dY0N857DCRLJrV/xL174FudeScfmXdHqdLYGRFMA # 21OZfG8wtMLK95h78lAh+iz5neInRvWocNKcSPpCZ1/UzKas8CTmPGHGGKJeXAgt # SO8fnrLussfErTCewfXYQ70yeRpI1ck0KZKZ+BQSQM3O7ncLf2Xpc1EA9q7Pb9ay # UhRlxfc0MIyC/mFmLaeF330fHJokmxyfV/yFlcD75/Uc1urxt2SHc5iBGc2vtB2c # 74a6+27d3Iaph1AwwY+cC3gvsTD3KSPLRSjPrj+vRJtAhFi3Ll4z0zcwggZxMIIE # WaADAgECAgphCYEqAAAAAAACMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9v # dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAeFw0xMDA3MDEyMTM2NTVaFw0y # NTA3MDEyMTQ2NTVaMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp # b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMIIBIjAN # BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqR0NvHcRijog7PwTl/X6f2mUa3RU # ENWlCgCChfvtfGhLLF/Fw+Vhwna3PmYrW/AVUycEMR9BGxqVHc4JE458YTBZsTBE # D/FgiIRUQwzXTbg4CLNC3ZOs1nMwVyaCo0UN0Or1R4HNvyRgMlhgRvJYR4YyhB50 # YWeRX4FUsc+TTJLBxKZd0WETbijGGvmGgLvfYfxGwScdJGcSchohiq9LZIlQYrFd # /XcfPfBXday9ikJNQFHRD5wGPmd/9WbAA5ZEfu/QS/1u5ZrKsajyeioKMfDaTgaR # togINeh4HLDpmc085y9Euqf03GS9pAHBIAmTeM38vMDJRF1eFpwBBU8iTQIDAQAB # o4IB5jCCAeIwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFNVjOlyKMZDzQ3t8 # RhvFM2hahW1VMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIB # hjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fO # mhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9w # a2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggr # BgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNv # bS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3J0MIGgBgNVHSAB # Af8EgZUwgZIwgY8GCSsGAQQBgjcuAzCBgTA9BggrBgEFBQcCARYxaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL1BLSS9kb2NzL0NQUy9kZWZhdWx0Lmh0bTBABggrBgEF # BQcCAjA0HjIgHQBMAGUAZwBhAGwAXwBQAG8AbABpAGMAeQBfAFMAdABhAHQAZQBt # AGUAbgB0AC4gHTANBgkqhkiG9w0BAQsFAAOCAgEAB+aIUQ3ixuCYP4FxAz2do6Eh # b7Prpsz1Mb7PBeKp/vpXbRkws8LFZslq3/Xn8Hi9x6ieJeP5vO1rVFcIK1GCRBL7 # uVOMzPRgEop2zEBAQZvcXBf/XPleFzWYJFZLdO9CEMivv3/Gf/I3fVo/HPKZeUqR # UgCvOA8X9S95gWXZqbVr5MfO9sp6AG9LMEQkIjzP7QOllo9ZKby2/QThcJ8ySif9 # Va8v/rbljjO7Yl+a21dA6fHOmWaQjP9qYn/dxUoLkSbiOewZSnFjnXshbcOco6I8 # +n99lmqQeKZt0uGc+R38ONiU9MalCpaGpL2eGq4EQoO4tYCbIjggtSXlZOz39L9+ # Y1klD3ouOVd2onGqBooPiRa6YacRy5rYDkeagMXQzafQ732D8OE7cQnfXXSYIghh # 2rBQHm+98eEA3+cxB6STOvdlR3jo+KhIq/fecn5ha293qYHLpwmsObvsxsvYgrRy # zR30uIUBHoD7G4kqVDmyW9rIDVWZeodzOwjmmC3qjeAzLhIp9cAvVCch98isTtoo # uLGp25ayp0Kiyc8ZQU3ghvkqmqMRZjDTu3QyS99je/WZii8bxyGvWbWu3EQ8l1Bx # 16HSxVXjad5XwdHeMMD9zOZN+w2/XU/pnR4ZOC+8z1gFLu8NoFA12u8JJxzVs341 # Hgi62jbb01+P3nSISRKhggLSMIICOwIBATCB/KGB1KSB0TCBzjELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEpMCcGA1UECxMgTWljcm9zb2Z0IE9w # ZXJhdGlvbnMgUHVlcnRvIFJpY28xJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOkM0 # QkQtRTM3Ri01RkZDMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2 # aWNloiMKAQEwBwYFKw4DAhoDFQC6F2aN4OKeF8LuDDUoEJ4z+/tXgaCBgzCBgKR+ # MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMT # HU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBBQUAAgUA # 4uUnKjAiGA8yMDIwMDgxNzE5NTYyNloYDzIwMjAwODE4MTk1NjI2WjB3MD0GCisG # AQQBhFkKBAExLzAtMAoCBQDi5ScqAgEAMAoCAQACAh5wAgH/MAcCAQACAhIBMAoC # BQDi5niqAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAIAgEA # AgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQEFBQADgYEAikkNlZMH202Z/AJo # Ym2IvX9q+j+M671PjnloN2UDgmYri3emTx1/D5H7AdxdUq7hPCZFyPMhy5t/LlIK # zhdiIacNE1sagAi/SpaJoWhtIJ0c1xN06cM1p+am2RsRoY17AYpK1kVnnXsrjlaM # CijKTWfC7ACeFJQ80z/pdGC+GW0xggMNMIIDCQIBATCBkzB8MQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGlt # ZS1TdGFtcCBQQ0EgMjAxMAITMwAAASM4sOSt2FqQnQAAAAABIzANBglghkgBZQME # AgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJ # BDEiBCCByOSCs0tpfKb/dLSJFezasPgzR67CVniu9jfYuh2BITCB+gYLKoZIhvcN # AQkQAi8xgeowgecwgeQwgb0EIBGaM4M/+0TMxA2jo6zEpAAMvynAomQzlidcqur7 # FYGzMIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAEj # OLDkrdhakJ0AAAAAASMwIgQgHG6y0aW7Kt6BQeYDWQhRU12mz9xWxaHH8Ha6e59d # vYswDQYJKoZIhvcNAQELBQAEggEAQ4AfHk6QAw+5CDFNgOGPTmIZ0lVzJa9kMW95 # f6/l/6poun4Kejli1XO8fGD0UOmUpws5FdLQpCsdZZ+ET9NQ8SCcj8ZjjveolZMT # JQctihz2g8xQCzsi0KYQ7vm4pB3grygdk+p1ppIaJZ8IFEqiZzkenV3ccidijPrw # chA0wpA3wZkQvnU0iTOYoRpscBzfVadx4ezqN22/Rt8UmlxPGgBuL23M61ZSPG8t # XAt5Bun2R0/tAbTVN6bqDxiLlEMsDqtxpW38jfelm1UQXHasH+Xrf1NV3vqQQm4A # IWjGdIen5lp+Yhgt/I6F/AQwLFucfux51C3BVHZAAcYzr3v9/g== # SIG # End signature block |