Skip to content

Commit

Permalink
Add DataType as input to validators
Browse files Browse the repository at this point in the history
  • Loading branch information
ivarne committed Dec 12, 2023
1 parent 3701d97 commit 159f0e0
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 10 deletions.
20 changes: 19 additions & 1 deletion src/Altinn.App.Core/Features/Validation/IDataElementValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,32 @@ namespace Altinn.App.Core.Features.Validation;
/// Validator for data elements.
/// See <see cref="IFormDataValidator"/> for an alternative validator for data elements with app logic.
/// and that support incremental validation on save.
/// For validating the content of files, see <see cref="IFileAnalyzer"/> and <see cref="IFileValidator"/>
/// </summary>
public interface IDataElementValidator
{
/// <summary>
/// The data type that this validator should run for. This is the id of the data type from applicationmetadata.json
/// </summary>
/// <remarks>
/// Used by default in <see cref="CanValidateDataType"/>. Overrides might ignore this.
/// </remarks>
string DataType { get; }

/// <summary>
/// Override this method to customize what data elements this validator should run for.
/// </summary>
bool CanValidateDataType(DataType dataType)
{
return DataType == dataType.Id;
}
string DataType { get; }

/// <summary>
/// Run validations for a data element. This is supposed to run quickly
/// </summary>
/// <param name="instance">The instance to validate</param>
/// <param name="dataElement"></param>
/// <param name="dataType"></param>
/// <returns></returns>
public Task<List<ValidationIssue>> ValidateDataElement(Instance instance, DataElement dataElement, DataType dataType);
}
9 changes: 7 additions & 2 deletions src/Altinn.App.Core/Features/Validation/IValidationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,15 @@ public interface IValidationService
Task<List<ValidationIssue>> ValidateDataElement(Instance instance, DataElement dataElement, DataType dataType);

/// <summary>
/// Validates a single data element. Used by frontend to continuously validate form data.
/// Validates a single data element. Used by frontend to continuously validate form data as it changes.
/// </summary>
/// <remarks>
/// This method executes validations for <see cref="IFormDataValidator"/>
/// </remarks>
Task<Dictionary<string, List<ValidationIssue>>> ValidateFormData(Instance instance, DataElement dataElement, object data, List<string>? changedFields = null);
/// <param name="instance">The instance to validate</param>
/// <param name="dataElement">The data element to run validations for</param>
/// <param name="dataType">The type of the data element</param>
/// <param name="data">The data deserialized to the strongly typed object that represents the form data</param>
/// <param name="changedFields">List of json paths for the fields that have changed (used for incremental validation)</param>
Task<Dictionary<string, List<ValidationIssue>>> ValidateFormData(Instance instance, DataElement dataElement, DataType dataType, object data, List<string>? changedFields = null);
}
6 changes: 3 additions & 3 deletions src/Altinn.App.Core/Features/Validation/ValidationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public async Task<List<ValidationIssue>> ValidateDataElement(Instance instance,
string app = instance.AppId.Split("/")[1];
int instanceOwnerPartyId = int.Parse(instance.InstanceOwner.PartyId);
var data = await _dataClient.GetFormData(instanceGuid, modelType, instance.Org, app, instanceOwnerPartyId, Guid.Parse(dataElement.Id)); // TODO: Add method that accepts instance and dataElement
var formDataIssuesDictionary = await ValidateFormData(instance, dataElement, data, null);
var formDataIssuesDictionary = await ValidateFormData(instance, dataElement, dataType, data, null);

return (await dataElementsIssuesTask).SelectMany(x=>x)
.Concat(formDataIssuesDictionary.SelectMany(kv=>kv.Value))
Expand All @@ -117,7 +117,7 @@ public async Task<List<ValidationIssue>> ValidateDataElement(Instance instance,

/// <inheritdoc/>
public async Task<Dictionary<string, List<ValidationIssue>>> ValidateFormData(Instance instance,
DataElement dataElement, object data, List<string>? changedFields = null)
DataElement dataElement, DataType dataType, object data, List<string>? changedFields = null)
{
ArgumentNullException.ThrowIfNull(instance);
ArgumentNullException.ThrowIfNull(dataElement);
Expand All @@ -141,7 +141,7 @@ public async Task<Dictionary<string, List<ValidationIssue>>> ValidateFormData(In
try
{
_logger.LogDebug("Start running validator {validatorName} on {dataType} for data element {dataElementId} in instance {instanceId}", v.GetType().Name, dataElement.DataType, dataElement.Id, instance.Id);

Check failure

Code scanning / CodeQL

Log entries created from user input High

This log entry depends on a
user-provided value
.
This log entry depends on a
user-provided value
.
This log entry depends on a
user-provided value
.
This log entry depends on a
user-provided value
.
This log entry depends on a
user-provided value
.
This log entry depends on a
user-provided value
.
This log entry depends on a user-provided value.
This log entry depends on a user-provided value.

Check failure

Code scanning / CodeQL

Log entries created from user input High

This log entry depends on a
user-provided value
.
This log entry depends on a
user-provided value
.
This log entry depends on a
user-provided value
.
This log entry depends on a
user-provided value
.
This log entry depends on a
user-provided value
.
This log entry depends on a
user-provided value
.
This log entry depends on a user-provided value.
This log entry depends on a user-provided value.

Check failure

Code scanning / CodeQL

Log entries created from user input High

This log entry depends on a
user-provided value
.
This log entry depends on a
user-provided value
.
This log entry depends on a
user-provided value
.
This log entry depends on a
user-provided value
.
This log entry depends on a
user-provided value
.
This log entry depends on a
user-provided value
.
This log entry depends on a user-provided value.
This log entry depends on a user-provided value.
var issues = await v.ValidateFormData(instance,dataElement, data, changedFields);
var issues = await v.ValidateFormData(instance, dataElement, data, changedFields);
if (v.Code is not null)
{
issues.ForEach(i=>i.Code = v.Code);// Ensure that the code is set to the validator code
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public async Task ValidateFormData_WithNoValidators_ReturnsNoErrors()

var validatorService = serviceProvider.GetRequiredService<IValidationService>();
var data = new MyModel { Name = "Ola" };
var result = await validatorService.ValidateFormData(new Instance(), DefaultDataElement, data);
var result = await validatorService.ValidateFormData(new Instance(), DefaultDataElement, null!, data);
result.Should().BeEmpty();
}

Expand All @@ -81,7 +81,7 @@ public async Task ValidateFormData_WithMyNameValidator_ReturnsNoErrorsWhenNameIs

var validatorService = serviceProvider.GetRequiredService<IValidationService>();
var data = new MyModel { Name = "Ola" };
var result = await validatorService.ValidateFormData(new Instance(), DefaultDataElement, data);
var result = await validatorService.ValidateFormData(new Instance(), DefaultDataElement, null!, data);
result.Should().ContainKey("Altinn.App.Core.Tests.Features.Validators.ValidationServiceTests+MyNameValidator-MyType").WhoseValue.Should().HaveCount(0);
result.Should().HaveCount(1);
}
Expand All @@ -94,7 +94,7 @@ public async Task ValidateFormData_WithMyNameValidator_ReturnsErrorsWhenNameIsKa

var validatorService = serviceProvider.GetRequiredService<IValidationService>();
var data = new MyModel { Name = "Kari" };
var result = await validatorService.ValidateFormData(new Instance(), DefaultDataElement, data);
var result = await validatorService.ValidateFormData(new Instance(), DefaultDataElement, null!, data);
result.Should().ContainKey("Altinn.App.Core.Tests.Features.Validators.ValidationServiceTests+MyNameValidator-MyType").WhoseValue.Should().ContainSingle().Which.CustomTextKey.Should().Be("NameNotOla");
result.Should().HaveCount(1);
}
Expand All @@ -107,7 +107,7 @@ public async Task ValidateFormData_WithMyNameValidator_ReturnsNoErrorsWhenOnlyAg

var validatorService = serviceProvider.GetRequiredService<IValidationService>();
var data = new MyModel { Name = "Kari" };
var result = await validatorService.ValidateFormData(new Instance(), DefaultDataElement, data, new List<string> { "age" });
var result = await validatorService.ValidateFormData(new Instance(), DefaultDataElement, null!, data, new List<string> { "age" });
result.Should()
.NotContainKey("Altinn.App.Core.Tests.Features.Validators.ValidationServiceTests+MyNameValidator");
result.Should().HaveCount(0);
Expand Down

0 comments on commit 159f0e0

Please sign in to comment.