/// <summary>
        /// Generates a random alternate Id search value for use in a
        /// <see cref="Rock.Model.PersonSearchKey" />.  It is comprised of random alpha
        /// numeric characters in the form ccccccc-ccccccc (7 random characters, a dash,
        /// and 7 more random characters). Example "f5f3df2-40b8946".
        /// </summary>
        /// <param name="verifyUnique">if set to <c>true</c> the key will be verified as unique across all existing "Alternate Id" search values.</param>
        /// <param name="rockContext">The rock context.  You MUST pass in a RockContext if this is going to be called from inside a WrapTransaction save.</param>
        /// <returns>
        /// A random key string
        /// </returns>
        public static string GenerateRandomAlternateId(bool verifyUnique = true, RockContext rockContext = null)
        {
            rockContext = rockContext ?? new RockContext();

            string key = string.Empty;

            if (verifyUnique)
            {
                lock ( _obj )
                {
                    int alternateValueId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSON_SEARCH_KEYS_ALTERNATE_ID.AsGuid()).Id;
                    var service          = new PersonSearchKeyService(rockContext);
                    do
                    {
                        key = GenerateRandomAlternateId();
                    } while (service.Queryable().AsNoTracking().Any(a => a.SearchTypeValueId == alternateValueId && a.SearchValue == key));
                }
            }
            else
            {
                key = GenerateRandomAlternateId();
            }

            return(key);
        }
예제 #2
0
        /// <summary>
        /// This method is called in the
        /// <see cref="M:Rock.Data.Model`1.PreSaveChanges(Rock.Data.DbContext,System.Data.Entity.Infrastructure.DbEntityEntry,System.Data.Entity.EntityState)" />
        /// method. Use it to populate <see cref="P:Rock.Data.Model`1.HistoryItems" /> if needed.
        /// These history items are queued to be written into the database post save (so that they
        /// are only written if the save actually occurs).
        /// </summary>
        /// <param name="dbContext">The database context.</param>
        /// <param name="entry">The entry.</param>
        /// <param name="state">The state.</param>
        protected override void BuildHistoryItems(Data.DbContext dbContext, DbEntityEntry entry, EntityState state)
        {
            // Sometimes, especially if the model is being deleted, some properties might not be
            // populated, but we can query to try to get their original value. We need to use a new
            // rock context to get the actual value from the DB
            var rockContext   = new RockContext();
            var service       = new PersonSearchKeyService(rockContext);
            var originalModel = service.Queryable("PersonAlias")
                                .FirstOrDefault(fpsa => fpsa.Id == Id);

            // Use the original value for the person alias or the new value if that is not set
            var personId = (originalModel?.PersonAlias ?? PersonAlias)?.PersonId;

            if (!personId.HasValue)
            {
                // If this model is new, it won't have any virtual properties hydrated or an original
                // record in the database
                if (PersonAliasId.HasValue)
                {
                    var personAliasService = new PersonAliasService(rockContext);
                    var personAlias        = personAliasService.Get(PersonAliasId.Value);
                    personId = personAlias?.PersonId;
                }

                // We can't log history if we don't know who the saved account belongs to
                if (!personId.HasValue)
                {
                    return;
                }
            }

            History.HistoryVerb verb;

            switch (state)
            {
            case EntityState.Added:
                verb = History.HistoryVerb.Add;
                break;

            case EntityState.Deleted:
                verb = History.HistoryVerb.Delete;
                break;

            case EntityState.Modified:
                verb = History.HistoryVerb.Modify;
                break;

            default:
                // As of now, there is no requirement to log other events
                return;
            }

            var caption = verb == History.HistoryVerb.Modify ?
                          "Person Search Key" :
                          GetCaptionForHistory(originalModel?.SearchValue ?? SearchValue, originalModel?.SearchTypeValueId ?? SearchTypeValueId);

            var historyChangeList = new History.HistoryChangeList();

            if (verb != History.HistoryVerb.Modify)
            {
                historyChangeList.AddChange(verb, History.HistoryChangeType.Record, "Person Search Key");
            }
            else
            {
                History.EvaluateChange(historyChangeList, $"SearchValue", entry.OriginalValues["SearchValue"].ToStringSafe(), SearchValue, false);

                var originalSearchType = DefinedValueCache.Get(entry.OriginalValues["SearchTypeValueId"].ToStringSafe().AsInteger());
                var currentSearchType  = DefinedValueCache.Get(SearchTypeValueId);
                History.EvaluateChange(historyChangeList, $"SearchType", originalSearchType?.Value, currentSearchType?.Value, false);
            }

            HistoryItems = HistoryService.GetChanges(
                typeof(Person),
                Rock.SystemGuid.Category.HISTORY_PERSON.AsGuid(),
                personId.Value,
                historyChangeList,
                caption,
                typeof(PersonSearchKey),
                Id,
                dbContext.GetCurrentPersonAlias()?.Id,
                dbContext.SourceOfChange);
        }