private async Task CreateChannelCSEntryChanges(string groupid, SchemaType schemaType) { if (!this.context.Types.Types.Contains("channel")) { return; } var channels = await GraphHelperTeams.GetChannels(this.betaClient, groupid, this.token); foreach (var channel in channels) { var members = await GraphHelperTeams.GetChannelMembers(this.betaClient, groupid, channel.Id, this.token); CSEntryChange c = CSEntryChange.Create(); c.ObjectType = "channel"; c.ObjectModificationType = ObjectModificationType.Add; c.AnchorAttributes.Add(AnchorAttribute.Create("id", channel.Id)); c.DN = channel.Id; c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("displayName", channel.DisplayName)); if (!string.IsNullOrWhiteSpace(channel.Description)) { c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("description", channel.Description)); } if (members.Count > 0) { c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("member", members.Select(t => t.Id).ToList <object>())); } this.context.ImportItems.Add(c, this.token); } }
private async Task <CSEntryChangeResult> PutCSEntryChangeDelete(CSEntryChange csentry) { string teamid = csentry.GetAnchorValueOrDefault <string>("teamid"); try { if (this.context.ConfigParameters[ConfigParameterNames.RandomizeChannelNameOnDelete].Value == "1") { string newname = $"deleted-{Guid.NewGuid():N}"; Beta.Channel c = new Beta.Channel(); c.DisplayName = newname; await GraphHelperTeams.UpdateChannel(this.betaClient, teamid, csentry.DN, c, this.token); logger.Info($"Renamed channel {csentry.DN} on team {teamid} to {newname}"); } await GraphHelperTeams.DeleteChannel(this.betaClient, teamid, csentry.DN, this.token); } catch (ServiceException ex) { if (ex.StatusCode == HttpStatusCode.NotFound) { logger.Warn($"The request to delete the channel {csentry.DN} failed because it doesn't exist"); } else { throw; } } return(CSEntryChangeResult.Create(csentry.Identifier, null, MAExportError.Success)); }
private async Task PutCSEntryChangeUpdateUnarchive(CSEntryChange csentry) { string teamid = csentry.GetAnchorValueOrDefault <string>("id"); logger.Trace($"Unarchiving team: {teamid}"); await GraphHelperTeams.UnarchiveTeam(this.betaClient, teamid, this.token); logger.Info($"Team successfully unarchived: {teamid}"); }
private async Task PutCSEntryChangeUpdateArchive(CSEntryChange csentry) { string teamid = csentry.GetAnchorValueOrDefault <string>("id"); logger.Trace($"Archiving team: {teamid}"); await GraphHelperTeams.ArchiveTeam(this.betaClient, teamid, this.context.ConfigParameters.GetBoolValueOrDefault(ConfigParameterNames.SetSpoReadOnly), this.token); logger.Info($"Team successfully archived: {teamid}"); }
private async Task <CSEntryChangeResult> PutCSEntryChangeAdd(CSEntryChange csentry) { string teamid = csentry.GetValueAdd <string>("team"); if (teamid == null) { logger.Error($"Export of item {csentry.DN} failed as no 'team' attribute was provided\r\n{string.Join(",", csentry.ChangedAttributeNames)}"); return(CSEntryChangeResult.Create(csentry.Identifier, null, MAExportError.ExportActionRetryReferenceAttribute)); } Beta.Channel c = new Beta.Channel(); c.DisplayName = csentry.GetValueAdd <string>("displayName"); c.Description = csentry.GetValueAdd <string>("description"); // 2020-05-15 This currently doesn't come in with a GET request, so for now, it needs to be initial-flow only // https://github.com/microsoftgraph/microsoft-graph-docs/issues/6792 c.IsFavoriteByDefault = csentry.HasAttributeChange("isFavoriteByDefault") && csentry.GetValueAdd <bool>("isFavoriteByDefault"); if (csentry.ObjectType == "privateChannel") { if (!csentry.HasAttributeChangeAdd("owner")) { throw new InvalidProvisioningStateException("At least one owner must be specified when creating a channel"); } string ownerID = csentry.GetValueAdds <string>("owner").First(); c.MembershipType = Beta.ChannelMembershipType.Private; c.AdditionalData = new Dictionary <string, object>(); c.AdditionalData.Add("members", new[] { GraphHelperTeams.CreateAadUserConversationMember(ownerID, "owner") }); } logger.Trace($"{csentry.DN}: Channel data: {JsonConvert.SerializeObject(c)}"); var channel = await GraphHelperTeams.CreateChannel(this.betaClient, teamid, c, this.token); logger.Trace($"Created channel {channel.Id} for team {teamid}"); if (csentry.ObjectType == "privateChannel") { await this.PutMemberChanges(csentry, teamid, channel.Id); } List <AttributeChange> anchorChanges = new List <AttributeChange>(); anchorChanges.Add(AttributeChange.CreateAttributeAdd("id", channel.Id)); anchorChanges.Add(AttributeChange.CreateAttributeAdd("teamid", teamid)); return(CSEntryChangeResult.Create(csentry.Identifier, anchorChanges, MAExportError.Success)); }
public static async Task <string> CreateTeam(Beta.GraphServiceClient client, Beta.Team team, CancellationToken token) { TeamsAsyncOperation result = await GraphHelperTeams.SubmitTeamCreateRequestAndWait(client, team, token); if (result.Status == TeamsAsyncOperationStatus.Succeeded) { return(result.TargetResourceId); } string serializedResponse = JsonConvert.SerializeObject(result); logger.Error($"Team creation failed\r\n{serializedResponse}"); throw new ServiceException(new Error() { Code = result.Error.Code, AdditionalData = result.Error.AdditionalData, Message = result.Error.Message }); }
private async Task PutCSEntryChangeUpdateTeam(CSEntryChange csentry) { string teamid = csentry.GetAnchorValueOrDefault <string>("id"); Beta.Team team = new Beta.Team(); team.MemberSettings = new Beta.TeamMemberSettings(); team.MemberSettings.ODataType = null; team.GuestSettings = new Beta.TeamGuestSettings(); team.GuestSettings.ODataType = null; team.MessagingSettings = new Beta.TeamMessagingSettings(); team.MessagingSettings.ODataType = null; team.FunSettings = new Beta.TeamFunSettings(); team.FunSettings.ODataType = null; bool changed = false; foreach (AttributeChange change in csentry.AttributeChanges) { if (!SchemaProvider.TeamsProperties.Contains(change.Name)) { continue; } if (change.Name == "visibility") { throw new InitialFlowAttributeModificationException("visibility"); } else if (change.Name == "template") { throw new InitialFlowAttributeModificationException("template"); } if (change.ModificationType == AttributeModificationType.Delete) { if (change.DataType == AttributeType.Boolean) { throw new UnsupportedBooleanAttributeDeleteException(change.Name); } else { throw new UnsupportedAttributeModificationException($"Deleting the value of attribute {change.Name} is not supported"); } } if (change.Name == "memberSettings_allowCreateUpdateChannels") { team.MemberSettings.AllowCreateUpdateChannels = change.GetValueAdd <bool>(); } else if (change.Name == "memberSettings_allowDeleteChannels") { team.MemberSettings.AllowDeleteChannels = change.GetValueAdd <bool>(); } else if (change.Name == "memberSettings_allowAddRemoveApps") { team.MemberSettings.AllowAddRemoveApps = change.GetValueAdd <bool>(); } else if (change.Name == "memberSettings_allowCreateUpdateRemoveTabs") { team.MemberSettings.AllowCreateUpdateRemoveTabs = change.GetValueAdd <bool>(); } else if (change.Name == "memberSettings_allowCreateUpdateRemoveConnectors") { team.MemberSettings.AllowCreateUpdateRemoveConnectors = change.GetValueAdd <bool>(); } else if (change.Name == "guestSettings_allowCreateUpdateChannels") { team.GuestSettings.AllowCreateUpdateChannels = change.GetValueAdd <bool>(); } else if (change.Name == "guestSettings_allowDeleteChannels") { team.GuestSettings.AllowDeleteChannels = change.GetValueAdd <bool>(); } else if (change.Name == "messagingSettings_allowUserEditMessages") { team.MessagingSettings.AllowUserEditMessages = change.GetValueAdd <bool>(); } else if (change.Name == "messagingSettings_allowUserDeleteMessages") { team.MessagingSettings.AllowUserDeleteMessages = change.GetValueAdd <bool>(); } else if (change.Name == "messagingSettings_allowOwnerDeleteMessages") { team.MessagingSettings.AllowOwnerDeleteMessages = change.GetValueAdd <bool>(); } else if (change.Name == "messagingSettings_allowTeamMentions") { team.MessagingSettings.AllowTeamMentions = change.GetValueAdd <bool>(); } else if (change.Name == "messagingSettings_allowChannelMentions") { team.MessagingSettings.AllowChannelMentions = change.GetValueAdd <bool>(); } else if (change.Name == "funSettings_allowGiphy") { team.FunSettings.AllowGiphy = change.GetValueAdd <bool>(); } else if (change.Name == "funSettings_giphyContentRating") { string value = change.GetValueAdd <string>(); if (!Enum.TryParse <Beta.GiphyRatingType>(value, false, out Beta.GiphyRatingType result)) { throw new UnsupportedAttributeModificationException($"The value '{result}' provided for attribute 'funSettings_giphyContentRating' was not supported. Allowed values are {string.Join(",", Enum.GetNames(typeof(Beta.GiphyRatingType)))}"); } team.FunSettings.GiphyContentRating = result; } else if (change.Name == "funSettings_allowStickersAndMemes") { team.FunSettings.AllowStickersAndMemes = change.GetValueAdd <bool>(); } else if (change.Name == "funSettings_allowCustomMemes") { team.FunSettings.AllowCustomMemes = change.GetValueAdd <bool>(); } else { continue; } changed = true; } if (changed) { logger.Trace($"{csentry.DN}:Updating team data: {JsonConvert.SerializeObject(team)}"); await GraphHelperTeams.UpdateTeam(this.betaClient, teamid, team, this.token); logger.Info($"{csentry.DN}: Updated team"); } }
private async Task <CSEntryChangeResult> PutCSEntryChangeUpdate(CSEntryChange csentry) { string teamid = csentry.GetAnchorValueOrDefault <string>("id"); bool archive = false; bool unarchive = false; if (csentry.HasAttributeChange("isArchived")) { logger.Trace("Archive state is changing"); if (csentry.AttributeChanges["isArchived"].ModificationType == AttributeModificationType.Delete) { throw new UnsupportedBooleanAttributeDeleteException("isArchived"); } var team = await GraphHelperTeams.GetTeam(this.betaClient, teamid, this.token); bool currentState = false; if (team.IsArchived == null) { logger.Trace("Current archive state value was null"); } else { currentState = team.IsArchived.Value; } logger.Trace($"Teams current archive state is {currentState}"); bool futureState = csentry.GetValueAdd <bool>("isArchived"); logger.Trace($"Requested archive state is {futureState}"); if (futureState != currentState) { if (futureState) { archive = true; logger.Trace("Flagging team for archiving"); } else { unarchive = true; logger.Trace("Flagging team for unarchiving"); } } else { logger.Trace("Current archive state matches target archive state"); } } else { logger.Trace("Archive state has not changed"); } if (unarchive) { await this.PutCSEntryChangeUpdateUnarchive(csentry); } await this.PutCSEntryChangeUpdateTeam(csentry); if (archive) { await this.PutCSEntryChangeUpdateArchive(csentry); } await this.PutCSEntryChangeUpdateGroup(csentry); return(CSEntryChangeResult.Create(csentry.Identifier, null, MAExportError.Success)); }
private async Task <string> CreateTeam(CSEntryChange csentry, Beta.GraphServiceClient client, string ownerId) { var team = new Beta.Team { MemberSettings = new Beta.TeamMemberSettings(), GuestSettings = new Beta.TeamGuestSettings(), MessagingSettings = new Beta.TeamMessagingSettings(), FunSettings = new Beta.TeamFunSettings(), ODataType = null }; team.MemberSettings.ODataType = null; team.GuestSettings.ODataType = null; team.MessagingSettings.ODataType = null; team.FunSettings.ODataType = null; team.AdditionalData = new Dictionary <string, object>(); team.DisplayName = csentry.GetValueAdd <string>("displayName"); team.Description = csentry.GetValueAdd <string>("description"); if (csentry.HasAttributeChange("visibility")) { string visibility = csentry.GetValueAdd <string>("visibility"); if (Enum.TryParse(visibility, out Beta.TeamVisibilityType result)) { team.Visibility = result; } else { throw new UnsupportedAttributeModificationException($"The value '{visibility}' provided for attribute 'visibility' was not supported. Allowed values are {string.Join(",", Enum.GetNames(typeof(Beta.TeamVisibilityType)))}"); } } string template = csentry.GetValueAdd <string>("template") ?? "https://graph.microsoft.com/beta/teamsTemplates('standard')"; if (!string.IsNullOrWhiteSpace(template)) { team.AdditionalData.Add("*****@*****.**", template); } team.AdditionalData.Add("*****@*****.**", new string[] { $"https://graph.microsoft.com/v1.0/users('{ownerId}')" }); team.MemberSettings.AllowCreateUpdateChannels = csentry.HasAttributeChange("memberSettings_allowCreateUpdateChannels") ? csentry.GetValueAdd <bool>("memberSettings_allowCreateUpdateChannels") : default(bool?); team.MemberSettings.AllowDeleteChannels = csentry.HasAttributeChange("memberSettings_allowDeleteChannels") ? csentry.GetValueAdd <bool>("memberSettings_allowDeleteChannels") : default(bool?); team.MemberSettings.AllowAddRemoveApps = csentry.HasAttributeChange("memberSettings_allowAddRemoveApps") ? csentry.GetValueAdd <bool>("memberSettings_allowAddRemoveApps") : default(bool?); team.MemberSettings.AllowCreateUpdateRemoveTabs = csentry.HasAttributeChange("memberSettings_allowCreateUpdateRemoveTabs") ? csentry.GetValueAdd <bool>("memberSettings_allowCreateUpdateRemoveTabs") : default(bool?); team.MemberSettings.AllowCreateUpdateRemoveConnectors = csentry.HasAttributeChange("memberSettings_allowCreateUpdateRemoveConnectors") ? csentry.GetValueAdd <bool>("memberSettings_allowCreateUpdateRemoveConnectors") : default(bool?); team.GuestSettings.AllowCreateUpdateChannels = csentry.HasAttributeChange("guestSettings_allowCreateUpdateChannels") ? csentry.GetValueAdd <bool>("guestSettings_allowCreateUpdateChannels") : default(bool?); team.GuestSettings.AllowDeleteChannels = csentry.HasAttributeChange("guestSettings_allowDeleteChannels") ? csentry.GetValueAdd <bool>("guestSettings_allowDeleteChannels") : default(bool?); team.MessagingSettings.AllowUserEditMessages = csentry.HasAttributeChange("messagingSettings_allowUserEditMessages") ? csentry.GetValueAdd <bool>("messagingSettings_allowUserEditMessages") : default(bool?); team.MessagingSettings.AllowUserDeleteMessages = csentry.HasAttributeChange("messagingSettings_allowUserDeleteMessages") ? csentry.GetValueAdd <bool>("messagingSettings_allowUserDeleteMessages") : default(bool?); team.MessagingSettings.AllowOwnerDeleteMessages = csentry.HasAttributeChange("messagingSettings_allowOwnerDeleteMessages") ? csentry.GetValueAdd <bool>("messagingSettings_allowOwnerDeleteMessages") : default(bool?); team.MessagingSettings.AllowTeamMentions = csentry.HasAttributeChange("messagingSettings_allowTeamMentions") ? csentry.GetValueAdd <bool>("messagingSettings_allowTeamMentions") : default(bool?); team.MessagingSettings.AllowChannelMentions = csentry.HasAttributeChange("messagingSettings_allowChannelMentions") ? csentry.GetValueAdd <bool>("messagingSettings_allowChannelMentions") : default(bool?); team.FunSettings.AllowGiphy = csentry.HasAttributeChange("funSettings_allowGiphy") ? csentry.GetValueAdd <bool>("funSettings_allowGiphy") : default(bool?); team.FunSettings.AllowStickersAndMemes = csentry.HasAttributeChange("funSettings_allowStickersAndMemes") ? csentry.GetValueAdd <bool>("funSettings_allowStickersAndMemes") : default(bool?); team.FunSettings.AllowCustomMemes = csentry.HasAttributeChange("funSettings_allowCustomMemes") ? csentry.GetValueAdd <bool>("funSettings_allowCustomMemes") : default(bool?); string gcr = csentry.GetValueAdd <string>("funSettings_giphyContentRating"); if (!string.IsNullOrWhiteSpace(gcr)) { if (!Enum.TryParse(gcr, false, out Beta.GiphyRatingType grt)) { throw new UnsupportedAttributeModificationException($"The value '{gcr}' provided for attribute 'funSettings_giphyContentRating' was not supported. Allowed values are {string.Join(",", Enum.GetNames(typeof(Beta.GiphyRatingType)))}"); } team.FunSettings.GiphyContentRating = grt; } logger.Info($"{csentry.DN}: Creating team using template {template ?? "standard"}"); logger.Trace($"{csentry.DN}: Team data: {JsonConvert.SerializeObject(team)}"); var tresult = await GraphHelperTeams.CreateTeam(client, team, this.token); logger.Info($"{csentry.DN}: Created team {tresult}"); await Task.Delay(TimeSpan.FromSeconds(MicrosoftTeamsMAConfigSection.Configuration.PostGroupCreateDelay), this.token); return(tresult); }
private async Task PutCSEntryChangeUpdateTeam(CSEntryChange csentry) { Beta.Team team = new Beta.Team(); team.MemberSettings = new Beta.TeamMemberSettings(); team.MemberSettings.ODataType = null; team.GuestSettings = new Beta.TeamGuestSettings(); team.GuestSettings.ODataType = null; team.MessagingSettings = new Beta.TeamMessagingSettings(); team.MessagingSettings.ODataType = null; team.FunSettings = new Beta.TeamFunSettings(); team.FunSettings.ODataType = null; bool changed = false; foreach (AttributeChange change in csentry.AttributeChanges) { if (!SchemaProvider.TeamsFromGroupProperties.Contains(change.Name)) { continue; } if (change.ModificationType == AttributeModificationType.Delete) { throw new UnknownOrUnsupportedModificationTypeException($"The property {change.Name} cannot be deleted. If it is a boolean value, set it to false"); } if (change.Name == "template") { throw new UnexpectedDataException("The template parameter can only be supplied during an 'add' operation"); } else if (change.Name == "isArchived") { team.IsArchived = change.GetValueAdd <bool>(); } else if (change.Name == "memberSettings_allowCreateUpdateChannels") { team.MemberSettings.AllowCreateUpdateChannels = change.GetValueAdd <bool>(); } else if (change.Name == "memberSettings_allowDeleteChannels") { team.MemberSettings.AllowDeleteChannels = change.GetValueAdd <bool>(); } else if (change.Name == "memberSettings_allowAddRemoveApps") { team.MemberSettings.AllowAddRemoveApps = change.GetValueAdd <bool>(); } else if (change.Name == "memberSettings_allowCreateUpdateRemoveTabs") { team.MemberSettings.AllowCreateUpdateRemoveTabs = change.GetValueAdd <bool>(); } else if (change.Name == "memberSettings_allowCreateUpdateRemoveConnectors") { team.MemberSettings.AllowCreateUpdateRemoveConnectors = change.GetValueAdd <bool>(); } else if (change.Name == "guestSettings_allowCreateUpdateChannels") { team.GuestSettings.AllowCreateUpdateChannels = change.GetValueAdd <bool>(); } else if (change.Name == "guestSettings_allowDeleteChannels") { team.GuestSettings.AllowDeleteChannels = change.GetValueAdd <bool>(); } else if (change.Name == "messagingSettings_allowUserEditMessages") { team.MessagingSettings.AllowUserEditMessages = change.GetValueAdd <bool>(); } else if (change.Name == "messagingSettings_allowUserDeleteMessages") { team.MessagingSettings.AllowUserDeleteMessages = change.GetValueAdd <bool>(); } else if (change.Name == "messagingSettings_allowOwnerDeleteMessages") { team.MessagingSettings.AllowOwnerDeleteMessages = change.GetValueAdd <bool>(); } else if (change.Name == "messagingSettings_allowTeamMentions") { team.MessagingSettings.AllowTeamMentions = change.GetValueAdd <bool>(); } else if (change.Name == "messagingSettings_allowChannelMentions") { team.MessagingSettings.AllowChannelMentions = change.GetValueAdd <bool>(); } else if (change.Name == "funSettings_allowGiphy") { team.FunSettings.AllowGiphy = change.GetValueAdd <bool>(); } else if (change.Name == "funSettings_giphyContentRating") { string value = change.GetValueAdd <string>(); if (!Enum.TryParse <Beta.GiphyRatingType>(value, false, out Beta.GiphyRatingType result)) { throw new UnexpectedDataException($"The value '{value}' was not a supported value for funSettings_giphyContentRating. Supported values are (case sensitive) 'Strict' or 'Moderate'"); } team.FunSettings.GiphyContentRating = result; } else if (change.Name == "funSettings_allowStickersAndMemes") { team.FunSettings.AllowStickersAndMemes = change.GetValueAdd <bool>(); } else if (change.Name == "funSettings_allowCustomMemes") { team.FunSettings.AllowCustomMemes = change.GetValueAdd <bool>(); } else { continue; } changed = true; } if (changed) { logger.Trace($"{csentry.DN}:Updating team data: {JsonConvert.SerializeObject(team)}"); await GraphHelperTeams.UpdateTeam(this.betaClient, csentry.DN, team, this.token); logger.Info($"{csentry.DN}: Updated team"); } }
private async Task CreateTeam(CSEntryChange csentry, string groupId) { Beta.Team team = new Beta.Team { MemberSettings = new Beta.TeamMemberSettings(), GuestSettings = new Beta.TeamGuestSettings(), MessagingSettings = new Beta.TeamMessagingSettings(), FunSettings = new Beta.TeamFunSettings(), ODataType = null }; team.MemberSettings.ODataType = null; team.GuestSettings.ODataType = null; team.MessagingSettings.ODataType = null; team.FunSettings.ODataType = null; team.AdditionalData = new Dictionary <string, object>(); string template = csentry.GetValueAdd <string>("template") ?? "https://graph.microsoft.com/beta/teamsTemplates('standard')"; // if (!string.IsNullOrWhiteSpace(template)) // { // team.AdditionalData.Add("*****@*****.**", template); //"https://graph.microsoft.com/beta/teamsTemplates('standard')" // } //team.AdditionalData.Add("*****@*****.**", $"https://graph.microsoft.com/v1.0/groups('{groupId}')"); team.MemberSettings.AllowCreateUpdateChannels = csentry.HasAttributeChange("memberSettings_allowCreateUpdateChannels") ? csentry.GetValueAdd <bool>("memberSettings_allowCreateUpdateChannels") : default(bool?); team.MemberSettings.AllowDeleteChannels = csentry.HasAttributeChange("memberSettings_allowDeleteChannels") ? csentry.GetValueAdd <bool>("memberSettings_allowDeleteChannels") : default(bool?); team.MemberSettings.AllowAddRemoveApps = csentry.HasAttributeChange("memberSettings_allowAddRemoveApps") ? csentry.GetValueAdd <bool>("memberSettings_allowAddRemoveApps") : default(bool?); team.MemberSettings.AllowCreateUpdateRemoveTabs = csentry.HasAttributeChange("memberSettings_allowCreateUpdateRemoveTabs") ? csentry.GetValueAdd <bool>("memberSettings_allowCreateUpdateRemoveTabs") : default(bool?); team.MemberSettings.AllowCreateUpdateRemoveConnectors = csentry.HasAttributeChange("memberSettings_allowCreateUpdateRemoveConnectors") ? csentry.GetValueAdd <bool>("memberSettings_allowCreateUpdateRemoveConnectors") : default(bool?); team.GuestSettings.AllowCreateUpdateChannels = csentry.HasAttributeChange("guestSettings_allowCreateUpdateChannels") ? csentry.GetValueAdd <bool>("guestSettings_allowCreateUpdateChannels") : default(bool?); team.GuestSettings.AllowCreateUpdateChannels = csentry.HasAttributeChange("guestSettings_allowDeleteChannels") ? csentry.GetValueAdd <bool>("guestSettings_allowDeleteChannels") : default(bool?); team.MessagingSettings.AllowUserEditMessages = csentry.HasAttributeChange("messagingSettings_allowUserEditMessages") ? csentry.GetValueAdd <bool>("messagingSettings_allowUserEditMessages") : default(bool?); team.MessagingSettings.AllowUserDeleteMessages = csentry.HasAttributeChange("messagingSettings_allowUserDeleteMessages") ? csentry.GetValueAdd <bool>("messagingSettings_allowUserDeleteMessages") : default(bool?); team.MessagingSettings.AllowOwnerDeleteMessages = csentry.HasAttributeChange("messagingSettings_allowOwnerDeleteMessages") ? csentry.GetValueAdd <bool>("messagingSettings_allowOwnerDeleteMessages") : default(bool?); team.MessagingSettings.AllowTeamMentions = csentry.HasAttributeChange("messagingSettings_allowTeamMentions") ? csentry.GetValueAdd <bool>("messagingSettings_allowTeamMentions") : default(bool?); team.MessagingSettings.AllowChannelMentions = csentry.HasAttributeChange("messagingSettings_allowChannelMentions") ? csentry.GetValueAdd <bool>("messagingSettings_allowChannelMentions") : default(bool?); team.FunSettings.AllowGiphy = csentry.HasAttributeChange("funSettings_allowGiphy") ? csentry.GetValueAdd <bool>("funSettings_allowGiphy") : default(bool?); team.FunSettings.AllowStickersAndMemes = csentry.HasAttributeChange("funSettings_allowStickersAndMemes") ? csentry.GetValueAdd <bool>("funSettings_allowStickersAndMemes") : default(bool?); team.FunSettings.AllowCustomMemes = csentry.HasAttributeChange("funSettings_allowCustomMemes") ? csentry.GetValueAdd <bool>("funSettings_allowCustomMemes") : default(bool?); string gcr = csentry.GetValueAdd <string>("funSettings_giphyContentRating"); if (!string.IsNullOrWhiteSpace(gcr)) { if (!Enum.TryParse(gcr, false, out Beta.GiphyRatingType grt)) { throw new UnexpectedDataException($"The value '{gcr}' was not a supported value for funSettings_giphyContentRating. Supported values are (case sensitive) 'Strict' or 'Moderate'"); } team.FunSettings.GiphyContentRating = grt; } logger.Info($"{csentry.DN}: Creating team for group {groupId} using template {template ?? "standard"}"); logger.Trace($"{csentry.DN}: Team data: {JsonConvert.SerializeObject(team)}"); Beta.Team tresult = await GraphHelperTeams.CreateTeamFromGroup(this.betaClient, groupId, team, this.token); logger.Info($"{csentry.DN}: Created team {tresult?.Id ?? "<unknown id>"} for group {groupId}"); }
private async Task PutMemberChanges(CSEntryChange csentry, string teamid, string channelid) { if (!csentry.HasAttributeChange("member") && !csentry.HasAttributeChange("owner")) { return; } IList <string> memberAdds = csentry.GetValueAdds <string>("member"); IList <string> memberDeletes = csentry.GetValueDeletes <string>("member"); IList <string> ownerAdds = csentry.GetValueAdds <string>("owner"); IList <string> ownerDeletes = csentry.GetValueDeletes <string>("owner"); if (csentry.ObjectModificationType == ObjectModificationType.Add) { if (ownerAdds.Count > 0) { ownerAdds.RemoveAt(0); } } if (csentry.HasAttributeChangeDelete("member") || csentry.HasAttributeChangeDelete("owner")) { var existingMembership = await GraphHelperTeams.GetChannelMembers(this.betaClient, teamid, channelid, this.token); if (csentry.HasAttributeChangeDelete("member")) { memberDeletes = existingMembership.Where(t => !this.userFilter.ShouldExclude(t.Id, this.token) && (t.Roles == null || !t.Roles.Any(u => string.Equals(u, "owner", StringComparison.OrdinalIgnoreCase)))).Select(t => t.Id).ToList(); } if (csentry.HasAttributeChangeDelete("owner")) { ownerDeletes = existingMembership.Where(t => !this.userFilter.ShouldExclude(t.Id, this.token) && t.Roles != null && t.Roles.Any(u => string.Equals(u, "owner", StringComparison.OrdinalIgnoreCase))).Select(t => t.Id).ToList(); } } var memberUpgradesToOwners = memberDeletes.Intersect(ownerAdds).ToList(); foreach (var m in memberUpgradesToOwners) { memberDeletes.Remove(m); ownerAdds.Remove(m); } var ownerDowngradeToMembers = ownerDeletes.Intersect(memberAdds).ToList(); foreach (var m in ownerDowngradeToMembers) { memberAdds.Remove(m); ownerDeletes.Remove(m); } List <Beta.AadUserConversationMember> cmToAdd = new List <Beta.AadUserConversationMember>(); List <Beta.AadUserConversationMember> cmToDelete = new List <Beta.AadUserConversationMember>(); List <Beta.AadUserConversationMember> cmToUpdate = new List <Beta.AadUserConversationMember>(); foreach (var m in memberDeletes) { cmToDelete.Add(GraphHelperTeams.CreateAadUserConversationMember(m)); } // If we try to delete the last owner on a channel, the operation will fail. If we are swapping out the full set of owners (eg an add/delete of 100 owners), this will never succeed if we do a 'delete' operation first. // If we do an 'add' operation first, and the channel already has the maximum number of owners, the call will fail. // So the order of events should be to // 1) Process all membership removals except for one owner (100-99 = 1 owner) // 2) Process all membership adds except for one owner (1 + 99 = 100 owners) // 3) Remove the final owner (100 - 1 = 99 owners) // 4) Add the final owner (99 + 1 = 100 owners) string lastOwnerToRemove = null; if (ownerDeletes.Count > 0) { lastOwnerToRemove = ownerDeletes[0]; ownerDeletes.RemoveAt(0); } string lastOwnerToAdd = null; if (ownerAdds.Count > 0) { lastOwnerToAdd = ownerAdds[0]; ownerAdds.RemoveAt(0); } foreach (var m in ownerDeletes) { cmToDelete.Add(GraphHelperTeams.CreateAadUserConversationMember(m)); } foreach (var m in memberAdds) { cmToAdd.Add(GraphHelperTeams.CreateAadUserConversationMember(m)); } foreach (var m in ownerAdds) { cmToAdd.Add(GraphHelperTeams.CreateAadUserConversationMember(m, "owner")); } foreach (var m in memberUpgradesToOwners) { cmToUpdate.Add(GraphHelperTeams.CreateAadUserConversationMember(m, "owner")); } foreach (var m in ownerDowngradeToMembers) { cmToUpdate.Add(GraphHelperTeams.CreateAadUserConversationMember(m, (string[])null)); } await GraphHelperTeams.RemoveChannelMembers(this.betaClient, teamid, channelid, cmToDelete, true, this.token); await GraphHelperTeams.UpdateChannelMembers(this.betaClient, teamid, channelid, cmToUpdate, this.token); await GraphHelperTeams.AddChannelMembers(this.betaClient, teamid, channelid, cmToAdd, true, this.token); if (lastOwnerToRemove != null) { cmToDelete.Clear(); cmToDelete.Add(GraphHelperTeams.CreateAadUserConversationMember(lastOwnerToRemove)); await GraphHelperTeams.RemoveChannelMembers(this.betaClient, teamid, channelid, cmToDelete, true, this.token); } if (lastOwnerToAdd != null) { cmToAdd.Clear(); cmToAdd.Add(GraphHelperTeams.CreateAadUserConversationMember(lastOwnerToAdd, "owner")); await GraphHelperTeams.AddChannelMembers(this.betaClient, teamid, channelid, cmToAdd, true, this.token); } logger.Info($"Membership modification for channel {teamid}:{channelid} completed. Members added: {memberAdds.Count}, members removed: {memberDeletes.Count}, owners added: {ownerAdds.Count}, owners removed: {ownerDeletes.Count}, owners downgraded to members: {ownerDowngradeToMembers.Count}, members upgraded to owners: {memberUpgradesToOwners.Count}"); }
private async Task PutCSEntryChangeUpdateChannel(CSEntryChange csentry) { string teamid = csentry.GetAnchorValueOrDefault <string>("teamid"); string channelid = csentry.GetAnchorValueOrDefault <string>("id"); bool changed = false; Beta.Channel channel = new Beta.Channel(); foreach (AttributeChange change in csentry.AttributeChanges) { if (change.DataType == AttributeType.Boolean && change.ModificationType == AttributeModificationType.Delete) { throw new UnsupportedBooleanAttributeDeleteException(change.Name); } if (change.Name == "team") { throw new InitialFlowAttributeModificationException(change.Name); } else if (change.Name == "isFavoriteByDefault") { channel.IsFavoriteByDefault = change.GetValueAdd <bool>(); } else if (change.Name == "displayName") { if (change.ModificationType == AttributeModificationType.Delete) { throw new UnsupportedAttributeDeleteException(change.Name); } channel.DisplayName = change.GetValueAdd <string>(); } else if (change.Name == "description") { if (change.ModificationType == AttributeModificationType.Delete) { channel.AssignNullToProperty("description"); } else { channel.Description = change.GetValueAdd <string>(); } } else { continue; } changed = true; } if (changed) { logger.Trace($"{csentry.DN}:Updating channel data: {JsonConvert.SerializeObject(channel)}"); await GraphHelperTeams.UpdateChannel(this.betaClient, teamid, channelid, channel, this.token); logger.Info($"{csentry.DN}: Updated channel"); } if (csentry.ObjectType == "privateChannel") { await this.PutMemberChanges(csentry, teamid, channelid); } }
public static async Task ArchiveTeam(Beta.GraphServiceClient client, string teamid, bool setSpoReadOnly, CancellationToken token) { await GraphHelperTeams.SubmitTeamArchiveRequestAndWait(client, teamid, setSpoReadOnly, token); }
private async Task TeamToCSEntryChange(CSEntryChange c, SchemaType schemaType) { Beta.Team team = await GraphHelperTeams.GetTeam(this.betaClient, c.DN, this.token); foreach (SchemaAttribute type in schemaType.Attributes) { switch (type.Name) { case "isArchived": c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(type.Name, team.IsArchived ?? false)); break; case "memberSettings_allowCreateUpdateChannels": c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(type.Name, team.MemberSettings.AllowCreateUpdateChannels ?? false)); break; case "memberSettings_allowDeleteChannels": c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(type.Name, team.MemberSettings.AllowDeleteChannels ?? false)); break; case "memberSettings_allowAddRemoveApps": c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(type.Name, team.MemberSettings.AllowAddRemoveApps ?? false)); break; case "memberSettings_allowCreateUpdateRemoveTabs": c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(type.Name, team.MemberSettings.AllowCreateUpdateRemoveTabs ?? false)); break; case "memberSettings_allowCreateUpdateRemoveConnectors": c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(type.Name, team.MemberSettings.AllowCreateUpdateRemoveConnectors ?? false)); break; case "guestSettings_allowCreateUpdateChannels": c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(type.Name, team.GuestSettings.AllowCreateUpdateChannels ?? false)); break; case "guestSettings_allowDeleteChannels": c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(type.Name, team.GuestSettings.AllowDeleteChannels ?? false)); break; case "messagingSettings_allowUserEditMessages": c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(type.Name, team.MessagingSettings.AllowUserEditMessages ?? false)); break; case "messagingSettings_allowUserDeleteMessages": c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(type.Name, team.MessagingSettings.AllowUserDeleteMessages ?? false)); break; case "messagingSettings_allowOwnerDeleteMessages": c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(type.Name, team.MessagingSettings.AllowOwnerDeleteMessages ?? false)); break; case "messagingSettings_allowTeamMentions": c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(type.Name, team.MessagingSettings.AllowTeamMentions ?? false)); break; case "messagingSettings_allowChannelMentions": c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(type.Name, team.MessagingSettings.AllowChannelMentions ?? false)); break; case "funSettings_allowGiphy": c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(type.Name, team.FunSettings.AllowGiphy ?? false)); break; case "funSettings_giphyContentRating": if (team.FunSettings.GiphyContentRating != null) { c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(type.Name, team.FunSettings.GiphyContentRating.ToString())); } break; case "funSettings_allowStickersAndMemes": c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(type.Name, team.FunSettings.AllowStickersAndMemes ?? false)); break; case "funSettings_allowCustomMemes": c.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(type.Name, team.FunSettings.AllowCustomMemes ?? false)); break; } } }
public static async Task UnarchiveTeam(Beta.GraphServiceClient client, string teamid, CancellationToken token) { await GraphHelperTeams.SubmitTeamUnarchiveRequestAndWait(client, teamid, token); }
private async Task CreateChannelCSEntryChanges(string groupid) { if (!this.context.Types.Types.Contains("publicChannel") && !this.context.Types.Types.Contains("privateChannel")) { return; } var channels = await GraphHelperTeams.GetChannels(this.betaClient, groupid, this.token); Regex regex = null; if (!string.IsNullOrWhiteSpace(this.context.ConfigParameters[ConfigParameterNames.ChannelNameFilter].Value)) { regex = new Regex(this.context.ConfigParameters[ConfigParameterNames.ChannelNameFilter].Value, RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase); } foreach (var channel in channels) { string objectType; if (channel.MembershipType.HasValue) { if (channel.MembershipType == Beta.ChannelMembershipType.UnknownFutureValue) { logger.Warn($"Ignoring unknown channel {channel.Id} of unknown type"); continue; } else { objectType = channel.MembershipType == Beta.ChannelMembershipType.Standard ? "publicChannel" : "privateChannel"; } } else { objectType = "publicChannel"; } if (!this.context.Types.Types.Contains(objectType)) { continue; } if (regex != null) { if (!regex.IsMatch(channel.DisplayName)) { logger.Trace($"Dropping channel {channel.Id} with display name {channel.DisplayName} as it did not match the regular expression filter"); continue; } } CSEntryChange c = CSEntryChange.Create(); c.ObjectModificationType = ObjectModificationType.Add; c.AnchorAttributes.Add(AnchorAttribute.Create("id", channel.Id)); c.AnchorAttributes.Add(AnchorAttribute.Create("teamid", groupid)); c.DN = channel.Id; c.ObjectType = objectType; c.CreateAttributeAdd("team", groupid); SchemaType schemaType = this.context.Types.Types[objectType]; if (schemaType.HasAttribute("displayName")) { c.CreateAttributeAdd("displayName", channel.DisplayName); } if (schemaType.HasAttribute("description") && !string.IsNullOrWhiteSpace(channel.Description)) { c.CreateAttributeAdd("description", channel.Description); } if (schemaType.HasAttribute("email") && !string.IsNullOrWhiteSpace(channel.Email)) { c.CreateAttributeAdd("email", channel.Email); } if (schemaType.HasAttribute("webUrl") && !string.IsNullOrWhiteSpace(channel.WebUrl)) { c.CreateAttributeAdd("webUrl", channel.WebUrl); } if (schemaType.HasAttribute("isFavoriteByDefault")) { c.CreateAttributeAdd("isFavoriteByDefault", channel.IsFavoriteByDefault ?? false); } if (channel.MembershipType == Beta.ChannelMembershipType.Private && (schemaType.HasAttribute("member") || schemaType.HasAttribute("owner"))) { List <Beta.AadUserConversationMember> members = await GraphHelperTeams.GetChannelMembers(this.betaClient, groupid, channel.Id, this.token); if (members.Count > 0) { List <object> memberList = new List <object>(); List <object> ownerList = new List <object>(); foreach (Beta.ConversationMember member in members) { string memberValue; if (member is Beta.AadUserConversationMember conMember) { memberValue = conMember.UserId; } else { if (member.AdditionalData == null) { logger.Warn("Member has no additional data and therefore no userId\r\n" + JsonConvert.SerializeObject(member)); continue; } if (!member.AdditionalData.ContainsKey("userId")) { logger.Warn("Member does not have userId\r\n" + JsonConvert.SerializeObject(member)); continue; } memberValue = member.AdditionalData["userId"] as string; } if (memberValue == null) { logger.Warn("Member userId was null\r\n" + JsonConvert.SerializeObject(member)); continue; } if (this.userFilter.ShouldExclude(memberValue, this.token)) { continue; } if (member.Roles.Contains("owner", StringComparer.OrdinalIgnoreCase)) { ownerList.Add(memberValue); } else { memberList.Add(memberValue); } } if (memberList.Count > 0 && schemaType.HasAttribute("member")) { c.CreateAttributeAdd("member", memberList); } if (ownerList.Count > 0 && schemaType.HasAttribute("owner")) { c.CreateAttributeAdd("owner", ownerList); } } } this.context.ImportItems.Add(c, this.token); } }