private void ApplyRulesToSchema(OpenApiSchema schema, SchemaFilterContext context, IValidator validator) { var lazyLog = new LazyLog(_logger, logger => logger.LogDebug($"Applying FluentValidation rules to swagger schema for type '{context.Type}'.")); foreach (var schemaPropertyName in schema?.Properties?.Keys ?? Array.Empty <string>()) { var validators = validator.GetValidatorsForMemberIgnoreCase(schemaPropertyName); foreach (var propertyValidator in validators) { foreach (var rule in _rules) { if (rule.Matches(propertyValidator)) { try { lazyLog.LogOnce(); rule.Apply(new RuleContext(schema, context, schemaPropertyName, propertyValidator)); _logger.LogDebug($"Rule '{rule.Name}' applied for property '{context.Type.Name}.{schemaPropertyName}'"); } catch (Exception e) { _logger.LogWarning(0, e, $"Error on apply rule '{rule.Name}' for property '{context.Type.Name}.{schemaPropertyName}'."); } } } } } }
/// <summary> /// Applies rules from validator. /// </summary> internal static void ApplyRulesToSchema( OpenApiSchema schema, Type schemaType, IEnumerable <string>?schemaPropertyNames, SchemaFilterContext?schemaFilterContext, IValidator validator, IReadOnlyCollection <FluentValidationRule> rules, ILogger logger) { var schemaTypeName = schemaType.Name; var lazyLog = new LazyLog(logger, l => l.LogDebug($"Applying FluentValidation rules to swagger schema '{schemaTypeName}'.")); schemaPropertyNames ??= schema.Properties?.Keys ?? Array.Empty <string>(); foreach (var schemaPropertyName in schemaPropertyNames) { var validationRules = validator.GetValidationRulesForMemberIgnoreCase(schemaPropertyName).ToArrayDebug(); foreach (var ruleContext in validationRules) { var propertyValidators = ruleContext.PropertyRule.Validators; foreach (var propertyValidator in propertyValidators) { foreach (var rule in rules) { if (rule.Matches(propertyValidator)) { try { var ruleHistoryItem = new RuleHistoryCache.RuleHistoryItem(schemaTypeName, schemaPropertyName, propertyValidator, rule.Name); if (!schema.ContainsRuleHistoryItem(ruleHistoryItem)) { lazyLog.LogOnce(); rule.Apply(new RuleContext(schema, schemaPropertyName, propertyValidator, schemaFilterContext, isCollectionValidator: ruleContext.IsCollectionRule)); 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}'."); } } } } } } }
void ApplyInternal(Operation operation, OperationFilterContext context) { if (operation.Parameters == null) { return; } var schemaIdSelector = _swaggerGenOptions.SchemaRegistryOptions.SchemaIdSelector ?? new SchemaRegistryOptions().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; } var key = modelMetadata.PropertyName; var validatorsForMember = validator.GetValidatorsForMemberIgnoreCase(key); var lazyLog = new LazyLog(_logger, logger => logger.LogDebug($"Applying FluentValidation rules to swagger schema for type '{parameterType}' from operation '{operation.OperationId}'.")); Schema schema = null; foreach (var propertyValidator in validatorsForMember) { foreach (var rule in _rules) { if (rule.Matches(propertyValidator)) { try { var schemaId = schemaIdSelector(parameterType); if (!context.SchemaRegistry.Definitions.TryGetValue(schemaId, out schema)) { schema = context.SchemaRegistry.GetOrRegister(parameterType); } if (schema.Properties == null && context.SchemaRegistry.Definitions.ContainsKey(schemaId)) { schema = context.SchemaRegistry.Definitions[schemaId]; } if (schema.Properties != null && schema.Properties.Count > 0) { lazyLog.LogOnce(); rule.Apply(new RuleContext(schema, new SchemaFilterContext(parameterType, null, context.SchemaRegistry), key.ToLowerCamelCase(), propertyValidator)); _logger.LogDebug($"Rule '{rule.Name}' applied for property '{parameterType.Name}.{key}'."); } else { _logger.LogDebug($"Rule '{rule.Name}' skipped for property '{parameterType.Name}.{key}'."); } } catch (Exception e) { _logger.LogWarning(0, e, $"Error on apply rule '{rule.Name}' for property '{parameterType.Name}.{key}'."); } } } } if (schema?.Required != null) { operationParameter.Required = schema.Required.Contains(key, StringComparer.InvariantCultureIgnoreCase); } if (schema?.Properties != null) { var parameterSchema = operationParameter as PartialSchema; if (operationParameter != null) { if (schema.Properties.TryGetValue(key.ToLowerCamelCase(), out var property) || schema.Properties.TryGetValue(key, out property)) { parameterSchema.MinLength = property.MinLength; parameterSchema.MaxLength = property.MaxLength; parameterSchema.Pattern = property.Pattern; parameterSchema.Minimum = property.Minimum; parameterSchema.Maximum = property.Maximum; parameterSchema.ExclusiveMaximum = property.ExclusiveMaximum; parameterSchema.ExclusiveMinimum = property.ExclusiveMinimum; } } } } } }
/// <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}'."); } } } } } } }