我是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中遇到了另一个问题:
我无法访问以下特定URL:https://vsaex.dev.azure.com
。
在其他API示例中,他们仅使用了https://dev.azure.com
,对我来说效果很好。我不明白vsaex
代表什么。添加“ vsaex”或忽略它都不起作用。我找不到与此有关的任何文档。
用户API的vsaex.dev.azure.com
也会出现同样的问题。
任何一种解决方案都将有所帮助。在此先感谢:)
答案 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
:
Network
如果它是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 令牌。