diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index b7c6b4d15..000000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.gitignore b/.gitignore index 88d30e8d9..5f122f278 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,7 @@ Source/Classes/vsteam.classes.ps1 /dist test-results.xml coverage.xml +.DS_Store +._.DS_Store +**/.DS_Store +**/._.DS_Store diff --git a/CHANGELOG.md b/CHANGELOG.md index fc96d3fd2..6bd3866ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,14 @@ Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/237) from [Mi ## 6.4.4 +Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/257) from [Michel Zehnder](https://github.com/MichelZ) which included the following: + +Fix bug in Get-VSTeamBuildArtifact with additional "properties" property + +Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/232) from [Mark Wragg](https://github.com/markwragg) which included the following: + +Bug fix in Get-VSTeamBuildArtifact where an error is returned because the API returns an extra record along with the list of artifacts that is called 'build.sourcelabel' and contains a URL but no "properties" object. + Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/231) from [Dave Neeley](https://github.com/daveneeley) which included the following: Removed a trailing slash from resource URIs generated by `_BuildRequestURI` when the ID parameter is not included in the function call. @@ -16,6 +24,10 @@ Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/225) from [Ca Added Get/Set-VSTeamPermissionInheritance +Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/224) from [Cadacious](https://github.com/Cadacious) which included the following: + +Adds Remove-VSTeamAccessControlEntry + ## 6.4.3 Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/229) from [Asif Mithawala](https://github.com/asifma) which included the following: diff --git a/README.md b/README.md index 5d418b8b8..f43e740c2 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,21 @@ The VSTeam module is also a provider allowing users to navigate their [Azure Dev To get started you can visit this blog [PowerShell I would like you to meet TFS and VSTS](http://www.donovanbrown.com/post/PowerShell-I-would-like-you-to-meet-TFS-and-VSTS) +Documentation of the cmdlets can be found in the [docs README](https://github.com/DarqueWarrior/vsteam/blob/master/docs/readme.md) or using `Get-Help VSTeam` once the module is installed. + +## Requirements + +- Windows PowerShell 5.0 or newer. +- PowerShell Core. + +## Installation + +Install this module from the [PowerShell Gallery](https://www.powershellgallery.com/packages/VSTeam) + +## Change Log + +[Change Log](CHANGELOG.md) + ## Pipeline Status You can review the status of every stage of the pipeline below. @@ -37,11 +52,6 @@ The build for VSTeam is run on macOS, Linux and Windows to ensure there are no c During the release the module is installed on macOS, Linux and Window and tested against [Azure DevOps Server](https://cda.ms/Bf) and [Azure DevOps](https://cda.ms/Bf) before being published to the PowerShell Gallery. -## Requirements - -- Windows PowerShell 5.0 or newer. -- PowerShell Core. - ## Module Dependencies - [SHiPS module](https://www.powershellgallery.com/packages/SHiPS/) @@ -100,14 +110,10 @@ Runs the tests, but executes only the unit tests that have the description "work [Guidelines](.github/CONTRIBUTING.md) -## Change Log - -[Change Log](CHANGELOG.md) - ## Maintainers - [Donovan Brown](https://github.com/darquewarrior) - [@DonovanBrown](https://twitter.com/DonovanBrown) ## License -This project is [licensed under the MIT License](LICENSE). \ No newline at end of file +This project is [licensed under the MIT License](LICENSE). diff --git a/Source/Private/applyTypes.ps1 b/Source/Private/applyTypes.ps1 index 8e55440f5..98da653a4 100644 --- a/Source/Private/applyTypes.ps1 +++ b/Source/Private/applyTypes.ps1 @@ -95,7 +95,7 @@ function _applyTypesToBuild { function _applyArtifactTypes { $item.PSObject.TypeNames.Insert(0, "Team.Build.Artifact") - if ($item.PSObject.Properties.Match('resource').count -gt 0 -and $null -ne $item.resource) { + if ($item.PSObject.Properties.Match('resource').count -gt 0 -and $null -ne $item.resource -and $item.resource.PSObject.Properties.Match('propeties').count -gt 0) { $item.resource.PSObject.TypeNames.Insert(0, 'Team.Build.Artifact.Resource') $item.resource.properties.PSObject.TypeNames.Insert(0, 'Team.Build.Artifact.Resource.Properties') } diff --git a/Source/Public/Remove-VSTeamAccessControlEntry.ps1 b/Source/Public/Remove-VSTeamAccessControlEntry.ps1 new file mode 100644 index 000000000..f24daaf33 --- /dev/null +++ b/Source/Public/Remove-VSTeamAccessControlEntry.ps1 @@ -0,0 +1,89 @@ +function Remove-VSTeamAccessControlEntry { + [CmdletBinding(DefaultParameterSetName = 'byNamespace', SupportsShouldProcess=$true, ConfirmImpact = 'High')] + [OutputType([System.String])] + param( + [Parameter(ParameterSetName = 'byNamespace', Mandatory = $true, ValueFromPipeline = $true)] + [VSTeamSecurityNamespace] $securityNamespace, + + [Parameter(ParameterSetName = 'byNamespaceId', Mandatory = $true)] + [guid] $securityNamespaceId, + + [Parameter(ParameterSetName = 'byNamespace', Mandatory = $true)] + [Parameter(ParameterSetName = 'byNamespaceId', Mandatory = $true)] + [string] $token, + + [Parameter(ParameterSetName = 'byNamespace', Mandatory = $true)] + [Parameter(ParameterSetName = 'byNamespaceId', Mandatory = $true)] + [System.Array] $descriptor + ) + + process { + if($securityNamespace) { + $securityNamespaceId = ($securityNamespace | Select-Object -ExpandProperty id -ErrorAction SilentlyContinue) + } + + if(($descriptor).count -gt 1) { + $descriptor = @() + + foreach($uniqueDescriptor in $descriptor) { + $uniqueDescriptor = ($uniqueDescriptor).split(".")[1] + try { + + $uniqueDescriptor = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("$uniqueDescriptor")) + } + catch [FormatException]{ + Write-Error "Could not convert base64 string to string." + continue + } + $uniqueDescriptor = "Microsoft.TeamFoundation.Identity;"+"$uniqueDescriptor" + + $descriptor += $uniqueDescriptor + } + + if(($descriptor).count -eq 0) { + Write-Error "No valid descriptors provided." + return + } + else + { + $descriptor = $descriptor -join "," + } + } + else { + $descriptor = ($descriptor).split(".")[1] + try { + $descriptor = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($descriptor)) + } + catch { + trap [FormatException]{} + Write-Error "Could not convert base64 string to string." + return + } + + $descriptor = "Microsoft.TeamFoundation.Identity;"+"$descriptor" + } + + if($PSCmdlet.ShouldProcess("$token")) { + # Call the REST API + $resp = _callAPI -method DELETE -Area "accesscontrolentries" -id $securityNamespaceId -ContentType "application/json" -Version $([VSTeamVersions]::Core) -QueryString @{token = $token; descriptors = $descriptor} -ErrorAction SilentlyContinue + } + + switch($resp) { + {($resp -eq $true)} + { + return "Removal of ACE from ACL succeeded." + } + + {($resp -eq $false)} + { + Write-Error "Removal of ACE from ACL failed. Ensure descriptor and token are correct." + return + } + {($resp -ne $true) -and ($resp -ne $false)} + { + Write-Error "Unexpected response from REST API." + return + } + } + } + } diff --git a/Source/VSTeam.psd1 b/Source/VSTeam.psd1 index 65a03ecf5..c82d83e89 100644 --- a/Source/VSTeam.psd1 +++ b/Source/VSTeam.psd1 @@ -124,4 +124,4 @@ # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. # DefaultCommandPrefix = '' -} \ No newline at end of file +} diff --git a/docs/Remove-VSTeamAccessControlEntry.md b/docs/Remove-VSTeamAccessControlEntry.md new file mode 100644 index 000000000..747c44b44 --- /dev/null +++ b/docs/Remove-VSTeamAccessControlEntry.md @@ -0,0 +1,203 @@ + + + +# Remove-VSTeamAccessControlEntry + +## SYNOPSIS + +Removes specified ACEs in the ACL for the provided token. The request URI contains the namespace ID, the target token, and a single or list of descriptors that should be removed. Only supports removing AzD based users/groups. + +## SYNTAX + +## DESCRIPTION + +Removes specified ACEs in the ACL for the provided token. The request URI contains the namespace ID, the target token, and a single or list of descriptors that should be removed. Only supports removing AzD based users/groups. + +## EXAMPLES +### -------------------------- EXAMPLE 1 -------------------------- + +```PowerShell +PS C:\> Remove-VSTeamAccessControlEntry -securityNamespaceId "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" -token "repov2/$projectid/$repoid" -descriptor @("vssgp.Uy0xLTktMTU1MTM3NDI0NS0xMzk4ODc2NjMwLTEwMTQ0ODQ4MTMtMzE5MDA4NTI4Ny0xNDU4NTkwODY1LTEtMzE1MjE3NTkwMy03NjE1NjY3OTMtMjgwMTUwMjI2Ny0zMjU5Mjg5MTIy") +``` + +This will remove the specified descriptor from the specified repository, using the security namespace id, while confirming for the remove action. + +### -------------------------- EXAMPLE 2 -------------------------- + +```PowerShell +PS C:\> Remove-VSTeamAccessControlEntry -securityNamespaceId "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" -token "repov2/$projectid/$repoid" -descriptor @("vssgp.Uy0xLTktMTU1MTM3NDI0NS0xMzk4ODc2NjMwLTEwMTQ0ODQ4MTMtMzE5MDA4NTI4Ny0xNDU4NTkwODY1LTEtMzE1MjE3NTkwMy03NjE1NjY3OTMtMjgwMTUwMjI2Ny0zMjU5Mjg5MTIy") -confirm:$false +``` + +This will remove the specified descriptor from the specified repository, using the security namespace id, with no confirmation for the remove action. + +### -------------------------- EXAMPLE 3 -------------------------- + +```PowerShell +PS C:\> Remove-VSTeamAccessControlEntry -securityNamespaceId "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" -token "repov2/$projectid/$repoid" -descriptor @("descriptor1","descriptor2") +``` + +This will remove multiple descriptors from the specified repository, using the security namespace id, while confirming for the remove action. + +### -------------------------- EXAMPLE 4 -------------------------- + +```PowerShell +PS C:\> Remove-VSTeamAccessControlEntry -securityNamespace [VSTeamSecurityNamespace]$securityNamespace -token "repov2/$projectid/$repoid" -descriptor @("vssgp.Uy0xLTktMTU1MTM3NDI0NS0xMzk4ODc2NjMwLTEwMTQ0ODQ4MTMtMzE5MDA4NTI4Ny0xNDU4NTkwODY1LTEtMzE1MjE3NTkwMy03NjE1NjY3OTMtMjgwMTUwMjI2Ny0zMjU5Mjg5MTIy") +``` + +This will remove the specified descriptor from the specified repository, using a security namespace object, while confirming for the remove action. + +### -------------------------- EXAMPLE 5 -------------------------- + +```PowerShell +PS C:\> Remove-VSTeamAccessControlEntry -securityNamespace [VSTeamSecurityNamespace]$securityNamespace -token "repov2/$projectid/$repoid" -descriptor @("vssgp.Uy0xLTktMTU1MTM3NDI0NS0xMzk4ODc2NjMwLTEwMTQ0ODQ4MTMtMzE5MDA4NTI4Ny0xNDU4NTkwODY1LTEtMzE1MjE3NTkwMy03NjE1NjY3OTMtMjgwMTUwMjI2Ny0zMjU5Mjg5MTIy") -confirm:$false +``` + +This will remove the specified descriptor from the specified repository, using a security namespace object, with no confirmation for the remove action. + +### -------------------------- EXAMPLE 6 -------------------------- + +```PowerShell +PS C:\> Remove-VSTeamAccessControlEntry -securityNamespace [VSTeamSecurityNamespace]$securityNamespace -token "repov2/$projectid/$repoid" -descriptor @("descriptor1","descriptor2") +``` + +This will remove multiple descriptors from the specified repository, using a security namespace object, while confirming for the remove action. + +## PARAMETERS + +### -SecurityNamespace + +VSTeamSecurityNamespace object. + +```yaml +Type: VSTeamSecurityNamespace +Required: True +``` + +### -SecurityNamespaceId + +Security namespace identifier. + +Valid IDs are: + +AzD: +- Analytics (58450c49-b02d-465a-ab12-59ae512d6531) +- AnalyticsViews (d34d3680-dfe5-4cc6-a949-7d9c68f73cba) +- ReleaseManagement (7c7d32f7-0e86-4cd6-892e-b35dbba870bd) +- ReleaseManagement2 (c788c23e-1b46-4162-8f5e-d7585343b5de) +- Identity (5a27515b-ccd7-42c9-84f1-54c998f03866) +- WorkItemTrackingAdministration (445d2788-c5fb-4132-bbef-09c4045ad93f) +- DistributedTask (101eae8c-1709-47f9-b228-0e476c35b3ba) +- WorkItemQueryFolders (71356614-aad7-4757-8f2c-0fb3bff6f680) +- GitRepositories (2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87) +- VersionControlItems2 (3c15a8b7-af1a-45c2-aa97-2cb97078332e) +- EventSubscriber (2bf24a2b-70ba-43d3-ad97-3d9e1f75622f) +- WorkItemTrackingProvision (5a6cd233-6615-414d-9393-48dbb252bd23) +- ServiceEndpoints (49b48001-ca20-4adc-8111-5b60c903a50c) +- ServiceHooks (cb594ebe-87dd-4fc9-ac2c-6a10a4c92046) +- Chat (bc295513-b1a2-4663-8d1a-7017fd760d18) +- Collection (3e65f728-f8bc-4ecd-8764-7e378b19bfa7) +- Proxy (cb4d56d2-e84b-457e-8845-81320a133fbb) +- Plan (bed337f8-e5f3-4fb9-80da-81e17d06e7a8) +- Process (2dab47f9-bd70-49ed-9bd5-8eb051e59c02) +- AccountAdminSecurity (11238e09-49f2-40c7-94d0-8f0307204ce4) +- Library (b7e84409-6553-448a-bbb2-af228e07cbeb) +- Environment (83d4c2e6-e57d-4d6e-892b-b87222b7ad20) +- Project (52d39943-cb85-4d7f-8fa8-c6baac873819) +- EventSubscription (58b176e7-3411-457a-89d0-c6d0ccb3c52b) +- CSS (83e28ad4-2d72-4ceb-97b0-c7726d5502c3) +- TeamLabSecurity (9e4894c3-ff9a-4eac-8a85-ce11cafdc6f1) +- ProjectAnalysisLanguageMetrics (fc5b7b85-5d6b-41eb-8534-e128cb10eb67) +- Tagging (bb50f182-8e5e-40b8-bc21-e8752a1e7ae2) +- MetaTask (f6a4de49-dbe2-4704-86dc-f8ec1a294436) +- Iteration (bf7bfa03-b2b7-47db-8113-fa2e002cc5b1) +- Favorites (fa557b48-b5bf-458a-bb2b-1b680426fe8b) +- Registry (4ae0db5d-8437-4ee8-a18b-1f6fb38bd34c) +- Graph (c2ee56c9-e8fa-4cdd-9d48-2c44f697a58e) +- ViewActivityPaneSecurity (dc02bf3d-cd48-46c3-8a41-345094ecc94b) +- Job (2a887f97-db68-4b7c-9ae3-5cebd7add999) +- WorkItemTracking (73e71c45-d483-40d5-bdba-62fd076f7f87) +- StrongBox (4a9e8381-289a-4dfd-8460-69028eaa93b3) +- Server (1f4179b3-6bac-4d01-b421-71ea09171400) +- TestManagement (e06e1c24-e93d-4e4a-908a-7d951187b483) +- SettingEntries (6ec4592e-048c-434e-8e6c-8671753a8418) +- BuildAdministration (302acaca-b667-436d-a946-87133492041c) +- Location (2725d2bc-7520-4af4-b0e3-8d876494731f) +- Boards (251e12d9-bea3-43a8-bfdb-901b98c0125e) +- UtilizationPermissions (83abde3a-4593-424e-b45f-9898af99034d) +- WorkItemsHub (c0e7a722-1cad-4ae6-b340-a8467501e7ce) +- WebPlatform (0582eb05-c896-449a-b933-aa3d99e121d6) +- VersionControlPrivileges (66312704-deb5-43f9-b51c-ab4ff5e351c3) +- Workspaces (93bafc04-9075-403a-9367-b7164eac6b5c) +- CrossProjectWidgetView (093cbb02-722b-4ad6-9f88-bc452043fa63) +- WorkItemTrackingConfiguration (35e35e8e-686d-4b01-aff6-c369d6e36ce0) +- Discussion Threads (0d140cae-8ac1-4f48-b6d1-c93ce0301a12) +- BoardsExternalIntegration (5ab15bc8-4ea1-d0f3-8344-cab8fe976877) +- DataProvider (7ffa7cf4-317c-4fea-8f1d-cfda50cfa956) +- Social (81c27cc8-7a9f-48ee-b63f-df1e1d0412dd) +- Security (9a82c708-bfbe-4f31-984c-e860c2196781) +- IdentityPicker (a60e0d84-c2f8-48e4-9c0c-f32da48d5fd1) +- ServicingOrchestration (84cc1aa4-15bc-423d-90d9-f97c450fc729) +- Build (33344d9c-fc72-4d6f-aba5-fa317101a7e9) +- DashboardsPrivileges (8adf73b7-389a-4276-b638-fe1653f7efc7) +- VersionControlItems (a39371cf-0841-4c16-bbd3-276e341bc052) + +VSSPS: +- EventSubscriber (2bf24a2b-70ba-43d3-ad97-3d9e1f75622f) (VSSPS) +- EventSubscription (58b176e7-3411-457a-89d0-c6d0ccb3c52b) (VSSPS) +- Registry (4ae0db5d-8437-4ee8-a18b-1f6fb38bd34c) (VSSPS) +- Graph (c2ee56c9-e8fa-4cdd-9d48-2c44f697a58e) (VSSPS) +- Invitation (ea0b4d1e-577a-4797-97b5-2f5755e548d5) (VSSPS) +- SystemGraph (b24dfdf1-285a-4ea6-a55b-32549a68121d) (VSSPS) +- Job (2a887f97-db68-4b7c-9ae3-5cebd7add999) (VSSPS) +- CommerceCollectionSecurity (307be2d3-12ed-45c2-aacf-6598760efca7) (VSSPS) +- StrongBox (4a9e8381-289a-4dfd-8460-69028eaa93b3) (VSSPS) +- GroupLicensing (c6a4fd35-b508-49eb-8ea7-7189df5f3698) (VSSPS) +- Server (1f4179b3-6bac-4d01-b421-71ea09171400) (VSSPS) +- SettingEntries (6ec4592e-048c-434e-8e6c-8671753a8418) (VSSPS) +- RemotableTemplateTest (ccdcb71c-4780-4a42-9bb4-8bce07a7628f) (VSSPS) +- Location (2725d2bc-7520-4af4-b0e3-8d876494731f) (VSSPS) +- WebPlatform (0582eb05-c896-449a-b933-aa3d99e121d6) (VSSPS) +- DataProvider (7ffa7cf4-317c-4fea-8f1d-cfda50cfa956) (VSSPS) +- Security (9a82c708-bfbe-4f31-984c-e860c2196781) (VSSPS) +- IdentityPicker (a60e0d84-c2f8-48e4-9c0c-f32da48d5fd1) (VSSPS) +- ServicingOrchestration (84cc1aa4-15bc-423d-90d9-f97c450fc729) (VSSPS) + +```yaml +Type: String +Required: True +``` + +### -Token + +The security Token + +Valid token formats are: + +- Git Repository (repov2/$projectID/$repositoryID) +- Build Definition ($projectID/$buildDefinitionID) +- Release Definition ($projectID/$releaseDefinitionID, $projectID/Path/to/Release/$releaseDefinitionID) + +```yaml +Type: String +Required: True +``` + +### -Descriptor + +An array of descriptors of users/groups to be removed + +```yaml +Type: System.Array +Required: True +``` + +## INPUTS + +## OUTPUTS + +## NOTES + +### This function outputs a non-terminating error if the ACE removal from the ACL returns $False. This can be due to the wrong descriptor being provided, or the descriptor already not being on the ACL. + +## RELATED LINKS + diff --git a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 new file mode 100644 index 000000000..569636813 --- /dev/null +++ b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 @@ -0,0 +1,170 @@ +Set-StrictMode -Version Latest + +InModuleScope VSTeam { + + # Set the account to use for testing. A normal user would do this + # using the Set-VSTeamAccount function. + [VSTeamVersions]::Account = 'https://dev.azure.com/test' + +$securityNamespace = +@" +{ + "namespaceId": "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87", + "name": "Git Repositories", + "displayName": "Git Repositories", + "separatorValue": "/", + "elementLength": -1, + "writePermission": 8192, + "readPermission": 2, + "dataspaceCategory": "Git", + "actions": [ + { + "DisplayName": "Administer", + "Name": "Administer", + "Bit": 1 + }, + { + "DisplayName": "Read", + "Name": "GenericRead", + "Bit": 2 + }, + { + "DisplayName": "Contribute", + "Name": "GenericContribute", + "Bit": 4 + }, + { + "DisplayName": "Force push (rewrite history, delete branches and tags)", + "Name": "ForcePush", + "Bit": 8 + }, + { + "DisplayName": "Create branch", + "Name": "CreateBranch", + "Bit": 16 + }, + { + "DisplayName": "Create tag", + "Name": "CreateTag", + "Bit": 32 + }, + { + "DisplayName": "Manage notes", + "Name": "ManageNote", + "Bit": 64 + }, + { + "DisplayName": "Bypass policies when pushing", + "Name": "PolicyExempt", + "Bit": 128 + }, + { + "DisplayName": "Create repository", + "Name": "CreateRepository", + "Bit": 256 + }, + { + "DisplayName": "Delete repository", + "Name": "DeleteRepository", + "Bit": 512 + }, + { + "DisplayName": "Rename repository", + "Name": "RenameRepository", + "Bit": 1024 + }, + { + "DisplayName": "Edit policies", + "Name": "EditPolicies", + "Bit": 2048 + }, + { + "DisplayName": "Remove others\u0027 locks", + "Name": "RemoveOthersLocks", + "Bit": 4096 + }, + { + "DisplayName": "Manage permissions", + "Name": "ManagePermissions", + "Bit": 8192 + }, + { + "DisplayName": "Contribute to pull requests", + "Name": "PullRequestContribute", + "Bit":"16384" + }, + { + "DisplayName": "Bypass policies when completing pull requests", + "Name": "PullRequestBypassPolicy", + "Bit": 32768 + } + ], + "structureValue": 1, + "extensionType": "Microsoft.TeamFoundation.Git.Server.Plugins.GitSecurityNamespaceExtension", + "isRemotable": true, + "useTokenTranslator": true, + "systemBitMask": 0 +} +"@ | ConvertFrom-Json + + Describe 'AccessControlEntry VSTS'{ + # You have to set the version or the api-version will not be Removed when + # [VSTeamVersions]::Core = '' + [VSTeamVersions]::Core = '5.1' + + + Mock Get-VSTeamSecurityNamespace { return $securityNamespace } + + Context 'Remove-VSTeamAccessControlEntry by SecurityNamespaceId'{ + It 'Should succeed with a properly formatted descriptor if descriptor is on ACL'{ + Mock _callAPI { return $true } -Verifiable + Remove-VSTeamAccessControlEntry -SecurityNamespaceId "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" -Descriptor @("vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04") -Token xyz -confirm:$false | Should be "Removal of ACE from ACL succeeded." + } + It 'Should fail with a properly formatted descriptor if descriptor is not on ACL already'{ + Mock _callAPI { return $false } -Verifiable + Remove-VSTeamAccessControlEntry -SecurityNamespaceId "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" -Descriptor @("vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04") -Token xyz -confirm:$false -ErrorVariable err -ErrorAction SilentlyContinue + $err.count | should be 1 + $err[0].Exception.Message | Should Be "Removal of ACE from ACL failed. Ensure descriptor and token are correct." + $err + } + It 'Should fail with an improperly formatted descriptor'{ + Remove-VSTeamAccessControlEntry -SecurityNamespaceId "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" -Descriptor @("vssgp.NotARealDescriptor") -Token xyz -confirm:$false -ErrorVariable err -ErrorAction SilentlyContinue + $err.count | should be 2 + $err[1].Exception.Message | Should Be "Could not convert base64 string to string." + } + It 'Should fail if the REST API gives a non true/false response'{ + Mock _callAPI { return "Not a valid return" } -Verifiable + Remove-VSTeamAccessControlEntry -SecurityNamespaceId "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" -Descriptor @("vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04") -Token xyz -confirm:$false -ErrorVariable err -ErrorAction SilentlyContinue + $err.count | should be 1 + $err[0].Exception.Message | Should Be "Unexpected response from REST API." + } + } + + Context 'Remove-VSTeamAccessControlEntry by SecurityNamespace'{ + It 'Should succeed with a properly formatted descriptor if descriptor is on ACL'{ + $securityNamespace = Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" + Mock _callAPI { return $true } -Verifiable + Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor @("vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04") -Token xyz -confirm:$false | Should be "Removal of ACE from ACL succeeded." + } + It 'Should fail with a properly formatted descriptor if descriptor is not on ACL already'{ + $securityNamespace = Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" + Mock _callAPI { return $false } -Verifiable + Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor @("vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04") -Token xyz -confirm:$false -ErrorVariable err -ErrorAction SilentlyContinue + $err.count | should be 1 + $err[0].Exception.Message | Should Be "Removal of ACE from ACL failed. Ensure descriptor and token are correct." + } + It 'Should fail with an improperly formatted descriptor'{ + $securityNamespace = Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" + Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor @("vssgp.NotARealDescriptor") -Token xyz -confirm:$false -ErrorVariable err -ErrorAction SilentlyContinue + $err.count | should be 2 + $err[1].Exception.Message | Should Be "Could not convert base64 string to string." + } + It 'Should fail if the REST API gives a non true/false response'{ + Mock _callAPI { return "Not a valid return" } -Verifiable + Remove-VSTeamAccessControlEntry -SecurityNamespaceId "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" -Descriptor @("vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04") -Token xyz -confirm:$false -ErrorVariable err -ErrorAction SilentlyContinue + $err.count | should be 1 + $err[0].Exception.Message | Should Be "Unexpected response from REST API." + } + } + } +} \ No newline at end of file diff --git a/unit/test/builds.Tests.ps1 b/unit/test/builds.Tests.ps1 index ceb7f2032..0bb44e3f8 100644 --- a/unit/test/builds.Tests.ps1 +++ b/unit/test/builds.Tests.ps1 @@ -317,6 +317,28 @@ InModuleScope VSTeam { } } } + + Context "Get-VSTeamBuildArtifact result without properties" { + Mock Invoke-RestMethod { return [PSCustomObject]@{ + value = [PSCustomObject]@{ + id = 150 + name = "Drop" + resource = [PSCustomObject]@{ + type = "filepath" + data = "C:\Test" + } + } + } + } + + Get-VSTeamBuildArtifact -projectName project -id 2 + + It 'should return the build artifact data' { + Assert-MockCalled Invoke-RestMethod -Exactly -Scope Context -Times 1 -ParameterFilter { + $Uri -eq "https://dev.azure.com/test/project/_apis/build/builds/2/artifacts?api-version=$([VSTeamVersions]::Build)" + } + } + } } Describe 'Builds TFS' {