Example #1
0
        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));
        }
Example #3
0
        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}");
        }
Example #4
0
        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
            });
        }
Example #7
0
        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");
            }
        }
Example #8
0
        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));
        }
Example #9
0
        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);
 }
Example #15
0
        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);
            }
        }