-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Start work on new validation #374
Conversation
07726d6
to
c2995db
Compare
test/Altinn.App.Core.Tests/Features/Validators/ValidationServiceTests.cs
Fixed
Show fixed
Hide fixed
foreach (var changedField in changedFields) | ||
{ | ||
if (IsMatch(changedField, prefix)) | ||
{ | ||
return true; | ||
} | ||
} |
Check notice
Code scanning / CodeQL
Missed opportunity to use Where Note
implicitly filters its target sequence
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CodeQL found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.
a4a3bf4
to
159f0e0
Compare
Improve GetJsonPath(Expression) and fix some sonarcloud issues Improve test coverage Full validation rewrite complete and existing tests work Probably still some issues and test coverage was spoty so more tests needs to be written. Make IInstanceValidator obsolete Add DataType as input to validators Fix a few issues to prepare for tests of expressions Add more tests
2657832
to
de315c7
Compare
} | ||
catch (Exception e) | ||
{ | ||
_logger.LogError(e, "Error while running validator {validatorName} on task {taskId} in instance {instanceId}", tv.GetType().Name, taskId, instance.Id); |
Check failure
Code scanning / CodeQL
Log entries created from user input High
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
} | ||
catch (Exception e) | ||
{ | ||
_logger.LogError(e, "Error while running validator {validatorName} on task {taskId} in instance {instanceId}", tv.GetType().Name, taskId, instance.Id); |
Check failure
Code scanning / CodeQL
Log entries created from user input High
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
{ | ||
try | ||
{ | ||
_logger.LogDebug("Start running validator {validatorName} on task {taskId} in instance {instanceId}", tv.GetType().Name, taskId, instance.Id); |
Check failure
Code scanning / CodeQL
Log entries created from user input High
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
{ | ||
try | ||
{ | ||
_logger.LogDebug("Start running validator {validatorName} on task {taskId} in instance {instanceId}", tv.GetType().Name, taskId, instance.Id); |
Check failure
Code scanning / CodeQL
Log entries created from user input High
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
} | ||
catch (Exception e) | ||
{ | ||
_logger.LogError(e, "Error while 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
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
{ | ||
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
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.
{ | ||
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
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.
src/Altinn.App.Core/Features/Validation/ValidationService.cs
Dismissed
Show dismissed
Hide dismissed
catch (Exception e) | ||
{ | ||
return Task.FromException<List<ValidationIssue>>(e); | ||
} |
Check notice
Code scanning / CodeQL
Generic catch clause Note
foreach (var file in files) | ||
{ | ||
var data = File.ReadAllText(file); | ||
ExpressionValidationTestModel testCase = JsonSerializer.Deserialize<ExpressionValidationTestModel>( | ||
data, | ||
new JsonSerializerOptions | ||
{ | ||
ReadCommentHandling = JsonCommentHandling.Skip, | ||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase, | ||
})!; | ||
yield return new object[] { testCase }; | ||
} |
Check notice
Code scanning / CodeQL
Missed opportunity to use Select Note test
maps its iteration variable to another variable
d34acd6
to
088c125
Compare
Also comment out KeyedService fetching
Quality Gate passedThe SonarCloud Quality Gate passed, but some issues were introduced. 11 New issues |
New service
IValidationService:
A ServiceLocator for validation that does the different kinds of validation. Some logic in data element validation to download the actual data if the element specifies AppLogic and can do that kind of deep validation.
New interfaces:
IValidationService
: The rest of the systems does all its validation needs through this service. It does not mutate any state in instance, process or data elements. Old extension points are accessed through this. Gets services from aSerivceProvider
with a service locator pattern.ValidateTask
: Validates that a task is ready for process next. Finds all relevant data elements and other validations to run.ValidateDataElement
: Used for partial or full validation of a single data element.ITaskValidator
: Interface for App developers to add functionality for whole task validation.TaskId
so that we know what tasks to trigger the validation for.IDataElementValidator
: Interface for validation of data elements without loading the actual content of the data element.IFormDataValidator
: Interface for App developers to add incremental validation to form data elements.DataType
to detect what Data elements to apply the validation to.ShouldRun
and aCode
that is automatically added to all validation issues allows many classes to be registered, but only run when relevant fields are changed. This means that the whole validation implementation needs to either run, or not run to ensure that we can tell front-end what validations has been updated and possibly fixed.New functionality
GenericFormDataValidator
: abstract class that app developers can use to simplify the implementation ofIFormDataValidator
adding a few convenience methodsValidateFormData
that gets the typed model, instead ofobject data
CreateValidationIssue
: Very convenient way of adding errors.m=>m.field.children[1].name
instead of a json path to bind the error to a field.AsyncLocal
to not have to pass or return a list of issues. Just causes less clutter, and works even if the service is registered as a singleton.LinqExpressionHelpers
: static methods to allow parsing of expressions instead of strings to create json paths.Validator registration
Validators can be registered in 3 ways
DataType
orTaskId
is set as"*"
and it is registered as a service in dependency injectionDataType
/TaskId
, set as a specific DataType or task to run (Typically custom validator in a specific app)DataType
/TaskId
and run on a general validator on a specific type)Compatibility
IValidation
, together withValidationAppSI
has been removed and all standard shared validation has been moved to default validatorsDataAnnotationValidation
: Runs attribute validation fromSystem.ComponentModel.DataAnnotations
(eg:[RegEx()]
)DefaultDataElementValidation
: Validates maxSize, contentType, and fileScanDefaultTaskValidator
: Validates min and max count for data elementsExpressionValidator
: Validates data elements with app logic and ensures that expression validation has run.LegacyIInstanceValidatorFormDataValidator
: Runs existingIInstanceValidator.ValidateData
class registered in dependency injection for backwards compatibilityLegacyIInstanceValidatorTaskValidator
: Runs existingIInstanceValidator.ValidateTask
class registered in dependency injection for backwards compatibilityRequiredLayoutValidator
: Runs expressions in layout to ensure that every visible component with"required"
actually has data.Related Issue(s)
Verification
Documentation