From 93f43cb6081f7d004b10e7c5efac8afd8663b238 Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 10:04:43 -0800 Subject: [PATCH 01/35] Added Remove-VSTeamAccessControlEntry.ps1 This function removes the user and/or group from the specified resource (token) in the specified security namespace. This function handles the conversion from the AzD format of vssgp. to the SID based value expected by the API. Function can accept multiple AzD formatted descriptors in comma separated format for bulk-removal of users/groups from a resource. --- .../Remove-VSTeamAccessControlEntry.ps1 | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 Source/Public/Remove-VSTeamAccessControlEntry.ps1 diff --git a/Source/Public/Remove-VSTeamAccessControlEntry.ps1 b/Source/Public/Remove-VSTeamAccessControlEntry.ps1 new file mode 100644 index 000000000..87fd3a124 --- /dev/null +++ b/Source/Public/Remove-VSTeamAccessControlEntry.ps1 @@ -0,0 +1,60 @@ +function Remove-VSTeamAccessControlEntry { + [CmdletBinding(DefaultParameterSetName = 'ByNamespace')] + param( + [Parameter(ParameterSetName = 'ByNamespace', Mandatory = $true, ValueFromPipeline = $true)] + [VSTeamSecurityNamespace] $SecurityNamespace, + + [Parameter(ParameterSetName = 'ByNamespaceId', Mandatory = $true)] + [ValidateScript({ + try { + [System.Guid]::Parse($_) | Out-Null + $true + } catch { + $false + } + })] + [string] $SecurityNamespaceId, + + [Parameter(ParameterSetName = 'ByNamespace', Mandatory = $true)] + [Parameter(ParameterSetName = 'ByNamespaceId', Mandatory = $true)] + [string] $Token, + + [Parameter(ParameterSetName = 'ByNamespace', Mandatory = $true)] + [Parameter(ParameterSetName = 'ByNamespaceId', Mandatory = $true)] + [string] $Descriptor + ) + + process { + if ($SecurityNamespace) + { + $SecurityNamespaceId = $SecurityNamespace.ID + } + + if ($Descriptor -like "*,*") + { + $Descriptors = @() + + foreach($UniqueDescriptor in $Descriptor.Split(",")) + { + $UniqueDescriptor = ($UniqueDescriptor).split(".")[1] + $UniqueDescriptor = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($UniqueDescriptor)) + $UniqueDescriptor = "Microsoft.TeamFoundation.Identity;"+"$UniqueDescriptor" + + $Descriptors += $UniqueDescriptor + } + + [Uri]$Uri = "$($env:TEAM_ACCT)/_apis/accesscontrolentries/$($securityNamespaceId)?token=$($token)&descriptors=$($descriptors -join ",")&api-version=5.1" + } + else + { + $Descriptor = ($descriptor).split(".")[1] + $Descriptor = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Descriptor)) + $Descriptor = "Microsoft.TeamFoundation.Identity;"+"$descriptor" + + [Uri]$Uri = "$($env:TEAM_ACCT)/_apis/accesscontrolentries/$($securityNamespaceId)?token=$($token)&descriptors=$($descriptor)&api-version=5.1" + } + + # Call the REST API + $resp = _callAPI -method DELETE -Url $Uri -ContentType "application/json" + } + } \ No newline at end of file From dae3a03458127d8201402f5ccf8d1425fabfd149 Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 12:18:31 -0800 Subject: [PATCH 02/35] Added Remove-VSTeamAccessControlEntry.md Added help file for Remove-VSTeamAccessControlEntry function --- docs/Remove-VSTeamAccessControlEntry.md | 141 ++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 docs/Remove-VSTeamAccessControlEntry.md diff --git a/docs/Remove-VSTeamAccessControlEntry.md b/docs/Remove-VSTeamAccessControlEntry.md new file mode 100644 index 000000000..ead67edbc --- /dev/null +++ b/docs/Remove-VSTeamAccessControlEntry.md @@ -0,0 +1,141 @@ + + + +# 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 + +## 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 + +```yaml +Type: String +Required: True +``` + +## INPUTS + +## OUTPUTS + +## NOTES + +### This function outputs a warning 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 + From 1af5bf70bfd7ef60e83c7c6d8d6575d35f30f5c8 Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 12:20:34 -0800 Subject: [PATCH 03/35] Updated CHANGELOG.md Updated change log with pull request information --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 546ac3148..f0e37c6ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 6.4.2 + +Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/) from [Steven Cady](https://github.com/cadacious) which included the following: + +Added Remove-VSTeamAccessControlEntry to delete users/groups from Access Control Lists within security namespaces. Supports removing single or multiple entries. Can remove vsts origin or aad origin, but not in the same run. Origin defaults to vsts if not specified. + ## 6.4.1 Fixed issue [Description on variable groups is not a required field #208](https://github.com/DarqueWarrior/vsteam/issues/208). From ceaca29e8aca58aeab7f149e7611ec1f5bd1ba96 Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 13:51:52 -0800 Subject: [PATCH 04/35] Added Remove-VSTeamAccessControlEntry.Tests Added pester file for new function Remove-VSTeamAccessControlEntry --- .../Remove-VSTeamAccessControlEntry.Tests.ps1 | 195 ++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 diff --git a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 new file mode 100644 index 000000000..94a32975e --- /dev/null +++ b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 @@ -0,0 +1,195 @@ +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 = +@" +{ + "DisplayName": "Git Repositories", + "SeparatorValue": "/", + "ElementLength": -1, + "WritePermission": 8192, + "ReadPermission": 2, + "DataspaceCategory": "Git", + "StructureValue": "1", + "ExtensionType": "Microsoft.TeamFoundation.Git.Server.Plugins.GitSecurityNamespaceExtension", + "IsRemotable": true, + "UseTokenTranslator": true, + "SystemBitMask": 0, + "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 + } + ], + "_internalObj": [ + { + "namespaceId": "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87", + "name": "Git Repositories", + "displayName": "Git Repositories", + "separatorValue": "/", + "elementLength": -1, + "writePermission": 8192, + "readPermission": 2, + "dataspaceCategory": "Git", + "actions": " ", + "structureValue": 1, + "extensionType": "Microsoft.TeamFoundation.Git.Server.Plugins.GitSecurityNamespaceExtension", + "isRemotable": true, + "useTokenTranslator": true, + "systemBitMask": 0 + } + ], + "ID": "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87", + "ProjectName": "", + "DisplayMode": "------", + "Name": "Git Repositories" +} +"@ | ConvertFrom-Json + + $securityNamespaceObject = [VSTeamSecurityNamespace]::new($securityNamespace) + + Describe 'AccessControlEntry VSTS' { + # You have to set the version or the api-version will not be Removeed when + # [VSTeamVersions]::Core = '' + [VSTeamVersions]::Core = '5.1' + + Context 'Remove-VSTeamAccessControlEntry by SecurityNamespaceId' { + Mock Invoke-RestMethod { return $true } + + Remove-VSTeamAccessControlEntry -SecurityNamespaceId 2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87 -Descriptor abc -Token xyz + + It 'Should have a properly constructed URL' { + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and + $Uri -like "*api-version=$([VSTeamVersions]::Core)*" -and + $Uri -like "*Microsoft.TeamFoundation.Identity;S-1*" -and + $Uri -like "*?token=xyz*" -and + $Uri -like "*&descriptors=abc*" -and + $ContentType -eq "application/json" -and + $Method -eq "Delete" + } + } + } + + Context 'Remove-VSTeamAccessControlEntry by SecurityNamespace' { + Mock Get-VSTeamSecurityNamespace { return $securityNamespaceObject } + Mock Invoke-RestMethod { return $true } + + $securityNamespace = Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" + Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor abc -Token xyz + + It 'Should have a properly constructed URL' { + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and + $Uri -like "*api-version=$([VSTeamVersions]::Core)*" -and + $Uri -like "*Microsoft.TeamFoundation.Identity;S-1*" -and + $Uri -like "*?token=xyz*" -and + $Uri -like "*&descriptors=abc*" -and + $ContentType -eq "application/json" -and + $Method -eq "Delete" + } + } + } + + Context 'Remove-VSTeamAccessControlEntry by SecurityNamespace (pipeline)' { + Mock Get-VSTeamSecurityNamespace { return $securityNamespaceObject } + Mock Invoke-RestMethod { return $true } + + Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" | ` + Remove-VSTeamAccessControlEntry -Descriptor abc -Token xyz + + It 'Should have a properly constructed URL' { + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and + $Uri -like "*api-version=$([VSTeamVersions]::Core)*" -and + $Uri -like "*Microsoft.TeamFoundation.Identity;S-1*" -and + $Uri -like "*?token=xyz*" -and + $Uri -like "*&descriptors=abc*" -and + $ContentType -eq "application/json" -and + $Method -eq "Delete" + } + } + } + } +} \ No newline at end of file From 5cc0ebc1914e97c99fd937117a06c7806981ecee Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 13:54:18 -0800 Subject: [PATCH 05/35] Updated VSTeams.psd1 Incremented version number --- Source/VSTeam.psd1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/VSTeam.psd1 b/Source/VSTeam.psd1 index 5ab4b5889..b00e357b2 100644 --- a/Source/VSTeam.psd1 +++ b/Source/VSTeam.psd1 @@ -12,7 +12,7 @@ RootModule = 'VSTeam.psm1' # Version number of this module. - ModuleVersion = '6.4.1' + ModuleVersion = '6.4.2' # Supported PSEditions # CompatiblePSEditions = @() @@ -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 +} From edb84b9b3ade61f9edee22f56727f2ba1ef59edd Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 14:03:28 -0800 Subject: [PATCH 06/35] Updated Remove-VSTeamAccessControlEntry Added valid Descriptor so conversion from base64 to SID would succeed for unit test validation. --- unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 index 94a32975e..6469b433e 100644 --- a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 +++ b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 @@ -137,7 +137,7 @@ InModuleScope VSTeam { Context 'Remove-VSTeamAccessControlEntry by SecurityNamespaceId' { Mock Invoke-RestMethod { return $true } - Remove-VSTeamAccessControlEntry -SecurityNamespaceId 2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87 -Descriptor abc -Token xyz + Remove-VSTeamAccessControlEntry -SecurityNamespaceId 2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87 -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0xODc2Mzk2MjA0LTIwNjc1NTI1ODctMzA2NDY5MTU3My0yNjkxODIxNjgzLTEtMjM0NjY4Mzk3Mi0yNDI0MDE0NjYzLTI5MzAxOTk4OTktMTU1MjUwNTM3MQ" -Token xyz It 'Should have a properly constructed URL' { Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { @@ -157,7 +157,7 @@ InModuleScope VSTeam { Mock Invoke-RestMethod { return $true } $securityNamespace = Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" - Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor abc -Token xyz + Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0xODc2Mzk2MjA0LTIwNjc1NTI1ODctMzA2NDY5MTU3My0yNjkxODIxNjgzLTEtMjM0NjY4Mzk3Mi0yNDI0MDE0NjYzLTI5MzAxOTk4OTktMTU1MjUwNTM3MQ" -Token xyz It 'Should have a properly constructed URL' { Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { @@ -177,7 +177,7 @@ InModuleScope VSTeam { Mock Invoke-RestMethod { return $true } Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" | ` - Remove-VSTeamAccessControlEntry -Descriptor abc -Token xyz + Remove-VSTeamAccessControlEntry -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0xODc2Mzk2MjA0LTIwNjc1NTI1ODctMzA2NDY5MTU3My0yNjkxODIxNjgzLTEtMjM0NjY4Mzk3Mi0yNDI0MDE0NjYzLTI5MzAxOTk4OTktMTU1MjUwNTM3MQ" -Token xyz It 'Should have a properly constructed URL' { Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { From 351b90e2636688226f0b9011b48f63bc07d3b11a Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 14:07:12 -0800 Subject: [PATCH 07/35] Updated CHANGELOG.md Changed wording of pull request summary --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0e37c6ad..da9b7a3dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/) from [Steven Cady](https://github.com/cadacious) which included the following: -Added Remove-VSTeamAccessControlEntry to delete users/groups from Access Control Lists within security namespaces. Supports removing single or multiple entries. Can remove vsts origin or aad origin, but not in the same run. Origin defaults to vsts if not specified. +Added Remove-VSTeamAccessControlEntry to delete users/groups from Access Control Lists within security namespaces. Supports removing single or multiple entries. Only supports removing vsts origin users/groups. ## 6.4.1 From e9562dcf9f46c53e8044c82b8aff5212866dedbf Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 14:10:44 -0800 Subject: [PATCH 08/35] Updated CHANGELOG.md Updated change request number for upcoming pull request --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da9b7a3dc..7908f3eb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 6.4.2 -Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/) from [Steven Cady](https://github.com/cadacious) which included the following: +Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/221) from [Steven Cady](https://github.com/cadacious) which included the following: Added Remove-VSTeamAccessControlEntry to delete users/groups from Access Control Lists within security namespaces. Supports removing single or multiple entries. Only supports removing vsts origin users/groups. From a7d035b77b65577b0a081e24c2cdc86585cef9bb Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 14:29:18 -0800 Subject: [PATCH 09/35] Updates Remove-VSTeamAccessControlEntry.Tests.ps1 Removed InternalObj portion of return of securityNamespace return, cleaned up unit test. --- .../Remove-VSTeamAccessControlEntry.Tests.ps1 | 28 +++---------------- 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 index 6469b433e..41116eb5e 100644 --- a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 +++ b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 @@ -6,7 +6,7 @@ InModuleScope VSTeam { # using the Set-VSTeamAccount function. [VSTeamVersions]::Account = 'https://dev.azure.com/test' - $securityNamespace = + [VSTeamSecurityNamespace]$securityNamespace = @" { "DisplayName": "Git Repositories", @@ -102,35 +102,15 @@ InModuleScope VSTeam { "Bit": 32768 } ], - "_internalObj": [ - { - "namespaceId": "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87", - "name": "Git Repositories", - "displayName": "Git Repositories", - "separatorValue": "/", - "elementLength": -1, - "writePermission": 8192, - "readPermission": 2, - "dataspaceCategory": "Git", - "actions": " ", - "structureValue": 1, - "extensionType": "Microsoft.TeamFoundation.Git.Server.Plugins.GitSecurityNamespaceExtension", - "isRemotable": true, - "useTokenTranslator": true, - "systemBitMask": 0 - } - ], "ID": "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87", "ProjectName": "", "DisplayMode": "------", "Name": "Git Repositories" } "@ | ConvertFrom-Json - - $securityNamespaceObject = [VSTeamSecurityNamespace]::new($securityNamespace) Describe 'AccessControlEntry VSTS' { - # You have to set the version or the api-version will not be Removeed when + # You have to set the version or the api-version will not be Removed when # [VSTeamVersions]::Core = '' [VSTeamVersions]::Core = '5.1' @@ -153,7 +133,7 @@ InModuleScope VSTeam { } Context 'Remove-VSTeamAccessControlEntry by SecurityNamespace' { - Mock Get-VSTeamSecurityNamespace { return $securityNamespaceObject } + Mock Get-VSTeamSecurityNamespace { return $securityNamespace } Mock Invoke-RestMethod { return $true } $securityNamespace = Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" @@ -173,7 +153,7 @@ InModuleScope VSTeam { } Context 'Remove-VSTeamAccessControlEntry by SecurityNamespace (pipeline)' { - Mock Get-VSTeamSecurityNamespace { return $securityNamespaceObject } + Mock Get-VSTeamSecurityNamespace { return $securityNamespace } Mock Invoke-RestMethod { return $true } Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" | ` From 5399e8f0b8f5f2ec19e8006934632102ec7562b9 Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 14:37:14 -0800 Subject: [PATCH 10/35] Updated Remove-VSTeamAccessControlEntry.Tests.ps1 Changed unit test --- unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 index 41116eb5e..c662859be 100644 --- a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 +++ b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 @@ -6,7 +6,7 @@ InModuleScope VSTeam { # using the Set-VSTeamAccount function. [VSTeamVersions]::Account = 'https://dev.azure.com/test' - [VSTeamSecurityNamespace]$securityNamespace = +$securityNamespace = @" { "DisplayName": "Git Repositories", From 350658b7280aa6de30600e0085bf95767e784ba5 Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 15:03:57 -0800 Subject: [PATCH 11/35] Updated Remove-VSTeamAccessControlEntry.Tests.ps1 Fixed structure of $securityNamespace to be what was expected for unit test. --- .../Remove-VSTeamAccessControlEntry.Tests.ps1 | 111 +++--------------- 1 file changed, 14 insertions(+), 97 deletions(-) diff --git a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 index c662859be..aebf8a7f2 100644 --- a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 +++ b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 @@ -9,103 +9,20 @@ InModuleScope VSTeam { $securityNamespace = @" { - "DisplayName": "Git Repositories", - "SeparatorValue": "/", - "ElementLength": -1, - "WritePermission": 8192, - "ReadPermission": 2, - "DataspaceCategory": "Git", - "StructureValue": "1", - "ExtensionType": "Microsoft.TeamFoundation.Git.Server.Plugins.GitSecurityNamespaceExtension", - "IsRemotable": true, - "UseTokenTranslator": true, - "SystemBitMask": 0, - "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 - } - ], - "ID": "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87", - "ProjectName": "", - "DisplayMode": "------", - "Name": "Git Repositories" + "namespaceId": "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87", + "name": "Git Repositories", + "displayName": "Git Repositories", + "separatorValue": "/", + "elementLength": -1, + "writePermission": 8192, + "readPermission": 2, + "dataspaceCategory": "Git", + "actions": " ", + "structureValue": 1, + "extensionType": "Microsoft.TeamFoundation.Git.Server.Plugins.GitSecurityNamespaceExtension", + "isRemotable": true, + "useTokenTranslator": true, + "systemBitMask": 0 } "@ | ConvertFrom-Json From f76220452c0defa560decf247cef0b34f06658b8 Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 15:20:47 -0800 Subject: [PATCH 12/35] Updated Remove-VSTeamAccessControlEntry.Tests.ps1 Fixed Actions section of $securityNamespace and fed pipeline input properly to function. --- .../Remove-VSTeamAccessControlEntry.Tests.ps1 | 86 ++++++++++++++++++- 1 file changed, 83 insertions(+), 3 deletions(-) diff --git a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 index aebf8a7f2..91bb5ba3e 100644 --- a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 +++ b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 @@ -1,5 +1,5 @@ Set-StrictMode -Version Latest - +Import-module .\Downloads\vsteam-master\bin\VSTeam.psd1 InModuleScope VSTeam { # Set the account to use for testing. A normal user would do this @@ -17,7 +17,87 @@ $securityNamespace = "writePermission": 8192, "readPermission": 2, "dataspaceCategory": "Git", - "actions": " ", + "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", + }, + { + "DisplayName": "Bypass policies when completing pull requests", + "Name": "PullRequestBypassPolicy", + "Bit": 32768 + } + ], "structureValue": 1, "extensionType": "Microsoft.TeamFoundation.Git.Server.Plugins.GitSecurityNamespaceExtension", "isRemotable": true, @@ -74,7 +154,7 @@ $securityNamespace = Mock Invoke-RestMethod { return $true } Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" | ` - Remove-VSTeamAccessControlEntry -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0xODc2Mzk2MjA0LTIwNjc1NTI1ODctMzA2NDY5MTU3My0yNjkxODIxNjgzLTEtMjM0NjY4Mzk3Mi0yNDI0MDE0NjYzLTI5MzAxOTk4OTktMTU1MjUwNTM3MQ" -Token xyz + Remove-VSTeamAccessControlEntry -SecurityNamespace $_ -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0xODc2Mzk2MjA0LTIwNjc1NTI1ODctMzA2NDY5MTU3My0yNjkxODIxNjgzLTEtMjM0NjY4Mzk3Mi0yNDI0MDE0NjYzLTI5MzAxOTk4OTktMTU1MjUwNTM3MQ" -Token xyz It 'Should have a properly constructed URL' { Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { From 538031de947288ddfb134b4860f118d5a38cb711 Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 15:24:39 -0800 Subject: [PATCH 13/35] Updated Remove-VSTeamAccessControlEntry.Tests.ps1 Removed bad import-module call. --- unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 index 91bb5ba3e..7fdae21f8 100644 --- a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 +++ b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 @@ -1,5 +1,5 @@ Set-StrictMode -Version Latest -Import-module .\Downloads\vsteam-master\bin\VSTeam.psd1 + InModuleScope VSTeam { # Set the account to use for testing. A normal user would do this From 20cc663cee19917fd74cd9176c056ea1493350d3 Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 15:33:20 -0800 Subject: [PATCH 14/35] Updated Remove-VSTeamAccessControlEntry.Tests.ps1 Added missing bit value for Contribute to pull requests --- unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 index 7fdae21f8..229a45522 100644 --- a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 +++ b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 @@ -91,6 +91,7 @@ $securityNamespace = { "DisplayName": "Contribute to pull requests", "Name": "PullRequestContribute", + "Bit":"16384" }, { "DisplayName": "Bypass policies when completing pull requests", From b71406955b64eaeee70506d356449a06ad4e35ed Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 15:49:26 -0800 Subject: [PATCH 15/35] Updated Remove-VSTeamAccessControlEntry.Tests.ps1 Fixed bad Descriptor in unit test code --- unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 index 229a45522..76bd1d1c4 100644 --- a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 +++ b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 @@ -115,7 +115,7 @@ $securityNamespace = Context 'Remove-VSTeamAccessControlEntry by SecurityNamespaceId' { Mock Invoke-RestMethod { return $true } - Remove-VSTeamAccessControlEntry -SecurityNamespaceId 2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87 -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0xODc2Mzk2MjA0LTIwNjc1NTI1ODctMzA2NDY5MTU3My0yNjkxODIxNjgzLTEtMjM0NjY4Mzk3Mi0yNDI0MDE0NjYzLTI5MzAxOTk4OTktMTU1MjUwNTM3MQ" -Token xyz + Remove-VSTeamAccessControlEntry -SecurityNamespaceId 2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87 -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz It 'Should have a properly constructed URL' { Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { @@ -135,7 +135,7 @@ $securityNamespace = Mock Invoke-RestMethod { return $true } $securityNamespace = Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" - Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0xODc2Mzk2MjA0LTIwNjc1NTI1ODctMzA2NDY5MTU3My0yNjkxODIxNjgzLTEtMjM0NjY4Mzk3Mi0yNDI0MDE0NjYzLTI5MzAxOTk4OTktMTU1MjUwNTM3MQ" -Token xyz + Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz It 'Should have a properly constructed URL' { Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { @@ -155,7 +155,7 @@ $securityNamespace = Mock Invoke-RestMethod { return $true } Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" | ` - Remove-VSTeamAccessControlEntry -SecurityNamespace $_ -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0xODc2Mzk2MjA0LTIwNjc1NTI1ODctMzA2NDY5MTU3My0yNjkxODIxNjgzLTEtMjM0NjY4Mzk3Mi0yNDI0MDE0NjYzLTI5MzAxOTk4OTktMTU1MjUwNTM3MQ" -Token xyz + Remove-VSTeamAccessControlEntry -SecurityNamespace $_ -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz It 'Should have a properly constructed URL' { Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { From 8f7bcfa4c45b42e91301ed8ffa093826614be5cc Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 16:07:02 -0800 Subject: [PATCH 16/35] Updated Remove-VSTeamAccessControlEntry.Tests.ps1 Fixed mock call for invoke-restmethod and fixed the filter it checks for on the call --- .../Remove-VSTeamAccessControlEntry.Tests.ps1 | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 index 76bd1d1c4..db06c7057 100644 --- a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 +++ b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 @@ -113,7 +113,7 @@ $securityNamespace = [VSTeamVersions]::Core = '5.1' Context 'Remove-VSTeamAccessControlEntry by SecurityNamespaceId' { - Mock Invoke-RestMethod { return $true } + Mock Invoke-RestMethod { return $true } -Verifiable Remove-VSTeamAccessControlEntry -SecurityNamespaceId 2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87 -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz @@ -121,9 +121,8 @@ $securityNamespace = Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { $Uri -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and $Uri -like "*api-version=$([VSTeamVersions]::Core)*" -and - $Uri -like "*Microsoft.TeamFoundation.Identity;S-1*" -and $Uri -like "*?token=xyz*" -and - $Uri -like "*&descriptors=abc*" -and + $Uri -like "*&descriptors=Microsoft.TeamFoundation.Identity;S-1*" -and $ContentType -eq "application/json" -and $Method -eq "Delete" } @@ -132,40 +131,38 @@ $securityNamespace = Context 'Remove-VSTeamAccessControlEntry by SecurityNamespace' { Mock Get-VSTeamSecurityNamespace { return $securityNamespace } - Mock Invoke-RestMethod { return $true } + Mock Invoke-RestMethod { return $true } -Verifiable $securityNamespace = Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz It 'Should have a properly constructed URL' { Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { - $Uri -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and - $Uri -like "*api-version=$([VSTeamVersions]::Core)*" -and - $Uri -like "*Microsoft.TeamFoundation.Identity;S-1*" -and - $Uri -like "*?token=xyz*" -and - $Uri -like "*&descriptors=abc*" -and - $ContentType -eq "application/json" -and - $Method -eq "Delete" + $Uri -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and + $Uri -like "*api-version=$([VSTeamVersions]::Core)*" -and + $Uri -like "*?token=xyz*" -and + $Uri -like "*&descriptors=Microsoft.TeamFoundation.Identity;S-1*" -and + $ContentType -eq "application/json" -and + $Method -eq "Delete" } } } Context 'Remove-VSTeamAccessControlEntry by SecurityNamespace (pipeline)' { Mock Get-VSTeamSecurityNamespace { return $securityNamespace } - Mock Invoke-RestMethod { return $true } + Mock Invoke-RestMethod { return $true } -Verifiable Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" | ` Remove-VSTeamAccessControlEntry -SecurityNamespace $_ -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz It 'Should have a properly constructed URL' { Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { - $Uri -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and - $Uri -like "*api-version=$([VSTeamVersions]::Core)*" -and - $Uri -like "*Microsoft.TeamFoundation.Identity;S-1*" -and - $Uri -like "*?token=xyz*" -and - $Uri -like "*&descriptors=abc*" -and - $ContentType -eq "application/json" -and - $Method -eq "Delete" + $Uri -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and + $Uri -like "*api-version=$([VSTeamVersions]::Core)*" -and + $Uri -like "*?token=xyz*" -and + $Uri -like "*&descriptors=Microsoft.TeamFoundation.Identity;S-1*" -and + $ContentType -eq "application/json" -and + $Method -eq "Delete" } } } From f098a768226e844215a2e161bdfdc01be881471b Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 16:17:59 -0800 Subject: [PATCH 17/35] Updated Remove-VSTeamAccessControlEntry.Tests.ps1 Restructured unit test and removed pipeline unit test --- .../Remove-VSTeamAccessControlEntry.Tests.ps1 | 41 +++++-------------- 1 file changed, 11 insertions(+), 30 deletions(-) diff --git a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 index db06c7057..1f9bef15f 100644 --- a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 +++ b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 @@ -113,12 +113,12 @@ $securityNamespace = [VSTeamVersions]::Core = '5.1' Context 'Remove-VSTeamAccessControlEntry by SecurityNamespaceId' { - Mock Invoke-RestMethod { return $true } -Verifiable - - Remove-VSTeamAccessControlEntry -SecurityNamespaceId 2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87 -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz - It 'Should have a properly constructed URL' { - Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + Mock Invoke-RestMethod { return $true } -Verifiable + + Remove-VSTeamAccessControlEntry -SecurityNamespaceId 2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87 -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz + + Assert-MockCalled Invoke-RestMethod -Exactly -Scope It -Times 1 -ParameterFilter { $Uri -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and $Uri -like "*api-version=$([VSTeamVersions]::Core)*" -and $Uri -like "*?token=xyz*" -and @@ -130,33 +130,14 @@ $securityNamespace = } Context 'Remove-VSTeamAccessControlEntry by SecurityNamespace' { - Mock Get-VSTeamSecurityNamespace { return $securityNamespace } - Mock Invoke-RestMethod { return $true } -Verifiable - - $securityNamespace = Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" - Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz - It 'Should have a properly constructed URL' { - Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { - $Uri -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and - $Uri -like "*api-version=$([VSTeamVersions]::Core)*" -and - $Uri -like "*?token=xyz*" -and - $Uri -like "*&descriptors=Microsoft.TeamFoundation.Identity;S-1*" -and - $ContentType -eq "application/json" -and - $Method -eq "Delete" - } - } - } - - Context 'Remove-VSTeamAccessControlEntry by SecurityNamespace (pipeline)' { - Mock Get-VSTeamSecurityNamespace { return $securityNamespace } - Mock Invoke-RestMethod { return $true } -Verifiable + Mock Get-VSTeamSecurityNamespace { return $securityNamespace } + Mock Invoke-RestMethod { return $true } -Verifiable + + $securityNamespace = Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" + Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz - Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" | ` - Remove-VSTeamAccessControlEntry -SecurityNamespace $_ -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz - - It 'Should have a properly constructed URL' { - Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + Assert-MockCalled Invoke-RestMethod -Exactly -Scope It -Times 1 -ParameterFilter { $Uri -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and $Uri -like "*api-version=$([VSTeamVersions]::Core)*" -and $Uri -like "*?token=xyz*" -and From 088ebfa559591e16a069c93a5579b1553d7a994d Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 16:25:37 -0800 Subject: [PATCH 18/35] Updated Remove-VSTeamAccessControlEntry.Tests.ps1 Further changes to unit test --- .../Remove-VSTeamAccessControlEntry.Tests.ps1 | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 index 1f9bef15f..8babd0fbe 100644 --- a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 +++ b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 @@ -114,15 +114,15 @@ $securityNamespace = Context 'Remove-VSTeamAccessControlEntry by SecurityNamespaceId' { It 'Should have a properly constructed URL' { - Mock Invoke-RestMethod { return $true } -Verifiable + Mock _callAPI { return $true } -Verifiable Remove-VSTeamAccessControlEntry -SecurityNamespaceId 2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87 -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz - Assert-MockCalled Invoke-RestMethod -Exactly -Scope It -Times 1 -ParameterFilter { - $Uri -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and - $Uri -like "*api-version=$([VSTeamVersions]::Core)*" -and - $Uri -like "*?token=xyz*" -and - $Uri -like "*&descriptors=Microsoft.TeamFoundation.Identity;S-1*" -and + Assert-MockCalled _callAPI -Exactly -Scope It -Times 1 -ParameterFilter { + $Url -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and + $Url -like "*api-version=$([VSTeamVersions]::Core)*" -and + $Url -like "*?token=xyz*" -and + $Url -like "*&descriptors=Microsoft.TeamFoundation.Identity;S-1*" -and $ContentType -eq "application/json" -and $Method -eq "Delete" } @@ -132,16 +132,16 @@ $securityNamespace = Context 'Remove-VSTeamAccessControlEntry by SecurityNamespace' { It 'Should have a properly constructed URL' { Mock Get-VSTeamSecurityNamespace { return $securityNamespace } - Mock Invoke-RestMethod { return $true } -Verifiable + Mock _callAPI { return $true } -Verifiable $securityNamespace = Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz - Assert-MockCalled Invoke-RestMethod -Exactly -Scope It -Times 1 -ParameterFilter { - $Uri -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and - $Uri -like "*api-version=$([VSTeamVersions]::Core)*" -and - $Uri -like "*?token=xyz*" -and - $Uri -like "*&descriptors=Microsoft.TeamFoundation.Identity;S-1*" -and + Assert-MockCalled _callAPI -Exactly -Scope It -Times 1 -ParameterFilter { + $Url -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and + $Url -like "*api-version=$([VSTeamVersions]::Core)*" -and + $Url -like "*?token=xyz*" -and + $Url -like "*&descriptors=Microsoft.TeamFoundation.Identity;S-1*" -and $ContentType -eq "application/json" -and $Method -eq "Delete" } From 4b244ea4959cdf4fddd58e0605d33b005492698f Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 16:42:38 -0800 Subject: [PATCH 19/35] Updated Remove-VSTeamAccessControlEntry.Tests.ps1 More changes to unit test --- .../Remove-VSTeamAccessControlEntry.Tests.ps1 | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 index 8babd0fbe..6e5b3dd21 100644 --- a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 +++ b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 @@ -114,15 +114,15 @@ $securityNamespace = Context 'Remove-VSTeamAccessControlEntry by SecurityNamespaceId' { It 'Should have a properly constructed URL' { - Mock _callAPI { return $true } -Verifiable + Mock Invoke-RestMethod { return $true } -Verifiable Remove-VSTeamAccessControlEntry -SecurityNamespaceId 2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87 -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz - Assert-MockCalled _callAPI -Exactly -Scope It -Times 1 -ParameterFilter { - $Url -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and - $Url -like "*api-version=$([VSTeamVersions]::Core)*" -and - $Url -like "*?token=xyz*" -and - $Url -like "*&descriptors=Microsoft.TeamFoundation.Identity;S-1*" -and + Assert-MockCalled Invoke-RestMethod -ParameterFilter { + $Uri -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and + $Uri -like "*api-version=$([VSTeamVersions]::Core)*" -and + $Uri -like "*?token=xyz*" -and + $Uri -like "*&descriptors=Microsoft.TeamFoundation.Identity;S-1*" -and $ContentType -eq "application/json" -and $Method -eq "Delete" } @@ -132,16 +132,16 @@ $securityNamespace = Context 'Remove-VSTeamAccessControlEntry by SecurityNamespace' { It 'Should have a properly constructed URL' { Mock Get-VSTeamSecurityNamespace { return $securityNamespace } - Mock _callAPI { return $true } -Verifiable + Mock Invoke-RestMethod { return $true } -Verifiable $securityNamespace = Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz - Assert-MockCalled _callAPI -Exactly -Scope It -Times 1 -ParameterFilter { - $Url -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and - $Url -like "*api-version=$([VSTeamVersions]::Core)*" -and - $Url -like "*?token=xyz*" -and - $Url -like "*&descriptors=Microsoft.TeamFoundation.Identity;S-1*" -and + Assert-MockCalled Invoke-RestMethod -ParameterFilter { + $Uri -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and + $Uri -like "*api-version=$([VSTeamVersions]::Core)*" -and + $Uri -like "*?token=xyz*" -and + $Uri -like "*&descriptors=Microsoft.TeamFoundation.Identity;S-1*" -and $ContentType -eq "application/json" -and $Method -eq "Delete" } From 1667f121f061b1aef00418a933c3ee2b447e2589 Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 20:40:20 -0800 Subject: [PATCH 20/35] Updated Remove-VSTeamAccessControlEntry.ps1 Added error handling for improperly formatted descriptor, added return of REST API call. This API returns only $True or $False. --- .../Remove-VSTeamAccessControlEntry.ps1 | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/Source/Public/Remove-VSTeamAccessControlEntry.ps1 b/Source/Public/Remove-VSTeamAccessControlEntry.ps1 index 87fd3a124..3e2f37094 100644 --- a/Source/Public/Remove-VSTeamAccessControlEntry.ps1 +++ b/Source/Public/Remove-VSTeamAccessControlEntry.ps1 @@ -37,7 +37,13 @@ function Remove-VSTeamAccessControlEntry { foreach($UniqueDescriptor in $Descriptor.Split(",")) { $UniqueDescriptor = ($UniqueDescriptor).split(".")[1] - $UniqueDescriptor = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($UniqueDescriptor)) + try{ + $UniqueDescriptor = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($UniqueDescriptor)) + } + catch + { + Throw "Could not convert base64 string to string." + } $UniqueDescriptor = "Microsoft.TeamFoundation.Identity;"+"$UniqueDescriptor" $Descriptors += $UniqueDescriptor @@ -48,7 +54,15 @@ function Remove-VSTeamAccessControlEntry { else { $Descriptor = ($descriptor).split(".")[1] - $Descriptor = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Descriptor)) + try + { + $Descriptor = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Descriptor)) + } + catch + { + Return "Could not convert base64 string to string." + } + $Descriptor = "Microsoft.TeamFoundation.Identity;"+"$descriptor" [Uri]$Uri = "$($env:TEAM_ACCT)/_apis/accesscontrolentries/$($securityNamespaceId)?token=$($token)&descriptors=$($descriptor)&api-version=5.1" @@ -56,5 +70,7 @@ function Remove-VSTeamAccessControlEntry { # Call the REST API $resp = _callAPI -method DELETE -Url $Uri -ContentType "application/json" + + return $resp } - } \ No newline at end of file + } From d7268975e769aeb2737cc031a9f3548038672e24 Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Thu, 28 Nov 2019 20:41:11 -0800 Subject: [PATCH 21/35] Updated Remove-VSTeamAccessControlEntry.Tests.ps1 Refactored unit tests completely. --- .../Remove-VSTeamAccessControlEntry.Tests.ps1 | 59 ++++++++----------- 1 file changed, 23 insertions(+), 36 deletions(-) diff --git a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 index 6e5b3dd21..53466ba0b 100644 --- a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 +++ b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 @@ -107,45 +107,32 @@ $securityNamespace = } "@ | 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' + Describe 'AccessControlEntry VSTS'{ + # You have to set the version or the api-version will not be Removed when + # [VSTeamVersions]::Core = '' + [VSTeamVersions]::Core = '5.1' - Context 'Remove-VSTeamAccessControlEntry by SecurityNamespaceId' { - It 'Should have a properly constructed URL' { - Mock Invoke-RestMethod { return $true } -Verifiable + Mock Invoke-RestMethod { return $true } -Verifiable + Mock Get-VSTeamSecurityNamespace { return $securityNamespace } - Remove-VSTeamAccessControlEntry -SecurityNamespaceId 2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87 -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz - - Assert-MockCalled Invoke-RestMethod -ParameterFilter { - $Uri -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and - $Uri -like "*api-version=$([VSTeamVersions]::Core)*" -and - $Uri -like "*?token=xyz*" -and - $Uri -like "*&descriptors=Microsoft.TeamFoundation.Identity;S-1*" -and - $ContentType -eq "application/json" -and - $Method -eq "Delete" + Context 'Remove-VSTeamAccessControlEntry by SecurityNamespaceId'{ + It 'Should succeed with a properly formatted descriptor'{ + Remove-VSTeamAccessControlEntry -SecurityNamespaceId 2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87 -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz | Should be $true } - } - } - - Context 'Remove-VSTeamAccessControlEntry by SecurityNamespace' { - It 'Should have a properly constructed URL' { - Mock Get-VSTeamSecurityNamespace { return $securityNamespace } - Mock Invoke-RestMethod { return $true } -Verifiable - - $securityNamespace = Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" - Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz + It 'Should fail with an improperly formatted descriptor'{ + Remove-VSTeamAccessControlEntry -SecurityNamespaceId 2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87 -Descriptor "vssgp.NotARealDescriptor" -Token xyz | Should belike "Could not convert base64 string to string*" + } + } - Assert-MockCalled Invoke-RestMethod -ParameterFilter { - $Uri -like "https://dev.azure.com/test/_apis/accesscontrolentries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87*" -and - $Uri -like "*api-version=$([VSTeamVersions]::Core)*" -and - $Uri -like "*?token=xyz*" -and - $Uri -like "*&descriptors=Microsoft.TeamFoundation.Identity;S-1*" -and - $ContentType -eq "application/json" -and - $Method -eq "Delete" + Context 'Remove-VSTeamAccessControlEntry by SecurityNamespace'{ + It 'Should succeed with a properly formatted descriptor'{ + $securityNamespace = Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" + Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz | Should be $true } - } - } - } + It 'Should succeed with a properly formatted descriptor'{ + $securityNamespace = Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" + Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor "vssgp.NotARealDescriptor" -Token xyz | Should belike "Could not convert base64 string to string*" + } + } + } } \ No newline at end of file From 9ee8456643988bc0d5fd1cca0261e1632d6fc44a Mon Sep 17 00:00:00 2001 From: Steven Cady Date: Sun, 1 Dec 2019 14:07:45 -0800 Subject: [PATCH 22/35] Added proper pull request number to change log. Removed hand built URIs and hard coded version numbers in Remove-VSTeamAccessControlEntry.ps1. Changed -securityNamespaceId parameter on Remove-VSTeamAccessControlEntry.ps1 from STRING to GUID. Added ShouldProcess and OutputType to Remove-VSTeamAccessControlEntry. Added examples to help file for Remove-VSTeamAccessControlEntry.ps1. Refactored unit tests to account for all exit points of function Remove-VSTeamAccessControlEntry. --- CHANGELOG.md | 2 +- .../Remove-VSTeamAccessControlEntry.ps1 | 117 ++++++++++-------- .../Remove-VSTeamAccessControlEntry.Tests.ps1 | 48 +++++-- 3 files changed, 106 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7908f3eb9..a4ccc41b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 6.4.2 -Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/221) from [Steven Cady](https://github.com/cadacious) which included the following: +Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/224) from [Steven Cady](https://github.com/cadacious) which included the following: Added Remove-VSTeamAccessControlEntry to delete users/groups from Access Control Lists within security namespaces. Supports removing single or multiple entries. Only supports removing vsts origin users/groups. diff --git a/Source/Public/Remove-VSTeamAccessControlEntry.ps1 b/Source/Public/Remove-VSTeamAccessControlEntry.ps1 index 3e2f37094..134b64d2d 100644 --- a/Source/Public/Remove-VSTeamAccessControlEntry.ps1 +++ b/Source/Public/Remove-VSTeamAccessControlEntry.ps1 @@ -1,76 +1,89 @@ function Remove-VSTeamAccessControlEntry { - [CmdletBinding(DefaultParameterSetName = 'ByNamespace')] + [CmdletBinding(DefaultParameterSetName = 'byNamespace', SupportsShouldProcess=$true, ConfirmImpact = 'High')] + [OutputType([System.String])] param( - [Parameter(ParameterSetName = 'ByNamespace', Mandatory = $true, ValueFromPipeline = $true)] - [VSTeamSecurityNamespace] $SecurityNamespace, + [Parameter(ParameterSetName = 'byNamespace', Mandatory = $true, ValueFromPipeline = $true)] + [VSTeamSecurityNamespace] $securityNamespace, - [Parameter(ParameterSetName = 'ByNamespaceId', Mandatory = $true)] - [ValidateScript({ - try { - [System.Guid]::Parse($_) | Out-Null - $true - } catch { - $false - } - })] - [string] $SecurityNamespaceId, + [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)] + [string] $token, - [Parameter(ParameterSetName = 'ByNamespace', Mandatory = $true)] - [Parameter(ParameterSetName = 'ByNamespaceId', Mandatory = $true)] - [string] $Descriptor + [Parameter(ParameterSetName = 'byNamespace', Mandatory = $true)] + [Parameter(ParameterSetName = 'byNamespaceId', Mandatory = $true)] + [System.Array] $descriptor ) process { - if ($SecurityNamespace) - { - $SecurityNamespaceId = $SecurityNamespace.ID + if($securityNamespace) { + $securityNamespaceId = ($securityNamespace | Select-Object -ExpandProperty id -ErrorAction SilentlyContinue) } - if ($Descriptor -like "*,*") - { - $Descriptors = @() + if(($descriptor).count -gt 1) { + $descriptor = @() - foreach($UniqueDescriptor in $Descriptor.Split(",")) - { - $UniqueDescriptor = ($UniqueDescriptor).split(".")[1] - try{ - $UniqueDescriptor = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($UniqueDescriptor)) + foreach($uniqueDescriptor in $descriptor) { + $uniqueDescriptor = ($uniqueDescriptor).split(".")[1] + try { + + $uniqueDescriptor = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("Uy0xLTktMTU1MTM3NDI0NS0xMzk4ODc2NjMwLTEwMTQ0ODQ4MTMtMzE5MDA4NTI4Ny0xNDU4NTkwODY1LTEtMzE1MjE3NTkwMy03NjE1NjY3OTMtMjgwMTUwMjI2Ny0zMjU5Mjg5MTIy")) } - catch - { - Throw "Could not convert base64 string to string." + catch [FormatException]{ + Write-Error "Could not convert base64 string to string." + continue } - $UniqueDescriptor = "Microsoft.TeamFoundation.Identity;"+"$UniqueDescriptor" + $uniqueDescriptor = "Microsoft.TeamFoundation.Identity;"+"$uniqueDescriptor" - $Descriptors += $UniqueDescriptor + $descriptor += $uniqueDescriptor } - - [Uri]$Uri = "$($env:TEAM_ACCT)/_apis/accesscontrolentries/$($securityNamespaceId)?token=$($token)&descriptors=$($descriptors -join ",")&api-version=5.1" - } - else - { - $Descriptor = ($descriptor).split(".")[1] - try - { - $Descriptor = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Descriptor)) + + if(($descriptor).count -eq 0) { + Write-Error "No valid descriptors provided." + return } - catch + else { - Return "Could not convert base64 string to string." + $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" - - [Uri]$Uri = "$($env:TEAM_ACCT)/_apis/accesscontrolentries/$($securityNamespaceId)?token=$($token)&descriptors=$($descriptor)&api-version=5.1" + $descriptor = "Microsoft.TeamFoundation.Identity;"+"$descriptor" } - + + if($PSCmdlet.ShouldProcess("$token")) { # Call the REST API - $resp = _callAPI -method DELETE -Url $Uri -ContentType "application/json" + $resp = _callAPI -method DELETE -Area "accesscontrolentries" -id $securityNamespaceId -ContentType "application/json" -Version $([VSTeamVersions]::Core) -QueryString @{token = $token; descriptors = $descriptor} -ErrorAction SilentlyContinue + } - return $resp + 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/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 index 53466ba0b..569636813 100644 --- a/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 +++ b/unit/test/Remove-VSTeamAccessControlEntry.Tests.ps1 @@ -112,26 +112,58 @@ $securityNamespace = # [VSTeamVersions]::Core = '' [VSTeamVersions]::Core = '5.1' - Mock Invoke-RestMethod { return $true } -Verifiable + Mock Get-VSTeamSecurityNamespace { return $securityNamespace } Context 'Remove-VSTeamAccessControlEntry by SecurityNamespaceId'{ - It 'Should succeed with a properly formatted descriptor'{ - Remove-VSTeamAccessControlEntry -SecurityNamespaceId 2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87 -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz | Should be $true + 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 | Should belike "Could not convert base64 string to string*" + 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'{ + It 'Should succeed with a properly formatted descriptor if descriptor is on ACL'{ $securityNamespace = Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" - Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yMTkxNDc4NTk1LTU1MDM1MzIxOC0yNDM3MjM2NDgzLTQyMjkyNzUyNDktMC0wLTAtOC04" -Token xyz | Should be $true + 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 succeed with a properly formatted descriptor'{ + It 'Should fail with a properly formatted descriptor if descriptor is not on ACL already'{ $securityNamespace = Get-VSTeamSecurityNamespace -Id "2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87" - Remove-VSTeamAccessControlEntry -SecurityNamespace $securityNamespace -Descriptor "vssgp.NotARealDescriptor" -Token xyz | Should belike "Could not convert base64 string to string*" + 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." } } } From 662cf99320b308b239f0fb9cc131e2bcc71bd9c5 Mon Sep 17 00:00:00 2001 From: Steven Cady Date: Sun, 1 Dec 2019 14:18:34 -0800 Subject: [PATCH 23/35] Updating Remove-VSTeamAccessControlEntry.md --- docs/Remove-VSTeamAccessControlEntry.md | 66 ++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/docs/Remove-VSTeamAccessControlEntry.md b/docs/Remove-VSTeamAccessControlEntry.md index ead67edbc..747c44b44 100644 --- a/docs/Remove-VSTeamAccessControlEntry.md +++ b/docs/Remove-VSTeamAccessControlEntry.md @@ -13,7 +13,54 @@ Removes specified ACEs in the ACL for the provided token. The request URI contai 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 +## 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 @@ -123,10 +170,25 @@ 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 @@ -135,7 +197,7 @@ Required: True ## NOTES -### This function outputs a warning 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. +### 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 From f6754a06fff2761405578028410fdb49dc0c82c2 Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Mon, 30 Dec 2019 12:21:42 -0800 Subject: [PATCH 24/35] Update Remove-VSTeamAccessControlEntry.ps1 Removed descriptor from script and replaced it with proper variable. --- Source/Public/Remove-VSTeamAccessControlEntry.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Public/Remove-VSTeamAccessControlEntry.ps1 b/Source/Public/Remove-VSTeamAccessControlEntry.ps1 index 134b64d2d..f24daaf33 100644 --- a/Source/Public/Remove-VSTeamAccessControlEntry.ps1 +++ b/Source/Public/Remove-VSTeamAccessControlEntry.ps1 @@ -29,7 +29,7 @@ function Remove-VSTeamAccessControlEntry { $uniqueDescriptor = ($uniqueDescriptor).split(".")[1] try { - $uniqueDescriptor = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("Uy0xLTktMTU1MTM3NDI0NS0xMzk4ODc2NjMwLTEwMTQ0ODQ4MTMtMzE5MDA4NTI4Ny0xNDU4NTkwODY1LTEtMzE1MjE3NTkwMy03NjE1NjY3OTMtMjgwMTUwMjI2Ny0zMjU5Mjg5MTIy")) + $uniqueDescriptor = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("$uniqueDescriptor")) } catch [FormatException]{ Write-Error "Could not convert base64 string to string." From b6fc7160423cf5e1da6ab25bcbce2e7a5b2a401f Mon Sep 17 00:00:00 2001 From: Cadacious <32421665+Cadacious@users.noreply.github.com> Date: Mon, 30 Dec 2019 12:25:25 -0800 Subject: [PATCH 25/35] Update CHANGELOG.md --- CHANGELOG.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4ccc41b1..b8fa7d6ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,25 @@ # Changelog - -## 6.4.2 +## 6.4.3 Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/224) from [Steven Cady](https://github.com/cadacious) which included the following: Added Remove-VSTeamAccessControlEntry to delete users/groups from Access Control Lists within security namespaces. Supports removing single or multiple entries. Only supports removing vsts origin users/groups. +## 6.4.2 + +Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/226) from [Asif Mithawala](https://github.com/asifma) which included the following: + +Added property checks in VSTeamJobRequest + +Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/227) from [Sebastian Schütze](https://github.com/SebastianSchuetze) which included the following: + +Added Remove-VSTeamWorkItem to delete work items + +- Added a parameter to filter unit tests +- Added documentation on parameters of Build-Module.ps1 in code and for README.MD +- Removed references to update the .PSD1 file in the PR template as well as in the contribution doc, since it does not seem to be needed anymore, because it is generated automatically. +- Added coverage.xml to the .gitignore file + ## 6.4.1 Fixed issue [Description on variable groups is not a required field #208](https://github.com/DarqueWarrior/vsteam/issues/208). From a514e0659a2b52fbdd7e3293a73fff4c7f2f58f1 Mon Sep 17 00:00:00 2001 From: Mark Wragg Date: Thu, 23 Jan 2020 12:29:33 +0000 Subject: [PATCH 26/35] For for #148 This fixes a bug 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. This PR filters out this result by excluding any build artifact records returned by the API that don't contain a "properties" object. Alternatively if we think its desirable to include this artifact in the result, we could just wrap an `if` statement around the line of code that attempts to add a typename to the `properties` property, so that it doesn't attempt to do this on the one artifact where it doesn't exist. --- Source/Private/applyTypes.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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') } From 22b653740eb38e160c830c557cf8186e1c91cfa0 Mon Sep 17 00:00:00 2001 From: Michel Zehnder Date: Mon, 24 Feb 2020 11:20:31 +0100 Subject: [PATCH 27/35] Rearrange readme for better visibility of key items --- README.md | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) 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). From 976ec814a5ee552992f1feecea9ee41e0abffb41 Mon Sep 17 00:00:00 2001 From: Michel Zehnder Date: Mon, 24 Feb 2020 15:00:52 +0100 Subject: [PATCH 28/35] Get rid of .DS_Store --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 88d30e8d9..eb1ac3f4f 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ Source/Classes/vsteam.classes.ps1 /dist test-results.xml coverage.xml +.DS_Store From f53df8d1da1b532ad428600dcd2d3ad6f09db904 Mon Sep 17 00:00:00 2001 From: Michel Zehnder Date: Mon, 24 Feb 2020 15:02:37 +0100 Subject: [PATCH 29/35] Delete .DS_Store --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index b7c6b4d15d3c749607e3ada5a49db2b479db9013..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK-EPw`6h7_`Z77I>kjiClkhtikcAJDIG^ungQY9FOlyL#5OPbP!Wl7bfRHGF2 zhIbf`fOrw^xa2{20Ql@!kff``%@80T$^QIv&T;(t*p7*aH79nRs7ypfB#ya@$j%Vn z&(o4*WXlyG6Fz$MknT~Bc7aM11B!vaodLdguZjKIqBeH!ul>76Eqa2UF0Ios*&WyK zTdr?GpC1-?kZye!f)Wl7vdO1D1u4CcDZM-m$fGrQHjXXkc{6)Ee|L(RK^V?qA$(oq z@&T0<9KANip6h!(B#)L+E-LKLJZ1?F1`4H@{kt^ch2vPHj zg5@>Hd`Wq@l=85`F1wSm)95k2@h+nD0q~3%&3;N*Wbr*?>L+I;BKb5H$$7-i3BGBN zjydA79M{az1Tp7OnDi(jIj&cteK6UDM-$P!4&MQGOFd=9BRXz{>N$&ym160f$5HMT z1B!uvj{$x@=tvwJ5*HDQqXU_E0swPp7J@SWJ>WLF#D>I0gy?~=$P^fvGWo<{kvZCR zsn?LWh%hoICLbS6j?Cl>g^AJOUl;1c8WE~oF`yVoGLVg`Wq$v+SHJ(0MyjS5Pz?N6 z46t0wXf-h`qau_*AX_y&>?^y$0+Y)D*0h!%+Y5fC(} KOfm3B8TbL=Q2%}a From 16c8de0191218027afa20c8c5c1605839a7f8de4 Mon Sep 17 00:00:00 2001 From: Michel Zehnder Date: Mon, 24 Feb 2020 15:06:16 +0100 Subject: [PATCH 30/35] Add .DS_Store variants to ignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index eb1ac3f4f..5f122f278 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,6 @@ Source/Classes/vsteam.classes.ps1 test-results.xml coverage.xml .DS_Store +._.DS_Store +**/.DS_Store +**/._.DS_Store From 4853bd492cb8851b027caec32971379df48ce96a Mon Sep 17 00:00:00 2001 From: Michel Zehnder Date: Mon, 24 Feb 2020 15:16:16 +0100 Subject: [PATCH 31/35] Improve Doc build to always go back to root directory even on errors --- Build-Module.ps1 | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Build-Module.ps1 b/Build-Module.ps1 index 0f84c1c3d..997399ec5 100644 --- a/Build-Module.ps1 +++ b/Build-Module.ps1 @@ -58,8 +58,11 @@ if ($buildHelp.IsPresent) { Write-Output 'Creating help files' Push-Location Set-Location ./.docs - ./gen-help.ps1 - Pop-Location + Try { + ./gen-help.ps1 + } Finally { + Pop-Location + } } Write-Output 'Publishing about help files' From 959e9ca3f2aad87d49a60fff050ad39c2a0828d4 Mon Sep 17 00:00:00 2001 From: Michel Zehnder Date: Mon, 24 Feb 2020 21:37:19 +0100 Subject: [PATCH 32/35] Fix Get-VSTeamBuildArtifact without properties property --- CHANGELOG.md | 6 ++++++ Source/Private/applyTypes.ps1 | 2 +- Source/VSTeam.psd1 | 2 +- unit/test/builds.Tests.ps1 | 22 ++++++++++++++++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e88b6495..6574a92ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 6.4.5 + +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 + ## 6.4.4 Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/231) from [Dave Neeley](https://github.com/daveneeley) which included the following: 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/VSTeam.psd1 b/Source/VSTeam.psd1 index 539e9e0d6..e490197d9 100644 --- a/Source/VSTeam.psd1 +++ b/Source/VSTeam.psd1 @@ -12,7 +12,7 @@ RootModule = 'VSTeam.psm1' # Version number of this module. - ModuleVersion = '6.4.4' + ModuleVersion = '6.4.5' # Supported PSEditions # CompatiblePSEditions = @() 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' { From cfc10f37a186785152c492f2f4fe71e32821f427 Mon Sep 17 00:00:00 2001 From: Michel Zehnder Date: Mon, 24 Feb 2020 21:39:41 +0100 Subject: [PATCH 33/35] Mixed up branches --- Build-Module.ps1 | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Build-Module.ps1 b/Build-Module.ps1 index 997399ec5..0f84c1c3d 100644 --- a/Build-Module.ps1 +++ b/Build-Module.ps1 @@ -58,11 +58,8 @@ if ($buildHelp.IsPresent) { Write-Output 'Creating help files' Push-Location Set-Location ./.docs - Try { - ./gen-help.ps1 - } Finally { - Pop-Location - } + ./gen-help.ps1 + Pop-Location } Write-Output 'Publishing about help files' From a63e44401aef1213406a042a64ae76d9c5ff1a61 Mon Sep 17 00:00:00 2001 From: Donovan Brown Date: Mon, 24 Feb 2020 17:53:33 -0600 Subject: [PATCH 34/35] Updated change log after merge. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b76e31679..dba66c5e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ # Changelog + ## 6.4.3 Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/224) from [Steven Cady](https://github.com/cadacious) which included the following: From b0bce90ec8732be13c1235248850936a636babb5 Mon Sep 17 00:00:00 2001 From: Donovan Brown Date: Mon, 24 Feb 2020 18:21:18 -0600 Subject: [PATCH 35/35] Updated changelog --- CHANGELOG.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6574a92ef..60d2fc772 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,14 @@ # Changelog -## 6.4.5 +## 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 -## 6.4.4 +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: @@ -16,6 +18,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: