/// <summary>
        ///     Called to write save audit log entries.
        /// </summary>
        /// <param name="success">if set to <c>true</c> [success].</param>
        /// <param name="accessRuleDetails">The user account details.</param>
        protected override void OnWriteSaveAuditLogEntries(bool success, AuditLogUserAccountDetails accessRuleDetails)
        {
            if (accessRuleDetails.IsTemporaryId)
            {
                // Entity is being created
                AuditLog.OnCreateUserAccount(success, accessRuleDetails.UserName);
            }

            if (!accessRuleDetails.IsTemporaryId &&
                accessRuleDetails.OldUserName != accessRuleDetails.UserName)
            {
                // Name has changed
                AuditLog.OnRenameUserAccount(success, accessRuleDetails.OldUserName, accessRuleDetails.UserName);
            }

            if (!accessRuleDetails.IsTemporaryId &&
                accessRuleDetails.HasPasswordChanged)
            {
                // Password has changed
                AuditLog.OnChangeUserAccountPassword(success, accessRuleDetails.UserName);
            }

            if (!accessRuleDetails.IsTemporaryId &&
                accessRuleDetails.ExpirationDate != accessRuleDetails.OldExpirationDate)
            {
                // Expiration date has changed
                AuditLog.OnChangeUserAccountExpiry(success, accessRuleDetails.UserName, accessRuleDetails.OldExpirationDate, accessRuleDetails.ExpirationDate);
            }

            if (!accessRuleDetails.IsTemporaryId &&
                accessRuleDetails.Status != accessRuleDetails.OldStatus)
            {
                // Status has changed
                switch (accessRuleDetails.Status)
                {
                case UserAccountStatusEnum_Enumeration.Expired:
                    AuditLog.OnExpiredUserAccount(success, accessRuleDetails.UserName);
                    break;

                case UserAccountStatusEnum_Enumeration.Locked:
                    AuditLog.OnLockUserAccount(success, accessRuleDetails.UserName);
                    break;

                default:
                    AuditLog.OnChangeUserAccountStatus(success, accessRuleDetails.UserName, accessRuleDetails.OldStatus.ToString(), accessRuleDetails.Status.ToString());
                    break;
                }
            }

            ISet <string> currentAccount = new HashSet <string> {
                accessRuleDetails.UserName
            };

            if (accessRuleDetails.AddedUserHasRoles.Count > 0)
            {
                foreach (string addedUserHasRole in accessRuleDetails.AddedUserHasRoles)
                {
                    // Role membership has changed
                    AuditLog.OnChangeUserRoleMembers(success, addedUserHasRole, currentAccount, new SortedSet <string>());
                }
            }

            if (accessRuleDetails.RemovedUserHasRoles.Count > 0)
            {
                foreach (string removedUserHasRole in accessRuleDetails.RemovedUserHasRoles)
                {
                    // Role membership has changed
                    AuditLog.OnChangeUserRoleMembers(success, removedUserHasRole, new SortedSet <string>(), currentAccount);
                }
            }
        }
        /// <summary>
        ///     Called to gather audit log entity details for save.
        /// </summary>
        /// <param name="userAccount">The user account.</param>
        /// <returns></returns>
        protected override AuditLogUserAccountDetails OnGatherAuditLogEntityDetailsForSave(UserAccount userAccount)
        {
            var userAccountInternal = userAccount as IEntityInternal;
            IEntityFieldValues fields;
            IDictionary <long, IChangeTracker <IMutableIdKey> > forwardRelationships;
            IDictionary <long, IChangeTracker <IMutableIdKey> > reverseRelationships;

            userAccount.GetChanges(out fields, out forwardRelationships, out reverseRelationships);

            var oldUserAccount = new Lazy <UserAccount>(() => Entity.Get <UserAccount>(userAccount.Id));

            var userAccountDetails = new AuditLogUserAccountDetails {
                UserName = userAccount.Name, OldUserName = userAccount.Name, IsTemporaryId = userAccountInternal.IsTemporaryId
            };

            IEnumerable <EntityRef> idsToLoad = new List <EntityRef> {
                "core:name", "core:password", "core:accountExpiration", "core:accountStatus", "core:userHasRole"
            };

            Dictionary <string, IEntity> fieldEntities = Entity.Get(idsToLoad).ToDictionary(e => e.Alias);

            if (fields != null && fields.Any())
            {
                object fieldObj;

                if (fields.TryGetValue(fieldEntities["name"].Id, out fieldObj))
                {
                    // Name was changed
                    userAccountDetails.OldUserName = oldUserAccount.Value.Name;
                }

                if (fields.TryGetValue(fieldEntities["password"].Id, out fieldObj))
                {
                    var newPassword = fieldObj as string;

                    // Password was changed
                    if (newPassword != oldUserAccount.Value.Password)
                    {
                        userAccountDetails.HasPasswordChanged = true;
                    }
                }

                if (fields.TryGetValue(fieldEntities["accountExpiration"].Id, out fieldObj))
                {
                    // Account expiration was changed
                    userAccountDetails.ExpirationDate    = fieldObj as DateTime?;
                    userAccountDetails.OldExpirationDate = oldUserAccount.Value.AccountExpiration;
                }
            }

            if (forwardRelationships != null && forwardRelationships.Count > 0)
            {
                IChangeTracker <IMutableIdKey> accountStatusTracker;

                if (forwardRelationships.TryGetValue(fieldEntities["accountStatus"].Id, out accountStatusTracker))
                {
                    userAccountDetails.Status    = userAccount.AccountStatus_Enum;
                    userAccountDetails.OldStatus = oldUserAccount.Value.AccountStatus_Enum;
                }

                IChangeTracker <IMutableIdKey> userRoleTracker;

                if (forwardRelationships.TryGetValue(fieldEntities["userHasRole"].Id, out userRoleTracker))
                {
                    IEnumerable <long> addedIds = userRoleTracker.Added.Select(a => a.Key);
                    userAccountDetails.AddedUserHasRoles.UnionWith(Entity.Get <Resource>(addedIds).Select(e => e.Name));

                    IEnumerable <long> removedIds = userRoleTracker.Removed.Select(a => a.Key);
                    userAccountDetails.RemovedUserHasRoles.UnionWith(Entity.Get <Resource>(removedIds).Select(e => e.Name));
                }
            }

            return(userAccountDetails);
        }
 /// <summary>
 ///     Called to write delete audit log entries.
 /// </summary>
 /// <param name="success">if set to <c>true</c> [success].</param>
 /// <param name="accessRuleDetails">The user account details.</param>
 protected override void OnWriteDeleteAuditLogEntries(bool success, AuditLogUserAccountDetails accessRuleDetails)
 {
     AuditLog.OnDeleteUserAccount(success, accessRuleDetails.UserName);
 }