Get all members/users from TFS via REST API - c#

I tried to get all members/users of TFS with the REST API and the .NET client libraries.
It works, but I get a maximum number of 50 identitys. Does anyone know, how I get all users, not only 50? (I prefer avoiding to use the old API, how it is suggested in this question)
Here is my code:
VssCredentials credentials = new VssCredentials();
VssConnection connection = new VssConnection(new Uri(url), credentials);
IdentityMruHttpClient identityMruHttpClient = connection.GetClient<IdentityMruHttpClient>();
List<IdentityRef> members = identityMruHttpClient.GetIdentityMruAsync(ProjectName).Result;

There is a REST API User Entitlements - List which can retrieve the user list from VSTS (Visual Studio Team Services), but it's only available for VSTS.
There isn't such a REST API to retrieve the user list from on-premise TFS (TFS 2017 in your scenario).
So, for now you can use the client API you mentioned above to retrieve the user list. Tested on my side, I can retrieve all the identities (more than 50 ) with below code:
You can also check the user list from userlist.txt file which under ..\..\ \bin\Debug\
using System;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using System.Linq;
using System.IO;
namespace Getuserlist
{
class Program
{
static void Main(string[] args)
{
TfsConfigurationServer tcs = new TfsConfigurationServer(new Uri("http://server:8080/tfs"));
IIdentityManagementService ims = tcs.GetService<IIdentityManagementService>();
TeamFoundationIdentity tfi = ims.ReadIdentity(IdentitySearchFactor.AccountName, "Project Collection Valid Users", MembershipQuery.Expanded, ReadIdentityOptions.None);
TeamFoundationIdentity[] ids = ims.ReadIdentities(tfi.Members, MembershipQuery.None, ReadIdentityOptions.None);
using (StreamWriter file = new StreamWriter("userlist.txt"))
foreach (TeamFoundationIdentity id in ids)
{
if (id.Descriptor.IdentityType == "System.Security.Principal.WindowsIdentity")
{ Console.WriteLine(id.DisplayName); }
//{ Console.WriteLine(id.UniqueName); }
file.WriteLine("[{0}]", id.DisplayName);
}
var count = ids.Count(x => ids.Contains(x));
Console.WriteLine(count);
Console.ReadLine();
}
}
}

Related

Bring up Sharepoint prompt in .NET5

We used to be able to log into SharePoint Online using the SharePointOnlineCredentials class eg here.
This class is not available in .NET5 and I don't have the necessary Azure permissions to configure the application in Azure AD as described here
I'd like a C# program bring up a prompt, so the user can log into Sharepoint manually. Once the user has done this the program will do what it needs to do. Is there some C# code that will bring up the Sharepoint online login prompt?
I've downloaded Pnp and CSOM. This code contains the following errors.
The name 'GetSecureString' does not exist in the current context
No overload for method 'GetContext' takes 3 arguments
'Program.GetContext(Uri, string, SecureString)': not all code paths return a value
The name 'context' does not exist in the current context
using System;
using System.Security;
using Microsoft.SharePoint.Client;
using System.Threading.Tasks;
using PnP.Framework;
namespace ConsoleApplication1
{
class Program
{
public static async Task Main(string[] args)
{
Uri site = new Uri("https://contoso.sharepoint.com/sites/siteA");
string user = "joe.doe#contoso.onmicrosoft.com";
SecureString password = GetSecureString($"Password for {user}");
// Note: The PnP Sites Core AuthenticationManager class also supports this
using (var authenticationManager = new AuthenticationManager())
using (var context = authenticationManager.GetContext(site, user, password))
{
context.Load(context.Web, p => p.Title);
await context.ExecuteQueryAsync();
Console.WriteLine($"Title: {context.Web.Title}");
}
}
public ClientContext GetContext(Uri web, string userPrincipalName,
SecureString userPassword)
{
context.ExecutingWebRequest += (sender, e) =>
{
// Get an access token using your preferred approach
string accessToken = MyCodeToGetAnAccessToken(new Uri($"
{web.Scheme}://{web.DnsSafeHost}"), userPrincipalName, new
System.Net.NetworkCredential(string.Empty, userPassword).Password);
// Insert the access token in the request
e.WebRequestExecutor.RequestHeaders["Authorization"] =
"Bearer " + accessToken;
};
}
}
}

What is Tenant in Office 365?

I'm new to Office 365 and SharePoint, while I'm trying to create a SharePoint site using CSOM in .NET I've used Tenant like (var tenant = new Tenant(clientContext);) can someone explain what "Tenant" exactly is and what is the use of it in here. When I searched for it I learnt something like Tenant ID which Unique for each Company, but Tenant ID and Tenant in CSOM is different right? and also What is ClientContext? in my code I have used both ClientContext and Tenant to create a SharePoint Site.
using System;
using System.Security;
using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.SharePoint.Client;
namespace CreateSiteCollections
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Program Started!");
//Opens the Admin URL
using(ClientContext tenantContext=new ClientContext("https://developer19-admin.sharepoint.com/"))
{
//Authenticating with Tenant Admin
SecureString passWord = new SecureString();
foreach (char c in "passCode1".ToCharArray())
passWord.AppendChar(c);
tenantContext.Credentials = new SharePointOnlineCredentials("kailash#developer19.onmicrosoft.com", passWord);
var tenant = new Tenant(tenantContext);
//Properties
var siteCreationProperties = new SiteCreationProperties();
//New-Site URL
siteCreationProperties.Url = "https://developer19.sharepoint.com/sites/codesite";
//Titie of the Root Site
siteCreationProperties.Title = "Coded Site";
//Login Name
siteCreationProperties.Owner = "kailash#developer19.onmicrosoft.com";
//Template Copied from Team Site
siteCreationProperties.Template = "STS#0";
//Storage Limit in MB
siteCreationProperties.StorageMaximumLevel = 100;
//UserCode resourse Points Allowed
siteCreationProperties.UserCodeMaximumLevel = 50;
//Creates Site Collection
SpoOperation spo = tenant.CreateSite(siteCreationProperties);
tenantContext.Load(tenant);
//IsComplete to check if provisioning is Completed
tenantContext.Load(spo, i => i.IsComplete);
tenantContext.ExecuteQuery();
while(!spo.IsComplete)
{
//Waits 30 Sec and tries again
System.Threading.Thread.Sleep(30000);
spo.RefreshLoad();
tenantContext.ExecuteQuery();
}
Console.WriteLine("SiteCollection Created.");
}
}
}
}
A Tenant is the Organisation or the Company. It's the "instance of Office 365" that is unique to your user base.
While it's not necessarily a single domain name, because a Tenant could have multiple domain names, that's one way to think of it.
A tenancy in Office 365 refers to the full Office 365 suite attached
to a domain. When Office 365 is set up, it creates a tenancy to store
all the data for Office 365 including things like SharePoint, OneDrive
and Yammer. This allows all of your organisations data to sit in the
same environment and be moved around within the tenant with ease.

Microsoft Graph API query involving externalUserState C#

Hi I'm trying to write a simple console app which I intend to make into a batch file and get a list of external users who were invited by email have and now they have guest accounts in our Azure tenant and they have redeemed the url that was sent to them in email. When they redeem, their extenalUserState sets to "Accepted". I want to find which ones have that status.
I was told that I have to point to beta version of the API and not v.1.0 of the graph endpoint.
I have the following rudimentary code I have written looking at various examples I could find on GitHub/MS documentation for API etc.
using Microsoft.Graph;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace CreateAzureADUser
{
class Program
{
static string TenantDomain;
static string TenantId;
static string ClientId;
static string ClientSecret;
static void Main(string[] args)
{
GetUsers();
//Console.WriteLine("------------------------------------------\n\n");
//GetGroupsAndMembers();
//CreateAzureADUserNow();
}
private static void GetUsers()
{
var graphServiceClient = CreateGraphServiceClient();
var users = graphServiceClient.Users.Request().Filter("userType eq 'Guest' and startswith(mail,'phs')")
.Select("id,mail,OnPremisesExtensionAttributes,userType,displayName,externalUserState")
.GetAsync()
.Result;
Console.WriteLine("Users found: {0}", users.Count);
Console.WriteLine();
foreach (var item in users)
{
Console.WriteLine("displayName: {3} \nuser id: {0} \nuser email: {1} \nExtensionAttribute8: {2}\n", item.Id, item.Mail, item.OnPremisesExtensionAttributes.ExtensionAttribute8, item.DisplayName);
}
}
public static GraphServiceClient CreateGraphServiceClient()
{
TenantDomain = "mycompanytenant.onmicrosoft.com";
TenantId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
ClientId = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";
ClientSecret = "zzzzzzzzzzzz";
var clientCredential = new ClientCredential(ClientId, ClientSecret);
var authenticationContext = new AuthenticationContext($"https://login.microsoftonline.com/mycompanytenant.onmicrosoft.com");
var authenticationResult = authenticationContext.AcquireTokenAsync("https://graph.microsoft.com", clientCredential).Result;
var delegateAuthProvider = new DelegateAuthenticationProvider((requestMessage) =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", authenticationResult.AccessToken);
return Task.FromResult(0);
});
// Use this for v.1.0 endpoint
//return new GraphServiceClient(delegateAuthProvider);
// Use this for connecting to beta endpoint
return new GraphServiceClient("https://graph.microsoft.com/beta", delegateAuthProvider);
}
}
}
When I run through the debugger, I do not see "ExternalUserState" as an attribute on the users that are returned.
How to access ExternalUserState attribute on the guest user object?
You're using the SDK so you're using Graph v1.0, not the Beta. The SDKs are all generated from v1.0 metadata so beta properties and methods simply do not exist in the models.
From time to time there is a beta build pushed out to GitHub but it is generally a few versions behind. Currently, the latest beta SDK available seems to be v1.12.0 (for reference, the current SDK is v1.15).

Unable to Create a systemuser in Dynamics CRM 365 online

On update field of contact record I want to create a systemuser(user) in dynamics crm 365 online.but I’m getting error like "usersettings With Id = 5fe33120-607f-e811-a95c-000d3af29269 Does Not Exist"
This is the below code I'm trying to create a user
Entity getEntity = (Entity)context.InputParameters["Target"];
string str = getEntity.Attributes["new_isaeon"].ToString();
if (str != null && str == "True")
{
// http://localhost:51625/api/Users
Entity sysuser = new Entity("systemuser");
sysuser.Attributes["fullname"] = "hsk";
sysuser.Attributes["internalemailaddress"] = "projectservice_9#crmdemo.dynamics.com";
sysuser.Attributes["domainname"] = "projectservice_9#crmdemo.dynamics.com";
Guid getGuid = new Guid("700F2217-786A-E811-A95A-000D3AF2793E");
sysuser.Attributes["businessunitid"] = new EntityReference("businessunit", getGuid);
sysuser.FormattedValues["accessmode"] = "Read-Write";
Guid getuserid = service.Create(sysuser);
}
can anyone help me on this thanks.
Update: Recently we started importing users in CRM online directly using OOB CSV import (this is new for me too), it will succeed, and later on when license assigned for same user - this wont create another user record, instead it will map the Azure object GUID to the existing user record based on username/domain name/email. This is more useful when creating stub users without license or roles quickly.
In Dynamics 365 CRM online, system users record creation/enabling flow happens from O365 Admin portal end. Read more
Steps go like this:
Security group has to be created in Active directory & mapped in O365 Admin portal for any CRM Org
Users has to be added in that AD Security group
All the users from SG will be replicated as system users in CRM instance
In O365 Admin portal, on assigning CRM license (Basic/Pro) against the user - the system user record will be enabled in CRM
In CRM side, we will assign Security role to complete user on-boarding
We cannot create system user using SDK directly because of above manual steps outside CRM online. Can be created using PowerShell like answered in community.
//Use below code to create User in D365
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
namespace PowerApps.Samples
{
public partial class SampleProgram
{
static void Main(string[] args)
{
JObject azureUser = new JObject();
JObject retrievedResult;
string queryOptions = string.Empty;
string domainName = string.Empty;
try
{
Console.WriteLine("Please enter domain name.");
domainName = Console.ReadLine();
string connectionString = ConfigurationManager.ConnectionStrings["Connect"].ConnectionString;
using (HttpClient client = SampleHelpers.GetHttpClient(
connectionString,
SampleHelpers.clientId,
SampleHelpers.redirectUrl,
"v9.1"))
{
queryOptions = "systemusers?$select=domainname&$filter=domainname eq '" + domainName + "'";
HttpResponseMessage retrieveResponse = client.GetAsync(client.BaseAddress.AbsoluteUri + queryOptions,
HttpCompletionOption.ResponseHeadersRead).Result;
if (retrieveResponse.IsSuccessStatusCode) //200
{
retrievedResult = JObject.Parse(retrieveResponse.Content.ReadAsStringAsync().Result);
string outputDomainname = (string)retrievedResult.SelectToken("value[0].domainname");
Console.WriteLine("Domain: " + outputDomainname);
if (outputDomainname == null)
{
Console.WriteLine("Adding user to Azure AD..");
HttpRequestMessage createrequest = new HttpRequestMessage(HttpMethod.Post,
client.BaseAddress + "systemusers");
Console.WriteLine("Enter first name");
azureUser.Add("firstname", Console.ReadLine());
Console.WriteLine("Enter last name");
azureUser.Add("lastname", Console.ReadLine());
Console.WriteLine("Enter internal email address");
azureUser.Add("internalemailaddress", Console.ReadLine());
azureUser.Add("isdisabled", false);
azureUser.Add("caltype", 7);
azureUser.Add("businessunitid#odata.bind", "/businessunits(8c44c8ac-f6a3-ea11-a812-000d3a0a74cb)");
createrequest.Content = new StringContent(azureUser.ToString());
createrequest.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
HttpResponseMessage createResponse = client.SendAsync(createrequest, HttpCompletionOption.ResponseHeadersRead).Result;
if (createResponse.IsSuccessStatusCode)
{
Console.WriteLine("Account created");
}
else
{
throw new Exception(string.Format("Failed to Post Records", createResponse.ReasonPhrase));
}
}
}
else
{
Console.WriteLine("Failed to retrieve domain: {0}",
retrieveResponse.ReasonPhrase);
throw new Exception(string.Format("Failed to retrieve domain: {0}", retrieveResponse.Content));
}
}
}
catch (Exception ex)
{
SampleHelpers.DisplayException(ex);
throw ex;
}
finally
{
Console.WriteLine("Press <Enter> to exit the program.");
Console.ReadLine();
}
}
}
}

Azure SqlManagementClient - Forbidden with TokenCloudCredentials

I am trying to connect to my SQL server in azure and list the dbs from a .net application, but I keep getting
ForbiddenError: The server failed to authenticate the request. Verify that the certificate is valid and is associated with this subscription.
even though i am trying to use the Sql Management client with TokenCloudCredentials.
var authContext = new AuthenticationContext(authority);
var clientCredential = new ClientCredential(clientId, appKey);
var result = authContext.AcquireTokenAsync(resource, clientCredential).Result;
var credentials = new Microsoft.Azure.TokenCloudCredentials(subscriptionId, result.AccessToken);
var client = new SqlManagementClient(credentials);
try
{
var servers = await client.Servers.ListAsync();
}
catch (CloudException c)
{
Console.WriteLine(c.Message);
throw;
}
The AD application have permissions to access the resource group and the Azure Management API.
Any ideas why it keeps complaining about a certificate, while using token?
EDIT: I managed to do it using the "new" fluent management API. You need to create an AD application associated with the subscription and have access to the resource group. Then just create credentials and initialize the fluent API.
using Microsoft.Azure.Management.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent.Authentication;
using Microsoft.Azure.Management.ResourceManager.Fluent.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AzureManagement
{
public class Program
{
public static void Main(string[] args)
{
var azureCredentials = new AzureCredentials(new
ServicePrincipalLoginInformation
{
ClientId = "clientId",
ClientSecret = "clientSecret="
}, "tenantId", AzureEnvironment.AzureGlobalCloud);
var _azure = Azure
.Configure()
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.Authenticate(azureCredentials)
.WithSubscription("subscriptionId");
var sql = _azure.SqlServers.List().ToList();
foreach (var s in sql)
{
var dbs = s.Databases.List().ToList();
}
Console.ReadLine();
}
}
}
I am not sure if this is supported. Please create a support case for this problem.
The code works like this.
You have to assign a role - in my use case I assigned the contributor role to the App registration, on to the Ressource Group

Categories

Resources