protected virtual bool ValidateProperties(ModelStateDictionary modelState, FluidityEntityPostModel postModel, FluidityEditorFieldConfig[] configProps)
        {
            foreach (var p in postModel.Properties)
            {
                if (configProps.Any(property => property.Property.Name == p.Alias) == false)
                {
                    throw new InvalidOperationException($"property with alias: {p.Alias} was not found");
                }
            }

            return(true);
        }
        protected virtual bool ValidatePropertyData(ModelStateDictionary modelState, FluidityEntityPostModel postModel, FluidityEditorFieldConfig[] configProps)
        {
            foreach (var p in configProps)
            {
                var dataTypeInfo = _dataTypeHelper.ResolveDataType(p);
                var postedValue  = postModel.Properties.Single(x => x.Alias == p.Property.Name).Value;

                // Validate against the prop editor validators
                foreach (var result in dataTypeInfo.PropertyEditor.ValueEditor.Validators
                         .SelectMany(v => v.Validate(postedValue, dataTypeInfo.PreValues, dataTypeInfo.PropertyEditor)))
                {
                    modelState.AddPropertyError(result, p.Property.Name);
                }

                // Now we need to validate the property based on the PropertyType validation (i.e. regex and required)
                // NOTE: These will become legacy once we have pre-value overrides.
                if (p.IsRequired)
                {
                    foreach (var result in dataTypeInfo.PropertyEditor.ValueEditor.RequiredValidator
                             .Validate(postedValue, "", dataTypeInfo.PreValues, dataTypeInfo.PropertyEditor))
                    {
                        modelState.AddPropertyError(result, p.Property.Name);
                    }
                }

                if (!p.ValidationRegex.IsNullOrWhiteSpace())
                {
                    // We only want to execute the regex statement if:
                    //  * the value is null or empty AND it is required OR
                    //  * the value is not null or empty
                    // See: http://issues.umbraco.org/issue/U4-4669

                    var asString = postedValue as string;

                    if (
                        //Value is not null or empty
                        (postedValue != null && asString.IsNullOrWhiteSpace() == false)
                        //It's required
                        || p.IsRequired)
                    {
                        foreach (var result in dataTypeInfo.PropertyEditor.ValueEditor.RegexValidator
                                 .Validate(postedValue, p.ValidationRegex, dataTypeInfo.PreValues, dataTypeInfo.PropertyEditor))
                        {
                            modelState.AddPropertyError(result, p.Property.Name);
                        }
                    }
                }
            }

            return(modelState.IsValid);
        }
        public object SaveEntity([ModelBinder(typeof(FluidityEntityBinder))] FluidityEntityPostModel postModel)
        {
            FluidityEntityEditModel display;

            var sectionConfig    = Context.Config.Sections[postModel.Section];
            var collectionConfig = sectionConfig.Tree.FlattenedTreeItems[postModel.Collection] as FluidityCollectionConfig;

            // Convert ID type for type checking
            var idProp    = collectionConfig.IdProperty;
            var defaultId = idProp.Type.GetDefaultValue();

            if (postModel.Id != null && postModel.Id.GetType() != idProp.Type)
            {
                var convert = postModel.Id.TryConvertTo(idProp.Type);
                if (convert.Success)
                {
                    postModel.Id = convert.Result;
                }
            }

            // Get or create entity
            var entity = postModel.Id != null && !postModel.Id.Equals(defaultId)
                ? Context.Services.EntityService.GetEntity(collectionConfig, postModel.Id)
                : Context.Services.EntityService.NewEntity(collectionConfig);

            // Map property values
            var mapper = new FluidityEntityMapper();

            entity = mapper.FromPostModel(sectionConfig, collectionConfig, postModel, entity);

            // Validate the property values (review ContentItemValidationHelper)
            var validator = new FluidityEntityPostValidator();

            validator.Validate(ModelState, postModel, entity, collectionConfig);

            // Check to see if model is valid
            if (!ModelState.IsValid)
            {
                display        = Context.Services.EntityService.GetEntityEditModel(sectionConfig, collectionConfig, entity);
                display.Errors = ModelState.ToErrorDictionary();
                throw new HttpResponseException(Request.CreateValidationErrorResponse(display));
            }

            // Do the save
            entity  = Context.Services.EntityService.SaveEntity(collectionConfig, entity);
            display = Context.Services.EntityService.GetEntityEditModel(sectionConfig, collectionConfig, entity);

            // Return the updated model
            return(display);
        }
        public void Validate(ModelStateDictionary modelState, FluidityEntityPostModel postModel, object entity, FluidityCollectionConfig config)
        {
            var configProps = config.Editor?.Tabs.SelectMany(x => x.Fields).ToArray() ?? new FluidityEditorFieldConfig[0];

            if (ValidateProperties(modelState, postModel, configProps) == false)
            {
                return;
            }
            if (ValidatePropertyData(modelState, postModel, configProps) == false)
            {
                return;
            }
            if (ValidateDataAnnotations(modelState, entity) == false)
            {
                return;
            }
        }
Ejemplo n.º 5
0
        public object FromPostModel(FluiditySectionConfig section, FluidityCollectionConfig collection, FluidityEntityPostModel postModel, object entity)
        {
            var editorProps = collection.Editor.Tabs.SelectMany(x => x.Fields).ToArray();

            // Update the name property
            if (collection.NameProperty != null)
            {
                entity.SetPropertyValue(collection.NameProperty, postModel.Name);
            }

            // Update the individual properties
            foreach (var prop in postModel.Properties)
            {
                // Get the prop config
                var propConfig = editorProps.First(x => x.Property.Name == prop.Alias);
                if (!propConfig.IsReadOnly)
                {
                    // Create additional data for file handling
                    var additionalData = new Dictionary <string, object>();

                    // Grab any uploaded files and add them to the additional data
                    var files = postModel.UploadedFiles.Where(x => x.PropertyAlias == prop.Alias).ToArray();
                    if (files.Length > 0)
                    {
                        additionalData.Add("files", files);
                    }

                    // Ensure safe filenames
                    foreach (var file in files)
                    {
                        file.FileName = file.FileName.ToSafeFileName();
                    }

                    // Add extra things needed to figure out where to put the files
                    // Looking into the core code, these are not actually used for any lookups,
                    // rather they are used to generate a unique path, so we just use the nearest
                    // equivilaants from the fluidity api.
                    var cuid = $"{section.Alias}_{collection.Alias}_{entity.GetPropertyValue(collection.IdProperty)}";
                    var puid = $"{section.Alias}_{collection.Alias}_{propConfig.Property.Name}";

                    additionalData.Add("cuid", ObjectExtensions.EncodeAsGuid(cuid));
                    additionalData.Add("puid", ObjectExtensions.EncodeAsGuid(puid));

                    var dataTypeInfo = _dataTypeHelper.ResolveDataType(propConfig, collection.IsReadOnly);
                    var data         = new ContentPropertyData(prop.Value, dataTypeInfo.PreValues, additionalData);

                    if (!dataTypeInfo.PropertyEditor.ValueEditor.IsReadOnly)
                    {
                        var currentValue = entity.GetPropertyValue(propConfig.Property);

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

                        if (propConfig.ValueMapper != null)
                        {
                            currentValue = propConfig.ValueMapper.ModelToEditor(currentValue);
                        }

                        var propVal = dataTypeInfo.PropertyEditor.ValueEditor.ConvertEditorToDb(data, currentValue);
                        var supportTagsAttribute = TagExtractor.GetAttribute(dataTypeInfo.PropertyEditor);
                        if (supportTagsAttribute != null)
                        {
                            var dummyProp = new Property(new PropertyType(dataTypeInfo.DataTypeDefinition), propVal);
                            TagExtractor.SetPropertyTags(dummyProp, data, propVal, supportTagsAttribute);
                            propVal = dummyProp.Value;
                        }

                        if (propConfig.ValueMapper != null)
                        {
                            propVal = propConfig.ValueMapper.EditorToModel(propVal);
                        }

                        if (encryptedProp != null)
                        {
                            propVal = SecurityHelper.Encrypt(propVal.ToString());
                        }

                        if (propVal != null && propVal.GetType() != propConfig.Property.Type)
                        {
                            var convert = propVal.TryConvertTo(propConfig.Property.Type);
                            if (convert.Success)
                            {
                                propVal = convert.Result;
                            }
                        }

                        entity.SetPropertyValue(propConfig.Property, propVal);
                    }
                }
            }

            return(entity);
        }