src/users.psm1

Set-StrictMode -Version Latest

# Load common code
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
. "$here\common.ps1"

# Apply types to the returned objects so format and type files can
# identify the object and act on it.
function _applyTypes {
    param(
        [Parameter(Mandatory = $true)]
        $item
    )

    $item.PSObject.TypeNames.Insert(0, 'Team.UserEntitlement')
    $item.accessLevel.PSObject.TypeNames.Insert(0, 'Team.AccessLevel')
}

function _supportsMemberEntitlementManagement {
    if (-not $VSTeamVersionTable.MemberEntitlementManagement) {
        throw 'This account does not support Member Entitlement.'
    } 
}

function Get-VSTeamUser {
    [CmdletBinding(DefaultParameterSetName = 'List')]
    param (
        [Parameter(ParameterSetName = 'List')]
        [int] $Top = 100,
 
        [Parameter(ParameterSetName = 'List')]
        [int] $Skip = 0,

        [Parameter(ParameterSetName = 'List')]
        [ValidateSet('Projects', 'Extensions', 'Grouprules')]
        [string[]] $Select,
 
        [Parameter(ParameterSetName = 'ByID')]
        [Alias('UserId')]
        [string[]] $Id
    )

    process {
        # Thi swill throw if this account does not support MemberEntitlementManagement
        _supportsMemberEntitlementManagement

        if ($Id) {
            foreach ($item in $Id) {
                # Build the url to return the single build
                # Call the REST API
                $resp = _callAPI -SubDomain 'vsaex' -Version $VSTeamVersionTable.MemberEntitlementManagement -Resource 'userentitlements' -id $item
            
                _applyTypes -item $resp

                Write-Output $resp
            }
        }
        else {
            # Build the url to list the teams
            # $listurl = _buildUserURL
            $listurl = _buildRequestURI -SubDomain 'vsaex' -Resource 'userentitlements' `
                -Version $VSTeamVersionTable.MemberEntitlementManagement
            
            $listurl += _appendQueryString -name "top" -value $top -retainZero
            $listurl += _appendQueryString -name "skip" -value $skip -retainZero
            $listurl += _appendQueryString -name "select" -value ($select -join ",")

            # Call the REST API
            $resp = _callAPI -url $listurl

            # Apply a Type Name so we can use custom format view and custom type extensions
            foreach ($item in $resp.value) {
                _applyTypes -item $item
            }

            Write-Output $resp.value
        }
    } 
}

function Add-VSTeamUser {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [Alias('UserEmail')]     
        [string]$Email,
        [ValidateSet('Advanced', 'EarlyAdopter', 'Express', 'None', 'Professional', 'StakeHolder')]
        [string]$License = 'EarlyAdopter',
        [ValidateSet('Custom', 'ProjectAdministrator', 'ProjectContributor', 'ProjectReader', 'ProjectStakeholder')]
        [string]$Group = 'ProjectContributor'
    )
   
    DynamicParam {
        _buildProjectNameDynamicParam -Mandatory $false
    }

    process {
        # Thi swill throw if this account does not support MemberEntitlementManagement
        _supportsMemberEntitlementManagement

        # Bind the parameter to a friendly variable
        $ProjectName = $PSBoundParameters["ProjectName"]

        $obj = @{
            accessLevel         = @{
                accountLicenseType = $License
            }
            user                = @{
                principalName = $email
                subjectKind   = 'user'
            }
            projectEntitlements = @{
                group      = @{
                    groupType = $Group
                }
                projectRef = @{
                    id = $ProjectName
                }
            }
        }

        $body = $obj | ConvertTo-Json

        # Call the REST API
        _callAPI  -Method Post -Body $body -SubDomain 'vsaex' -Resource 'userentitlements' -Version $VSTeamVersionTable.MemberEntitlementManagement -ContentType "application/json"
    }
}

function Remove-VSTeamUser {
    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = "High", DefaultParameterSetName = 'ById')]
    param(
        [Parameter(ParameterSetName = 'ById', Mandatory = $True, ValueFromPipelineByPropertyName = $true)]
        [Alias('UserId')]
        [string]$Id,

        [Parameter(ParameterSetName = 'ByEmail', Mandatory = $True, ValueFromPipelineByPropertyName = $true)]
        [Alias('UserEmail')]
        [string]$Email,

        [switch]$Force
    )

    process { 
        # Thi swill throw if this account does not support MemberEntitlementManagement
        _supportsMemberEntitlementManagement
        
        if ($email) {
            # We have to go find the id
            $user = Get-VSTeamUser | Where-Object email -eq $email

            if (-not $user) {
                throw "Could not find user with an email equal to $email"
            }

            $id = $user.id
        }

        if ($Force -or $PSCmdlet.ShouldProcess($Id, "Delete user")) {
            # Call the REST API
            _callAPI -Method Delete -SubDomain 'vsaex' -Resource 'userentitlements' -Id $Id -Version $VSTeamVersionTable.MemberEntitlementManagement | Out-Null

            Write-Output "Deleted user $Id"
        }
    }
}

Set-Alias Get-User Get-VSTeamUser
Set-Alias Add-User Add-VSTeamUser
Set-Alias Update-User Update-VSTeamUser
Set-Alias Remove-User Remove-VSTeamUser

Export-ModuleMember `
    -Function Get-VSTeamUser, Add-VSTeamUser, Update-VSTeamUser, Remove-VSTeamUser `
    -Alias Get-User, Add-User, Update-User, Remove-User