Skip to content

Commit

Permalink
Fix sonar cloud issues
Browse files Browse the repository at this point in the history
  • Loading branch information
ivarne committed Jan 4, 2024
1 parent de315c7 commit 088c125
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ namespace Altinn.App.Core.Features.Validation.Default;
/// </summary>
public class DefaultDataElementValidation : IDataElementValidator
{
public string DataType { get; }
/// <inheritdoc />
public string DataType { get; } = "*";

/// <summary>
/// Runs on all data elements to validate metadata and file scan results.
/// </summary>
public bool CanValidateDataType(DataType dataType) => true;

/// <inheritdoc />
public Task<List<ValidationIssue>> ValidateDataElement(Instance instance, DataElement dataElement, DataType dataType)
{
var issues = new List<ValidationIssue>();
Expand All @@ -35,7 +37,7 @@ public Task<List<ValidationIssue>> ValidateDataElement(Instance instance, DataEl
var contentTypeWithoutEncoding = dataElement.ContentType.Split(";")[0];

if (dataType.AllowedContentTypes != null && dataType.AllowedContentTypes.Count > 0 &&
dataType.AllowedContentTypes.All(ct =>
dataType.AllowedContentTypes.TrueForAll(ct =>
!ct.Equals(contentTypeWithoutEncoding, StringComparison.OrdinalIgnoreCase)))
{
issues.Add( new ValidationIssue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ public class DefaultTaskValidator : ITaskValidator
{
private readonly IAppMetadata _appMetadata;

/// <summary>
/// Initializes a new instance of the <see cref="DefaultTaskValidator"/> class.
/// </summary>
public DefaultTaskValidator([ServiceKey] string taskId, IAppMetadata appMetadata)
{
TaskId = taskId;
Expand All @@ -22,6 +25,7 @@ public DefaultTaskValidator([ServiceKey] string taskId, IAppMetadata appMetadata
/// <inheritdoc />
public string TaskId { get; }

/// <inheritdoc />
public async Task<List<ValidationIssue>> ValidateTask(Instance instance)
{
var messages = new List<ValidationIssue>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,14 @@ public class ExpressionValidator : IFormDataValidator
private readonly IAppResources _appResourceService;
private readonly LayoutEvaluatorStateInitializer _layoutEvaluatorStateInitializer;

private static readonly JsonSerializerOptions _jsonOptions = new()
{
ReadCommentHandling = JsonCommentHandling.Skip,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};

/// <summary>
/// Constructor
/// Constructor for the expression validator
/// </summary>
public ExpressionValidator([ServiceKey] string dataType, ILogger<ExpressionValidator> logger, IAppResources appResourceService, LayoutEvaluatorStateInitializer layoutEvaluatorStateInitializer)
{
Expand All @@ -37,6 +43,7 @@ public ExpressionValidator([ServiceKey] string dataType, ILogger<ExpressionValid
/// </summary>
public bool ShouldRunForIncrementalValidation(List<string>? changedFields = null) => true;

/// <inheritdoc />
public async Task<List<ValidationIssue>> ValidateFormData(Instance instance, DataElement dataElement, object data, List<string>? changedFields = null)
{
var rawValidationConfig = _appResourceService.GetValidationConfiguration(dataElement.DataType);
Expand All @@ -52,8 +59,7 @@ public async Task<List<ValidationIssue>> ValidateFormData(Instance instance, Dat
}



public static List<ValidationIssue> Validate(JsonElement validationConfig, LayoutEvaluatorState evaluatorState, ILogger logger)
internal static List<ValidationIssue> Validate(JsonElement validationConfig, LayoutEvaluatorState evaluatorState, ILogger logger)
{
var validationIssues = new List<ValidationIssue>();
var expressionValidations = ParseExpressionValidationConfig(validationConfig, logger);
Expand Down Expand Up @@ -108,22 +114,19 @@ public static List<ValidationIssue> Validate(JsonElement validationConfig, Layou
private static RawExpressionValidation? ResolveValidationDefinition(string name, JsonElement definition, Dictionary<string, RawExpressionValidation> resolvedDefinitions, ILogger logger)
{
var resolvedDefinition = new RawExpressionValidation();
var rawDefinition = definition.Deserialize<RawExpressionValidation>(new JsonSerializerOptions
{
ReadCommentHandling = JsonCommentHandling.Skip,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
});

var rawDefinition = definition.Deserialize<RawExpressionValidation>(_jsonOptions);
if (rawDefinition == null)
{
logger.LogError($"Validation definition {name} could not be parsed");
logger.LogError("Validation definition {name} could not be parsed", name);
return null;
}
if (rawDefinition.Ref != null)
{
var reference = resolvedDefinitions.GetValueOrDefault(rawDefinition.Ref);
if (reference == null)
{
logger.LogError($"Could not resolve reference {rawDefinition.Ref} for validation {name}");
logger.LogError("Could not resolve reference {rawDefinitionRef} for validation {name}", rawDefinition.Ref, name);
return null;

}
Expand All @@ -149,13 +152,13 @@ public static List<ValidationIssue> Validate(JsonElement validationConfig, Layou

if (resolvedDefinition.Message == null)
{
logger.LogError($"Validation {name} is missing message");
logger.LogError("Validation {name} is missing message", name);
return null;
}

if (resolvedDefinition.Condition == null)
{
logger.LogError($"Validation {name} is missing condition");
logger.LogError("Validation {name} is missing condition", name);
return null;
}

Expand All @@ -172,13 +175,13 @@ public static List<ValidationIssue> Validate(JsonElement validationConfig, Layou
var stringReference = definition.GetString();
if (stringReference == null)
{
logger.LogError($"Could not resolve null reference for validation for field {field}");
logger.LogError("Could not resolve null reference for validation for field {field}", field);
return null;
}
var reference = resolvedDefinitions.GetValueOrDefault(stringReference);
if (reference == null)
{
logger.LogError($"Could not resolve reference {stringReference} for validation for field {field}");
logger.LogError("Could not resolve reference {stringReference} for validation for field {field}", stringReference, field);
return null;
}
rawExpressionValidatıon.Message = reference.Message;
Expand All @@ -187,14 +190,10 @@ public static List<ValidationIssue> Validate(JsonElement validationConfig, Layou
}
else
{
var expressionDefinition = definition.Deserialize<RawExpressionValidation>(new JsonSerializerOptions
{
ReadCommentHandling = JsonCommentHandling.Skip,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
});
var expressionDefinition = definition.Deserialize<RawExpressionValidation>(_jsonOptions);
if (expressionDefinition == null)
{
logger.LogError($"Validation for field {field} could not be parsed");
logger.LogError("Validation for field {field} could not be parsed", field);
return null;
}

Expand All @@ -203,7 +202,7 @@ public static List<ValidationIssue> Validate(JsonElement validationConfig, Layou
var reference = resolvedDefinitions.GetValueOrDefault(expressionDefinition.Ref);
if (reference == null)
{
logger.LogError($"Could not resolve reference {expressionDefinition.Ref} for validation for field {field}");
logger.LogError("Could not resolve reference {expressionDefinitionRef} for validation for field {field}", expressionDefinition.Ref, field);
return null;

}
Expand All @@ -230,13 +229,13 @@ public static List<ValidationIssue> Validate(JsonElement validationConfig, Layou

if (rawExpressionValidatıon.Message == null)
{
logger.LogError($"Validation for field {field} is missing message");
logger.LogError("Validation for field {field} is missing message", field);
return null;
}

if (rawExpressionValidatıon.Condition == null)
{
logger.LogError($"Validation for field {field} is missing condition");
logger.LogError("Validation for field {field} is missing condition", field);
return null;
}

Expand Down Expand Up @@ -264,7 +263,7 @@ private static Dictionary<string, List<ExpressionValidation>> ParseExpressionVal
var resolvedDefinition = ResolveValidationDefinition(name, definition, expressionValidationDefinitions, logger);
if (resolvedDefinition == null)
{
logger.LogError($"Validation definition {name} could not be resolved");
logger.LogError("Validation definition {name} could not be resolved", name);
continue;
}
expressionValidationDefinitions[name] = resolvedDefinition;
Expand All @@ -281,17 +280,18 @@ private static Dictionary<string, List<ExpressionValidation>> ParseExpressionVal
var validations = validationArray.Value;
foreach (var validation in validations.EnumerateArray())
{
if (!expressionValidations.ContainsKey(field))
if (!expressionValidations.TryGetValue(field, out var expressionValidation))
{
expressionValidations[field] = new List<ExpressionValidation>();
expressionValidation = new List<ExpressionValidation>();
expressionValidations[field] = expressionValidation;
}
var resolvedExpressionValidation = ResolveExpressionValidation(field, validation, expressionValidationDefinitions, logger);
if (resolvedExpressionValidation == null)
{
logger.LogError($"Validation for field {field} could not be resolved");
logger.LogError("Validation for field {field} could not be resolved", field);
continue;
}
expressionValidations[field].Add(resolvedExpressionValidation);
expressionValidation.Add(resolvedExpressionValidation);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ public LegacyIValidationFormDataValidator(IInstanceValidator? instanceValidator,
}

/// <summary>
///
/// The legacy validator should run for all data types
/// </summary>
public string DataType { get; } = "AnyType";
public string DataType { get; } = "*";

/// <summary>
/// Always run for incremental validation
/// </summary>
public bool ShouldRunForIncrementalValidation(List<string>? changedFields = null) => true;
public bool ShouldRunForIncrementalValidation(List<string>? changedFields = null) => _instanceValidator is not null;


/// <inheritdoc />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@

namespace Altinn.App.Core.Features.Validation.Default;

/// <summary>
/// Validator that runs the required rules in the layout
/// </summary>
public class RequiredLayoutValidator : IFormDataValidator
{
private readonly LayoutEvaluatorStateInitializer _layoutEvaluatorStateInitializer;
private readonly IAppResources _appResourcesService;
private readonly IAppMetadata _appMetadata;

/// <summary>
/// Initializes a new instance of the <see cref="RequiredLayoutValidator"/> class.
/// </summary>
public RequiredLayoutValidator([ServiceKey] string dataType, LayoutEvaluatorStateInitializer layoutEvaluatorStateInitializer, IAppResources appResourcesService, IAppMetadata appMetadata)
{
DataType = dataType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,31 +71,41 @@ protected void RunFor<T1>(Expression<Func<TModel, T1>> selector)
_runForPrefixes.Add(LinqExpressionHelpers.GetJsonPath(selector));
}

/// <summary>
/// Convenience method to create a validation issue for a field using a linq expression instead of a key
/// </summary>
protected void CreateValidationIssue<T>(Expression<Func<TModel,T>> selector, string textKey, ValidationIssueSeverity severity = ValidationIssueSeverity.Error)
{
Debug.Assert(ValidationIssues.Value is not null);
ValidationIssues.Value.Add( new ValidationIssue
AddValidationIssue(new ValidationIssue
{
Field = LinqExpressionHelpers.GetJsonPath(selector),
CustomTextKey = textKey,
Severity = severity
});
}

/// <summary>
/// Allows inheriting classes to add validation issues.
/// </summary>
protected void AddValidationIssue(ValidationIssue issue)
{
Debug.Assert(ValidationIssues.Value is not null);
ValidationIssues.Value.Add(issue);
}

/// <summary>
/// Implementation of the generic <see cref="IFormDataValidator"/> interface to call the corretly typed
/// validation method implemented by the inheriting class.
/// </summary>
public async Task<List<ValidationIssue>> ValidateFormData(Instance instance, DataElement dataElement, object data, List<string>? changedFields = null)
{
if (data is not TModel model)
{
throw new ArgumentException($"Data is not of type {typeof(TModel)}");
}

ValidationIssues.Value = new List<ValidationIssue>();;
ValidationIssues.Value = new List<ValidationIssue>();
await ValidateFormData(instance, dataElement, model);
return ValidationIssues.Value;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
using System.Collections;
using System.Text.Json.Serialization;
using Altinn.App.Core.Configuration;
using Altinn.App.Core.Features.Validation.Default;
using Altinn.App.Core.Models.Validation;
using Altinn.Platform.Storage.Interface.Models;
using Microsoft.AspNetCore.Mvc.ModelBinding;

namespace Altinn.App.Core.Features.Validation.Helpers;

/// <summary>
/// Static helpers to make map from <see cref="ModelStateDictionary"/> to list of <see cref="ValidationIssue"/>
/// </summary>
public static class ModelStateHelpers
{
/// <summary>
/// Get a list of issues from a <see cref="ModelStateDictionary" />
/// </summary>
/// <param name="modelState"></param>
/// <param name="instance">The instance used for populating issue.InstanceId</param>
/// <param name="dataElement">Data element for populating issue.DataElementId</param>
/// <param name="generalSettings">General settings to get *Fixed* prefixes</param>
/// <param name="objectType">Type of the object to map ModelStateDictionary key to the json path field (might be different)</param>
/// <param name="source">issue.Source</param>
/// <returns>A list of the issues as our standard ValidationIssue</returns>
public static List<ValidationIssue> ModelStateToIssueList(ModelStateDictionary modelState, Instance instance,
DataElement dataElement, GeneralSettings generalSettings, Type objectType, string source)
{
Expand Down Expand Up @@ -49,8 +63,7 @@ private static (ValidationIssueSeverity Severity, string Message) GetSeverityFro
originalMessage.Remove(0, generalSettings.SoftValidationPrefix.Length));
}

if (generalSettings.FixedValidationPrefix != null
&& originalMessage.StartsWith(generalSettings.FixedValidationPrefix))
if (originalMessage.StartsWith(generalSettings.FixedValidationPrefix))
{
return (ValidationIssueSeverity.Fixed,
originalMessage.Remove(0, generalSettings.FixedValidationPrefix.Length));
Expand Down Expand Up @@ -126,6 +139,10 @@ private static (ValidationIssueSeverity Severity, string Message) GetSeverityFro
return $"{jsonPropertyName}.{ModelKeyToField(rest, childType)}";
}

/// <summary>
/// Same as <see cref="ModelStateToIssueList"/>, but without information about a specific field
/// used by <see cref="LegacyIValidationTaskValidator"/>
/// </summary>
public static List<ValidationIssue> MapModelStateToIssueList(ModelStateDictionary modelState, Instance instance,
GeneralSettings generalSettings)
{
Expand Down
7 changes: 0 additions & 7 deletions src/Altinn.App.Core/Features/Validation/ValidationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ public async Task<List<ValidationIssue>> ValidateInstanceAtTask(Instance instanc
ArgumentNullException.ThrowIfNull(instance);
ArgumentNullException.ThrowIfNull(taskId);

var issues = new List<ValidationIssue>();

// Run task validations
var taskValidators = _serviceProvider.GetServices<ITaskValidator>()
.Where(tv => tv.TaskId == taskId)
Expand Down Expand Up @@ -131,11 +129,6 @@ public async Task<Dictionary<string, List<ValidationIssue>>> ValidateFormData(In
.Where(dv => dv.ShouldRunForIncrementalValidation(changedFields))
.ToArray();

if (dataValidators.Length > 0)
{
// TODO: Remove hidden data before validation
}

var issuesLists = await Task.WhenAll(dataValidators.Select(async (v) =>
{
try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public async Task ValidateFormData_NoErrors()
var changedFields = new List<string>();

var validator = new LegacyIValidationFormDataValidator(null, Options.Create(new GeneralSettings()));
validator.ShouldRunForIncrementalValidation(changedFields).Should().BeTrue();
validator.ShouldRunForIncrementalValidation(changedFields).Should().BeFalse();

// Act
var result = await validator.ValidateFormData(new Instance(), new DataElement(), data, changedFields);
Expand Down
Loading

0 comments on commit 088c125

Please sign in to comment.