public async Task Process(IBatchMigrationContext batchContext) { object identityObject = null; string identityValue = null; HashSet <string> identitiesToProcess = new HashSet <string>(StringComparer.CurrentCultureIgnoreCase); foreach (var sourceWorkItem in batchContext.SourceWorkItems) { foreach (var field in context.IdentityFields) { if (sourceWorkItem.Fields.TryGetValueIgnoringCase(field, out identityObject)) { identityValue = (string)identityObject; if (!string.IsNullOrEmpty(identityValue) && identityValue.Contains("<") && identityValue.Contains(">") && (identityValue.Contains("@"))) { // parse out email address from the combo string identityValue = identityValue.Substring(identityValue.LastIndexOf("<") + 1, identityValue.LastIndexOf(">") - identityValue.LastIndexOf("<") - 1); if (!identitiesToProcess.Contains(identityValue) && !this.context.ValidatedIdentities.Contains(identityValue) && !this.context.InvalidIdentities.Contains(identityValue)) { Logger.LogTrace(LogDestination.File, $"Found identity {identityValue} in batch {batchContext.BatchId} which has not yet been validated for the target account"); identitiesToProcess.Add(identityValue); } } } } } Logger.LogTrace(LogDestination.File, $"Adding {identitiesToProcess.Count} identities to the account for batch {batchContext.BatchId}"); foreach (var identity in identitiesToProcess) { try { await RetryHelper.RetryAsync(async() => { return(await graphClient.CreateUserAsync(new GraphUserPrincipalNameCreationContext() { PrincipalName = identity }, Groups)); }, 5); context.ValidatedIdentities.Add(identity); } catch (Exception ex) { Logger.LogWarning(LogDestination.File, ex, $"Unable to add identity {identity} to the target account for batch {batchContext.BatchId}"); context.InvalidIdentities.Add(identity); } } Logger.LogTrace(LogDestination.File, $"Completed adding {identitiesToProcess.Count} identities to the account for batch {batchContext.BatchId}"); }
public void AddRemoveAADUserByOIDWithStorageKey() { // Get the client VssConnection connection = Context.Connection; GraphHttpClient graphClient = connection.GetClient <GraphHttpClient>(); // // Part 1: add the AAD user // ClientSampleHttpLogger.SetOperationName(this.Context, "MaterializeAADUserByOIDWithStorageKey"); GraphUserCreationContext addAADUserContext = new GraphUserOriginIdCreationContext { OriginId = "27dbfced-5593-4756-98a3-913c39af7612", StorageKey = new Guid("9b71f216-4c4f-6b74-a911-efb0fa9c777f") }; GraphUser newUser = graphClient.CreateUserAsync(addAADUserContext).Result; string userDescriptor = newUser.Descriptor; Context.Log("New user added! ID: {0}", userDescriptor); // // Part 2: get the user // ClientSampleHttpLogger.SetOperationName(this.Context, "GetUser-AddRemoveAADUserByOIDWithStorageKey"); newUser = graphClient.GetUserAsync(userDescriptor).Result; // // Part 3: remove the user // ClientSampleHttpLogger.SetOperationName(this.Context, "DeleteUser-AddRemoveAADUserByOIDWithStorageKey"); graphClient.DeleteUserAsync(userDescriptor).SyncResult(); // Try to get the deleted user ClientSampleHttpLogger.SetOperationName(this.Context, "GetMembershipState-AddRemoveAADUserByOIDWithStorageKey"); GraphMembershipState membershipState = graphClient.GetMembershipStateAsync(userDescriptor).Result; try { if (membershipState.Active) { throw new Exception(); } } catch (Exception) { Context.Log("The deleted user is not disabled!"); } }
public void AddRemoveAADUserByUPN() { // Get the client VssConnection connection = Context.Connection; GraphHttpClient graphClient = connection.GetClient <GraphHttpClient>(); // // Part 1: add the AAD user // ClientSampleHttpLogger.SetOperationName(this.Context, "CreateUserAAD"); GraphUserCreationContext addAADUserContext = new GraphUserPrincipalNameCreationContext { PrincipalName = "*****@*****.**" }; GraphUser newUser = graphClient.CreateUserAsync(addAADUserContext).Result; string userDescriptor = newUser.Descriptor; Context.Log("New user added! ID: {0}", userDescriptor); // // Part 2: get the user // ClientSampleHttpLogger.SetOperationName(this.Context, "GetUserAAD"); newUser = graphClient.GetUserAsync(userDescriptor).Result; // // Part 3: remove the user // ClientSampleHttpLogger.SetOperationName(this.Context, "DeleteUserAAD"); graphClient.DeleteUserAsync(userDescriptor).SyncResult(); // Try to get the deleted user ClientSampleHttpLogger.SetOperationName(this.Context, "GetMembershipStateAAD"); GraphMembershipState membershipState = graphClient.GetMembershipStateAsync(userDescriptor).Result; try { if (membershipState.Active) { throw new Exception(); } } catch (Exception) { Context.Log("The deleted user is not disabled!"); } }
public void AddRemoveAADUserByOID() { // Get the client VssConnection connection = Context.Connection; GraphHttpClient graphClient = connection.GetClient <GraphHttpClient>(); // // Part 1: add the AAD user // ClientSampleHttpLogger.SetOperationName(this.Context, "MaterializeAADUserByOID"); GraphUserCreationContext addAADUserContext = new GraphUserOriginIdCreationContext { OriginId = "e97b0e7f-0a61-41ad-860c-748ec5fcb20b" }; GraphUser newUser = graphClient.CreateUserAsync(addAADUserContext).Result; string userDescriptor = newUser.Descriptor; Context.Log("New user added! ID: {0}", userDescriptor); // // Part 2: get the user // ClientSampleHttpLogger.SetOperationName(this.Context, "GetUser-AddRemoveAADUserByOID"); newUser = graphClient.GetUserAsync(userDescriptor).Result; // // Part 3: remove the user // ClientSampleHttpLogger.SetOperationName(this.Context, "DeleteUser-AddRemoveAADUserByOID"); graphClient.DeleteUserAsync(userDescriptor).SyncResult(); // Try to get the deleted user ClientSampleHttpLogger.SetOperationName(this.Context, "GetMembershipState-AddRemoveAADUserByOID"); GraphMembershipState membershipState = graphClient.GetMembershipStateAsync(userDescriptor).Result; try { if (membershipState.Active) { throw new Exception(); } } catch (Exception) { Context.Log("The deleted user is not disabled!"); } }
public void LookupSubject() { // Get the client VssConnection connection = Context.Connection; GraphHttpClient graphClient = connection.GetClient <GraphHttpClient>(); // // Part 1: add the AAD user // ClientSampleHttpLogger.SetOperationName(this.Context, "MaterializeAADUserByOIDWithStorageKey"); GraphUserCreationContext addAADUserContext = new GraphUserOriginIdCreationContext { OriginId = "e97b0e7f-0a61-41ad-860c-748ec5fcb20b", StorageKey = Guid.NewGuid() }; GraphUser newUser = graphClient.CreateUserAsync(addAADUserContext).Result; string userDescriptor = newUser.Descriptor; Context.Log("New user added! ID: {0}", userDescriptor); // // Part 2: add the AAD group // ClientSampleHttpLogger.SetOperationName(this.Context, "MaterializeAADGroupByOIDWithStorageKey"); GraphGroupCreationContext addAADGroupContext = new GraphGroupOriginIdCreationContext { OriginId = "f0d20172-7b96-42f6-9436-941433654b48", StorageKey = Guid.NewGuid() }; GraphGroup newGroup = graphClient.CreateGroupAsync(addAADGroupContext).Result; string groupDescriptor = newGroup.Descriptor; Context.Log("New group created! ID: {0}", groupDescriptor); // // Part 3: lookup subjects // GraphSubjectLookup subjectLookup = new GraphSubjectLookup(new[] { new GraphSubjectLookupKey(newGroup.Descriptor), new GraphSubjectLookupKey(newUser.Descriptor) }); ClientSampleHttpLogger.SetOperationName(this.Context, "LookupSubjects"); IReadOnlyDictionary <SubjectDescriptor, GraphSubject> lookups = graphClient.LookupSubjectsAsync(subjectLookup).Result; }
public void AddRemoveAADUserByUPN() { // Get the client VssConnection connection = Context.Connection; GraphHttpClient graphClient = connection.GetClient <GraphHttpClient>(); // // Part 1: add the AAD user // ClientSampleHttpLogger.SetOperationName(this.Context, "CreateUserAAD"); GraphUserCreationContext addAADUserContext = new GraphUserPrincipalNameCreationContext { PrincipalName = "*****@*****.**" }; GraphUser newUser = graphClient.CreateUserAsync(addAADUserContext).Result; string userDescriptor = newUser.Descriptor; Context.Log("New user added! ID: {0}", userDescriptor); // // Part 2: get the user // ClientSampleHttpLogger.SetOperationName(this.Context, "GetUserAAD"); //newUser = graphClient.GetUserAsync(userDescriptor).Result; //BUG ???: {"TF14045: The identity with type 'Microsoft.IdentityModel.Claims.ClaimsIdentity' and identifier '45aa3d2d-7442-473d-b4d3-3c670da9dd96\\[email protected]' could not be found."} // // Part 3: remove the user // ClientSampleHttpLogger.SetOperationName(this.Context, "DeleteUserAAD"); graphClient.DeleteUserAsync(userDescriptor).SyncResult(); // Try to get the deleted user try { ClientSampleHttpLogger.SetOperationName(this.Context, "GetDisabledUserAAD"); newUser = graphClient.GetUserAsync(userDescriptor).Result; if (!newUser.Disabled) { throw new Exception(); } } catch (Exception) { Context.Log("The deleted user is not disabled!"); } }
public void AddRemoveAADUserByOID() { // Get the client VssConnection connection = Context.Connection; GraphHttpClient graphClient = connection.GetClient <GraphHttpClient>(); // // Part 1: add the AAD user // ClientSampleHttpLogger.SetOperationName(this.Context, "MaterializeAADUserByOID"); GraphUserCreationContext addAADUserContext = new GraphUserOriginIdCreationContext { OriginId = "e97b0e7f-0a61-41ad-860c-748ec5fcb20b" }; GraphUser newUser = graphClient.CreateUserAsync(addAADUserContext).Result; string userDescriptor = newUser.Descriptor; Context.Log("New user added! ID: {0}", userDescriptor); // // Part 2: get the user // //newUser = graphClient.GetUserAsync(userDescriptor).Result; //BUG ???: TF14045: The identity with type 'Microsoft.IdentityModel.Claims.ClaimsIdentity' and identifier '45aa3d2d-7442-473d-b4d3-3c670da9dd96\[email protected]' could not be found. // // Part 3: remove the user // graphClient.DeleteUserAsync(userDescriptor).SyncResult(); // Try to get the deleted user try { newUser = graphClient.GetUserAsync(userDescriptor).Result; if (!newUser.Disabled) { throw new Exception(); } } catch (Exception) { Context.Log("The deleted user is not disabled!"); } }
public void AddRemoveAADUserByOIDWithVSID() { // Get the client VssConnection connection = Context.Connection; GraphHttpClient graphClient = connection.GetClient <GraphHttpClient>(); // // Part 1: add the AAD user // ClientSampleHttpLogger.SetOperationName(this.Context, "MaterializeAADUserByOIDWithVSID"); GraphUserCreationContext addAADUserContext = new GraphUserOriginIdCreationContext { OriginId = "e97b0e7f-0a61-41ad-860c-748ec5fcb20b" /* TODO: Id = Guid.NewGuid() */ }; GraphUser newUser = graphClient.CreateUserAsync(addAADUserContext).Result; string userDescriptor = newUser.Descriptor; Context.Log("New user added! ID: {0}", userDescriptor); // // Part 2: get the user // //newUser = graphClient.GetUserAsync(userDescriptor).Result; // // Part 3: remove the user // graphClient.DeleteUserAsync(userDescriptor).SyncResult(); // Try to get the deleted user try { newUser = graphClient.GetUserAsync(userDescriptor).Result; // TODO: if (!newUser.Disabled) throw new Exception(); } catch (Exception) { Context.Log("The deleted user is not disabled!"); } }
public void AddRemoveUserMembership() { // Get the client VssConnection connection = Context.Connection; GraphHttpClient graphClient = connection.GetClient <GraphHttpClient>(); // // Part 1: create a group at the account level // GraphGroupCreationContext createGroupContext = new GraphGroupVstsCreationContext { DisplayName = "Developers-" + Guid.NewGuid(), Description = "Group created via client library" }; GraphGroup newGroup = graphClient.CreateGroupAsync(createGroupContext).Result; string groupDescriptor = newGroup.Descriptor; Context.Log("New group created! ID: {0}", groupDescriptor); // // Part 2: add the user // GraphUserCreationContext addUserContext = new GraphUserPrincipalNameCreationContext { PrincipalName = "*****@*****.**" }; GraphUser newUser = graphClient.CreateUserAsync(addUserContext).Result; string userDescriptor = newUser.Descriptor; Context.Log("New user added! ID: {0}", userDescriptor); // // Part 3: Make the user a member of the group // ClientSampleHttpLogger.SetOperationName(this.Context, "CreateMembershipUser"); GraphMembership graphMembership = graphClient.AddMembershipAsync(userDescriptor, groupDescriptor).Result; // // Part 4: get the membership // ClientSampleHttpLogger.SetOperationName(this.Context, "GetMembershipUser"); graphMembership = graphClient.GetMembershipAsync(userDescriptor, groupDescriptor).Result; // // Part 5: Check to see if the user is a member of the group // ClientSampleHttpLogger.SetOperationName(this.Context, "CheckMembershipUser"); graphClient.CheckMembershipAsync(userDescriptor, groupDescriptor).SyncResult(); // // Part 6: Get every group the subject(user) is a member of // ClientSampleHttpLogger.SetOperationName(this.Context, "GetMembershipsUserUp"); List <GraphMembership> membershipsForUser = graphClient.GetMembershipsAsync(userDescriptor).Result; // // Part 7: Get every member of the group // ClientSampleHttpLogger.SetOperationName(this.Context, "GetMembershipsGroupDown"); List <GraphMembership> membershipsOfGroup = graphClient.GetMembershipsAsync(groupDescriptor, Microsoft.VisualStudio.Services.Graph.GraphTraversalDirection.Down.ToString()).Result; //Bug 967647: REST: GetMembershipsAsync shouldn't take direction as string, it should be the GraphTraversalDirection enum // // Part 8: Remove member from the group // ClientSampleHttpLogger.SetOperationName(this.Context, "DeleteMembershipUser"); graphClient.RemoveMembershipAsync(userDescriptor, groupDescriptor).SyncResult(); try { graphClient.CheckMembershipAsync(userDescriptor, groupDescriptor).SyncResult(); } catch (Exception e) { Context.Log("User is no longer a member of the group:" + e.Message); } // // Part 9: delete the group // graphClient.DeleteGroupAsync(groupDescriptor).SyncResult(); // // Part 10: remove the user graphClient.DeleteUserAsync(userDescriptor).SyncResult(); // // Try to get the deleted user try { newUser = graphClient.GetUserAsync(userDescriptor).Result; if (!newUser.Disabled) { throw new Exception(); } } catch (Exception) { Context.Log("The deleted user is not disabled!"); } }
public void AddRemoveAADUserByUPNToGroup() { // Get the client VssConnection connection = Context.Connection; GraphHttpClient graphClient = connection.GetClient <GraphHttpClient>(); // // Part 1: create a group at the account level // GraphGroupCreationContext createGroupContext = new GraphGroupVstsCreationContext { DisplayName = "Developers-" + Guid.NewGuid(), Description = "Group created via client library" }; GraphGroup newVSTSGroup = graphClient.CreateGroupAsync(createGroupContext).Result; IEnumerable <VisualStudio.Services.Common.SubjectDescriptor> parentGroup = new List <VisualStudio.Services.Common.SubjectDescriptor>() { newVSTSGroup.Descriptor }; string groupDescriptor = newVSTSGroup.Descriptor; Context.Log("New group created! ID: {0}", groupDescriptor); // // Part 2: add the AAD user // ClientSampleHttpLogger.SetOperationName(this.Context, "MaterializeAADUserByOIDAsMember"); GraphUserCreationContext addAADUserContext = new GraphUserPrincipalNameCreationContext { PrincipalName = "*****@*****.**" }; GraphUser newUser = graphClient.CreateUserAsync(addAADUserContext, parentGroup).Result; string userDescriptor = newUser.Descriptor; Context.Log("New user added! ID: {0}", userDescriptor); // // Part 3: get the user // ClientSampleHttpLogger.SetOperationName(this.Context, "GetUser-AddRemoveAADUserByUPNToGroup"); newUser = graphClient.GetUserAsync(userDescriptor).Result; // // Part 4: remove the user // ClientSampleHttpLogger.SetOperationName(this.Context, "DeleteUser-AddRemoveAADUserByUPNToGroup"); graphClient.DeleteUserAsync(userDescriptor).SyncResult(); // Try to get the deleted user ClientSampleHttpLogger.SetOperationName(this.Context, "GetMembershipState-AddRemoveAADUserByUPNToGroup"); GraphMembershipState membershipState = graphClient.GetMembershipStateAsync(userDescriptor).Result; try { if (membershipState.Active) { throw new Exception(); } } catch (Exception) { Context.Log("The deleted user is not disabled!"); } // Part 5: remove the group graphClient.DeleteGroupAsync(groupDescriptor).SyncResult(); // Try to get the deleted group ClientSampleHttpLogger.SetOperationName(this.Context, "GetMembershipStateAADGroup"); membershipState = graphClient.GetMembershipStateAsync(groupDescriptor).Result; try { if (membershipState.Active) { throw new Exception(); } } catch (Exception) { Context.Log("The deleted group is not disabled!"); } }
public void AddRemoveAADUserByUPNToGroup() { // Get the client VssConnection connection = Context.Connection; GraphHttpClient graphClient = connection.GetClient <GraphHttpClient>(); // // Part 1: create a group at the account level // GraphGroupCreationContext createGroupContext = new GraphGroupVstsCreationContext { DisplayName = "Developers-" + Guid.NewGuid(), Description = "Group created via client library" }; GraphGroup newVSTSGroup = graphClient.CreateGroupAsync(createGroupContext).Result; IEnumerable <VisualStudio.Services.Common.SubjectDescriptor> parentGroup = new List <VisualStudio.Services.Common.SubjectDescriptor>() { newVSTSGroup.Descriptor }; string groupDescriptor = newVSTSGroup.Descriptor; Context.Log("New group created! ID: {0}", groupDescriptor); // // Part 2: add the AAD user // ClientSampleHttpLogger.SetOperationName(this.Context, "MaterializeAADUserByOIDAsMember"); GraphUserCreationContext addAADUserContext = new GraphUserPrincipalNameCreationContext { PrincipalName = "*****@*****.**" }; GraphUser newUser = graphClient.CreateUserAsync(addAADUserContext, parentGroup).Result; string userDescriptor = newUser.Descriptor; Context.Log("New user added! ID: {0}", userDescriptor); // // Part 3: get the user // //newUser = graphClient.GetUserAsync(userDescriptor).Result; //BUG ???: {"TF14045: The identity with type 'Microsoft.IdentityModel.Claims.ClaimsIdentity' and identifier '45aa3d2d-7442-473d-b4d3-3c670da9dd96\\[email protected]' could not be found."} // // Part 4: remove the user // graphClient.DeleteUserAsync(userDescriptor).SyncResult(); // Try to get the deleted user try { newUser = graphClient.GetUserAsync(userDescriptor).Result; // TODO: if (!newUser.Disabled) throw new Exception(); } catch (Exception) { Context.Log("The deleted user is not disabled!"); } // Part 5: remove the group graphClient.DeleteGroupAsync(groupDescriptor).SyncResult(); }
public async Task Process(IBatchMigrationContext batchContext) { object identityObject = null; string identityValue = null; HashSet <string> identitiesToProcess = new HashSet <string>(StringComparer.CurrentCultureIgnoreCase); foreach (var sourceWorkItem in batchContext.SourceWorkItems) { foreach (var field in context.IdentityFields) { if (sourceWorkItem.Fields.TryGetValueIgnoringCase(field, out identityObject)) { identityValue = (string)identityObject; if (!string.IsNullOrEmpty(identityValue) && identityValue.Contains("<") && identityValue.Contains(">") && (identityValue.Contains("@"))) { // parse out email address from the combo string identityValue = identityValue.Substring(identityValue.LastIndexOf("<") + 1, identityValue.LastIndexOf(">") - identityValue.LastIndexOf("<") - 1); if (!identitiesToProcess.Contains(identityValue) && !this.context.ValidatedIdentities.Contains(identityValue) && !this.context.InvalidIdentities.Contains(identityValue)) { Logger.LogTrace(LogDestination.File, $"Found identity {identityValue} in batch {batchContext.BatchId} which has not yet been validated for the target account"); identitiesToProcess.Add(identityValue); } } } } } Logger.LogTrace(LogDestination.File, $"Adding {identitiesToProcess.Count} identities to the account for batch {batchContext.BatchId}"); foreach (var identity in identitiesToProcess) { try { var createUserResult = await RetryHelper.RetryAsync(async() => { return(await graphClient.CreateUserAsync(new GraphUserPrincipalNameCreationContext() { PrincipalName = identity })); }, 5); // using identity from createUserResult since the identity could be in a mangled format that ReadIdentities does not support var identities = await RetryHelper.RetryAsync(async() => { return(await identityHttpClient.ReadIdentitiesAsync(IdentitySearchFilter.MailAddress, createUserResult.MailAddress)); }, 5); if (identities.Count == 0) { Logger.LogWarning(LogDestination.File, $"Unable to add identity {identity} to the target account for batch {batchContext.BatchId}"); context.InvalidIdentities.Add(identity); } else { var assignResult = await RetryHelper.RetryAsync(async() => { return(await licensingHttpClient.AssignAvailableEntitlementAsync(identities[0].Id, dontNotifyUser: true)); }, 5); context.ValidatedIdentities.Add(identity); } } catch (Exception ex) { Logger.LogWarning(LogDestination.File, ex, $"Unable to add identity {identity} to the target account for batch {batchContext.BatchId}"); context.InvalidIdentities.Add(identity); } } Logger.LogTrace(LogDestination.File, $"Completed adding {identitiesToProcess.Count} identities to the account for batch {batchContext.BatchId}"); }
public async Task <bool> AddUser(string organization, string projectName, string userId) { if (string.IsNullOrWhiteSpace(organization)) { throw new ArgumentException($"'{nameof(organization)}' cannot be null or whitespace.", nameof(organization)); } if (string.IsNullOrWhiteSpace(projectName)) { throw new ArgumentException($"'{nameof(projectName)}' cannot be null or whitespace.", nameof(projectName)); } if (string.IsNullOrWhiteSpace(userId)) { throw new ArgumentException($"'{nameof(userId)}' cannot be null or whitespace.", nameof(userId)); } VssConnection connection = null; GraphHttpClient graphHttpClient = null; TeamHttpClient teamClient = null; var result = false; try { string url = $"https://dev.azure.com/{organization}"; if (_adoConfig.UsePta) { connection = new VssConnection(new Uri(url), new VssBasicCredential(string.Empty, _adoConfig.AdoPersonalAccessToken)); } else { //connection = new VssConnection(new Uri(url), new VssCredentials(true)); connection = new VssConnection(new Uri(url), new VssClientCredentials(true)); } teamClient = connection.GetClient <TeamHttpClient>(); var allteams = await teamClient.GetTeamsAsync(projectName, null, null, null, true); var defTeamGroupName = $"{projectName} Team"; var defTeam = allteams?.FirstOrDefault(a => a.Name.Contains(defTeamGroupName)); if (defTeam != null) { //var members = await teamClient.GetTeamMembersWithExtendedPropertiesAsync(projectName, defTeam.Id.ToString()); graphHttpClient = connection.GetClient <GraphHttpClient>(); List <SubjectDescriptor> groupSubjectDescriptors = new(); groupSubjectDescriptors.Add(SubjectDescriptor.FromString(defTeam.Identity.Descriptor.Identifier)); var contextCreate = new GraphUserPrincipalNameCreationContext { PrincipalName = userId }; var added = await graphHttpClient.CreateUserAsync(contextCreate, groupSubjectDescriptors); //var membersAfter = await teamClient.GetTeamMembersWithExtendedPropertiesAsync(projectName, defTeam.Id.ToString()); result = true; } } catch (Exception ex) { //Console.WriteLine("Exception during create project: ", ex.Message); throw; } finally { connection?.Dispose(); graphHttpClient?.Dispose(); teamClient?.Dispose(); } return(result); }