private bool UpdateMemberProperties(IUser user, BackOfficeIdentityUser identityUser)
    {
        var anythingChanged = false;

        // don't assign anything if nothing has changed as this will trigger the track changes of the model
        if (identityUser.IsPropertyDirty(nameof(BackOfficeIdentityUser.LastLoginDateUtc)) ||
            (user.LastLoginDate != default && identityUser.LastLoginDateUtc.HasValue == false) ||
            (identityUser.LastLoginDateUtc.HasValue &&
             user.LastLoginDate?.ToUniversalTime() != identityUser.LastLoginDateUtc.Value))
        {
            anythingChanged = true;

            // if the LastLoginDate is being set to MinValue, don't convert it ToLocalTime
            DateTime?dt = identityUser.LastLoginDateUtc?.ToLocalTime();
            user.LastLoginDate = dt;
        }

        if (identityUser.IsPropertyDirty(nameof(BackOfficeIdentityUser.InviteDateUtc)) ||
            user.InvitedDate?.ToUniversalTime() != identityUser.InviteDateUtc)
        {
            anythingChanged  = true;
            user.InvitedDate = identityUser.InviteDateUtc?.ToLocalTime();
        }

        if (identityUser.IsPropertyDirty(nameof(BackOfficeIdentityUser.LastPasswordChangeDateUtc)) ||
            (user.LastPasswordChangeDate.HasValue && user.LastPasswordChangeDate.Value != default &&
             identityUser.LastPasswordChangeDateUtc.HasValue == false) ||
            (identityUser.LastPasswordChangeDateUtc.HasValue && user.LastPasswordChangeDate?.ToUniversalTime() !=
             identityUser.LastPasswordChangeDateUtc.Value))
        {
            anythingChanged             = true;
            user.LastPasswordChangeDate = identityUser.LastPasswordChangeDateUtc?.ToLocalTime() ?? DateTime.Now;
        }

        if (identityUser.IsPropertyDirty(nameof(BackOfficeIdentityUser.EmailConfirmed)) ||
            (user.EmailConfirmedDate.HasValue && user.EmailConfirmedDate.Value != default &&
             identityUser.EmailConfirmed == false) ||
            ((user.EmailConfirmedDate.HasValue == false || user.EmailConfirmedDate.Value == default) &&
             identityUser.EmailConfirmed))
        {
            anythingChanged         = true;
            user.EmailConfirmedDate = identityUser.EmailConfirmed ? DateTime.Now : null;
        }

        if (identityUser.IsPropertyDirty(nameof(BackOfficeIdentityUser.Name)) &&
            user.Name != identityUser.Name && identityUser.Name.IsNullOrWhiteSpace() == false)
        {
            anythingChanged = true;
            user.Name       = identityUser.Name ?? string.Empty;
        }

        if (identityUser.IsPropertyDirty(nameof(BackOfficeIdentityUser.Email)) &&
            user.Email != identityUser.Email && identityUser.Email.IsNullOrWhiteSpace() == false)
        {
            anythingChanged = true;
            user.Email      = identityUser.Email;
        }

        if (identityUser.IsPropertyDirty(nameof(BackOfficeIdentityUser.AccessFailedCount)) &&
            user.FailedPasswordAttempts != identityUser.AccessFailedCount)
        {
            anythingChanged             = true;
            user.FailedPasswordAttempts = identityUser.AccessFailedCount;
        }

        if (user.IsApproved != identityUser.IsApproved)
        {
            anythingChanged = true;
            user.IsApproved = identityUser.IsApproved;
        }

        if (user.IsLockedOut != identityUser.IsLockedOut)
        {
            anythingChanged  = true;
            user.IsLockedOut = identityUser.IsLockedOut;

            if (user.IsLockedOut)
            {
                // need to set the last lockout date
                user.LastLockoutDate = DateTime.Now;
            }
        }

        if (identityUser.IsPropertyDirty(nameof(BackOfficeIdentityUser.UserName)) &&
            user.Username != identityUser.UserName && identityUser.UserName.IsNullOrWhiteSpace() == false)
        {
            anythingChanged = true;
            user.Username   = identityUser.UserName;
        }

        if (identityUser.IsPropertyDirty(nameof(BackOfficeIdentityUser.PasswordHash)) &&
            user.RawPasswordValue != identityUser.PasswordHash &&
            identityUser.PasswordHash.IsNullOrWhiteSpace() == false)
        {
            anythingChanged            = true;
            user.RawPasswordValue      = identityUser.PasswordHash;
            user.PasswordConfiguration = identityUser.PasswordConfig;
        }

        if (identityUser.IsPropertyDirty(nameof(BackOfficeIdentityUser.Culture)) &&
            user.Language != identityUser.Culture && identityUser.Culture.IsNullOrWhiteSpace() == false)
        {
            anythingChanged = true;
            user.Language   = identityUser.Culture;
        }

        if (identityUser.IsPropertyDirty(nameof(BackOfficeIdentityUser.StartMediaIds)) &&
            user.StartMediaIds.UnsortedSequenceEqual(identityUser.StartMediaIds) == false)
        {
            anythingChanged    = true;
            user.StartMediaIds = identityUser.StartMediaIds;
        }

        if (identityUser.IsPropertyDirty(nameof(BackOfficeIdentityUser.StartContentIds)) &&
            user.StartContentIds.UnsortedSequenceEqual(identityUser.StartContentIds) == false)
        {
            anythingChanged      = true;
            user.StartContentIds = identityUser.StartContentIds;
        }

        if (user.SecurityStamp != identityUser.SecurityStamp)
        {
            anythingChanged    = true;
            user.SecurityStamp = identityUser.SecurityStamp;
        }

        if (identityUser.IsPropertyDirty(nameof(BackOfficeIdentityUser.Roles)))
        {
            var identityUserRoles = identityUser.Roles.Select(x => x.RoleId).Where(x => x is not null).ToArray();

            anythingChanged = true;

            // clear out the current groups (need to ToArray since we are modifying the iterator)
            user.ClearGroups();

            // go lookup all these groups
            IReadOnlyUserGroup[] groups = _userService.GetUserGroupsByAlias(identityUserRoles)
                                          .Select(x => x.ToReadOnlyGroup()).ToArray();

            // use all of the ones assigned and add them
            foreach (IReadOnlyUserGroup group in groups)
            {
                user.AddGroup(group);
            }

            // re-assign
            identityUser.SetGroups(groups);
        }

        // we should re-set the calculated start nodes
        identityUser.CalculatedMediaStartNodeIds   = user.CalculateMediaStartNodeIds(_entityService, _appCaches);
        identityUser.CalculatedContentStartNodeIds = user.CalculateContentStartNodeIds(_entityService, _appCaches);

        // reset all changes
        identityUser.ResetDirtyProperties(false);

        return(anythingChanged);
    }