Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement continuationToken management (body and headers) on v8.0.0 branch #509

Draft
wants to merge 5 commits into
base: feature/v8.0.0
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
125 changes: 124 additions & 1 deletion .docs/Get-VSTeamUserEntitlement.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

<!-- #include "./synopsis/Get-VSTeamUserEntitlement.md" -->

Please note that Filter, Name, UserType and License parameters only works when MemberEntitlementManagement module version is 6.0 or upper
In the same way Top and Skip paramerers only works up to version 5.1

You can setup the specific version for the MemberEntitlementManagement calling Set-VSTeamAPIVersion -Service MemberEntitlementManagement -Version VersionNumberYouNeed.

## SYNTAX

## DESCRIPTION
Expand All @@ -14,6 +19,44 @@

## EXAMPLES

### Example 1: Get user by Id

```powershell
Get-VSTeamUserEntitlement -Id f1ef22eb-5dd6-4e26-907c-986a0311b106
```

This command gets the user entitlement of the user identified by id.

### Example 2: Get users by name

```powershell
Get-VSTeamUserEntitlement -Name username
```

This command gets a list of users which mail or user name contains 'username'.
Filtering by Name, License, or UserType is available only when MemberEntitlementManagement service version is 6.0 or upper. See Get-VSTeamAPIVersion and Set-VSTeamAPIVersion commands


### Example 3: Filter with some conditions

```powershell
Get-VSTeamUserEntitlement -Filter "licenseId eq 'Account-Express' and licenseStatus eq 'Disabled'"
```

This command gets a list of users that match the license status and license type conditions.
The -Filter parameter is available only when MemberEntitlementManagement service version is 6.0 or upper. See Get-VSTeamAPIVersion and Set-VSTeamAPIVersion commands


### Example 4: List paged users

```powershell
Get-VSTeamUserEntitlement -Skip 100 -Top 100
```

This command list the from the user in the 101 position, the next 100 users
Filtering using the -Top -Skip parameters only works when MemberEntitlementManagement service version is below 6.0. See Get-VSTeamAPIVersion and Set-VSTeamAPIVersion commands


## PARAMETERS

### Skip
Expand Down Expand Up @@ -53,11 +96,91 @@ Comma (",") separated list of properties to select in the result entitlements.

```yaml
Type: String
Parameter Sets: List
Parameter Sets: List,PagedFilter,PagedParams
Required: True
Default value: None
```

### MaxPages

User entlitement API returs a paged result. This parameter allows to limit the number of pages to be retrieved. Default is 0 = all pages.

```yaml
Type: int
Parameter Sets: PagedFilter,PagedParams
Required: False
Default value: $null
```

### Filter

Equality operators relating to searching user entitlements seperated by and clauses. Valid filters include: licenseId, licenseStatus, userType, and name.
- licenseId: filters based on license assignment using license names. i.e. licenseId eq 'Account-Stakeholder' or licenseId eq 'Account-Express'.
- licenseStatus: filters based on license status. currently only supports disabled. i.e. licenseStatus eq 'Disabled'. To get disabled basic licenses, you would pass (licenseId eq 'Account-Express' and licenseStatus eq 'Disabled')
- userType: filters off identity type. Suppored types are member or guest i.e. userType eq 'member'.
- name: filters on if the user's display name or email contians given input. i.e. get all users with "test" in email or displayname is "name eq 'test'".

A valid query could be: (licenseId eq 'Account-Stakeholder' or (licenseId eq 'Account-Express' and licenseStatus eq 'Disabled')) and name eq 'test' and userType eq 'guest'.

Currently, filter names and values must match exactly the case. i.e.:
* LicenseID will throw Invalid filter message.
* licenseId eq 'account-stakeholder' will return an empty list

```yaml
Type: string
Parameter Sets: PagedFilter
Required: False
Default value: None
```

### License

Filters based on license assignment using license names

The acceptable values for this parameter are:
- Account-Stakeholder: Stakeholder
- Account-Express: Basic
- Account-Advanced: Basic + Test Plans

Other licenses which source (licenseSource) is MSDN cannot be filtered here
Parameter values are case sensitive

```yaml
Type: string
Parameter Sets: PagedParams
Required: False
Default value: None
```

### UserType

Filters based on user type

The acceptable values for this parameter are:
- member
- guest

Parameter values are case sensitive

```yaml
Type: string
Parameter Sets: PagedParams
Required: False
Default value: None
```

### Name

Filters on if the user's display name or email contains given input

```yaml
Type: string
Parameter Sets: PagedParams
Required: False
Default value: None
```


## INPUTS

## OUTPUTS
Expand Down
2 changes: 1 addition & 1 deletion .docs/synopsis/Get-VSTeamUserEntitlement.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Get User Entitlement for a user.
Get User Entitlement for a user, or a paged list of users matching the specified filter
108 changes: 93 additions & 15 deletions Source/Private/common.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ function _callAPI {
[string]$Url,
[object]$QueryString,
[hashtable]$AdditionalHeaders = @{ },
# Name of the output variable that will content the response headers
# Specify the name of the variable without the $ prefix
[string]$ResponseHeadersVariable,
# Some API calls require the Project ID and not the project name.
# However, the dynamic project name parameter only shows you names
# and not the Project IDs. Using this flag the project name provided
Expand All @@ -41,7 +44,20 @@ function _callAPI {
# This flag makes sure that no specific account is used
# some APIs do not have an account in their API uri because
# they are not account specific in the url path itself. (e.g. user profile, pipeline billing)
[switch]$NoAccount
[switch]$NoAccount,
[ValidateSet('None', 'Header', 'Body')]
[string]$UseContinuationToken = 'None',
# Allows to specify a header or continuation token property different of the default values.
# If this parameter is not specified, the default value is X-MS-ContinuationToken or continuationToken
# depending if $UseHeader is present or not, respectively. Ignored if $UseContinuationToken -eq 'None'
[string]$ContinuationTokenName,
# Number of pages to be retrieved. If 0, or not specified, it will return all the available pages.
# Ignored if $UseContinuationToken -eq 'None'
[int]$MaxPages = 0,
# When using continuationToken, it is neccesary expand a specific property to get the real
# collection of objects. Ignored if $UseContinuationToken -eq 'None'
[string]$CollectionPropertyName

)

process {
Expand Down Expand Up @@ -77,6 +93,18 @@ function _callAPI {
# do not use header when requested. Then bearer must be provided with additional headers
$params.Add('Headers', @{ })

# configure continuationToken management
if ($UseContinuationToken -ne 'None' -and [string]::IsNullOrEmpty($ContinuationTokenName)) {
if ($UseContinuationToken -eq 'Body') {
$ContinuationTokenName = 'continuationToken'
} else {
$ContinuationTokenName = 'X-MS-ContinuationToken'
}
}
if ($UseContinuationToken -eq 'Header') {
$params.Add('ResponseHeadersVariable', 'ResponseHeaders')
}

# checking if an authorization token is provided already with the additional headers
# use case: sometimes other tokens for certain APIs have to be used (buying pipelines) in order to work
# some parts of internal APIs use their own token based on the PAT
Expand All @@ -99,28 +127,50 @@ function _callAPI {
}

# We have to remove any extra parameters not used by Invoke-RestMethod
$extra = 'NoAccount', 'NoProject', 'UseProjectId', 'Area', 'Resource', 'SubDomain', 'Id', 'Version', 'JSON', 'ProjectName', 'Team', 'Url', 'QueryString', 'AdditionalHeaders', 'CustomBearer'
$extra = 'NoAccount', 'NoProject', 'UseProjectId', 'Area', 'Resource', 'SubDomain', 'Id', 'Version', 'JSON', 'ProjectName',
'Team', 'Url', 'QueryString', 'AdditionalHeaders', 'CustomBearer', 'UseContinuationToken', 'ContinuationTokenName',
'MaxPages', 'CollectionPropertyName'

foreach ($e in $extra) { $params.Remove($e) | Out-Null }

try {
$resp = Invoke-RestMethod @params
$page = 0
$obj = @()
$requestUri = $params['Uri']
do {
try {
$resp = Invoke-RestMethod @params

if ($resp) {
Write-Verbose "return type: $($resp.gettype())"
Write-Verbose $resp
if ($resp) {
Write-Verbose "return type: $($resp.gettype())"
Write-Verbose $resp
}
if ($UseContinuationToken -eq 'Body') {
$continuationToken = $resp."$ContinuationTokenName"
$continuationToken = [uri]::EscapeDataString($continuationToken)
$params['Uri'] = "${requestUri}&continuationToken=$continuationToken"
$obj += $resp."$CollectionPropertyName"
} elseif ($UseContinuationToken -eq 'Header') {
$continuationToken = $ResponseHeaders[$ContinuationTokenName]
$params['Uri'] = "${requestUri}&continuationToken=$continuationToken"
$obj += $resp."$CollectionPropertyName"
} else {
return $resp
}
$page++
Write-Verbose "page $page"
}
catch {
_handleException $_

return $resp
}
catch {
_handleException $_

throw
}
throw
}
} while (-not [string]::IsNullOrEmpty($continuationToken) -and $i -lt $MaxPages)
return $obj
}
}



# Not all versions support the name features.

function _supportsGraph {
Expand Down Expand Up @@ -175,9 +225,22 @@ function _supportsSecurityNamespace {
}

function _supportsMemberEntitlementManagement {
[CmdletBinding(DefaultParameterSetName="upto")]
param(
[parameter(ParameterSetName="upto")]
[string]$UpTo = $null,
[parameter(ParameterSetName="onwards")]
[string]$Onwards = $null

)
_hasAccount
if (-not $(_getApiVersion MemberEntitlementManagement)) {
$apiVer = _getApiVersion MemberEntitlementManagement
if (-not $apiVer) {
throw 'This account does not support Member Entitlement.'
} elseif (-not [string]::IsNullOrEmpty($UpTo) -and $apiVer -gt $UpTo) {
throw "EntitlementManagemen version must be equal or lower than $UpTo for this call, current value $apiVer"
} elseif (-not [string]::IsNullOrEmpty($Onwards) -and $apiVer -lt $Onwards) {
throw "EntitlementManagemen version must be equal or greater than $Onwards for this call, current value $apiVer"
}
}

Expand Down Expand Up @@ -1181,4 +1244,19 @@ function _checkForModuleUpdates {
}
}

}

function _countParameters() {
param(
$BoundParameters
)
$counter = 0
$advancedPameters = @('Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'InformationAction', 'ErrorVariable', 'WarningVariable', 'InformationVariable', 'OutVariable', 'OutBuffer', 'PipelineVariable')
foreach($p in $BoundParameters.GetEnumerator()) {
if ($p.Key -notin $advancedPameters) {
$counter++
}
}
Write-Verbose "Found $counter parameters"
$counter
}