Exemple #1
0
        /// <summary>
        /// Job that will sync groups.
        ///
        /// Called by the <see cref="IScheduler" /> when a
        /// <see cref="ITrigger" /> fires that is associated with
        /// the <see cref="IJob" />.
        /// </summary>
        public virtual void Execute(IJobExecutionContext context)
        {
            // Get the job setting(s)
            JobDataMap dataMap = context.JobDetail.JobDataMap;
            bool       requirePasswordReset = dataMap.GetBoolean("RequirePasswordReset");
            var        commandTimeout       = dataMap.GetString("CommandTimeout").AsIntegerOrNull() ?? 180;

            // Counters for displaying results
            int    groupsSynced  = 0;
            int    groupsChanged = 0;
            string groupName     = string.Empty;
            string dataViewName  = string.Empty;
            var    errors        = new List <string>();

            try
            {
                // get groups set to sync
                var activeSyncList = new List <GroupSyncInfo>();
                using (var rockContext = new RockContext())
                {
                    // Get groups that are not archived and are still active.
                    activeSyncList = new GroupSyncService(rockContext)
                                     .Queryable()
                                     .AsNoTracking()
                                     .AreNotArchived()
                                     .AreActive()
                                     .NeedToBeSynced()
                                     .Select(x => new GroupSyncInfo {
                        SyncId = x.Id, GroupName = x.Group.Name
                    })
                                     .ToList();
                }

                foreach (var syncInfo in activeSyncList)
                {
                    int  syncId         = syncInfo.SyncId;
                    bool hasSyncChanged = false;
                    context.UpdateLastStatusMessage($"Syncing group {syncInfo.GroupName}");

                    // Use a fresh rockContext per sync so that ChangeTracker doesn't get bogged down
                    using (var rockContext = new RockContext())
                    {
                        // increase the timeout just in case the data view source is slow
                        rockContext.Database.CommandTimeout = commandTimeout;
                        rockContext.SourceOfChange          = "Group Sync";

                        // Get the Sync
                        var sync = new GroupSyncService(rockContext)
                                   .Queryable()
                                   .Include(a => a.Group)
                                   .Include(a => a.SyncDataView)
                                   .AsNoTracking()
                                   .FirstOrDefault(s => s.Id == syncId);

                        if (sync == null || sync.SyncDataView.EntityTypeId != EntityTypeCache.Get(typeof(Person)).Id)
                        {
                            // invalid sync or invalid SyncDataView
                            continue;
                        }

                        List <string> syncErrors = new List <string>();

                        dataViewName = sync.SyncDataView.Name;
                        groupName    = sync.Group.Name;

                        Stopwatch stopwatch = Stopwatch.StartNew();
                        // Get the person id's from the data view (source)
                        var dataViewQry     = sync.SyncDataView.GetQuery(null, rockContext, commandTimeout, out syncErrors);
                        var sourcePersonIds = dataViewQry.Select(q => q.Id).ToList();
                        stopwatch.Stop();
                        DataViewService.AddRunDataViewTransaction(sync.SyncDataView.Id,
                                                                  Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds));
                        // If any error occurred trying get the 'where expression' from the sync-data-view,
                        // just skip trying to sync that particular group's Sync Data View for now.
                        if (syncErrors.Count > 0)
                        {
                            errors.AddRange(syncErrors);
                            ExceptionLogService.LogException(new Exception(string.Format("An error occurred while trying to GroupSync group '{0}' and data view '{1}' so the sync was skipped. Error: {2}", groupName, dataViewName, String.Join(",", syncErrors))));
                            continue;
                        }

                        // Get the person id's in the group (target) for the role being synced.
                        // Note: targetPersonIds must include archived group members
                        // so we don't try to delete anyone who's already archived, and
                        // it must include deceased members so we can remove them if they
                        // are no longer in the data view.
                        var existingGroupMemberPersonList = new GroupMemberService(rockContext)
                                                            .Queryable(true, true).AsNoTracking()
                                                            .Where(gm => gm.GroupId == sync.GroupId)
                                                            .Where(gm => gm.GroupRoleId == sync.GroupTypeRoleId)
                                                            .Select(gm => new
                        {
                            PersonId   = gm.PersonId,
                            IsArchived = gm.IsArchived
                        })
                                                            .ToList();

                        var targetPersonIdsToDelete = existingGroupMemberPersonList.Where(t => !sourcePersonIds.Contains(t.PersonId) && t.IsArchived != true).ToList();
                        if (targetPersonIdsToDelete.Any())
                        {
                            context.UpdateLastStatusMessage($"Deleting {targetPersonIdsToDelete.Count()} group records in {syncInfo.GroupName} that are no longer in the sync data view");
                        }

                        int deletedCount = 0;

                        // Delete people from the group/role that are no longer in the data view --
                        // but not the ones that are already archived.
                        foreach (var targetPerson in targetPersonIdsToDelete)
                        {
                            deletedCount++;
                            if (deletedCount % 100 == 0)
                            {
                                context.UpdateLastStatusMessage($"Deleted {deletedCount} of {targetPersonIdsToDelete.Count()} group member records for group {syncInfo.GroupName}");
                            }

                            try
                            {
                                // Use a new context to limit the amount of change-tracking required
                                using (var groupMemberContext = new RockContext())
                                {
                                    // Delete the records for that person's group and role.
                                    // NOTE: just in case there are duplicate records, delete all group member records for that person and role
                                    var groupMemberService = new GroupMemberService(groupMemberContext);
                                    foreach (var groupMember in groupMemberService
                                             .Queryable(true, true)
                                             .Where(m =>
                                                    m.GroupId == sync.GroupId &&
                                                    m.GroupRoleId == sync.GroupTypeRoleId &&
                                                    m.PersonId == targetPerson.PersonId)
                                             .ToList())
                                    {
                                        groupMemberService.Delete(groupMember);
                                    }

                                    groupMemberContext.SaveChanges();

                                    // If the Group has an exit email, and person has an email address, send them the exit email
                                    if (sync.ExitSystemCommunication != null)
                                    {
                                        var person = new PersonService(groupMemberContext).Get(targetPerson.PersonId);
                                        if (person.CanReceiveEmail(false))
                                        {
                                            // Send the exit email
                                            var mergeFields = new Dictionary <string, object>();
                                            mergeFields.Add("Group", sync.Group);
                                            mergeFields.Add("Person", person);
                                            var emailMessage = new RockEmailMessage(sync.ExitSystemCommunication);
                                            emailMessage.AddRecipient(new RockEmailMessageRecipient(person, mergeFields));
                                            var emailErrors = new List <string>();
                                            emailMessage.Send(out emailErrors);
                                            errors.AddRange(emailErrors);
                                        }
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                ExceptionLogService.LogException(ex);
                                continue;
                            }

                            hasSyncChanged = true;
                        }


                        // Now find all the people in the source list who are NOT already in the target list (as Unarchived)
                        var targetPersonIdsToAdd = sourcePersonIds.Where(s => !existingGroupMemberPersonList.Any(t => t.PersonId == s && t.IsArchived == false)).ToList();

                        // Make a list of PersonIds that have an Archived group member record
                        // if this person isn't already a member of the list as an Unarchived member, we can Restore the group member for that PersonId instead
                        var archivedTargetPersonIds = existingGroupMemberPersonList.Where(t => t.IsArchived == true).Select(a => a.PersonId).ToList();

                        context.UpdateLastStatusMessage($"Adding {targetPersonIdsToAdd.Count()} group member records for group {syncInfo.GroupName}");
                        int addedCount    = 0;
                        int notAddedCount = 0;
                        foreach (var personId in targetPersonIdsToAdd)
                        {
                            if ((addedCount + notAddedCount) % 100 == 0)
                            {
                                string notAddedMessage = string.Empty;
                                if (notAddedCount > 0)
                                {
                                    notAddedMessage = $"{Environment.NewLine} There are {notAddedCount} members that could not be added due to group requirements.";
                                }
                                context.UpdateLastStatusMessage($"Added {addedCount} of {targetPersonIdsToAdd.Count()} group member records for group {syncInfo.GroupName}. {notAddedMessage}");
                            }
                            try
                            {
                                // Use a new context to limit the amount of change-tracking required
                                using (var groupMemberContext = new RockContext())
                                {
                                    var groupMemberService = new GroupMemberService(groupMemberContext);
                                    var groupService       = new GroupService(groupMemberContext);

                                    // If this person is currently archived...
                                    if (archivedTargetPersonIds.Contains(personId))
                                    {
                                        // ...then we'll just restore them;
                                        GroupMember archivedGroupMember = groupService.GetArchivedGroupMember(sync.Group, personId, sync.GroupTypeRoleId);

                                        if (archivedGroupMember == null)
                                        {
                                            // shouldn't happen, but just in case
                                            continue;
                                        }

                                        archivedGroupMember.GroupMemberStatus = GroupMemberStatus.Active;
                                        if (archivedGroupMember.IsValidGroupMember(groupMemberContext))
                                        {
                                            addedCount++;
                                            groupMemberService.Restore(archivedGroupMember);
                                            groupMemberContext.SaveChanges();
                                        }
                                        else
                                        {
                                            notAddedCount++;
                                            // Validation errors will get added to the ValidationResults collection. Add those results to the log and then move on to the next person.
                                            var ex = new GroupMemberValidationException(string.Join(",", archivedGroupMember.ValidationResults.Select(r => r.ErrorMessage).ToArray()));
                                            ExceptionLogService.LogException(ex);
                                            continue;
                                        }
                                    }
                                    else
                                    {
                                        // ...otherwise we will add a new person to the group with the role specified in the sync.
                                        var newGroupMember = new GroupMember {
                                            Id = 0
                                        };
                                        newGroupMember.PersonId          = personId;
                                        newGroupMember.GroupId           = sync.GroupId;
                                        newGroupMember.GroupMemberStatus = GroupMemberStatus.Active;
                                        newGroupMember.GroupRoleId       = sync.GroupTypeRoleId;

                                        if (newGroupMember.IsValidGroupMember(groupMemberContext))
                                        {
                                            addedCount++;
                                            groupMemberService.Add(newGroupMember);
                                            groupMemberContext.SaveChanges();
                                        }
                                        else
                                        {
                                            notAddedCount++;
                                            // Validation errors will get added to the ValidationResults collection. Add those results to the log and then move on to the next person.
                                            var ex = new GroupMemberValidationException(string.Join(",", newGroupMember.ValidationResults.Select(r => r.ErrorMessage).ToArray()));
                                            ExceptionLogService.LogException(ex);
                                            continue;
                                        }
                                    }

                                    // If the Group has a welcome email, and person has an email address, send them the welcome email and possibly create a login
                                    if (sync.WelcomeSystemCommunication != null)
                                    {
                                        var person = new PersonService(groupMemberContext).Get(personId);
                                        if (person.CanReceiveEmail(false))
                                        {
                                            // If the group is configured to add a user account for anyone added to the group, and person does not yet have an
                                            // account, add one for them.
                                            string newPassword = string.Empty;
                                            bool   createLogin = sync.AddUserAccountsDuringSync;

                                            // Only create a login if requested, no logins exist and we have enough information to generate a user name.
                                            if (createLogin && !person.Users.Any() && !string.IsNullOrWhiteSpace(person.NickName) && !string.IsNullOrWhiteSpace(person.LastName))
                                            {
                                                newPassword = System.Web.Security.Membership.GeneratePassword(9, 1);
                                                string username = Rock.Security.Authentication.Database.GenerateUsername(person.NickName, person.LastName);

                                                UserLogin login = UserLoginService.Create(
                                                    groupMemberContext,
                                                    person,
                                                    AuthenticationServiceType.Internal,
                                                    EntityTypeCache.Get(Rock.SystemGuid.EntityType.AUTHENTICATION_DATABASE.AsGuid()).Id,
                                                    username,
                                                    newPassword,
                                                    true,
                                                    requirePasswordReset);
                                            }

                                            // Send the welcome email
                                            var mergeFields = new Dictionary <string, object>();
                                            mergeFields.Add("Group", sync.Group);
                                            mergeFields.Add("Person", person);
                                            mergeFields.Add("NewPassword", newPassword);
                                            mergeFields.Add("CreateLogin", createLogin);
                                            var emailMessage = new RockEmailMessage(sync.WelcomeSystemCommunication);
                                            emailMessage.AddRecipient(new RockEmailMessageRecipient(person, mergeFields));
                                            var emailErrors = new List <string>();
                                            emailMessage.Send(out emailErrors);
                                            errors.AddRange(emailErrors);
                                        }
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                ExceptionLogService.LogException(ex);
                                continue;
                            }

                            hasSyncChanged = true;
                        }

                        // Increment Groups Changed Counter (if people were deleted or added to the group)
                        if (hasSyncChanged)
                        {
                            groupsChanged++;
                        }

                        // Increment the Groups Synced Counter
                        groupsSynced++;
                    }

                    // Update last refresh datetime in different context to avoid side-effects.
                    using (var rockContext = new RockContext())
                    {
                        var sync = new GroupSyncService(rockContext)
                                   .Queryable()
                                   .FirstOrDefault(s => s.Id == syncId);

                        sync.LastRefreshDateTime = RockDateTime.Now;

                        rockContext.SaveChanges();
                    }
                }

                // Format the result message
                var resultMessage = string.Empty;
                if (groupsSynced == 0)
                {
                    resultMessage = "No groups to sync";
                }
                else if (groupsSynced == 1)
                {
                    resultMessage = "1 group was synced";
                }
                else
                {
                    resultMessage = string.Format("{0} groups were synced", groupsSynced);
                }

                resultMessage += string.Format(" and {0} groups were changed", groupsChanged);

                if (errors.Any())
                {
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine();
                    sb.Append("Errors: ");
                    errors.ForEach(e => { sb.AppendLine(); sb.Append(e); });
                    string errorMessage = sb.ToString();
                    resultMessage += errorMessage;
                    throw new Exception(errorMessage);
                }

                context.Result = resultMessage;
            }
            catch (System.Exception ex)
            {
                HttpContext context2 = HttpContext.Current;
                ExceptionLogService.LogException(ex, context2);
                throw;
            }
        }
Exemple #2
0
        /// <summary>
        /// Job that will sync groups.
        ///
        /// Called by the <see cref="IScheduler" /> when a
        /// <see cref="ITrigger" /> fires that is associated with
        /// the <see cref="IJob" />.
        /// </summary>
        public virtual void Execute(IJobExecutionContext context)
        {
            // Get the job setting(s)
            JobDataMap dataMap = context.JobDetail.JobDataMap;
            bool       requirePasswordReset = dataMap.GetBoolean("RequirePasswordReset");
            var        commandTimeout       = dataMap.GetString("CommandTimeout").AsIntegerOrNull() ?? 180;

            // Counters for displaying results
            int    groupsSynced  = 0;
            int    groupsChanged = 0;
            string groupName     = string.Empty;
            string dataViewName  = string.Empty;
            var    errors        = new List <string>();

            try
            {
                // get groups set to sync
                var activeSyncIds = new List <int>();
                using (var rockContext = new RockContext())
                {
                    // Get groups that are not archived and are still active.
                    activeSyncIds = new GroupSyncService(rockContext)
                                    .Queryable().AsNoTracking()
                                    .Where(x => !x.Group.IsArchived && x.Group.IsActive)
                                    .Select(x => x.Id)
                                    .ToList();
                }

                foreach (var syncId in activeSyncIds)
                {
                    bool hasSyncChanged = false;

                    // Use a fresh rockContext per sync so that ChangeTracker doesn't get bogged down
                    using (var rockContext = new RockContext())
                    {
                        // increase the timeout just in case the data view source is slow
                        rockContext.Database.CommandTimeout = commandTimeout;
                        rockContext.SourceOfChange          = "Group Sync";

                        // Get the Sync
                        var sync = new GroupSyncService(rockContext)
                                   .Queryable().AsNoTracking()
                                   .FirstOrDefault(s => s.Id == syncId);

                        // Ensure that the group's Sync Data View is a person data view
                        if (sync != null && sync.SyncDataView.EntityTypeId == EntityTypeCache.Get(typeof(Person)).Id)
                        {
                            List <string> syncErrors = new List <string>();

                            dataViewName = sync.SyncDataView.Name;
                            groupName    = sync.Group.Name;

                            // Get the person id's from the data view (source)
                            var personService   = new PersonService(rockContext);
                            var sourcePersonIds = sync.SyncDataView.GetQuery(null, rockContext, commandTimeout, out syncErrors)
                                                  .Select(q => q.Id).ToList();

                            // If any error occurred trying get the 'where expression' from the sync-data-view,
                            // just skip trying to sync that particular group's Sync Data View for now.
                            if (syncErrors.Count > 0)
                            {
                                errors.AddRange(syncErrors);
                                ExceptionLogService.LogException(new Exception(string.Format("An error occurred while trying to GroupSync group '{0}' and data view '{1}' so the sync was skipped. Error: {2}", groupName, dataViewName, String.Join(",", syncErrors))));
                                continue;
                            }

                            // Get the person id's in the group (target) for the role being synced.
                            // Note: targetPersonIds must include archived group members
                            // so we don't try to delete anyone who's already archived, and
                            // it must include deceased members so we can remove them if they
                            // are no longer in the data view.
                            var targetPersonIds = new GroupMemberService(rockContext)
                                                  .Queryable(true, true).AsNoTracking()
                                                  .Where(gm => gm.GroupId == sync.GroupId)
                                                  .Where(gm => gm.GroupRoleId == sync.GroupTypeRoleId)
                                                  .Select(gm => new {
                                PersonId   = gm.PersonId,
                                IsArchived = gm.IsArchived
                            })
                                                  .ToList();

                            // Delete people from the group/role that are no longer in the data view --
                            // but not the ones that are already archived.
                            foreach (var targetPerson in targetPersonIds.Where(t => !sourcePersonIds.Contains(t.PersonId) && t.IsArchived != true))
                            {
                                try
                                {
                                    // Use a new context to limit the amount of change-tracking required
                                    using (var groupMemberContext = new RockContext())
                                    {
                                        // Delete the records for that person's group and role
                                        var groupMemberService = new GroupMemberService(groupMemberContext);
                                        foreach (var groupMember in groupMemberService
                                                 .Queryable(true, true)
                                                 .Where(m =>
                                                        m.GroupId == sync.GroupId &&
                                                        m.GroupRoleId == sync.GroupTypeRoleId &&
                                                        m.PersonId == targetPerson.PersonId)
                                                 .ToList())
                                        {
                                            groupMemberService.Delete(groupMember);
                                        }

                                        groupMemberContext.SaveChanges();

                                        // If the Group has an exit email, and person has an email address, send them the exit email
                                        if (sync.ExitSystemEmail != null)
                                        {
                                            var person = new PersonService(groupMemberContext).Get(targetPerson.PersonId);
                                            if (person.Email.IsNotNullOrWhiteSpace())
                                            {
                                                // Send the exit email
                                                var mergeFields = new Dictionary <string, object>();
                                                mergeFields.Add("Group", sync.Group);
                                                mergeFields.Add("Person", person);
                                                var emailMessage = new RockEmailMessage(sync.ExitSystemEmail);
                                                emailMessage.AddRecipient(new RecipientData(person.Email, mergeFields));
                                                var emailErrors = new List <string>();
                                                emailMessage.Send(out emailErrors);
                                                errors.AddRange(emailErrors);
                                            }
                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                    ExceptionLogService.LogException(ex);
                                    continue;
                                }

                                hasSyncChanged = true;
                            }

                            // Now find all the people in the source list who are NOT already in the target list
                            // or in the target list as archived (so we can restore them).
                            foreach (var personId in sourcePersonIds.Where(s => !targetPersonIds.Any(t => t.PersonId == s) ||
                                                                           targetPersonIds.Any(t => t.PersonId == s && t.IsArchived)))
                            {
                                try
                                {
                                    // Use a new context to limit the amount of change-tracking required
                                    using (var groupMemberContext = new RockContext())
                                    {
                                        var groupMemberService = new GroupMemberService(groupMemberContext);

                                        // If this person is currently archived...
                                        if (targetPersonIds.Any(t => t.PersonId == personId && t.IsArchived == true))
                                        {
                                            // ...then we'll just restore them;

                                            // NOTE: AddOrRestoreGroupMember will find the exact group member record and
                                            // sets their IsArchived back to false.
                                            var newGroupMember = groupMemberService.AddOrRestoreGroupMember(sync.Group, personId, sync.GroupTypeRoleId);
                                            newGroupMember.GroupMemberStatus = GroupMemberStatus.Active;
                                            groupMemberContext.SaveChanges();
                                        }
                                        else
                                        {
                                            // ...otherwise we will add a new person to the group with the role specified in the sync.
                                            var newGroupMember = new GroupMember {
                                                Id = 0
                                            };
                                            newGroupMember.PersonId          = personId;
                                            newGroupMember.GroupId           = sync.GroupId;
                                            newGroupMember.GroupMemberStatus = GroupMemberStatus.Active;
                                            newGroupMember.GroupRoleId       = sync.GroupTypeRoleId;

                                            if (newGroupMember.IsValidGroupMember(groupMemberContext))
                                            {
                                                groupMemberService.Add(newGroupMember);
                                                groupMemberContext.SaveChanges();
                                            }
                                            else
                                            {
                                                // Validation errors will get added to the ValidationResults collection. Add those results to the log and then move on to the next person.
                                                var ex = new GroupMemberValidationException(string.Join(",", newGroupMember.ValidationResults.Select(r => r.ErrorMessage).ToArray()));
                                                ExceptionLogService.LogException(ex);
                                                continue;
                                            }
                                        }

                                        // If the Group has a welcome email, and person has an email address, send them the welcome email and possibly create a login
                                        if (sync.WelcomeSystemEmail != null)
                                        {
                                            var person = new PersonService(groupMemberContext).Get(personId);
                                            if (person.Email.IsNotNullOrWhiteSpace())
                                            {
                                                // If the group is configured to add a user account for anyone added to the group, and person does not yet have an
                                                // account, add one for them.
                                                string newPassword = string.Empty;
                                                bool   createLogin = sync.AddUserAccountsDuringSync;

                                                // Only create a login if requested, no logins exist and we have enough information to generate a user name.
                                                if (createLogin && !person.Users.Any() && !string.IsNullOrWhiteSpace(person.NickName) && !string.IsNullOrWhiteSpace(person.LastName))
                                                {
                                                    newPassword = System.Web.Security.Membership.GeneratePassword(9, 1);
                                                    string username = Rock.Security.Authentication.Database.GenerateUsername(person.NickName, person.LastName);

                                                    UserLogin login = UserLoginService.Create(
                                                        groupMemberContext,
                                                        person,
                                                        AuthenticationServiceType.Internal,
                                                        EntityTypeCache.Get(Rock.SystemGuid.EntityType.AUTHENTICATION_DATABASE.AsGuid()).Id,
                                                        username,
                                                        newPassword,
                                                        true,
                                                        requirePasswordReset);
                                                }

                                                // Send the welcome email
                                                var mergeFields = new Dictionary <string, object>();
                                                mergeFields.Add("Group", sync.Group);
                                                mergeFields.Add("Person", person);
                                                mergeFields.Add("NewPassword", newPassword);
                                                mergeFields.Add("CreateLogin", createLogin);
                                                var emailMessage = new RockEmailMessage(sync.WelcomeSystemEmail);
                                                emailMessage.AddRecipient(new RecipientData(person.Email, mergeFields));
                                                var emailErrors = new List <string>();
                                                emailMessage.Send(out emailErrors);
                                                errors.AddRange(emailErrors);
                                            }
                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                    ExceptionLogService.LogException(ex);
                                    continue;
                                }

                                hasSyncChanged = true;
                            }

                            // Increment Groups Changed Counter (if people were deleted or added to the group)
                            if (hasSyncChanged)
                            {
                                groupsChanged++;
                            }

                            // Increment the Groups Synced Counter
                            groupsSynced++;
                        }
                    }
                }

                // Format the result message
                var resultMessage = string.Empty;
                if (groupsSynced == 0)
                {
                    resultMessage = "No groups to sync";
                }
                else if (groupsSynced == 1)
                {
                    resultMessage = "1 group was synced";
                }
                else
                {
                    resultMessage = string.Format("{0} groups were synced", groupsSynced);
                }

                resultMessage += string.Format(" and {0} groups were changed", groupsChanged);

                if (errors.Any())
                {
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine();
                    sb.Append("Errors: ");
                    errors.ForEach(e => { sb.AppendLine(); sb.Append(e); });
                    string errorMessage = sb.ToString();
                    resultMessage += errorMessage;
                    throw new Exception(errorMessage);
                }

                context.Result = resultMessage;
            }
            catch (System.Exception ex)
            {
                HttpContext context2 = HttpContext.Current;
                ExceptionLogService.LogException(ex, context2);
                throw;
            }
        }
        /// <summary>
        /// Saves the changes.
        /// </summary>
        /// <param name="item">The item.</param>
        protected void SaveChanges(RepeaterItem item)
        {
            var hfGroupId = item.FindControl("hfGroupId") as HiddenField;
            var cbCommunicationListIsSubscribed = item.FindControl("cbCommunicationListIsSubscribed") as RockCheckBox;
            var tglCommunicationPreference      = item.FindControl("tglCommunicationPreference") as Toggle;
            var nbGroupNotification             = item.FindControl("nbGroupNotification") as NotificationBox;

            nbGroupNotification.Visible = false;

            using (var rockContext = new RockContext())
            {
                int groupId            = hfGroupId.Value.AsInteger();
                var groupMemberService = new GroupMemberService(rockContext);
                var group = new GroupService(rockContext).Get(groupId);
                var groupMemberRecordsForPerson = groupMemberService.Queryable().Where(a => a.GroupId == groupId && a.PersonId == this.CurrentPersonId).ToList();
                if (groupMemberRecordsForPerson.Any())
                {
                    // normally there would be at most 1 group member record for the person, but just in case, mark them all
                    foreach (var groupMember in groupMemberRecordsForPerson)
                    {
                        if (cbCommunicationListIsSubscribed.Checked)
                        {
                            if (groupMember.GroupMemberStatus == GroupMemberStatus.Inactive)
                            {
                                groupMember.GroupMemberStatus = GroupMemberStatus.Active;
                                if (groupMember.Note == "Unsubscribed")
                                {
                                    groupMember.Note = string.Empty;
                                }
                            }
                        }
                        else
                        {
                            if (groupMember.GroupMemberStatus == GroupMemberStatus.Active)
                            {
                                groupMember.GroupMemberStatus = GroupMemberStatus.Inactive;
                                if (groupMember.Note.IsNullOrWhiteSpace())
                                {
                                    groupMember.Note = "Unsubscribed";
                                }
                            }
                        }

                        groupMember.LoadAttributes();
                        CommunicationType communicationType = tglCommunicationPreference.Checked ? CommunicationType.Email : CommunicationType.SMS;
                        groupMember.SetAttributeValue("PreferredCommunicationMedium", communicationType.ConvertToInt().ToString());
                        groupMember.SaveAttributeValue("PreferredCommunicationMedium", rockContext);
                    }
                }
                else
                {
                    // they are not currently in the Group
                    if (cbCommunicationListIsSubscribed.Checked)
                    {
                        var groupMember = new GroupMember();
                        groupMember.PersonId = this.CurrentPersonId.Value;
                        groupMember.GroupId  = group.Id;
                        int?defaultGroupRoleId = GroupTypeCache.Get(group.GroupTypeId).DefaultGroupRoleId;
                        if (defaultGroupRoleId.HasValue)
                        {
                            groupMember.GroupRoleId = defaultGroupRoleId.Value;
                        }
                        else
                        {
                            nbGroupNotification.Text                = "Unable to add to group.";
                            nbGroupNotification.Details             = "Group has no default group role";
                            nbGroupNotification.NotificationBoxType = NotificationBoxType.Danger;
                            nbGroupNotification.Visible             = true;
                        }

                        groupMember.GroupMemberStatus = GroupMemberStatus.Active;
                        groupMember.LoadAttributes();
                        CommunicationType communicationType = tglCommunicationPreference.Checked ? CommunicationType.Email : CommunicationType.SMS;
                        groupMember.SetAttributeValue("PreferredCommunicationMedium", communicationType.ConvertToInt().ToString());

                        if (groupMember.IsValidGroupMember(rockContext))
                        {
                            groupMemberService.Add(groupMember);
                            rockContext.SaveChanges();
                            groupMember.SaveAttributeValue("PreferredCommunicationMedium", rockContext);
                        }
                        else
                        {
                            // if the group member couldn't be added (for example, one of the group membership rules didn't pass), add the validation messages to the errormessages
                            nbGroupNotification.Text                = "Unable to add to group.";
                            nbGroupNotification.Details             = groupMember.ValidationResults.Select(a => a.ErrorMessage).ToList().AsDelimited("<br />");
                            nbGroupNotification.NotificationBoxType = NotificationBoxType.Danger;
                            nbGroupNotification.Visible             = true;
                        }
                    }
                }

                rockContext.SaveChanges();
            }
        }
Exemple #4
0
        /// <summary>
        /// Executes the specified workflow.
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="action">The action.</param>
        /// <param name="entity">The entity.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        public override bool Execute(RockContext rockContext, WorkflowAction action, Object entity, out List <string> errorMessages)
        {
            errorMessages = new List <string>();

            // Determine which group to add the person to
            Group group       = null;
            int?  groupRoleId = null;

            var groupAndRoleValues = (GetAttributeValue(action, "GroupAndRole") ?? string.Empty).Split('|');

            if (groupAndRoleValues.Count() > 1)
            {
                var groupGuid = groupAndRoleValues[1].AsGuidOrNull();
                if (groupGuid.HasValue)
                {
                    group = new GroupService(rockContext).Get(groupGuid.Value);

                    if (groupAndRoleValues.Count() > 2)
                    {
                        var groupTypeRoleGuid = groupAndRoleValues[2].AsGuidOrNull();
                        if (groupTypeRoleGuid.HasValue)
                        {
                            var groupRole = new GroupTypeRoleService(rockContext).Get(groupTypeRoleGuid.Value);
                            if (groupRole != null)
                            {
                                groupRoleId = groupRole.Id;
                            }
                        }
                    }

                    if (!groupRoleId.HasValue && group != null)
                    {
                        // use the group's grouptype's default group role if a group role wasn't specified
                        groupRoleId = group.GroupType.DefaultGroupRoleId;
                    }
                }
            }

            if (group == null)
            {
                errorMessages.Add("No group was provided");
            }

            if (!groupRoleId.HasValue)
            {
                errorMessages.Add("No group role was provided and group doesn't have a default group role");
            }

            // determine the person that will be added to the group
            Person person = null;

            // get the Attribute.Guid for this workflow's Person Attribute so that we can lookup the value
            var guidPersonAttribute = GetAttributeValue(action, "Person").AsGuidOrNull();

            if (guidPersonAttribute.HasValue)
            {
                var attributePerson = AttributeCache.Read(guidPersonAttribute.Value, rockContext);
                if (attributePerson != null)
                {
                    string attributePersonValue = action.GetWorklowAttributeValue(guidPersonAttribute.Value);
                    if (!string.IsNullOrWhiteSpace(attributePersonValue))
                    {
                        if (attributePerson.FieldType.Class == typeof(Rock.Field.Types.PersonFieldType).FullName)
                        {
                            Guid personAliasGuid = attributePersonValue.AsGuid();
                            if (!personAliasGuid.IsEmpty())
                            {
                                person = new PersonAliasService(rockContext).Queryable()
                                         .Where(a => a.Guid.Equals(personAliasGuid))
                                         .Select(a => a.Person)
                                         .FirstOrDefault();
                            }
                        }
                        else
                        {
                            errorMessages.Add("The attribute used to provide the person was not of type 'Person'.");
                        }
                    }
                }
            }

            if (person == null)
            {
                errorMessages.Add(string.Format("Person could not be found for selected value ('{0}')!", guidPersonAttribute.ToString()));
            }

            // Add Person to Group
            if (!errorMessages.Any())
            {
                var groupMemberService = new GroupMemberService(rockContext);
                var groupMember        = new GroupMember();
                groupMember.PersonId          = person.Id;
                groupMember.GroupId           = group.Id;
                groupMember.GroupRoleId       = groupRoleId.Value;
                groupMember.GroupMemberStatus = this.GetAttributeValue(action, "GroupMemberStatus").ConvertToEnum <GroupMemberStatus>(GroupMemberStatus.Active);
                if (groupMember.IsValidGroupMember(rockContext))
                {
                    groupMemberService.Add(groupMember);
                    rockContext.SaveChanges();

                    if (group.IsSecurityRole || group.GroupType.Guid.Equals(Rock.SystemGuid.GroupType.GROUPTYPE_SECURITY_ROLE.AsGuid()))
                    {
                        Rock.Security.Role.Flush(group.Id);
                    }
                }
                else
                {
                    // if the group member couldn't be added (for example, one of the group membership rules didn't pass), add the validation messages to the errormessages
                    errorMessages.AddRange(groupMember.ValidationResults.Select(a => a.ErrorMessage));
                }
            }

            errorMessages.ForEach(m => action.AddLogEntry(m, true));

            return(true);
        }
Exemple #5
0
        public void UpdateSubscription(Guid communicationListGuid, bool subscribed)
        {
            using (var rockContext = new RockContext())
            {
                var groupMemberService = new GroupMemberService(rockContext);
                var group = new GroupService(rockContext).Get(communicationListGuid);
                var groupMemberRecordsForPerson = groupMemberService.Queryable()
                                                  .Where(a => a.GroupId == group.Id && a.PersonId == RequestContext.CurrentPerson.Id)
                                                  .ToList();

                if (groupMemberRecordsForPerson.Any())
                {
                    // normally there would be at most 1 group member record for the person, but just in case, mark them all
                    foreach (var groupMember in groupMemberRecordsForPerson)
                    {
                        if (subscribed)
                        {
                            if (groupMember.GroupMemberStatus == GroupMemberStatus.Inactive)
                            {
                                groupMember.GroupMemberStatus = GroupMemberStatus.Active;
                                if (groupMember.Note == "Unsubscribed")
                                {
                                    groupMember.Note = string.Empty;
                                }
                            }
                        }
                        else
                        {
                            if (groupMember.GroupMemberStatus == GroupMemberStatus.Active)
                            {
                                groupMember.GroupMemberStatus = GroupMemberStatus.Inactive;
                                if (groupMember.Note.IsNullOrWhiteSpace())
                                {
                                    groupMember.Note = "Unsubscribed";
                                }
                            }
                        }

                        // TODO: Change this to null.
                        groupMember.CommunicationPreference = CommunicationType.Email;
                    }
                }
                else if (subscribed)
                {
                    var groupMember = new GroupMember
                    {
                        PersonId = RequestContext.CurrentPerson.Id,
                        GroupId  = group.Id
                    };

                    int?defaultGroupRoleId = GroupTypeCache.Get(group.GroupTypeId).DefaultGroupRoleId;
                    if (defaultGroupRoleId.HasValue)
                    {
                        groupMember.GroupRoleId = defaultGroupRoleId.Value;
                    }

                    groupMember.GroupMemberStatus = GroupMemberStatus.Active;

                    if (groupMember.IsValidGroupMember(rockContext))
                    {
                        groupMemberService.Add(groupMember);
                        rockContext.SaveChanges();
                    }
                }

                rockContext.SaveChanges();
            }
        }