Exemple #1
0
        public FluidityEntityDisplayModel ToDisplayModel(FluiditySectionConfig section, FluidityCollectionConfig collection, object entity)
        {
            var entityId          = entity?.GetPropertyValue(collection.IdProperty);
            var entityCompositeId = entityId != null
                ? collection.Alias + "!" + entityId
                : null;

            var name = "";

            if (collection.NameProperty != null)
            {
                name = entity.GetPropertyValue(collection.NameProperty).ToString();
            }
            else if (collection.NameFormat != null)
            {
                name = collection.NameFormat(entity);
            }
            else
            {
                name = entity?.ToString();
            }

            var display = new FluidityEntityDisplayModel
            {
                Id         = entity?.GetPropertyValue(collection.IdProperty),
                Name       = name,
                Icon       = collection.IconSingular + (collection.IconColor != null ? " color-" + collection.IconColor : ""),
                Section    = section.Alias,
                Tree       = section.Tree.Alias,
                Collection = collection.Alias,
                CreateDate = entity != null && collection.DateCreatedProperty != null ? (DateTime)entity.GetPropertyValue(collection.DateCreatedProperty) : DateTime.MinValue,
                UpdateDate = entity != null && collection.DateModifiedProperty != null ? (DateTime)entity.GetPropertyValue(collection.DateModifiedProperty) : DateTime.MinValue,
                EditPath   = $"{section.Alias}/fluidity/edit/{entityCompositeId}",
            };

            if (collection.ListView != null)
            {
                var properties = new List <ContentPropertyBasic>();

                foreach (var field in collection.ListView.Fields)
                {
                    var value = entity?.GetPropertyValue(field.Property);

                    var encryptedProp = collection.EncryptedProperties?.FirstOrDefault(x => x.Name == field.Property.Name);
                    if (encryptedProp != null)
                    {
                        value = SecurityHelper.Decrypt(value.ToString());
                    }

                    if (field.Format != null)
                    {
                        value = field.Format(value, entity);
                    }

                    var propertyScaffold = new ContentPropertyBasic
                    {
                        Id    = properties.Count,
                        Alias = field.Property.Name,
                        Value = value?.ToString()
                    };

                    properties.Add(propertyScaffold);
                }

                display.Properties = properties;
            }

            return(display);
        }
Exemple #2
0
 private void Map(Property source, ContentPropertyBasic target, MapperContext context)
 {
     // assume this is mapping everything and no MapAll is required
     _contentPropertyBasicConverter.Map(source, target, context);
 }
        /// <summary>
        /// Update existing member data
        /// </summary>
        /// <param name="contentItem">The member to save</param>
        /// <remarks>
        /// We need to use both IMemberService and ASP.NET Identity to do our updates because Identity is responsible for passwords/security.
        /// When this method is called, the IMember will already have updated/mapped values from the http POST.
        /// So then we do this in order:
        /// 1. Deal with sensitive property values on IMember
        /// 2. Use IMemberService to persist all changes
        /// 3. Use ASP.NET and MemberUserManager to deal with lockouts
        /// 4. Use ASP.NET, MemberUserManager and password changer to deal with passwords
        /// 5. Deal with groups/roles
        /// </remarks>
        private async Task <ActionResult <bool> > UpdateMemberAsync(MemberSave contentItem)
        {
            contentItem.PersistedContent.WriterId = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser.Id;

            // If the user doesn't have access to sensitive values, then we need to check if any of the built in member property types
            // have been marked as sensitive. If that is the case we cannot change these persisted values no matter what value has been posted.
            // There's only 3 special ones we need to deal with that are part of the MemberSave instance: Comments, IsApproved, IsLockedOut
            // but we will take care of this in a generic way below so that it works for all props.
            if (!_backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser.HasAccessToSensitiveData())
            {
                IMemberType memberType          = _memberTypeService.Get(contentItem.PersistedContent.ContentTypeId);
                var         sensitiveProperties = memberType
                                                  .PropertyTypes.Where(x => memberType.IsSensitiveProperty(x.Alias))
                                                  .ToList();

                foreach (IPropertyType sensitiveProperty in sensitiveProperties)
                {
                    // TODO: This logic seems to deviate from the logic that is in v8 where we are explitly checking
                    // against 3 properties: Comments, IsApproved, IsLockedOut, is the v8 version incorrect?

                    ContentPropertyBasic destProp = contentItem.Properties.FirstOrDefault(x => x.Alias == sensitiveProperty.Alias);
                    if (destProp != null)
                    {
                        // if found, change the value of the contentItem model to the persisted value so it remains unchanged
                        object origValue = contentItem.PersistedContent.GetValue(sensitiveProperty.Alias);
                        destProp.Value = origValue;
                    }
                }
            }

            // First save the IMember with mapped values before we start updating data with aspnet identity
            _memberService.Save(contentItem.PersistedContent);

            bool needsResync = false;

            MemberIdentityUser identityMember = await _memberManager.FindByIdAsync(contentItem.Id.ToString());

            if (identityMember == null)
            {
                return(ValidationProblem("Member was not found"));
            }

            // Handle unlocking with the member manager (takes care of other nuances)
            if (identityMember.IsLockedOut && contentItem.IsLockedOut == false)
            {
                IdentityResult unlockResult = await _memberManager.SetLockoutEndDateAsync(identityMember, DateTimeOffset.Now.AddMinutes(-1));

                if (unlockResult.Succeeded == false)
                {
                    return(ValidationProblem(
                               $"Could not unlock for member {contentItem.Id} - error {unlockResult.Errors.ToErrorMessage()}"));
                }
                needsResync = true;
            }
            else if (identityMember.IsLockedOut == false && contentItem.IsLockedOut)
            {
                // NOTE: This should not ever happen unless someone is mucking around with the request data.
                // An admin cannot simply lock a user, they get locked out by password attempts, but an admin can unlock them
                return(ValidationProblem("An admin cannot lock a member"));
            }

            // If we're changing the password...
            // Handle changing with the member manager & password changer (takes care of other nuances)
            if (contentItem.Password != null)
            {
                IdentityResult validatePassword = await _memberManager.ValidatePasswordAsync(contentItem.Password.NewPassword);

                if (validatePassword.Succeeded == false)
                {
                    return(ValidationProblem(validatePassword.Errors.ToErrorMessage()));
                }

                if (!int.TryParse(identityMember.Id, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intId))
                {
                    return(ValidationProblem("Member ID was not valid"));
                }

                var changingPasswordModel = new ChangingPasswordModel
                {
                    Id          = intId,
                    OldPassword = contentItem.Password.OldPassword,
                    NewPassword = contentItem.Password.NewPassword,
                };

                // Change and persist the password
                Attempt <PasswordChangedModel> passwordChangeResult = await _passwordChanger.ChangePasswordWithIdentityAsync(changingPasswordModel, _memberManager);

                if (!passwordChangeResult.Success)
                {
                    foreach (string memberName in passwordChangeResult.Result?.ChangeError?.MemberNames ?? Enumerable.Empty <string>())
                    {
                        ModelState.AddModelError(memberName, passwordChangeResult.Result.ChangeError?.ErrorMessage ?? string.Empty);
                    }
                    return(ValidationProblem(ModelState));
                }

                needsResync = true;
            }

            // Update the roles and check for changes
            ActionResult <bool> rolesChanged = await AddOrUpdateRoles(contentItem.Groups, identityMember);

            if (!rolesChanged.Value && rolesChanged.Result != null)
            {
                return(rolesChanged.Result);
            }
            else
            {
                needsResync = true;
            }

            // If there have been underlying changes made by ASP.NET Identity, then we need to resync the
            // IMember on the PersistedContent with what is stored since it will be mapped to display.
            if (needsResync)
            {
                contentItem.PersistedContent = _memberService.GetById(contentItem.PersistedContent.Id);
            }

            return(true);
        }