如何通过API在Azure Devops中添加团队成员?此外,Groups API不起作用

时间:2019-11-18 13:58:40

标签: azure azure-devops azure-devops-rest-api azure-rest-api

我是Azure Devops的新手,目前正在迁移到它。我想通过REST API为我的azure项目添加团队成员。我参考了以下文档,但没有提及。 'Teams'API没有向其添加成员的功能,只能使用您选择的团队名称创建一个团队。

https://docs.microsoft.com/en-us/rest/api/azure/devops/?view=azure-devops-rest-5.1

我在Group Entitlements API中遇到了另一个问题:

https://docs.microsoft.com/en-us/rest/api/azure/devops/memberentitlementmanagement/group%20entitlements/list?view=azure-devops-rest-5.1

我无法访问以下特定URL:https://vsaex.dev.azure.com。 在其他API示例中,他们仅使用了https://dev.azure.com,对我来说效果很好。我不明白vsaex代表什么。添加“ vsaex”或忽略它都不起作用。我找不到与此有关的任何文档。 用户API的vsaex.dev.azure.com也会出现同样的问题。

任何一种解决方案都将有所帮助。在此先感谢:)

4 个答案:

答案 0 :(得分:2)

我最近编写了一个PowerShell脚本来解决您的第一个问题,但是仅在本地Azureure Devops服务器上进行了测试。

class REST {
    #PROPERTIES
    [string]$ContentType = "application/json;charset=utf-8"
    [string]$PAT
    [System.Collections.IDictionary]$Headers
    [string]$Url
    [string]$Collection
    [string]$_Project

    #STATIC PROPERTIES
    static [int]$Timeout = 30

    #CONSTRUCTOR
    REST([string]$PAT, [string]$Url, [string]$Collection, [string]$Project) { $this.Init($PAT, $Url, $Collection, $Project) }
    REST([string]$PAT, [string]$Url, [string]$Collection) { $this.Init($PAT, $Url, $Collection, $null) }
    REST([string]$PAT, [string]$Url) { $this.Init($PAT, $Url, $null, $null) }
    REST([string]$PAT) { $this.Init($PAT, $null, $null, $null) }

    #INITIALIZE
    [void]Init([string]$PAT, [string]$Url, [string]$Collection, [string]$Project) {
        $this.PAT = $PAT
        $this.Url = $Url
        $this.Collection = $Collection
        $this._Project = $Project
        $this.Headers = $(Headers -PAT $PAT) 
    }

    #GET
    [PSCustomObject]Get([string]$Uri) { return Invoke-RestMethod -Uri $Uri -Method GET -ContentType $this.ContentType -Headers $this.Headers -TimeoutSec $([REST]::Timeout) -Verbose }

    #PUT
    [PSCustomObject]Put([string]$Uri, $Body) { return Invoke-RestMethod -Uri $Uri -Method PUT -ContentType $this.ContentType -Headers $this.Headers -Body $Body -TimeoutSec $([REST]::Timeout) -Verbose }

    #POST
    [PSCustomObject]Post([string]$Uri, $Body) { return Invoke-RestMethod -Uri $Uri -Method POST -ContentType $this.ContentType -Headers $this.Headers -Body $Body -TimeoutSec $([REST]::Timeout) -Verbose }

    #DELETE
    [PSCustomObject]Delete([string]$Uri) { return Invoke-RestMethod -Uri $Uri -Method DELETE -ContentType $this.ContentType -Headers $this.Headers -TimeoutSec $([REST]::Timeout) -Verbose }


    #TEAMS
    [PSCustomObject]Teams([string]$Url, [string]$Collection, [string]$Project) { return $($this.Get($(Combine @($Url, $Collection, $Project, "_settings/teams?__rt=fps&__ver=2")))).fps.dataProviders.data.'ms.vss-tfs-web.team-data' }
    [PSCustomObject]Teams([string]$Collection, [string]$Project) { return $this.Teams($this.Url, $Collection, $Project) }
    [PSCustomObject]Teams([string]$Project) { return $this.Teams($this.Url, $this.Collection, $Project) }
    [PSCustomObject]Teams() { return $this.Teams($this.Url, $this.Collection, $this._Project) }

    #TEAM MEMBERS
    [PSCustomObject]TeamMembers([string]$Url, [string]$Collection, [string]$Project, [string]$TeamId) { return $this.Get($(Combine @($Url, $Collection, $Project, "_api/_identity/ReadGroupMembers?__v=5&scope=$($TeamId)&readMembers=true&scopedMembershipQuery=1"))) }
    [PSCustomObject]TeamMembers([string]$Collection, [string]$Project, [string]$TeamId) { return $this.TeamMembers($this.Url, $Collection, $Project, $TeamId) }
    [PSCustomObject]TeamMembers([string]$Project, [string]$TeamId) { return $this.TeamMembers($this.Url, $this.Collection, $Project, $TeamId) }
    [PSCustomObject]TeamMembers([string]$TeamId) { return $this.TeamMembers($this.Url, $this.Collection, $this._Project, $TeamId) }

    #TEAM MEMBER POST
    [PSCustomObject]TeamMemberPost([string]$Url, [string]$Collection, [string]$Project, [string]$TeamId, [string]$Domain, [string]$Name) { $body = '{{''newUsersJson'':''[\''{0}\\\\{1}\'']'',''existingUsersJson'':''[]'',''groupsToJoinJson'':''[\''{2}\'']'',''aadGroupsJson'':''[]''}}' -f ($Domain, $Name, $TeamId); return $this.Post($(Combine @($Url, $Collection, $Project, "_api/_identity/AddIdentities?__v=5")), $body) }
    [PSCustomObject]TeamMemberPost([string]$Collection, [string]$Project, [string]$TeamId, [string]$Domain, [string]$Name) { return $this.TeamMemberPost($this.Url, $Collection, $Project, $TeamId, $Domain, $Name) }
    [PSCustomObject]TeamMemberPost([string]$Project, [string]$TeamId, [string]$Domain, [string]$Name) { return $this.TeamMemberPost($this.Url, $this.Collection, $Project, $TeamId, $Domain, $Name) }
    [PSCustomObject]TeamMemberPost([string]$TeamId, [string]$Domain, [string]$Name) { return $this.TeamMemberPost($this.Url, $this.Collection, $this._Project, $TeamId, $Domain, $Name) }
}

这些是我使用的REST-API调用。

  • #TEAMS将项目的所有团队返回为json。通话还会为您提供 $TeamId
  • #TEAM MEMBERS为您提供团队的所有成员
  • #TEAM MEMBER POST允许您添加新成员。 重要:Azure DevOps必须知道成员,这意味着他们必须在您的域中(我不知道它在azure devops服务中的组织方式)

使用方法:(但是要在与REST类相同的文件中使用,或先将REST类作为模块或文件加载)

#ADD = LIST OF VALID AND KNOWN MEMBERS OF YOUR AZURE DEVOPS SERVICE (STORE IT IN A .TXT FILE OR SOMETHING)
$ADD = @("member1@xyz.com", "member2@xyz.com")

#INITIALIZE REST API
$REST = [REST]::new($PAT, $Uri, $Collection, $Project) #$PAT ~ "atfghfrhfdgdwnx6jnyrculcmaas2g5j6rrogpmn7aza266hrudsahq"; $Uri = https://server.com

#REQUEST TEAMS
$result = $REST.Teams()
$team = $result.team

#REQUEST TEAM MEMBERS
$result = $REST.TeamMembers($team.id)
$members = $result.identities.MailAddress

#ADD MISSING MEMBERS TO TEAM
foreach ($item in $ADD) {

    if (-not $members.Contains($item)) {
        Write-Host "[ps1] add: '$item'" -ForegroundColor Yellow

        #POST ADD MEMBER
        $name = $item.Replace($mail, "")
        $result = $REST.TeamMemberPost($team.id, $domain, $name)
        if ("AddedIdentities" -in $result.PSobject.Properties.Name) { Write-Host "[ps1] successful added: $($result.AddedIdentities.DisplayName) ($($result.AddedIdentities.TeamFoundationId))" -ForegroundColor Green } 
        else { Write-Host "[ps1] fail to add: '$name'" -ForegroundColor Red }
    }
}

我从脚本中摘录了片段。我没有时间测试这些东西,所以请期待错误。


如何自行找出正确的URLs

  • 打开浏览器(我使用Edge)
  • 按F12
  • 转到Network
  • 导航到您要观看的事件

enter image description here

  • 清除列表
  • 执行事件(单击按钮)
  • 像sceen shot一样,使用application / json查看GET / POST:

enter image description here

如果它是GET / POST事件,则可以在text下显示转移的json

{
  "newUsersJson": "[\"Domain\\\\user\"]",
  "existingUsersJson": "[]",
  "groupsToJoinJson": "[\"2d1dfa03-a108-4421-958a-bdsfdsf161696\"]",
  "aadGroupsJson": "[]"
}

希望这会有所帮助。

答案 1 :(得分:2)

不是 100% 回答您的问题,但也许它可以帮助您或其他人。

最近我不得不将用户添加到 AzDo 项目中的团队。我有用户的电子邮件和团队名称。

我在 AzDo 版本 M183_20210320.1 中使用了以下 Powershell 代码:

$PAT = "my-path"; # get your Personal access token https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page
$Headers += @{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($PAT)")) };
 
$Collection = 'my-organisation';
$Project = 'my-project';
$Timeout = 30;
$TeamToAddUser = "my-team-name>";
$EmailToAddToTeam = "my@email.com";
# get project id
$ProjectId = (Invoke-RestMethod -Uri "https://dev.azure.com/$($Collection)/_apis/projects/$($Project)?api-version=6.0" -Method GET -ContentType "application/json;charset=utf-8" -Headers $Headers -TimeoutSec $Timeout).id;
Write-Host "ProjectId: $ProjectId";
# get project descriptor
$ProjecDescriptor = (Invoke-RestMethod -Uri "https://vssps.dev.azure.com/$($Collection)/_apis/graph/descriptors/$($ProjectId)?api-version=6.0-preview" -Method GET -ContentType "application/json;charset=utf-8" -Headers $Headers -TimeoutSec $Timeout).value;
Write-Host "ProjecDescriptor: $ProjecDescriptor";
   
# get all teams in project
$TeamsInProject = (Invoke-RestMethod -Uri "https://vssps.dev.azure.com/$($Collection)/_apis/graph/groups?scopeDescriptor=$($ProjecDescriptor)&api-version=6.0-preview" -Method GET -ContentType "application/json;charset=utf-8" -Headers $Headers -TimeoutSec $Timeout).value;
Write-Host "TeamsInProject: $($TeamsInProject | forEach { "`n - $($_.displayName) : $($_.descriptor)" }) `n";

# get the team 
$Team = $TeamsInProject | Where-Object { $_.displayName -eq $TeamToAddUser }
Write-Host "Team: $($Team.displayName) : $($Team.descriptor)";

# get user id from email
$User = (Invoke-RestMethod -Uri "https://vsaex.dev.azure.com/$($Collection)/_apis/userentitlements?api-version=6.0-preview.3&`$filter=name eq '$(${EmailToAddToTeam})'" -Method GET -ContentType "application/json;charset=utf-8" -Headers $Headers -TimeoutSec $Timeout).members[0];
Write-Host "User to add user: $($User.user.displayName) : $($User.user.originId)";

# add user to team
$body = @{
   "originId" = $User.user.originId
};
$result = (Invoke-RestMethod -Uri "https://vssps.dev.azure.com/$($Collection)/_apis/graph/Users?groupDescriptors=$($Team.descriptor)&api-version=6.0-preview" -Method POST -ContentType "application/json;charset=utf-8" -Headers $Headers -Body $($body | ConvertTo-Json -Depth 10 -Compress) -TimeoutSec $Timeout)

答案 2 :(得分:1)

您可以使用member add api来吸引团队成员。

PUT https://vsaex.dev.azure.com/{organization}/_apis/GroupEntitlements/{groupId}/members/{memberId}?api-version=5.1-preview.1

当您转到项目设置下的权限时,您会发现该团队实际上被列为一组。因此,我尝试在上述api中将team ID用作groupId。而且有效。

经过测试,memeberId实际上是用户ID。

您可以通过以下“获取用户权利” api获取用户ID:检查here以获得详细信息。

GET https://vsaex.dev.azure.com/{organization}/_apis/userentitlements?top={top}&skip={skip}&filter={filter}&sortOption={sortOption}&api-version=5.1-preview.2

然后您可以调用上述成员添加api来将用户添加到团队中。

$uri ="https://vsaex.dev.azure.com/{ORG}/_apis/GroupEntitlements/{teamid}/members/{userid}?api-version=5.1-preview.1"

$connectionToken="PAT"

$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))

# Invoke the REST call and capture the results (notice this uses the PATCH methodg
$result = Invoke-RestMethod -Uri $group -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method put

如果您无法点击https://vsaex.dev.azure.com。您可能需要检查{PAT}是否具有执行添加成员操作的所有权限范围。检查here以获得有关PAT的更多信息。

缺少有关vsaex的信息。但是我想vsaex是用户广告数据的服务器域。由于Microsoft在与其他数据不同的服务器中管理用户广告数据信息。

答案 3 :(得分:0)

在通过 API 花费数小时完成此操作后,我找到了一个解决方案,您可以使用

TimeoutException

您可以在请求正文中添加电子邮件,JSON 看起来像

POST   https://vssps.dev.azure.com/{organization}/_apis/graph/users?groupDescriptors={groupDescriptor}&api-version=6.0-preview.1

为了获取组描述符使用下面的 GET 调用

{
  "principalName": "yourmail@goeshere.com"
}

在响应中检查“displayName”为“{your project name} Team”的组,并获取该组的组描述符。

如果您使用 Postman 进行此调用,请选择基本身份验证作为授权,并将用户名设为空,密码作为 PAT 令牌。