如何通过API在Azure Devops中添加团队成员?此外,Groups API不起作用 [英] How to add team members in Azure Devops via API? Also Groups API does not work

查看:143
本文介绍了如何通过API在Azure Devops中添加团队成员?此外,Groups API不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

https://docs.microsoft.com/zh-cn/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也会出现同样的问题.

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

解决方案

我最近编写了一个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
  • 导航到您要观看的事件

  • 清除列表
  • 执行事件(单击按钮)
  • 使用application/json签出GET/POST,如场景截图所示:

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

下显示已传输的json.

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

希望这会有所帮助.

I am new to Azure Devops and currently migrating to it. I want to add team members for my azure project via REST API. I referred the following documentation, but there is no mention of it. 'Teams' API has no functionality to add Members to it, rather only to create a Team with the Team Name of your choice.

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

I encountered another problem in the Group Entitlements API:

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

I am unable to hit this particular URL: https://vsaex.dev.azure.com. In the other API examples, they have used only https://dev.azure.com which works perfectly fine for me. I do not understand what the vsaex stands for. Adding 'vsaex' or ignoring it did not work either. I could not find any documentation regarding this. Same problem arises for vsaex.dev.azure.com for Users API.

Solutions to any of these would be helpful. Thanks in advance :)

解决方案

I recently write a PowerShell Script to solve your first problem, but it is only tested on a local azure devops server.

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) }
}

These are the REST-API calls I used for.

  • #TEAMS returns all teams of a project as json. The call also gives you the $TeamId
  • #TEAM MEMBERS give you all members of a team
  • #TEAM MEMBER POST allows you to add you new members. Important: the members must be known by Azure DevOps, that means they need to be in your domain (I don't know how it is organized in azure devops service)

How to use: (but this in the same file like the REST class or load the REST class as module or file before)

#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 }
    }
}

I take the snippts from my script. I don't have the time to test this stuff, so please expect errors.


How to find out the correct URLs by your self:

  • Open Browser (I used Edge)
  • Press F12
  • Go to Network
  • Navigate to the event you want to observe

  • Clear the list
  • Execute the event (click button)
  • Check out the GET/POST with application/json like in sceen shot:

If it is a GET/POST Event you can display the the transfered json under text

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

Hope this helps.

这篇关于如何通过API在Azure Devops中添加团队成员?此外,Groups API不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆