Example #1
0
        private static List <EntitySet> CreateEntitySets(SchemaGenerationContext context)
        {
            var entitySets = new List <EntitySet>();

            foreach (var entityType in context.EntityTypes)
            {
                entitySets.Add(new EntitySet
                {
                    Name       = entityType.Name,
                    EntityType = string.Concat(schemaNamespace, ".", entityType.Name),
                });
            }
            return(entitySets);
        }
        /// <inheritdoc />
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        {
            if (_validatorFactory == null)
            {
                _logger.LogWarning(0, "ValidatorFactory is not provided. Please register FluentValidation.");
                return;
            }

            if (schema == null)
            {
                return;
            }

            IValidator?validator = null;

            try
            {
                validator = _validatorFactory.GetValidator(context.Type);
            }
            catch (Exception e)
            {
                _logger.LogWarning(0, e, $"GetValidator for type '{context.Type}' fails.");
            }

            if (validator == null)
            {
                return;
            }

            var schemaProvider = new SwashbuckleSchemaProvider(context.SchemaRepository, context.SchemaGenerator, _schemaGenerationSettings.SchemaIdSelector);

            var schemaContext = new SchemaGenerationContext(
                schema: schema,
                schemaType: context.Type,
                rules: _rules,
                schemaGenerationOptions: _schemaGenerationOptions,
                schemaGenerationSettings: _schemaGenerationSettings,
                schemaProvider: schemaProvider);

            ApplyRulesToSchema(context, validator, schemaContext);

            try
            {
                AddRulesFromIncludedValidators(context, validator, schemaContext);
            }
            catch (Exception e)
            {
                _logger.LogWarning(0, e, $"Applying IncludeRules for type '{context.Type}' fails.");
            }
        }
Example #3
0
        private static void CreateEntityType(Content content, SchemaGenerationContext context, bool isCollection)
        {
            var list = content.ContentHandler as ContentList;

            if (list == null)
            {
                list = (ContentList)content.ContentHandler.LoadContentList();
            }
            context.ListFieldSettings = list == null ? EmtpyFieldSettings : list.FieldSettings;

            if (isCollection)
            {
                IEnumerable <ContentType> contentTypes = null;

                var gc = content.ContentHandler as GenericContent;
                if (gc != null)
                {
                    contentTypes = gc.GetAllowedChildTypes();
                }

                if (contentTypes == null || contentTypes.Count() == 0)
                {
                    context.Flattening = true;
                    contentTypes       = ContentType.GetContentTypes();
                }
                else
                {
                    context.Flattening = false;
                }

                CreateEntityTypes(contentTypes, context);
            }
            else
            {
                var contentType = content.ContentType;
                context.Flattening = true;

                var entityType = new EntityType
                {
                    Name                 = contentType.Name,
                    BaseType             = contentType.ParentTypeName,
                    Key                  = GetKey(contentType, context),
                    Properties           = new List <Property>(),
                    NavigationProperties = new List <NavigationProperty>()
                };
                context.EntityTypes.Add(entityType);

                CreatePropertiesFromFieldSettings(content.ContentType.FieldSettings, contentType, entityType, context);
            }
        }
Example #4
0
        private static void CreateEntityType(ContentType contentType, SchemaGenerationContext context)
        {
            var entityType = new EntityType
            {
                Name                 = contentType.Name,
                BaseType             = contentType.ParentTypeName,
                Key                  = GetKey(contentType, context),
                Properties           = new List <Property>(),
                NavigationProperties = new List <NavigationProperty>()
            };

            context.EntityTypes.Add(entityType);

            CreatePropertiesFromFieldSettings(contentType.FieldSettings, contentType, entityType, context);
        }
Example #5
0
        private static void CreateComplexType(Type type, SchemaGenerationContext context)
        {
            var typeName = type.FullName.Replace("+", ".");

            if (typeName.StartsWith("System."))
            {
                return;
            }
            if (context.ComplexTypes.Any(x => x.Name == typeName))
            {
                return;
            }
            if (IsContentHandler(type))
            {
                return;
            }

            var complexType = new ComplexType {
                Name = typeName, Properties = new List <Property>()
            };

            context.ComplexTypes.Add(complexType);
            foreach (var propInfo in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                var attrs = propInfo.GetCustomAttributes(true).Select(x => x.GetType());
                if (_prohibitiveAttributes.Except(attrs).Count() != _prohibitiveAttributes.Length)
                {
                    continue;
                }

                var property = CreateProperty(propInfo.Name, propInfo.PropertyType, context);
                if (property != null)
                {
                    complexType.Properties.Add(property);
                }
            }
            foreach (var fieldInfo in type.GetFields(BindingFlags.Public | BindingFlags.Instance))
            {
                var property = CreateProperty(fieldInfo.Name, fieldInfo.FieldType, context);
                if (property != null)
                {
                    complexType.Properties.Add(property);
                }
            }
        }
Example #6
0
        private static List <AssociationSet> CreateAssociationSets(SchemaGenerationContext context)
        {
            var associationSets = new List <AssociationSet>();

            foreach (var association in context.Associations)
            {
                associationSets.Add(new AssociationSet
                {
                    Name        = association.Name,
                    Association = string.Concat(schemaNamespace, ".", association.Name),
                    End1        = new AssociationSetEnd {
                        Role = association.End1.Role, EntitySet = association.End1.Type
                    },
                    End2 = new AssociationSetEnd {
                        Role = association.End2.Role, EntitySet = association.End2.Type
                    }
                });
            }
            return(associationSets);
        }
Example #7
0
        private static Edmx CreateEdmx(Content content, bool isCollection)
        {
            var context = new SchemaGenerationContext();

            CreateEntityType(content, context, isCollection);
            return(new Edmx
            {
                DataServices = new DataServices
                {
                    DataServiceVersion = MetaGenerator.dataServiceVersion,
                    Schemas = new[] { new Metadata.Schema
                                      {
                                          EntityTypes = context.EntityTypes,
                                          ComplexTypes = context.ComplexTypes,
                                          EnumTypes = context.EnumTypes,
                                          Associations = context.Associations,
                                          EntityContainer = CreateEntityContainer(context)
                                      } }
                }
            });
        }
Example #8
0
        private static Property CreateProperty(string name, Type type, SchemaGenerationContext context)
        {
            var attributes = new List <KeyValue>();

            if (name == "Name")
            {
                attributes.Add(new KeyValue {
                    Key = "m:FC_TargetPath", Value = "SyndicationTitle"
                });
                attributes.Add(new KeyValue {
                    Key = "m:FC_ContentKind", Value = "text"
                });
                attributes.Add(new KeyValue {
                    Key = "m:FC_KeepInContent", Value = "false"
                });
            }
            if (name == "Description")
            {
                attributes.Add(new KeyValue {
                    Key = "m:FC_TargetPath", Value = "SyndicationSummary"
                });
                attributes.Add(new KeyValue {
                    Key = "m:FC_ContentKind", Value = "text"
                });
                attributes.Add(new KeyValue {
                    Key = "m:FC_KeepInContent", Value = "false"
                });
            }

            var nullable = true;
            var property = new Property
            {
                Name       = name,
                Type       = GetPropertyType(type, context),
                Nullable   = nullable,
                Attributes = attributes.Count > 0 ? attributes : null,
            };

            return(property);
        }
Example #9
0
        private static void CreatePropertyFromFieldSetting(FieldSetting fieldSetting, ContentType contentType, EntityType entityType, SchemaGenerationContext context)
        {
            if (!context.Flattening && fieldSetting.Owner != contentType && fieldSetting.Owner != ContentListContentType)
            {
                return;
            }
            if (ODataHandler.DisabledFieldNames.Contains(fieldSetting.Name))
            {
                return;
            }

            var refField = fieldSetting as ReferenceFieldSetting;

            if (refField != null)
            {
                entityType.NavigationProperties.Add(CreateNavigationProperty(refField, context));
                return;
            }
            entityType.Properties.Add(CreateProperty(fieldSetting, context));
        }
Example #10
0
        private static void CreatePropertiesFromFieldSettings(IEnumerable <FieldSetting> fieldSettings, ContentType contentType, EntityType entityType, SchemaGenerationContext context)
        {
            var properties           = entityType.Properties;
            var navigationProperties = entityType.NavigationProperties;

            foreach (var fieldSetting in fieldSettings)
            {
                CreatePropertyFromFieldSetting(fieldSetting, contentType, entityType, context);
            }
            foreach (var fieldSetting in context.ListFieldSettings)
            {
                CreatePropertyFromFieldSetting(fieldSetting, contentType, entityType, context);
            }
        }
 private void AddRulesFromIncludedValidators(SchemaFilterContext context, IValidator validator, SchemaGenerationContext schemaGenerationContext)
 {
     FluentValidationSchemaBuilder.AddRulesFromIncludedValidators(
         validator: validator,
         logger: _logger,
         schemaGenerationContext: schemaGenerationContext);
 }
        /// <summary>
        /// Applies rules from validator.
        /// </summary>
        internal static void ApplyRulesToSchema(
            Type schemaType,
            IEnumerable <string>?schemaPropertyNames,
            IValidator validator,
            ILogger logger,
            SchemaGenerationContext schemaGenerationContext)
        {
            OpenApiSchema schema         = schemaGenerationContext.Schema;
            var           schemaTypeName = schemaType.Name;

            var lazyLog = new LazyLog(logger, l => l.LogDebug($"Applying FluentValidation rules to swagger schema '{schemaTypeName}'."));

            var validationRules = validator
                                  .GetValidationRules()
                                  .Where(context => context.ReflectionContext != null)
                                  .ToArray();

            schemaPropertyNames ??= schema.Properties?.Keys ?? Array.Empty <string>();
            foreach (var schemaPropertyName in schemaPropertyNames)
            {
                ValidationRuleInfo?validationRuleInfo = validationRules
                                                        .FirstOrDefault(propertyRule => IsMatchesRule(propertyRule, schemaPropertyName, schemaGenerationContext.SchemaGenerationSettings));

                if (validationRuleInfo != null)
                {
                    var propertyValidators = validationRuleInfo.PropertyRule.GetValidators();

                    foreach (var propertyValidator in propertyValidators)
                    {
                        foreach (var rule in schemaGenerationContext.Rules)
                        {
                            if (rule.IsMatches(propertyValidator))
                            {
                                try
                                {
                                    var ruleHistoryItem = new RuleHistoryCache.RuleHistoryItem(schemaTypeName, schemaPropertyName, propertyValidator, rule.Name);
                                    if (!schema.ContainsRuleHistoryItem(ruleHistoryItem))
                                    {
                                        lazyLog.LogOnce();

                                        var ruleContext = new RuleContext(
                                            schema: schema,
                                            propertyKey: schemaPropertyName,
                                            validationRuleInfo: validationRuleInfo,
                                            propertyValidator: propertyValidator,
                                            reflectionContext: validationRuleInfo.ReflectionContext);
                                        rule.Apply(ruleContext);

                                        logger.LogDebug($"Rule '{rule.Name}' applied for property '{schemaTypeName}.{schemaPropertyName}'.");
                                        schema.AddRuleHistoryItem(ruleHistoryItem);
                                    }
                                    else
                                    {
                                        logger.LogDebug($"Rule '{rule.Name}' already applied for property '{schemaTypeName}.{schemaPropertyName}'.");
                                    }
                                }
                                catch (Exception e)
                                {
                                    logger.LogWarning(0, e, $"Error on apply rule '{rule.Name}' for property '{schemaTypeName}.{schemaPropertyName}'.");
                                }
                            }
                        }
                    }
                }
            }
        }
        internal static void AddRulesFromIncludedValidators(
            IValidator validator,
            ILogger logger,
            SchemaGenerationContext schemaGenerationContext)
        {
            // Note: IValidatorDescriptor doesn't return IncludeRules so we need to get validators manually.
            var validationRules = validator
                                  .GetValidationRules()
                                  .ToArrayDebug();

            var propertiesWithChildAdapters = validationRules
                                              .Select(context => (context.PropertyRule, context.PropertyRule.GetValidators().OfType <IChildValidatorAdaptor>().ToArray()))
                                              .ToArrayDebug();

            foreach ((IValidationRule propertyRule, IChildValidatorAdaptor[] childAdapters) in propertiesWithChildAdapters)
            {
                foreach (var childAdapter in childAdapters)
                {
                    IValidator?childValidator = childAdapter.GetValidatorFromChildValidatorAdapter();
                    if (childValidator != null)
                    {
                        var canValidateInstancesOfType = childValidator.CanValidateInstancesOfType(schemaGenerationContext.SchemaType);

                        if (canValidateInstancesOfType)
                        {
                            // It's a validator for current type (Include for example) so apply changes to current schema.
                            ApplyRulesToSchema(
                                schemaType: schemaGenerationContext.SchemaType,
                                schemaPropertyNames: null,
                                validator: childValidator,
                                logger: logger,
                                schemaGenerationContext: schemaGenerationContext);

                            AddRulesFromIncludedValidators(
                                validator: childValidator,
                                logger: logger,
                                schemaGenerationContext: schemaGenerationContext);
                        }
                        else
                        {
                            // It's a validator for sub schema so get schema and apply changes to it.
                            var schemaForChildValidator = schemaGenerationContext.SchemaProvider.GetSchemaForType(propertyRule.TypeToValidate);

                            var childSchemaContext = schemaGenerationContext with
                            {
                                Schema = schemaForChildValidator
                            };

                            ApplyRulesToSchema(
                                schemaType: propertyRule.TypeToValidate,
                                schemaPropertyNames: null,
                                validator: childValidator,
                                logger: logger,
                                schemaGenerationContext: childSchemaContext);

                            AddRulesFromIncludedValidators(
                                validator: childValidator,
                                logger: logger,
                                schemaGenerationContext: childSchemaContext);
                        }
                    }
                }
            }
        }
Example #14
0
        private void ApplyInternal(OpenApiOperation operation, OperationFilterContext context)
        {
            if (operation.Parameters == null)
            {
                return;
            }

            if (_validatorFactory == null)
            {
                _logger.LogWarning(0, "ValidatorFactory is not provided. Please register FluentValidation.");
                return;
            }

            var schemaProvider = new SwashbuckleSchemaProvider(context.SchemaRepository, context.SchemaGenerator, _schemaGenerationSettings.SchemaIdSelector);

            foreach (var operationParameter in operation.Parameters)
            {
                var apiParameterDescription = context.ApiDescription.ParameterDescriptions.FirstOrDefault(description =>
                                                                                                          description.Name.Equals(operationParameter.Name, StringComparison.InvariantCultureIgnoreCase));

                var modelMetadata = apiParameterDescription?.ModelMetadata;
                if (modelMetadata != null)
                {
                    var parameterType = modelMetadata.ContainerType;
                    if (parameterType == null)
                    {
                        continue;
                    }

                    var validator = _validatorFactory.GetValidator(parameterType);
                    if (validator == null)
                    {
                        continue;
                    }

                    OpenApiSchema schema = schemaProvider.GetSchemaForType(parameterType);

                    if (schema.Properties != null && schema.Properties.Count > 0)
                    {
                        var schemaPropertyName = operationParameter.Name;

                        KeyValuePair <string, OpenApiSchema> apiProperty = schema.Properties.FirstOrDefault(property => property.Key.EqualsIgnoreAll(schemaPropertyName));
                        if (apiProperty.Key != null)
                        {
                            schemaPropertyName = apiProperty.Key;
                        }
                        else
                        {
                            var propertyInfo = parameterType.GetProperty(schemaPropertyName);
                            if (propertyInfo != null && _schemaGenerationSettings.NameResolver != null)
                            {
                                schemaPropertyName = _schemaGenerationSettings.NameResolver?.GetPropertyName(propertyInfo);
                            }
                        }

                        var schemaContext = new SchemaGenerationContext(
                            schema: schema,
                            schemaType: parameterType,
                            rules: _rules,
                            schemaGenerationOptions: _schemaGenerationOptions,
                            schemaGenerationSettings: _schemaGenerationSettings,
                            schemaProvider: schemaProvider);

                        FluentValidationSchemaBuilder.ApplyRulesToSchema(
                            schemaType: parameterType,
                            schemaPropertyNames: new[] { schemaPropertyName },
                            validator: validator,
                            logger: _logger,
                            schemaGenerationContext: schemaContext);

                        if (schema.Required != null)
                        {
                            operationParameter.Required = schema.Required.Contains(schemaPropertyName, IgnoreAllStringComparer.Instance);
                        }

                        var parameterSchema = operationParameter.Schema;
                        if (parameterSchema != null)
                        {
                            if (schema.Properties.TryGetValue(schemaPropertyName.ToLowerCamelCase(), out var property) ||
                                schema.Properties.TryGetValue(schemaPropertyName, out property))
                            {
                                // Copy from property schema to parameter schema.
                                parameterSchema.MinLength        = property.MinLength;
                                parameterSchema.Nullable         = property.Nullable;
                                parameterSchema.MaxLength        = property.MaxLength;
                                parameterSchema.Pattern          = property.Pattern;
                                parameterSchema.Minimum          = property.Minimum;
                                parameterSchema.Maximum          = property.Maximum;
                                parameterSchema.ExclusiveMaximum = property.ExclusiveMaximum;
                                parameterSchema.ExclusiveMinimum = property.ExclusiveMinimum;
                                parameterSchema.AllOf            = property.AllOf;
                            }
                        }
                    }
                }
            }
        }
Example #15
0
        private static NavigationProperty CreateNavigationProperty(ReferenceFieldSetting refField, SchemaGenerationContext context)
        {
            var associationName = String.Concat(refField.Owner.Name, "_", refField.Name);
            var fromName        = String.Concat(associationName, "_From");
            var toName          = String.Concat(associationName, "_To");

            if (!context.Associations.Any(x => x.Name == associationName))
            {
                var ancestorName = GetNearestAncestorName(refField.AllowedTypes);
                context.Associations.Add(new Association
                {
                    Name = associationName,
                    End1 = new AssociationEnd
                    {
                        Type         = refField.Owner.Name,
                        Role         = fromName,
                        Multiplicity = "1"
                    },
                    End2 = new AssociationEnd
                    {
                        Type         = ancestorName,
                        Role         = toName,
                        Multiplicity = refField.AllowMultiple == true ? "*" : refField.Compulsory == true ? "1" : "0..1"
                    }
                });
            }

            return(new NavigationProperty
            {
                Name = refField.Name,
                ToRole = toName,
                FromRole = fromName,
                Relationship = associationName
            });
        }
Example #16
0
        private static Property CreateProperty(FieldSetting fieldSetting, SchemaGenerationContext context)
        {
            Property property;
            var      attributes = new List <KeyValue>();

            if (fieldSetting.Name == "Name")
            {
                attributes.Add(new KeyValue {
                    Key = "m:FC_TargetPath", Value = "SyndicationTitle"
                });
                attributes.Add(new KeyValue {
                    Key = "m:FC_ContentKind", Value = "text"
                });
                attributes.Add(new KeyValue {
                    Key = "m:FC_KeepInContent", Value = "false"
                });
            }
            if (fieldSetting.Name == "Description")
            {
                attributes.Add(new KeyValue {
                    Key = "m:FC_TargetPath", Value = "SyndicationSummary"
                });
                attributes.Add(new KeyValue {
                    Key = "m:FC_ContentKind", Value = "text"
                });
                attributes.Add(new KeyValue {
                    Key = "m:FC_KeepInContent", Value = "false"
                });
            }

            var choiceFieldSetting = fieldSetting as ChoiceFieldSetting;

            if (choiceFieldSetting != null)
            {
                var choiceTypeName = String.Concat(choiceFieldSetting.Owner.Name, ".", fieldSetting.Name);

                if (!context.EnumTypes.Any(x => x.Name == choiceTypeName))
                {
                    EnumType enumType;
                    if (choiceFieldSetting.FieldDataType.IsEnum)
                    {
                        enumType = new EnumType {
                            Name = choiceTypeName, UnderlyingEnumType = choiceFieldSetting.FieldDataType
                        }
                    }
                    ;
                    else
                    {
                        enumType = new EnumType {
                            Name = choiceTypeName, UnderlyingFieldSetting = choiceFieldSetting
                        }
                    };
                    context.EnumTypes.Add(enumType);
                }

                property = new Property
                {
                    Name         = fieldSetting.Name,
                    FieldType    = fieldSetting.ShortName,
                    Type         = choiceTypeName,
                    Nullable     = !fieldSetting.Compulsory.HasValue || !fieldSetting.Compulsory.Value,
                    DefaultValue = fieldSetting.DefaultValue,
                    Attributes   = attributes.Count > 0 ? attributes : null,
                };

                return(property);
            }

            property = new Property
            {
                Name         = fieldSetting.Name,
                Type         = GetPropertyType(fieldSetting, context),
                FieldType    = fieldSetting.ShortName,
                Nullable     = !fieldSetting.Compulsory.HasValue || !fieldSetting.Compulsory.Value,
                DefaultValue = fieldSetting.DefaultValue,
                Attributes   = attributes.Count > 0 ? attributes : null,
            };

            var textFieldSetting = fieldSetting as TextFieldSetting;

            if (textFieldSetting != null)
            {
                property.MaxLength = textFieldSetting.MaxLength;
            }

            return(property);
        }
Example #17
0
 private static void CreateEntityTypes(SchemaGenerationContext context)
 {
     context.WithChildren      = true;
     context.ListFieldSettings = EmtpyFieldSettings;
     CreateEntityTypes(ContentType.GetRootTypes(), context);
 }
Example #18
0
 private static List <FunctionImport> CreateFunctionImports(SchemaGenerationContext context)
 {
     return(new List <FunctionImport>());
 }
Example #19
0
 private static void CreateEntityTypes(IEnumerable <ContentType> contentTypes, SchemaGenerationContext context)
 {
     context.Flattening = true;
     foreach (var contentType in contentTypes)
     {
         CreateEntityType(contentType, context);
     }
 }
Example #20
0
        private static string GetPropertyType(Type t, SchemaGenerationContext context)
        {
            if (t == null)
            {
                return("null");
            }

            var type = GetPrimitivePropertyType(t);

            if (type != null)
            {
                return(type);
            }

            if (t.IsEnum)
            {
                if (!context.EnumTypes.Any(x => x.Name == t.FullName))
                {
                    var enumType = new EnumType {
                        Name = t.FullName, UnderlyingEnumType = t
                    };
                    context.EnumTypes.Add(enumType);
                }
                return(t.FullName);
            }

            if (t.IsInterface)
            {
                if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable <>))
                {
                    type = String.Concat("Collection(", GetPropertyType(t.GetGenericArguments()[0], context), ")");
                }
                else if (typeof(IEnumerable).IsAssignableFrom(t))
                {
                    type = String.Concat("Collection(", typeof(object).Name, ")");
                }
                else
                {
                    CreateComplexType(t, context);
                    type = t.FullName;
                }
            }
            else
            {
                var iface = t.GetInterfaces().FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IEnumerable <>));
                if (iface != null)
                {
                    type = String.Concat("Collection(", GetPropertyType(iface.GetGenericArguments()[0], context), ")");
                }
                else if (typeof(IEnumerable).IsAssignableFrom(t))
                {
                    type = String.Concat("Collection(", typeof(object).Name, ")");
                }
                else
                {
                    CreateComplexType(t, context);
                    type = t.FullName.Replace("+", ".");
                }
            }
            return(type);
        }
Example #21
0
 private static void CreateEntityTypes(SchemaGenerationContext context)
 {
     context.ListFieldSettings = EmtpyFieldSettings;
     CreateEntityTypes(ContentType.GetContentTypes(), context);
 }
Example #22
0
 private static void CreateEntityTypes(IEnumerable <ContentType> contentTypes, SchemaGenerationContext context)
 {
     foreach (var contentType in contentTypes)
     {
         if (context.IsPermitteType(contentType))
         {
             CreateEntityType(contentType, context);
         }
     }
 }
 private void ApplyRulesToSchema(SchemaFilterContext context, IValidator validator, SchemaGenerationContext schemaGenerationContext)
 {
     FluentValidationSchemaBuilder.ApplyRulesToSchema(
         schemaType: context.Type,
         schemaPropertyNames: null,
         validator: validator,
         logger: _logger,
         schemaGenerationContext: schemaGenerationContext);
 }