-
Notifications
You must be signed in to change notification settings - Fork 356
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
fix: Move TE request validations to appropiate layers [TECH-1656] #15732
fix: Move TE request validations to appropiate layers [TECH-1656] #15732
Conversation
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## master #15732 +/- ##
============================================
+ Coverage 66.33% 66.34% +0.01%
+ Complexity 31430 31429 -1
============================================
Files 3489 3489
Lines 130103 130091 -12
Branches 15201 15191 -10
============================================
+ Hits 86302 86312 +10
+ Misses 36718 36700 -18
+ Partials 7083 7079 -4
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 1 file with indirect coverage changes Continue to review full report in Codecov by Sentry.
|
...his/webapi/controller/tracker/export/trackedentity/TrackedEntityRequestParamsMapperTest.java
Fixed
Show fixed
Hide fixed
...bapi/controller/tracker/export/trackedentity/TrackedEntityImportRequestParamsMapperTest.java
Fixed
Show fixed
Hide fixed
@Test | ||
void shouldMapCorrectlyWhenTrackedEntityAndSpecificUpdatedRangeSupplied() | ||
throws BadRequestException { | ||
trackedEntityRequestParams.setOuMode(CAPTURE); |
Check notice
Code scanning / CodeQL
Deprecated method or constructor invocation Note test
TrackedEntityRequestParams.setOuMode
@@ -66,22 +75,36 @@ class TrackedEntityOperationParamsMapper { | |||
|
|||
@Nonnull private final TrackedEntityAttributeService attributeService; | |||
|
|||
@Nonnull private final AclService aclService; | |||
|
|||
@Nonnull private final TrackedEntityStore trackedEntityStore; |
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.
I don't like having the store dependency in the mapper, but this is meant to be a temporary solution until we work on https://dhis2.atlassian.net/browse/DHIS2-15915
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.
I agree with you.
Can we at least add a comment or a TODO to it?
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.
Most of the comments are in fact on the old code that was just moved somewhere else but I think that now is the moment to clean up that code too.
The check removed for F_TRACKED_ENTITY_INSTANCE_SEARCH_IN_ALL_ORGUNITS
seems a big deal to me, I am not sure if it is supposed to be in this PR
if (user == null | ||
|| user.isSuper() | ||
|| user.isAuthorized(F_TRACKED_ENTITY_INSTANCE_SEARCH_IN_ALL_ORGUNITS)) { | ||
if (user == null || user.isSuper()) { |
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.
This seems like a bug fixing.
Should it be here in this PR?
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.
I can create a new ticket and add it there
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.
I think so because this probably needs to be backported, right?
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.
it's possible yes
...sp/dhis/webapi/controller/tracker/export/trackedentity/TrackedEntityRequestParamsMapper.java
Outdated
Show resolved
Hide resolved
if (params.getProgram() == null) { | ||
if (params.getProgramStatus() != null) { | ||
violation = "Program must be defined when program status is defined"; | ||
} | ||
|
||
if (params.getFollowUp() != null) { | ||
violation = "Program must be defined when follow up status is defined"; | ||
} | ||
|
||
if (params.getEnrollmentEnrolledAfter() != null) { | ||
violation = "Program must be defined when program enrollment start date is specified"; | ||
} | ||
|
||
if (params.getEnrollmentEnrolledBefore() != null) { | ||
violation = "Program must be defined when program enrollment end date is specified"; | ||
} | ||
|
||
if (params.getEnrollmentOccurredAfter() != null) { | ||
violation = "Program must be defined when program incident start date is specified"; | ||
} | ||
|
||
if (params.getEnrollmentOccurredBefore() != null) { | ||
violation = "Program must be defined when program incident end date is specified"; | ||
} | ||
} | ||
|
||
if (params.getEventStatus() != null | ||
&& (params.getEventOccurredAfter() == null || params.getEventOccurredBefore() == null)) { | ||
violation = "Event start and end date must be specified when event status is specified"; | ||
} | ||
|
||
if (params.getUpdatedWithin() != null | ||
&& (params.getUpdatedAfter() != null || params.getUpdatedBefore() != null)) { | ||
violation = | ||
"Last updated from and/or to and last updated duration cannot be specified simultaneously"; | ||
} |
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.
Can you review the naming here?
For example, we don't have incident date
anymore and last updated
is just called updated now.
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.
I'm reading the release notes, I see in the DB, the column name incidentdate
is now called ocurreddate
, but I don't see any mention to the parameters used in the payload. Is this explained somewhere else?
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.
The parameters used in the payload didn't change so they are not in the release notes.
Here it is just a matter to check how things are called in the if statement and change the error message accordly.
I would even use a notation with back quotes to highlight the parameters that needs to be corrected
private List<TrackedEntityType> filterAndValidateTrackedEntityTypes( | ||
User user, TrackedEntityType trackedEntityType, Program program) throws BadRequestException { | ||
List<TrackedEntityType> trackedEntityTypes = new ArrayList<>(); | ||
if (trackedEntityType == null) { |
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.
If program is not null, should we still define the trackedEntityTypes
?
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.
when the program is not null we still need to do it, but that's a good point, because we don't need to do it if a trackedEntityType
is present in the request.
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.
If Program is not null, shouldn't be somoething like this?
trackedEntityTypes = List.of(program.getTrackedEntityType)
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.
I did it this way because it's how it's done before this refactor.
When no trackedEntityType
is specified, it gets all the ones accessible by the user. Is there a reason why we should use the one of the program instead?
@@ -66,22 +75,36 @@ class TrackedEntityOperationParamsMapper { | |||
|
|||
@Nonnull private final TrackedEntityAttributeService attributeService; | |||
|
|||
@Nonnull private final AclService aclService; | |||
|
|||
@Nonnull private final TrackedEntityStore trackedEntityStore; |
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.
I agree with you.
Can we at least add a comment or a TODO to it?
.toList(); | ||
|
||
if (program == null && trackedEntityTypes.isEmpty()) { | ||
throw new BadRequestException("User has no access to any Tracked Entity Type"); |
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.
Not sure if this is correct. Need to check if the query can return results if program is null and user has no access to any tet. In that case, the message will still be Either a program or tracked entity type must be specified
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.
A TrackedEntity must have a TrackedEntityType even if it is not enforced at DB level.
So it is correct to stop the user to get a collection of TEs if it has no access to any TrackedEntityType
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.
It's also possible to run a request if trackedEntities
is present, also when program
and trackedEntityType
are null.
.toList(); | ||
|
||
if (program == null && trackedEntityTypes.isEmpty()) { | ||
throw new BadRequestException("User has no access to any Tracked Entity Type"); |
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.
A TrackedEntity must have a TrackedEntityType even if it is not enforced at DB level.
So it is correct to stop the user to get a collection of TEs if it has no access to any TrackedEntityType
|
||
if (params.getProgram() != null && params.getTrackedEntityType() != null) { | ||
throw new BadRequestException( | ||
"Program and tracked entity cannot be specified simultaneously"); |
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.
"Program and tracked entity cannot be specified simultaneously"); | |
"Program and tracked entity type cannot be specified simultaneously"); |
return emptyList(); | ||
} | ||
|
||
private List<TrackedEntityType> filterAndValidateTrackedEntityTypes(User user) { |
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.
I still think we should validate if user has no access to any Tracked Entity Types because if we skip this validation in the case the client specifies something in trackedEntities then we could return some results even if the user has no access to.
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.
When we run the query against the DB we join the tracked entity type table and we filter by the value we found here. In case there's no value, the result of the query will be an empty list, so in theory we should not leak any information. But I agree that it's better to stop the request here instead of running a query against a database when we already know we'll return an empty list.
…ies-operation-layer' into TECH-1656-refactor-tracked-entities-operation-layer
Kudos, SonarCloud Quality Gate passed! |
We had a few validations regarding tracked entities that were scattered around the service, outside the mapper. They were mainly
decideAccess()
,validate()
, andvalidateSearchScope()
.Now the three of them are split and all the contained validations are in the mapper.
Ticket: https://dhis2.atlassian.net/browse/TECH-1656