Skip to content

Commit

Permalink
Add validation on file scan status pending (#168)
Browse files Browse the repository at this point in the history
Co-authored-by: Ronny Birkeli <[email protected]>
  • Loading branch information
RonnyB71 and Ronny Birkeli authored Jan 25, 2023
1 parent 856a4b6 commit 0fd8cc6
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 41 deletions.
2 changes: 1 addition & 1 deletion src/Altinn.App.Api/Altinn.App.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

<ItemGroup>
<PackageReference Include="Altinn.Common.PEP" Version="1.1.0" />
<PackageReference Include="Altinn.Platform.Storage.Interface" Version="3.14.0" />
<PackageReference Include="Altinn.Platform.Storage.Interface" Version="3.15.0" />
</ItemGroup>

<ItemGroup Condition="'$(Configuration)'=='Debug'">
Expand Down
2 changes: 1 addition & 1 deletion src/Altinn.App.Core/Altinn.App.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<PackageReference Include="Altinn.Common.EFormidlingClient" Version="1.3.3" />
<PackageReference Include="Altinn.Common.PEP" Version="1.1.0" />
<PackageReference Include="Altinn.Platform.Models" Version="1.1.2" />
<PackageReference Include="Altinn.Platform.Storage.Interface" Version="3.14.0" />
<PackageReference Include="Altinn.Platform.Storage.Interface" Version="3.15.0" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.46" />
<PackageReference Include="JWTCookieAuthentication" Version="2.4.2" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.21.0" />
Expand Down
27 changes: 13 additions & 14 deletions src/Altinn.App.Core/Features/Validation/ValidationAppSI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,20 +199,19 @@ public async Task<List<ValidationIssue>> ValidateDataElement(Instance instance,
messages.Add(message);
}

//TODO: Awaits new property on pending file scans
//if (dataType.EnableFileScan && dataElement.ValidationErrorOnPendingFileScan && dataElement.FileScanResult == FileScanResult.Pending)
//{
// ValidationIssue message = new ValidationIssue()
// {
// InstanceId = instance.Id,
// DataElementId = dataElement.Id,
// Code = ValidationIssueCodes.DataElementCodes.DataElementFileScanPending,
// Severity = ValidationIssueSeverity.Error,
// Description = ValidationIssueCodes.DataElementCodes.DataElementFileScanPending,
// Field = dataType.Id
// };
// messages.Add(message);
//}
if (dataType.EnableFileScan && dataType.ValidationErrorOnPendingFileScan && dataElement.FileScanResult == FileScanResult.Pending)
{
ValidationIssue message = new ValidationIssue()
{
InstanceId = instance.Id,
DataElementId = dataElement.Id,
Code = ValidationIssueCodes.DataElementCodes.DataElementFileScanPending,
Severity = ValidationIssueSeverity.Error,
Description = ValidationIssueCodes.DataElementCodes.DataElementFileScanPending,
Field = dataType.Id
};
messages.Add(message);
}

if (dataType.AppLogic?.ClassRef != null)
{
Expand Down
161 changes: 136 additions & 25 deletions test/Altinn.App.Core.Tests/Features/Validators/ValidationAppSITests.cs
Original file line number Diff line number Diff line change
@@ -1,57 +1,135 @@
#nullable enable
using System.Linq;
using System.Text.Json.Serialization;

using Altinn.App.Core.Features;
using Altinn.App.Core.Features.Validation;
using Altinn.App.Core.Infrastructure.Clients.Events;
using Altinn.App.Core.Interface;
using Altinn.App.Core.Internal.AppModel;
using Altinn.App.Core.Internal.Expressions;
using Altinn.App.Core.Models.Validation;
using Altinn.Platform.Storage.Interface.Enums;
using Altinn.Platform.Storage.Interface.Models;
using FluentAssertions;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Moq;
using Xunit;

namespace Altinn.App.Core.Tests.Features.Validators;

public class ValidationAppSITests
{
[Fact]
public void ModelKeyToField_NullInputWithoutType_ReturnsNull()
public async Task FileScanEnabled_VirusFound_ValidationShouldFail()
{
ValidationAppSI.ModelKeyToField(null, null!).Should().BeNull();
ValidationAppSI validationAppSI = ConfigureMockServicesForValidation();

var instance = new Instance();
var dataType = new DataType() { EnableFileScan = true };
var dataElement = new DataElement()
{
FileScanResult = FileScanResult.Infected
};

List<ValidationIssue> validationIssues = await validationAppSI.ValidateDataElement(instance, dataType, dataElement);

validationIssues.FirstOrDefault(vi => vi.Code == "DataElementFileInfected").Should().NotBeNull();
}

[Fact]
public void ModelKeyToField_StringInputWithoutType_ReturnsSameString()
public async Task FileScanEnabled_PendingScanNotEnabled_ValidationShouldNotFail()
{
ValidationAppSI.ModelKeyToField("null", null!).Should().Be("null");
ValidationAppSI validationAppSI = ConfigureMockServicesForValidation();

var instance = new Instance();
var dataType = new DataType() { EnableFileScan = true };
var dataElement = new DataElement()
{
FileScanResult = FileScanResult.Pending
};

List<ValidationIssue> validationIssues = await validationAppSI.ValidateDataElement(instance, dataType, dataElement);

validationIssues.FirstOrDefault(vi => vi.Code == "DataElementFileScanPending").Should().BeNull();
}

public class TestModel
[Fact]
public async Task FileScanEnabled_PendingScanEnabled_ValidationShouldNotFail()
{
[JsonPropertyName("level1")]
public string FirstLevelProp { get; set; } = default!;
ValidationAppSI validationAppSI = ConfigureMockServicesForValidation();

[JsonPropertyName("sub")]
public SubTestModel SubTestModel { get; set; } = default!;
var instance = new Instance();
var dataType = new DataType() { EnableFileScan = true, ValidationErrorOnPendingFileScan = true };
var dataElement = new DataElement()
{
FileScanResult = FileScanResult.Pending
};

[JsonPropertyName("subnull")]
public SubTestModel? SubTestModelNull { get; set; } = default!;
List<ValidationIssue> validationIssues = await validationAppSI.ValidateDataElement(instance, dataType, dataElement);

[JsonPropertyName("subList")]
public List<SubTestModel> SubTestModelList { get; set; } = default!;
validationIssues.FirstOrDefault(vi => vi.Code == "DataElementFileScanPending").Should().NotBeNull();
}

public class SubTestModel
[Fact]
public async Task FileScanEnabled_Clean_ValidationShouldNotFail()
{
[JsonPropertyName("decimal")]
public decimal DecimalNumber { get; set; } = default!;
ValidationAppSI validationAppSI = ConfigureMockServicesForValidation();

[JsonPropertyName("nullableString")]
public string? StringNullable { get; set; } = default!;
var instance = new Instance();
var dataType = new DataType() { EnableFileScan = true, ValidationErrorOnPendingFileScan = true };
var dataElement = new DataElement()
{
FileScanResult = FileScanResult.Clean
};

[JsonPropertyName("decimalList")]
public List<decimal> ListOfDecimal { get; set; } = default!;
List<ValidationIssue> validationIssues = await validationAppSI.ValidateDataElement(instance, dataType, dataElement);

[JsonPropertyName("nullableDecimalList")]
public List<decimal?> ListOfNullableDecimal { get; set; } = default!;
validationIssues.FirstOrDefault(vi => vi.Code == "DataElementFileInfected").Should().BeNull();
validationIssues.FirstOrDefault(vi => vi.Code == "DataElementFileScanPending").Should().BeNull();
}

[JsonPropertyName("subList")]
public List<SubTestModel> SubTestModelList { get; set; } = default!;
private static ValidationAppSI ConfigureMockServicesForValidation()
{
Mock<ILogger<ValidationAppSI>> loggerMock = new();
var dataMock = new Mock<IData>();
var instanceMock = new Mock<IInstance>();
var instanceValidator = new Mock<IInstanceValidator>();
var appModelMock = new Mock<IAppModel>();
var appResourcesMock = new Mock<IAppResources>();
var objectModelValidatorMock = new Mock<IObjectModelValidator>();
var layoutEvaluatorStateInitializer = new LayoutEvaluatorStateInitializer(appResourcesMock.Object, Options.Create(new Configuration.FrontEndSettings()));
var httpContextAccessorMock = new Mock<IHttpContextAccessor>();
var generalSettings = Options.Create(new Configuration.GeneralSettings());
var appSettings = Options.Create(new Configuration.AppSettings());

var validationAppSI = new ValidationAppSI(
loggerMock.Object,
dataMock.Object,
instanceMock.Object,
instanceValidator.Object,
appModelMock.Object,
appResourcesMock.Object,
objectModelValidatorMock.Object,
layoutEvaluatorStateInitializer,
httpContextAccessorMock.Object,
generalSettings,
appSettings);
return validationAppSI;
}

[Fact]
public void ModelKeyToField_NullInputWithoutType_ReturnsNull()
{
ValidationAppSI.ModelKeyToField(null, null!).Should().BeNull();
}

[Fact]
public void ModelKeyToField_StringInputWithoutType_ReturnsSameString()
{
ValidationAppSI.ModelKeyToField("null", null!).Should().Be("null");
}

[Fact]
Expand Down Expand Up @@ -144,4 +222,37 @@ public void ModelKeyToField_ListOfListOfListNullable_IgnoresMissingButPropagates
{
ValidationAppSI.ModelKeyToField("SubTestModelList[123].SubTestModelList.ListOfNullableDecimal[123456]", typeof(TestModel)).Should().Be("subList[123].subList.nullableDecimalList[123456]");
}

public class TestModel
{
[JsonPropertyName("level1")]
public string FirstLevelProp { get; set; } = default!;

[JsonPropertyName("sub")]
public SubTestModel SubTestModel { get; set; } = default!;

[JsonPropertyName("subnull")]
public SubTestModel? SubTestModelNull { get; set; } = default!;

[JsonPropertyName("subList")]
public List<SubTestModel> SubTestModelList { get; set; } = default!;
}

public class SubTestModel
{
[JsonPropertyName("decimal")]
public decimal DecimalNumber { get; set; } = default!;

[JsonPropertyName("nullableString")]
public string? StringNullable { get; set; } = default!;

[JsonPropertyName("decimalList")]
public List<decimal> ListOfDecimal { get; set; } = default!;

[JsonPropertyName("nullableDecimalList")]
public List<decimal?> ListOfNullableDecimal { get; set; } = default!;

[JsonPropertyName("subList")]
public List<SubTestModel> SubTestModelList { get; set; } = default!;
}
}

0 comments on commit 0fd8cc6

Please sign in to comment.