Refactor repo to open up room for quickstarts and other samples
This commit is contained in:
Родитель
15a0aead89
Коммит
8b9d2d64dd
|
@ -0,0 +1,3 @@
|
|||
# Quickstarts
|
||||
|
||||
Self-contained programs demonstrating a specific scenario, typically by calling multiple APIs.
|
До Ширина: | Высота: | Размер: 14 KiB После Ширина: | Высота: | Размер: 14 KiB |
|
@ -0,0 +1,88 @@
|
|||
# Team Services client library snippets
|
||||
|
||||
This folder contains C# samples that show how to integrate with Team Services and Team Foundation Server using our [public client libraries](https://www.nuget.org/profiles/nugetvss). Most samples are short snippets that call just a single API.
|
||||
|
||||
You can use these snippets to jumpstart your own apps and services.
|
||||
|
||||
## Explore
|
||||
|
||||
Samples are organized by "area" (service) and "resource" within the `Microsoft.TeamServices.Samples.Client` project. Each sample class shows various ways for interacting with Team Services and Team Foundation Server.
|
||||
|
||||
## Run the samples
|
||||
|
||||
1. Clone this repository and open in Visual Studio (2015 or later)
|
||||
|
||||
2. Build the solution (you may need to restore the required NuGet packages first)
|
||||
|
||||
3. Run the `Microsoft.TeamServices.Samples.Client.Runner` project with the required arguments:
|
||||
* `/url:{value}`: URL of the account/collection to run the samples against.
|
||||
* `/area:{value}`: API area (work, wit, notification, git, core, build) to run the client samples for. Use * to include all areas.
|
||||
* `/resource:{value}`: API resource to run the client samples for. Use * to include all resources.
|
||||
|
||||
> **IMPORTANT**: some samples are destructive. It is recommended that you run these samples against a test account.
|
||||
|
||||
### Examples of how to run different samples
|
||||
|
||||
#### Run all samples
|
||||
|
||||
```
|
||||
Microsoft.TeamServices.Samples.Client.Runner.exe
|
||||
/url:https://fabrikam.visualstudio.com /area:* /resource:*
|
||||
```
|
||||
|
||||
#### Run all work item tracking samples
|
||||
|
||||
```
|
||||
Microsoft.TeamServices.Samples.Client.Runner.exe
|
||||
/url:https://fabrikam.visualstudio.com /area:wit /resource:*
|
||||
```
|
||||
|
||||
#### Run all graph samples against vsts
|
||||
|
||||
```
|
||||
Microsoft.TeamServices.Samples.Client.Runner.exe
|
||||
/url:https://fabrikam.vssps.visualstudio.com /area:graph /resource:*
|
||||
```
|
||||
|
||||
#### Run all Git pull request samples
|
||||
|
||||
```
|
||||
Microsoft.TeamServices.Samples.Client.Runner.exe
|
||||
/url:https://fabrikam.visualstudio.com /area:git /resource:pullrequests
|
||||
```
|
||||
|
||||
#### Run all samples against a TFS on-premises collection
|
||||
|
||||
```
|
||||
Microsoft.TeamServices.Samples.Client.Runner.exe
|
||||
/url:https://mytfs:8080/tfs/testcollection /area:git /resource:*
|
||||
```
|
||||
|
||||
### Save request and response data to a JSON file
|
||||
|
||||
To persist the HTTP request/response as JSON for each client sample method that is run, set the `/outputPath:{value}` argument. For example:
|
||||
|
||||
```
|
||||
Microsoft.TeamServices.Samples.Client.Runner.exe
|
||||
/url:https://fabrikam.visualstudio.com /area:* /resource:* /outputPath:c:\temp\http-output
|
||||
```
|
||||
|
||||
This creates a folder for each area, a folder for each resource under the area folder, and a file for each client sample method that was run. The name of the JSON file is determined by the name of the client sample method. For example:
|
||||
|
||||
```
|
||||
|-- temp
|
||||
|-- http-output
|
||||
|-- Notification
|
||||
|-- EventTypes
|
||||
|-- ...
|
||||
|-- Subscriptions
|
||||
|-- CreateSubscriptionForUser.json
|
||||
|-- QuerySubscriptionsByEventType.json
|
||||
|-- ...
|
||||
```
|
||||
|
||||
Note: certain HTTP headers like `Authorization` are removed for security/privacy purposes.
|
||||
|
||||
## Contribute
|
||||
|
||||
For developers that want to contribute, learn how to [contribute a snippet sample](./contribute.md).
|
148
README.md
148
README.md
|
@ -1,100 +1,82 @@
|
|||
# Team Services Samples for .NET
|
||||
# .NET samples for Visual Studio Team Services
|
||||
|
||||
![buildstatus](https://mseng.visualstudio.com/_apis/public/build/definitions/b924d696-3eae-4116-8443-9a18392d8544/5045/badge)
|
||||
[![buildstatus](https://mseng.visualstudio.com/_apis/public/build/definitions/b924d696-3eae-4116-8443-9a18392d8544/5045/badge)](https://mseng.visualstudio.com/VSOnline/Open%20ALM/_build/index?context=mine&path=%5C&definitionId=5045&_a=completed)
|
||||
|
||||
This repository contains C# samples that show how to integrate with Team Services and Team Foundation Server using our [public client libraries](https://www.nuget.org/profiles/nugetvss).
|
||||
This repository contains C# samples that show how to integrate with Team Services and Team Foundation Server using our [public client libraries](https://www.nuget.org/profiles/nugetvss), service hooks, and more.
|
||||
|
||||
## Explore
|
||||
## Explore the samples
|
||||
|
||||
Samples are organized by "area" (service) and "resource" within the `Microsoft.TeamServices.Samples.Client` project. Each sample class shows various ways for interacting with Team Services and Team Foundation Server.
|
||||
Take a minute to explore the repo. It contains short snippets as well as longer examples that demonstrate how to integrate with Team Services and Team Foundation
|
||||
|
||||
## Run the samples
|
||||
* **Snippets**: short reusable code blocks demonstrating how to call specific APIs.
|
||||
* **Quickstarts**: self-contained programs demonstrating a specific scenario, typically by calling multiple APIs.
|
||||
|
||||
1. Clone this repository and open in Visual Studio (2015 or later)
|
||||
## About the official client libraries
|
||||
|
||||
2. Build the solution (you may need to restore the required NuGet packages first)
|
||||
For .NET developers, the primary (and highly recommended) way to integrate with Team Services and Team Foundation Server is via our public .NET client libraries available on Nuget. [Microsoft.TeamFoundationServer.Client](https://www.nuget.org/packages/Microsoft.TeamFoundationServer.Client) is the most popular Nuget package and contains clients for interacting with work item tracking, Git, version control, build, release management and other services.
|
||||
|
||||
3. Run the `Microsoft.TeamServices.Samples.Client.Runner` project with the required arguments:
|
||||
* `/url:{value}`: URL of the account/collection to run the samples against.
|
||||
* `/area:{value}`: API area (work, wit, notification, git, core, build) to run the client samples for. Use * to include all areas.
|
||||
* `/resource:{value}`: API resource to run the client samples for. Use * to include all resources.
|
||||
See the [Team Services client library documentation](https://www.visualstudio.com/docs/integrate/get-started/client-libraries/dotnet) for more details.
|
||||
|
||||
> **IMPORTANT**: some samples are destructive. It is recommended that you first run the samples against a test account.
|
||||
### Sample console program
|
||||
|
||||
### Examples
|
||||
Simple console program that connects to Team Services using a personal access token and displays the field values of a work item.
|
||||
|
||||
#### Run all samples
|
||||
```cs
|
||||
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
|
||||
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
|
||||
using Microsoft.VisualStudio.Services.Common;
|
||||
using Microsoft.VisualStudio.Services.WebApi;
|
||||
using System;
|
||||
|
||||
```
|
||||
Microsoft.TeamServices.Samples.Client.Runner.exe
|
||||
/url:https://fabrikam.visualstudio.com /area:* /resource:*
|
||||
namespace ConsoleApp
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
if (args.Length == 3)
|
||||
{
|
||||
Uri accountUri = new Uri(args[0]); // Account URL, for example: https://fabrikam.visualstudio.com
|
||||
String personalAccessToken = args[1]; // See https://www.visualstudio.com/docs/integrate/get-started/authentication/pats
|
||||
int workItemId = int.Parse(args[2]); // ID of a work item, for example: 12
|
||||
|
||||
// Create a connection to the account
|
||||
VssConnection connection = new VssConnection(accountUri, new VssBasicCredential(string.Empty, personalAccessToken));
|
||||
|
||||
// Get an instance of the work item tracking client
|
||||
WorkItemTrackingHttpClient witClient = connection.GetClient<WorkItemTrackingHttpClient>();
|
||||
|
||||
try
|
||||
{
|
||||
// Get the specified work item
|
||||
WorkItem workitem = witClient.GetWorkItemAsync(workItemId).Result;
|
||||
|
||||
// Output the work item's field values
|
||||
foreach (var field in workitem.Fields)
|
||||
{
|
||||
Console.WriteLine(" {0}: {1}", field.Key, field.Value);
|
||||
}
|
||||
}
|
||||
catch (AggregateException aex)
|
||||
{
|
||||
VssServiceException vssex = aex.InnerException as VssServiceException;
|
||||
if (vssex != null)
|
||||
{
|
||||
Console.WriteLine(vssex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Usage: ConsoleApp {accountUri} {personalAccessToken} {workItemId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Run all work item tracking samples
|
||||
## Request other samples
|
||||
|
||||
```
|
||||
Microsoft.TeamServices.Samples.Client.Runner.exe
|
||||
/url:https://fabrikam.visualstudio.com /area:wit /resource:*
|
||||
```
|
||||
Not finding a sample that demonstrates something you are trying to do? Let us know by opening an issue.
|
||||
|
||||
#### Run all graph samples against vsts
|
||||
|
||||
```
|
||||
Microsoft.TeamServices.Samples.Client.Runner.exe
|
||||
/url:https://fabrikam.vssps.visualstudio.com /area:graph /resource:*
|
||||
```
|
||||
|
||||
#### Run all Git pull request samples
|
||||
|
||||
```
|
||||
Microsoft.TeamServices.Samples.Client.Runner.exe
|
||||
/url:https://fabrikam.visualstudio.com /area:git /resource:pullrequests
|
||||
```
|
||||
|
||||
#### Run all samples against a TFS on-premises collection
|
||||
|
||||
```
|
||||
Microsoft.TeamServices.Samples.Client.Runner.exe
|
||||
/url:https://mytfs:8080/tfs/testcollection /area:git /resource:*
|
||||
```
|
||||
|
||||
### Save request and response data to a JSON file
|
||||
|
||||
To persist the HTTP request/response as JSON for each client sample method that is run, set the `/outputPath:{value}` argument. For example:
|
||||
|
||||
```
|
||||
Microsoft.TeamServices.Samples.Client.Runner.exe
|
||||
/url:https://fabrikam.visualstudio.com /area:* /resource:* /outputPath:c:\temp\http-output
|
||||
```
|
||||
|
||||
This creates a folder for each area, a folder for each resource under the area folder, and a file for each client sample method that was run. The name of the JSON file is determined by the name of the client sample method. For example:
|
||||
|
||||
```
|
||||
|-- temp
|
||||
|-- http-output
|
||||
|-- Notification
|
||||
|-- EventTypes
|
||||
|-- ...
|
||||
|-- Subscriptions
|
||||
|-- CreateSubscriptionForUser.json
|
||||
|-- QuerySubscriptionsByEventType.json
|
||||
|-- ...
|
||||
```
|
||||
|
||||
Note: certain HTTP headers like `Authorization` are removed for security/privacy purposes.
|
||||
|
||||
## About the client libraries
|
||||
|
||||
For .NET developers building Windows apps and services that integrate with Visual Studio Team Services, client libraries are available for integrating with work item tracking, version control, build, and other services are now available. These packages replace the traditional TFS Client OM installer and make it easy to acquire and redistribute the libraries needed by your app or service.
|
||||
|
||||
See [.NET client libraries for Team Services documentation](https://www.visualstudio.com/docs/integrate/get-started/client-libraries/dotnet) for more getting started details.
|
||||
|
||||
### Other useful resources
|
||||
|
||||
* [Official NuGet packages](https://www.nuget.org/profiles/nugetvss)
|
||||
* [.NET Client library intro](https://www.visualstudio.com/docs/integrate/get-started/client-libraries/dotnet)
|
||||
* [WIQL reference](https://msdn.microsoft.com/en-us/library/bb130198(v=vs.90).aspx)
|
||||
|
||||
## Contribute
|
||||
|
||||
For developers that want to contribute, learn how to [contribute a sample](./contribute.md).
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
|
@ -0,0 +1,245 @@
|
|||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
[Xx]64/
|
||||
[Xx]86/
|
||||
[Bb]uild/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# DNX
|
||||
project.lock.json
|
||||
artifacts/
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
|
||||
# TODO: Un-comment the next line if you do not want to checkin
|
||||
# your web deploy settings because they may include unencrypted
|
||||
# passwords
|
||||
#*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/packages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignoreable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Microsoft Azure ApplicationInsights config file
|
||||
ApplicationInsights.config
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
orleans.codegen.cs
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# LightSwitch generated files
|
||||
GeneratedArtifacts/
|
||||
ModelManifest.xml
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
|
||||
</startup>
|
||||
<system.serviceModel>
|
||||
<extensions>
|
||||
<!-- In this extension section we are introducing all known service bus extensions. User can remove the ones they don't need. -->
|
||||
<behaviorExtensions>
|
||||
<add name="connectionStatusBehavior" type="Microsoft.ServiceBus.Configuration.ConnectionStatusElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
<add name="transportClientEndpointBehavior" type="Microsoft.ServiceBus.Configuration.TransportClientEndpointBehaviorElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
<add name="serviceRegistrySettings" type="Microsoft.ServiceBus.Configuration.ServiceRegistrySettingsElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
</behaviorExtensions>
|
||||
<bindingElementExtensions>
|
||||
<add name="netMessagingTransport" type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingTransportExtensionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
<add name="tcpRelayTransport" type="Microsoft.ServiceBus.Configuration.TcpRelayTransportElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
<add name="httpRelayTransport" type="Microsoft.ServiceBus.Configuration.HttpRelayTransportElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
<add name="httpsRelayTransport" type="Microsoft.ServiceBus.Configuration.HttpsRelayTransportElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
<add name="onewayRelayTransport" type="Microsoft.ServiceBus.Configuration.RelayedOnewayTransportElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
</bindingElementExtensions>
|
||||
<bindingExtensions>
|
||||
<add name="basicHttpRelayBinding" type="Microsoft.ServiceBus.Configuration.BasicHttpRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
<add name="webHttpRelayBinding" type="Microsoft.ServiceBus.Configuration.WebHttpRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
<add name="ws2007HttpRelayBinding" type="Microsoft.ServiceBus.Configuration.WS2007HttpRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
<add name="netTcpRelayBinding" type="Microsoft.ServiceBus.Configuration.NetTcpRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
<add name="netOnewayRelayBinding" type="Microsoft.ServiceBus.Configuration.NetOnewayRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
<add name="netEventRelayBinding" type="Microsoft.ServiceBus.Configuration.NetEventRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
<add name="netMessagingBinding" type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
</bindingExtensions>
|
||||
</extensions>
|
||||
</system.serviceModel><appSettings>
|
||||
<!-- Service Bus specific app setings for messaging connections -->
|
||||
<add key="Microsoft.ServiceBus.ConnectionString" value="Endpoint=sb://[your namespace].servicebus.windows.net;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=[your secret]" />
|
||||
</appSettings>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.22.0.0" newVersion="2.22.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
|
@ -0,0 +1,133 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{E449C3C1-8272-4781-A658-DDA4A3682A44}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Microsoft.TeamServices.Samples.ServiceHooks</RootNamespace>
|
||||
<AssemblyName>Microsoft.TeamServices.Samples.ServiceHooks</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject>Microsoft.TeamServices.Samples.ServiceHooks.Program</StartupObject>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=2.22.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.22.302111727\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms, Version=2.22.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.22.302111727\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ServiceBus, Version=2.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>packages\WindowsAzure.ServiceBus.2.5.1.0\lib\net40-full\Microsoft.ServiceBus.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.TeamFoundation.Client, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.TeamFoundationServer.ExtendedClient.14.102.0\lib\net45\Microsoft.TeamFoundation.Client.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.TeamFoundation.Common, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.VisualStudio.Services.Client.14.102.0\lib\net45\Microsoft.TeamFoundation.Common.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.TeamFoundation.Core.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.TeamFoundationServer.Client.14.102.0\lib\net45\Microsoft.TeamFoundation.Core.WebApi.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.Services.Client, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.VisualStudio.Services.InteractiveClient.14.102.0\lib\net45\Microsoft.VisualStudio.Services.Client.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.Services.Common, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.VisualStudio.Services.Client.14.102.0\lib\net45\Microsoft.VisualStudio.Services.Common.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.VisualStudio.Services.Client.14.102.0\lib\net45\Microsoft.VisualStudio.Services.WebApi.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.WindowsAzure.Configuration, Version=1.7.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.WindowsAzure.ConfigurationManager.1.7.0.0\lib\net35-full\Microsoft.WindowsAzure.Configuration.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.IdentityModel.Tokens.Jwt, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.IdentityModel.Tokens.Jwt.4.0.0\lib\net45\System.IdentityModel.Tokens.Jwt.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.Formatting, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.AspNet.WebApi.Client.5.2.2\lib\net45\System.Net.Http.Formatting.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Web.Http, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.AspNet.WebApi.Core.5.2.2\lib\net45\System.Web.Http.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="RestrictPermissionsToOneGroup.cs" />
|
||||
<Compile Include="RestoreManagePermissionsToProjectAdminGroups.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="packages\Microsoft.TeamFoundationServer.ExtendedClient.14.102.0\build\Microsoft.TeamFoundationServer.ExtendedClient.targets" Condition="Exists('packages\Microsoft.TeamFoundationServer.ExtendedClient.14.102.0\build\Microsoft.TeamFoundationServer.ExtendedClient.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('packages\Microsoft.TeamFoundationServer.ExtendedClient.14.102.0\build\Microsoft.TeamFoundationServer.ExtendedClient.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.TeamFoundationServer.ExtendedClient.14.102.0\build\Microsoft.TeamFoundationServer.ExtendedClient.targets'))" />
|
||||
</Target>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26223.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.TeamServices.Samples.ServiceHooks", "Microsoft.TeamServices.Samples.ServiceHooks.csproj", "{E449C3C1-8272-4781-A658-DDA4A3682A44}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{E449C3C1-8272-4781-A658-DDA4A3682A44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E449C3C1-8272-4781-A658-DDA4A3682A44}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E449C3C1-8272-4781-A658-DDA4A3682A44}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E449C3C1-8272-4781-A658-DDA4A3682A44}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.TeamServices.Samples.ServiceHooks
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
string command = (args.Length > 0 ? args[0] : null);
|
||||
|
||||
if (command == null || args.Length < 2)
|
||||
{
|
||||
Console.WriteLine("Usage: Microsoft.TeamServices.Samples.ServiceHooks [command] [collection URL]");
|
||||
}
|
||||
else if (String.Equals(command, "restore", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
RestoreManagePermissionsToProjectAdminGroups r = new RestoreManagePermissionsToProjectAdminGroups();
|
||||
r.Run(new Uri(args[1]));
|
||||
}
|
||||
else if(String.Equals(command, "restrict", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
RestrictPermissionsToOneGroup r = new RestrictPermissionsToOneGroup();
|
||||
r.Run(new Uri(args[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Microsoft.TeamServices.Samples.ServiceHooks")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Microsoft")]
|
||||
[assembly: AssemblyProduct("Visual Studio Team Services")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2017")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("e449c3c1-8272-4781-a658-dda4a3682a44")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,86 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.TeamFoundation.Client;
|
||||
using Microsoft.TeamFoundation.Framework.Client;
|
||||
using Microsoft.TeamFoundation.Core.WebApi;
|
||||
using Microsoft.TeamFoundation.Framework.Common;
|
||||
|
||||
namespace Microsoft.TeamServices.Samples.ServiceHooks
|
||||
{
|
||||
public class RestoreManagePermissionsToProjectAdminGroups
|
||||
{
|
||||
private static readonly Guid ServiceHooksSecurityNamespaceId = new Guid("cb594ebe-87dd-4fc9-ac2c-6a10a4c92046");
|
||||
|
||||
public void Run(Uri collectionUri)
|
||||
{
|
||||
Console.WriteLine("Utility to restore Service Hooks manage permissions to the project administrator group");
|
||||
Console.WriteLine("");
|
||||
|
||||
if (collectionUri != null)
|
||||
{
|
||||
TfsTeamProjectCollection connection = new TfsTeamProjectCollection(collectionUri);
|
||||
|
||||
// Get Core, security, and identity services
|
||||
ISecurityService securityService = connection.GetService<ISecurityService>();
|
||||
SecurityNamespace hooksSecurity = securityService.GetSecurityNamespace(ServiceHooksSecurityNamespaceId);
|
||||
IIdentityManagementService2 identityService = connection.GetService<IIdentityManagementService2>();
|
||||
ProjectHttpClient projectClient = connection.GetClient<ProjectHttpClient>();
|
||||
|
||||
IEnumerable<TeamProjectReference> projects = projectClient.GetProjects(stateFilter: Microsoft.TeamFoundation.Common.ProjectState.WellFormed).Result;
|
||||
|
||||
// Iterate over each project, check SH permissions, and grant if needed
|
||||
foreach (var project in projects)
|
||||
{
|
||||
Console.WriteLine(String.Format("Project {0} ({1})", project.Name, project.Id));
|
||||
|
||||
var groups = identityService.ListApplicationGroups(project.Id.ToString(), ReadIdentityOptions.None, null, Microsoft.TeamFoundation.Framework.Common.IdentityPropertyScope.Both);
|
||||
|
||||
String adminGroupName = String.Format("vstfs:///Classification/TeamProject/{0}\\Project Administrators", project.Id);
|
||||
|
||||
try
|
||||
{
|
||||
TeamFoundationIdentity adminGroup = groups.First(g => String.Equals(g.UniqueName, adminGroupName, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
Console.WriteLine(" - Checking Project Administrators group permissions");
|
||||
|
||||
AccessControlEntry ace = new AccessControlEntry(adminGroup.Descriptor, 7, 0); // 7 = view, create, delete
|
||||
String securityToken = "PublisherSecurity/" + project.Id;
|
||||
|
||||
bool hasPermission = hooksSecurity.HasPermission(securityToken, adminGroup.Descriptor, 7, false);
|
||||
|
||||
if (!hasPermission)
|
||||
{
|
||||
Console.WriteLine(" - Missing. Granting...");
|
||||
|
||||
hooksSecurity.SetAccessControlEntry(securityToken, ace, true);
|
||||
|
||||
// check permission again after granting
|
||||
hasPermission = hooksSecurity.HasPermission(securityToken, adminGroup.Descriptor, 7, false);
|
||||
if (hasPermission)
|
||||
{
|
||||
Console.WriteLine(" - Granted");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine(" - Still does not have permission. Check to make sure it has not been explicitly denied.");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine(" - Already has permission");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(String.Format("Admin group: Not found! ({0})", ex.Message));
|
||||
}
|
||||
|
||||
Console.WriteLine("");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.TeamFoundation.Client;
|
||||
using Microsoft.TeamFoundation.Framework.Client;
|
||||
using Microsoft.TeamFoundation.Core.WebApi;
|
||||
using Microsoft.TeamFoundation.Framework.Common;
|
||||
|
||||
namespace Microsoft.TeamServices.Samples.ServiceHooks
|
||||
{
|
||||
public class RestrictPermissionsToOneGroup
|
||||
{
|
||||
private static readonly Guid ServiceHooksSecurityNamespaceId = new Guid("cb594ebe-87dd-4fc9-ac2c-6a10a4c92046");
|
||||
private static Int32 ManagePermissions = 7; // view, create, delete
|
||||
private static Int32 ViewPermissions = 1; // view
|
||||
private static readonly string SpecialGroupName = "Service Hooks Administrators"; // assumed to be a collection-level group containing people that will have management permissions for SH in each project
|
||||
|
||||
public void Run(Uri collectionUri)
|
||||
{
|
||||
Console.WriteLine("Utility to remove Service Hooks management permissions from the Project Administrators groups.");
|
||||
Console.WriteLine("");
|
||||
Console.WriteLine(" All projects in account/collection: " + collectionUri);
|
||||
Console.WriteLine("");
|
||||
|
||||
Console.WriteLine("WARNING! This operation will remove the permissions.\n\n Are you sure you want to continue (Y/N)?");
|
||||
int confirmChar = Console.In.Read();
|
||||
if (confirmChar != 'y' || confirmChar != 'Y')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (collectionUri != null)
|
||||
{
|
||||
TfsTeamProjectCollection connection = new TfsTeamProjectCollection(collectionUri);
|
||||
|
||||
// Get Core, security, and identity services
|
||||
ISecurityService securityService = connection.GetService<ISecurityService>();
|
||||
SecurityNamespace hooksSecurity = securityService.GetSecurityNamespace(ServiceHooksSecurityNamespaceId);
|
||||
IIdentityManagementService2 identityService = connection.GetService<IIdentityManagementService2>();
|
||||
ProjectHttpClient projectClient = connection.GetClient<ProjectHttpClient>();
|
||||
|
||||
IEnumerable<TeamProjectReference> projects = projectClient.GetProjects(stateFilter: Microsoft.TeamFoundation.Common.ProjectState.WellFormed).Result;
|
||||
|
||||
// Iterate over each project, check SH permissions, and remove if the project administrators group has access
|
||||
foreach (var project in projects)
|
||||
{
|
||||
// Remove manage permissions from the project's administrators group (but leave it "view" access)
|
||||
Console.WriteLine(String.Format("Project {0} ({1})", project.Name, project.Id));
|
||||
|
||||
var groups = identityService.ListApplicationGroups(project.Id.ToString(), ReadIdentityOptions.None, null, Microsoft.TeamFoundation.Framework.Common.IdentityPropertyScope.Both);
|
||||
|
||||
String adminGroupName = String.Format("vstfs:///Classification/TeamProject/{0}\\Project Administrators", project.Id);
|
||||
|
||||
try
|
||||
{
|
||||
TeamFoundationIdentity adminGroup = groups.First(g => String.Equals(g.UniqueName, adminGroupName, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
Console.WriteLine(" - Checking Project Administrators group permissions");
|
||||
|
||||
String securityToken = "PublisherSecurity/" + project.Id;
|
||||
|
||||
bool hasPermission = hooksSecurity.HasPermission(securityToken, adminGroup.Descriptor, ManagePermissions, false);
|
||||
|
||||
// Project admin group has "manage" permissions for SH in the project
|
||||
if (hasPermission)
|
||||
{
|
||||
// Remove manage permissions from the project's administrators group (but leave it "view" access)
|
||||
Console.WriteLine(" - Has permissions. Removing...");
|
||||
|
||||
// Give the admin group only view permissions
|
||||
hooksSecurity.SetPermissions(securityToken, adminGroup.Descriptor, ViewPermissions, 0, false);
|
||||
|
||||
// check permission again after granting
|
||||
hasPermission = hooksSecurity.HasPermission(securityToken, adminGroup.Descriptor, ManagePermissions, false);
|
||||
if (!hasPermission)
|
||||
{
|
||||
Console.WriteLine(" - Verified permissions correctly removed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine(" - Project Administrators Group still has manage permissions.");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine(" - Does not have permissions to manage service hook subscriptions.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(String.Format("Admin group: Not found! ({0})", ex.Message));
|
||||
}
|
||||
|
||||
Console.WriteLine("");
|
||||
}
|
||||
|
||||
// Grant the group manage permissions across the entire collection
|
||||
TeamFoundationIdentity specialGroup = identityService.ReadIdentity(IdentitySearchFactor.DisplayName, SpecialGroupName, MembershipQuery.None, ReadIdentityOptions.None);
|
||||
|
||||
if (specialGroup != null)
|
||||
{
|
||||
Console.WriteLine("Granting full manage permissions to: {0}", specialGroup.UniqueName);
|
||||
|
||||
String rootSecurityToken = "PublisherSecurity/";
|
||||
hooksSecurity.SetPermissions(rootSecurityToken, specialGroup.Descriptor, ManagePermissions, 0, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Could not find this group.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.2" targetFramework="net452" />
|
||||
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.2" targetFramework="net452" />
|
||||
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="2.22.302111727" targetFramework="net452" />
|
||||
<package id="Microsoft.TeamFoundationServer.Client" version="14.102.0" targetFramework="net452" />
|
||||
<package id="Microsoft.TeamFoundationServer.ExtendedClient" version="14.102.0" targetFramework="net452" />
|
||||
<package id="Microsoft.VisualStudio.Services.Client" version="14.102.0" targetFramework="net452" />
|
||||
<package id="Microsoft.VisualStudio.Services.InteractiveClient" version="14.102.0" targetFramework="net452" />
|
||||
<package id="Microsoft.WindowsAzure.ConfigurationManager" version="1.7.0.0" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net452" />
|
||||
<package id="System.IdentityModel.Tokens.Jwt" version="4.0.0" targetFramework="net452" />
|
||||
<package id="WindowsAzure.ServiceBus" version="2.5.1.0" targetFramework="net452" />
|
||||
</packages>
|
Загрузка…
Ссылка в новой задаче