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

如何通过API在Azure Devops中添加团队成员?此外,组API也不起作用,azure,azure-devops,azure-devops-rest-api,azure-rest-api,Azure,Azure Devops,Azure Devops Rest Api,Azure Rest Api,我是Azure Devops的新手,目前正在迁移到Azure Devops。我想通过RESTAPI为我的azure项目添加团队成员。我参考了以下文件,但没有提及。”团队的API没有向其中添加成员的功能,而只是使用您选择的团队名称创建团队 我在集团权利API中遇到了另一个问题: 我无法点击此特定URL:https://vsaex.dev.azure.com。 在其他API示例中,他们只使用了https://dev.azure.com这对我来说非常好。我不明白vsaex代表什么。添加“vsaex

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

我在集团权利API中遇到了另一个问题:

我无法点击此特定URL:
https://vsaex.dev.azure.com
。 在其他API示例中,他们只使用了
https://dev.azure.com
这对我来说非常好。我不明白
vsaex
代表什么。添加“vsaex”或忽略它也不起作用。我找不到与此相关的任何文档。 同样的问题也出现在用户API的
vsaex.dev.azure.com


这些问题的解决方案都会很有帮助。提前感谢:)

我最近编写了一个PowerShell脚本来解决您的第一个问题,但它只在本地azure 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
  • #团队成员
    为您提供团队的所有成员
  • #团队成员帖子
    允许您添加新成员重要提示:Azure DevOps必须知道成员,这意味着他们需要在您的域中(我不知道Azure DevOps服务中是如何组织的)

如何使用:(但这与REST类在同一个文件中,或者之前将REST类作为模块或文件加载)

我从我的剧本中摘取剪报。我没有时间测试这些东西,所以请期待出现错误。


如何自行查找正确的
URL

  • 打开浏览器(我使用了Edge)
  • 按F12
  • 转到
    网络
  • 导航到要观察的事件

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

如果是GET/POST事件,您可以在
text

{
  "newUsersJson": "[\"Domain\\\\user\"]",
  "existingUsersJson": "[]",
  "groupsToJoinJson": "[\"2d1dfa03-a108-4421-958a-bdsfdsf161696\"]",
  "aadGroupsJson": "[]"
}
希望这对您有所帮助。

您可以使用它从用户到团队成员

PUT https://vsaex.dev.azure.com/{organization}/_apis/GroupEntitlements/{groupId}/members/{memberId}?api-version=5.1-preview.1
当您转到项目设置下的权限时,您会发现团队实际上是作为一个组列出的。所以我尝试在上面的api中使用团队Id作为groupId。它成功了

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

您可以使用下面的获取用户权限api获取用户id:查看详细信息

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
如果你打不到。您可能需要检查您的{PAT}是否具有执行添加成员操作的所有权限范围。查看有关PAT的更多信息


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

对你的问题不是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)

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

POST   https://vssps.dev.azure.com/{organization}/_apis/graph/users?groupDescriptors={groupDescriptor}&api-version=6.0-preview.1
您可以在requestbody中添加电子邮件,JSON如下所示

{
  "principalName": "yourmail@goeshere.com"
}
要获取组描述符,请使用下面的GET调用

GET https://vssps.dev.azure.com/{organization}/_apis/graph/groups?api-version=6.0-preview.1
在响应中检查“displayName”为“{your project name}Team”的组,并获取该组的组描述符


如果您使用邮递员进行此呼叫,请选择“基本身份验证”作为授权,并将用户名为空,密码为PAT令牌。

当我尝试在我的实际azure URL前使用“vsaex”前缀时,它表示URL本身无效。->连接到上面为我编写的脚本“{MyAzureURL}/blabla”时出错。你能分享你完整的api azure URL和更多的错误信息吗?你有机会尝试下面的答案吗?请告诉我进展如何?我们可以讨论一下,共同制定出更好的解决方案。
GET https://vssps.dev.azure.com/{organization}/_apis/graph/groups?api-version=6.0-preview.1