private async Task ApplyGroupPermissionsAsync( GraphService gService, GroupCollection allUsers, Guid projectId, PermissionSchemaManifest permissionEntry, VstsGroup targetGroup) { using var op = Insights.BeginOperation($"Updating membership of [{targetGroup.PrincipalName}]...", "GroupPermissions"); // get existing members - so later we can remove the unwanted members (no longer in yaml) var outdatedMembership = await gService.GetGroupMembersAsync(targetGroup.Descriptor); var survivorDescriptors = new List <string>(); if (permissionEntry.Membership.Groups != null && permissionEntry.Membership.Groups.Any()) { foreach (var gp in permissionEntry.Membership.Groups) { var groupObject = await GetGroupByNameAsync(IdentityOrigin.Aad.ToString(), gp.Name, gp.Id); if (groupObject != null) { await gService.AddMemberAsync(projectId, targetGroup.Descriptor, groupObject.Descriptor); survivorDescriptors.Add(groupObject.Descriptor); } } } if (permissionEntry.Membership.Users != null && permissionEntry.Membership.Users.Any()) { foreach (var user in permissionEntry.Membership.Users) { var userInfo = allUsers.Value.FirstOrDefault(u => u.OriginId.Equals(user.Id)); if (userInfo != null) { await gService.AddMemberAsync(projectId, targetGroup.Descriptor, userInfo.Descriptor); survivorDescriptors.Add(userInfo.Descriptor); } } } if (outdatedMembership != null && outdatedMembership.Members != null && outdatedMembership.Members.Any()) { foreach (var potentialOutdatedMember in outdatedMembership.Members) { var remainValid = survivorDescriptors .Exists(s => s.Contains(potentialOutdatedMember.MemberDescriptor, StringComparison.OrdinalIgnoreCase)); if (!remainValid) { await gService.RemoveMembershipAsync(projectId, targetGroup.Descriptor, potentialOutdatedMember.MemberDescriptor); } } } }
private static async Task <Group> CreateUnifiedGroupAsync(GraphService graphClient, CreateFlightTeamRequest request) { // Initialize members list with pilots and flight attendants var members = await graphClient.GetUserIds(request.Pilots, request.FlightAttendants); // Handle admins var admin = await graphClient.GetUserByUpn(request.Admin); var me = await graphClient.GetMe(); // Add admin and me as members members.Add($"https://graph.microsoft.com/beta/users/{admin.Id}"); members.Add($"https://graph.microsoft.com/beta/users/{me.Id}"); // Create owner list var owners = new List <string>() { $"https://graph.microsoft.com/beta/users/{admin.Id}", $"https://graph.microsoft.com/beta/users/{me.Id}" }; // Create the group var flightGroup = new Group { DisplayName = $"Flight {request.FlightNumber}", Description = request.Description, Visibility = "Private", MailEnabled = true, MailNickname = $"flight{request.FlightNumber}{GetTimestamp()}", GroupTypes = new string[] { "Unified" }, SecurityEnabled = false, Extension = new ProvisioningExtension { SharePointItemId = request.SharePointItemId }, Members = members.Distinct().ToList(), Owners = owners.Distinct().ToList() }; var createdGroup = await graphClient.CreateGroupAsync(flightGroup); logger.Info("Created group"); // Add catering liaison as a guest var guestInvite = new Invitation { InvitedUserEmailAddress = request.CateringLiaison, InviteRedirectUrl = "https://teams.microsoft.com", SendInvitationMessage = true }; var createdInvite = await graphClient.CreateGuestInvitationAsync(guestInvite); // Add guest user to team await graphClient.AddMemberAsync(createdGroup.Id, createdInvite.InvitedUser.Id); logger.Info("Added guest user"); return(createdGroup); }
public static async Task UpdateTeamAsync(FlightTeam originalTeam, FlightTeam updatedTeam) { // Look for changes that require an update via Graph // Did the admin change? var admin = await graphClient.GetUserByUpn(updatedTeam.Admin); updatedTeam.Admin = admin.Id; if (!admin.Id.Equals(originalTeam.Admin)) { // Add new owner await graphClient.AddMemberAsync(originalTeam.TeamId, admin.Id, true); // Remove old owner await graphClient.RemoveMemberAsync(originalTeam.TeamId, admin.Id, true); } bool isCrewChanged = false; // Add new pilots var newPilots = updatedTeam.Pilots.Except(originalTeam.Pilots); foreach (var pilot in newPilots) { isCrewChanged = true; var pilotUser = await graphClient.GetUserByUpn(pilot); await graphClient.AddMemberAsync(originalTeam.TeamId, pilotUser.Id); } if (newPilots.Count() > 0) { await TeamProvisioning.AddFlightToCalendars(updatedTeam, newPilots.ToList()); } // Remove any removed pilots var removedPilots = originalTeam.Pilots.Except(updatedTeam.Pilots); foreach (var pilot in removedPilots) { isCrewChanged = true; var pilotUser = await graphClient.GetUserByUpn(pilot); await graphClient.RemoveMemberAsync(originalTeam.TeamId, pilotUser.Id); } if (removedPilots.Count() > 0) { await TeamProvisioning.RemoveFlightFromCalendars(removedPilots.ToList(), updatedTeam.FlightNumber); } // Add new flight attendants var newFlightAttendants = updatedTeam.FlightAttendants.Except(originalTeam.FlightAttendants); foreach (var attendant in newFlightAttendants) { isCrewChanged = true; var attendantUser = await graphClient.GetUserByUpn(attendant); await graphClient.AddMemberAsync(originalTeam.TeamId, attendantUser.Id); } if (newFlightAttendants.Count() > 0) { await TeamProvisioning.AddFlightToCalendars(updatedTeam, newFlightAttendants.ToList()); } // Remove any removed flight attendants var removedFlightAttendants = originalTeam.FlightAttendants.Except(updatedTeam.FlightAttendants); foreach (var attendant in removedFlightAttendants) { isCrewChanged = true; var attendantUser = await graphClient.GetUserByUpn(attendant); await graphClient.RemoveMemberAsync(originalTeam.TeamId, attendantUser.Id); } if (removedFlightAttendants.Count() > 0) { await TeamProvisioning.RemoveFlightFromCalendars(removedFlightAttendants.ToList(), updatedTeam.FlightNumber); } // Swap out catering liaison if needed if (updatedTeam.CateringLiaison != null && !updatedTeam.CateringLiaison.Equals(originalTeam.CateringLiaison)) { var oldCateringLiaison = await graphClient.GetUserByEmail(originalTeam.CateringLiaison); await graphClient.RemoveMemberAsync(originalTeam.TeamId, oldCateringLiaison.Id); await AddGuestUser(originalTeam.TeamId, updatedTeam.CateringLiaison); } // Check for changes to gate, time bool isGateChanged = updatedTeam.DepartureGate != originalTeam.DepartureGate; bool isDepartureTimeChanged = updatedTeam.DepartureTime != originalTeam.DepartureTime; List <string> crew = null; string newGate = null; if (isCrewChanged || isGateChanged || isDepartureTimeChanged) { crew = await graphClient.GetUserIds(updatedTeam.Pilots, updatedTeam.FlightAttendants); newGate = isGateChanged ? updatedTeam.DepartureGate : null; logger.LogInformation("Updating flight in crew members' calendars"); if (isDepartureTimeChanged) { await TeamProvisioning.UpdateFlightInCalendars(crew, updatedTeam.FlightNumber, updatedTeam.DepartureGate, updatedTeam.DepartureTime); } else { await TeamProvisioning.UpdateFlightInCalendars(crew, updatedTeam.FlightNumber, updatedTeam.DepartureGate); } } if (isGateChanged || isDepartureTimeChanged) { var localTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"); string newDepartureTime = isDepartureTimeChanged ? TimeZoneInfo.ConvertTime(updatedTeam.DepartureTime, localTimeZone).ToString("g") : null; logger.LogInformation("Sending notification to crew members' devices"); await TeamProvisioning.SendDeviceNotifications(crew, updatedTeam.FlightNumber, newGate, newDepartureTime); } }