-
Notifications
You must be signed in to change notification settings - Fork 193
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 bug: change sql-query in localArtifactRepository #820
- fix bug: change sql-query in localArtifactRepository #820
Conversation
Thanks for taking the time to contribute to hawkBit! We really appreciate this. Make yourself comfortable while I'm looking for a committer to help you with your contribution. |
|
||
createArtifactForTenant(tenant1, "myInput", module.getId(), "myFirstFile"); | ||
createArtifactForTenant(tenant2, "myInput", module2.getId(), "mySecondFile"); | ||
final Artifact artifactTenant2 = createArtifactForTenant(tenant2, "myInput", module2.getId(), "myThirdFile"); |
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.
already tested with the previous test case
check other artifact storage extensions if file handling is covered as well |
20199f2
to
2b738c3
Compare
*/ | ||
@Query("SELECT CASE WHEN COUNT(a)>0 THEN 'true' ELSE 'false' END FROM JpaArtifact a WHERE a.sha1Hash = :sha1 AND a.softwareModule.id != :moduleId AND a.softwareModule.deleted = 0") | ||
boolean existsWithSha1HashAndSoftwareModuleIdIsNot(@Param("sha1") String sha1, @Param("moduleId") Long moduleId); | ||
@Query("SELECT CASE WHEN COUNT (a)>1 THEN 'true' ELSE 'false' END FROM JpaArtifact a WHERE a.sha1Hash = :sha1 AND a.tenant = :tenant AND a.softwareModule.deleted = 0") |
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.
we can get rid of the @Query
annotation and use the Jpa support for Entities:
long countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse(@Param("sha1") String sha1, @Param("tenant") String tenant);
We can later just check the count if greater than 1
* Verifies if an artifact exists that has given hash and is still related | ||
* to a {@link SoftwareModule} other than a given one and not | ||
* {@link SoftwareModule#isDeleted()}. | ||
* Verifies if in the same tenant one then more {@link Artifact}s with the |
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.
Needs to be adapted:
/**
* Counts current elements based on the sha1 and tenant, as well as having
* the {@link SoftwareModule} property 'deleted' with value 'false'
*
* @param sha1
* the sha1 of the {@link Artifact}
* @param tenant
* the current tenant
*
* @return the count of the elements
*/
@@ -166,8 +165,8 @@ private void assertMaxArtifactStorageQuota(final String filename, final long art | |||
@Retryable(include = { | |||
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) | |||
public boolean clearArtifactBinary(final String sha1Hash, final long moduleId) { | |||
|
|||
if (localArtifactRepository.existsWithSha1HashAndSoftwareModuleIdIsNot(sha1Hash, moduleId)) { | |||
if (localArtifactRepository.existsForMoreThenOneArtifactInTheSameTenantWithSha1HashAndSoftwareModuleIsNotDeleted(sha1Hash, |
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.
Could be refactored:
final long count = localArtifactRepository.countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse(sha1Hash,
tenantAware.getCurrentTenant());
if (count > 1) {
// there are still other artifacts that need the binary
return false;
}
@Test | ||
@Description("Verifies that you cannot delete an artifact which exists with the same hash, in the same tenant and the SoftwareModule is not deleted .") | ||
public void deleteArtifactWithSameHashAndSoftwareModuleIsNotDeletedInSameTenants() | ||
throws NoSuchAlgorithmException, IOException { |
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.
remove the throws NoSuchAlgorithmException
, not thrown in this context.
Could you please also double check in the whole file, there are many redundant throws declarations like this (from before) that need to be cleaned up.
.existsForMoreThenOneArtifactInTheSameTenantWithSha1HashAndSoftwareModuleIsNotDeleted( | ||
artifact1.getSha1Hash(), artifact1.getTenant())).isTrue(); | ||
|
||
artifactRepository.deleteById(artifact1.getId()); |
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.
maybe here we can add another assertion for the binary file contents
try (final InputStream inputStream = artifactManagement.loadArtifactBinary(artifact2.getSha1Hash()).get()
.getFileInputStream()) {
assertTrue("The stored binary matches the given binary",
IOUtils.contentEquals(new ByteArrayInputStream(randomBytes), inputStream));
}
Btw, this assertion is used in other places in this class, so maybe you can extract it to an own method, maybe with the name assertEqualFileContents(Optional<AbstractDBArtifact> artifact, byte[] randomBytes)
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.
resolved
*/ | ||
@Query("SELECT CASE WHEN COUNT(a)>0 THEN 'true' ELSE 'false' END FROM JpaArtifact a WHERE a.sha1Hash = :sha1 AND a.softwareModule.id != :moduleId AND a.softwareModule.deleted = 0") | ||
boolean existsWithSha1HashAndSoftwareModuleIdIsNot(@Param("sha1") String sha1, @Param("moduleId") Long moduleId); | ||
default boolean existsForMoreThenOneArtifactInTheSameTenantWithSha1HashAndSoftwareModuleIsNotDeleted( |
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.
is this method used anywhere or can it be removed?
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.
good catch!
* | ||
* @return the boolean whether the atrifact exists or not | ||
*/ | ||
boolean existsByTenantAndSha1(@NotEmpty String Tenant, @NotEmpty String sha1Hash); |
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.
6b15408
to
3080740
Compare
|
||
assertArtifactQuota(moduleId, 1); | ||
assertMaxArtifactSizeQuota(filename, moduleId, artifactUpload.getFilesize()); | ||
assertMaxArtifactStorageQuota(filename, artifactUpload.getFilesize()); | ||
|
||
AbstractDbArtifact result = getOrCreateArtifact(artifactUpload); |
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.
You could use the Optional in order to get rid of null checks:
AbstractDbArtifact result = getOrCreateArtifact(artifactUpload); | |
return getOrCreateArtifact(artifactUpload) | |
.map(artifact -> storeArtifactMetadata(softwareModule, filename, artifact, existing)).orElse(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.
Yes, looks much cleaner indeed, thank you for the hint! 👍
return result == null ? null : storeArtifactMetadata(softwareModule, filename, result, existing); | ||
} | ||
|
||
private AbstractDbArtifact getOrCreateArtifact(final ArtifactUpload artifactUpload) { |
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.
Then you need to change this method correspondingly:
private AbstractDbArtifact getOrCreateArtifact(final ArtifactUpload artifactUpload) { | |
private Optional<AbstractDbArtifact> getOrCreateArtifact(final ArtifactUpload artifactUpload) { | |
final String providedSha1Sum = artifactUpload.getProvidedSha1Sum(); | |
if (!StringUtils.isEmpty(providedSha1Sum)) { | |
final AbstractDbArtifact artifact = artifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), | |
providedSha1Sum); | |
if (artifact != null) { | |
return Optional.of(artifact); | |
} | |
} | |
return Optional.ofNullable(storeArtifact(artifactUpload)); | |
} |
if (!StringUtils.isEmpty(providedSha1Sum)) { | ||
artifact = artifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), providedSha1Sum); | ||
} | ||
return Optional.ofNullable(artifact == null ? storeArtifact(artifactUpload) : artifact); |
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 would still propose my previous solution (with 2 return statements and final AbstractDbArtifact) in order to get rid of conditional here
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.
Yes, but then we have "multiple return statements" and we still have to do the null check anyway.
I could move the check to an own line to make it simpler maybe. What do you think?
artifact = (artifact == null) ? storeArtifact(artifactUpload) : artifact;
return Optional.ofNullable(artifact);
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.
Ok, let it be our consensus for this question :)
39a0126
to
06a198f
Compare
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.
Looks Good!
- tests added in ArtifactManagementTest: -ensure that an Artifact can not deleted when the Artifact with the same hash exist -ensure that Artifacts with the same hash from one tenant can not deleted by an other tenant Signed-off-by: Nazife Basbaz <[email protected]>
Signed-off-by: Nazife Basbaz<[email protected]>
Signed-off-by: Nazife Basbaz <[email protected]>
-replace the @query annotation with the Jpa support for entities -adapt tests -remove unused exceptions Signed-off-by: Nazife Basbaz <[email protected]>
Signed-off-by: Ahmed Sayed <[email protected]>
Signed-off-by: Ahmed Sayed <[email protected]>
Signed-off-by: Ahmed Sayed <[email protected]>
Signed-off-by: Ahmed Sayed <[email protected]>
Signed-off-by: Ahmed Sayed <[email protected]>
Signed-off-by: Nazife Basbaz <[email protected]>
Signed-off-by: Ahmed Sayed <[email protected]>
Signed-off-by: Ahmed Sayed <[email protected]>
Signed-off-by: Ahmed Sayed <[email protected]>
Signed-off-by: Ahmed Sayed <[email protected]>
Signed-off-by: Ahmed Sayed <[email protected]>
Signed-off-by: Ahmed Sayed <[email protected]>
06a198f
to
6f0a0fc
Compare
…#820) Also-by: Nazife Basbaz <[email protected]> Signed-off-by: Ahmed Sayed <[email protected]>
-ensure that an Artifact can not deleted when the Artifact with the
same hash exist
-ensure that Artifacts with the same hash from one tenant can not
deleted by an other tenant
Signed-off-by: Nazife Basbaz [email protected]