From 5feb5873c498ca409565dc40065e70c5a1ceeebe Mon Sep 17 00:00:00 2001 From: Sebastian Firsching <56029682+sebastian-firsching@users.noreply.github.com> Date: Mon, 13 Jan 2020 12:36:14 +0100 Subject: [PATCH] Feature mgmtapi add sha256 to softwaremodules (#918) * Add sha256 hash to softwaremodules in mgmt api Signed-off-by: Sebastian Firsching * Adapt rest docs Signed-off-by: Sebastian Firsching * Edit comments Signed-off-by: Sebastian Firsching * Add proper license header Signed-off-by: Sebastian Firsching --- .../hawkbit/exception/SpServerError.java | 9 +++- .../exception/InvalidSHA256HashException.java | 47 +++++++++++++++++++ .../repository/model/ArtifactUpload.java | 8 ++-- .../repository/jpa/JpaArtifactManagement.java | 17 ++++--- .../jpa/ArtifactManagementTest.java | 6 +-- .../json/model/artifact/MgmtArtifactHash.java | 10 +++- .../rest/api/MgmtSoftwareModuleRestApi.java | 5 +- .../resource/MgmtSoftwareModuleMapper.java | 3 +- .../resource/MgmtSoftwareModuleResource.java | 7 +-- .../MgmtSoftwareModuleResourceTest.java | 36 +++++++++++--- .../exception/ResponseExceptionHandler.java | 10 ++-- .../documentation/MgmtApiModelProperties.java | 1 + .../SoftwaremodulesDocumentationTest.java | 6 +++ .../upload/AbstractFileTransferHandler.java | 2 +- 14 files changed, 134 insertions(+), 33 deletions(-) create mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA256HashException.java diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java index 86757325c..15dbfe884 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java @@ -109,6 +109,12 @@ public enum SpServerError { SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH("hawkbit.server.error.artifact.uploadFailed.checksum.sha1.match", "Upload of artifact failed as the provided SHA1 checksum did not match with the provided artifact."), + /** + * + */ + SP_ARTIFACT_UPLOAD_FAILED_SHA256_MATCH("hawkbit.server.error.artifact.uploadFailed.checksum.sha256.match", + "Upload of artifact failed as the provided SHA256 checksum did not match with the provided artifact."), + /** * */ @@ -145,7 +151,8 @@ public enum SpServerError { /** * error that describes that size of uploaded file exceeds storage quota */ - SP_STORAGE_QUOTA_EXCEEDED("hawkbit.server.error.quota.storageExceeded", "Storage quota will be exceeded if file is uploaded."), + SP_STORAGE_QUOTA_EXCEEDED("hawkbit.server.error.quota.storageExceeded", + "Storage quota will be exceeded if file is uploaded."), /** * error message, which describes that the action can not be canceled cause diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA256HashException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA256HashException.java new file mode 100644 index 000000000..297951ad1 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA256HashException.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2019 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.repository.exception; + +import org.eclipse.hawkbit.exception.AbstractServerRtException; +import org.eclipse.hawkbit.exception.SpServerError; + +/** + * Thrown if SHA256 checksum check fails. + */ +public class InvalidSHA256HashException extends AbstractServerRtException { + + private static final long serialVersionUID = 1L; + + /** + * Creates a new FileUploadFailedException with + * {@link SpServerError#SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH} error. + */ + public InvalidSHA256HashException() { + super(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA256_MATCH); + } + + /** + * @param message + * of the error + * @param cause + * for the exception + */ + public InvalidSHA256HashException(final String message, final Throwable cause) { + super(message, SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA256_MATCH, cause); + } + + /** + * @param message + * of the error + */ + public InvalidSHA256HashException(final String message) { + super(message, SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA256_MATCH); + } + +} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ArtifactUpload.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ArtifactUpload.java index fe6ee39e5..08923f832 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ArtifactUpload.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ArtifactUpload.java @@ -60,7 +60,7 @@ public class ArtifactUpload { */ public ArtifactUpload(final InputStream inputStream, final long moduleId, final String filename, final boolean overrideExisting, final long filesize) { - this(inputStream, moduleId, filename, null, null, overrideExisting, null, filesize); + this(inputStream, moduleId, filename, null, null, null, overrideExisting, null, filesize); } /** @@ -85,14 +85,14 @@ public class ArtifactUpload { * the size of the file in bytes. */ public ArtifactUpload(final InputStream inputStream, final long moduleId, final String filename, - final String providedMd5Sum, final String providedSha1Sum, final boolean overrideExisting, - final String contentType, final long filesize) { + final String providedMd5Sum, final String providedSha1Sum, final String providedSha256Sum, + final boolean overrideExisting, final String contentType, final long filesize) { this.inputStream = inputStream; this.moduleId = moduleId; this.filename = filename; this.providedMd5Sum = providedMd5Sum; this.providedSha1Sum = providedSha1Sum; - this.providedSha256Sum = null; + this.providedSha256Sum = providedSha256Sum; this.overrideExisting = overrideExisting; this.contentType = contentType; this.filesize = filesize; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java index f158e0455..3ddeb8a0f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java @@ -25,11 +25,12 @@ import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.InvalidMD5HashException; import org.eclipse.hawkbit.repository.exception.InvalidSHA1HashException; +import org.eclipse.hawkbit.repository.exception.InvalidSHA256HashException; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; -import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.jpa.utils.FileSizeAndStorageQuotaCheckingInputStream; +import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.ArtifactUpload; import org.eclipse.hawkbit.repository.model.SoftwareModule; @@ -121,16 +122,17 @@ public class JpaArtifactManagement implements ArtifactManagement { } private AbstractDbArtifact storeArtifact(final ArtifactUpload artifactUpload) { - try(final InputStream quotaStream = wrapInQuotaStream(artifactUpload.getInputStream())) { - return artifactRepository.store(tenantAware.getCurrentTenant(), quotaStream, - artifactUpload.getFilename(), artifactUpload.getContentType(), - new DbArtifactHash(artifactUpload.getProvidedSha1Sum(), artifactUpload.getProvidedMd5Sum(), - artifactUpload.getProvidedSha256Sum())); + try (final InputStream quotaStream = wrapInQuotaStream(artifactUpload.getInputStream())) { + return artifactRepository.store(tenantAware.getCurrentTenant(), quotaStream, artifactUpload.getFilename(), + artifactUpload.getContentType(), new DbArtifactHash(artifactUpload.getProvidedSha1Sum(), + artifactUpload.getProvidedMd5Sum(), artifactUpload.getProvidedSha256Sum())); } catch (final ArtifactStoreException | IOException e) { throw new ArtifactUploadFailedException(e); } catch (final HashNotMatchException e) { if (e.getHashFunction().equals(HashNotMatchException.SHA1)) { throw new InvalidSHA1HashException(e.getMessage(), e); + } else if (e.getHashFunction().equals(HashNotMatchException.SHA256)) { + throw new InvalidSHA256HashException(e.getMessage(), e); } else { throw new InvalidMD5HashException(e.getMessage(), e); } @@ -148,7 +150,8 @@ public class JpaArtifactManagement implements ArtifactManagement { final long currentlyUsed = localArtifactRepository.getSumOfUndeletedArtifactSize().orElse(0L); final long maxArtifactSizeTotal = quotaManagement.getMaxArtifactStorage(); - return new FileSizeAndStorageQuotaCheckingInputStream(in, maxArtifactSize, maxArtifactSizeTotal - currentlyUsed); + return new FileSizeAndStorageQuotaCheckingInputStream(in, maxArtifactSize, + maxArtifactSizeTotal - currentlyUsed); } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ArtifactManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ArtifactManagementTest.java index 3e6387836..83b6159c5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ArtifactManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ArtifactManagementTest.java @@ -30,9 +30,9 @@ import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.event.remote.SoftwareModuleDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.FileSizeQuotaExceededException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; -import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.StorageQuotaExceededException; import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; @@ -84,12 +84,12 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { final int artifactSize = artifactData.length(); verifyThrownExceptionBy( () -> artifactManagement.create(new ArtifactUpload(IOUtils.toInputStream(artifactData, "UTF-8"), - NOT_EXIST_IDL, "xxx", null, null, false, null, artifactSize)), + NOT_EXIST_IDL, "xxx", null, null, null, false, null, artifactSize)), "SoftwareModule"); verifyThrownExceptionBy( () -> artifactManagement.create(new ArtifactUpload(IOUtils.toInputStream(artifactData, "UTF-8"), - NOT_EXIST_IDL, "xxx", null, null, false, null, artifactSize)), + NOT_EXIST_IDL, "xxx", null, null, null, false, null, artifactSize)), "SoftwareModule"); verifyThrownExceptionBy(() -> artifactManagement.delete(NOT_EXIST_IDL), "Artifact"); diff --git a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifactHash.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifactHash.java index cc5a15266..db5e42733 100644 --- a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifactHash.java +++ b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifactHash.java @@ -23,6 +23,9 @@ public class MgmtArtifactHash { @JsonProperty private String md5; + @JsonProperty + private String sha256; + /** * Default constructor. */ @@ -33,9 +36,10 @@ public class MgmtArtifactHash { /** * Public constructor. */ - public MgmtArtifactHash(final String sha1, final String md5) { + public MgmtArtifactHash(final String sha1, final String md5, final String sha256) { this.sha1 = sha1; this.md5 = md5; + this.sha256 = sha256; } public String getSha1() { @@ -46,4 +50,8 @@ public class MgmtArtifactHash { return md5; } + public String getSha256() { + return sha256; + } + } diff --git a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java index b98121d13..68ad7ea3b 100644 --- a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java +++ b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java @@ -52,6 +52,8 @@ public interface MgmtSoftwareModuleRestApi { * checksum for uploaded content check * @param sha1Sum * checksum for uploaded content check + * @param sha256Sum + * checksum for uploaded content check * * @return In case all sets could successful be created the ResponseEntity * with status code 201 - Created but without ResponseBody. In any @@ -64,7 +66,8 @@ public interface MgmtSoftwareModuleRestApi { @RequestPart("file") final MultipartFile file, @RequestParam(value = "filename", required = false) final String optionalFileName, @RequestParam(value = "md5sum", required = false) final String md5Sum, - @RequestParam(value = "sha1sum", required = false) final String sha1Sum); + @RequestParam(value = "sha1sum", required = false) final String sha1Sum, + @RequestParam(value = "sha256sum", required = false) final String sha256sum); /** * Handles the GET request of retrieving all meta data of artifacts assigned diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java index 13eadbb34..d7f006499 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java @@ -132,7 +132,8 @@ public final class MgmtSoftwareModuleMapper { final MgmtArtifact artifactRest = new MgmtArtifact(); artifactRest.setArtifactId(artifact.getId()); artifactRest.setSize(artifact.getSize()); - artifactRest.setHashes(new MgmtArtifactHash(artifact.getSha1Hash(), artifact.getMd5Hash())); + artifactRest.setHashes( + new MgmtArtifactHash(artifact.getSha1Hash(), artifact.getMd5Hash(), artifact.getSha256Hash())); artifactRest.setProvidedFilename(artifact.getFilename()); diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java index 6ce5ad375..43c7bf8a9 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java @@ -74,7 +74,8 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi { @RequestPart("file") final MultipartFile file, @RequestParam(value = "filename", required = false) final String optionalFileName, @RequestParam(value = "md5sum", required = false) final String md5Sum, - @RequestParam(value = "sha1sum", required = false) final String sha1Sum) { + @RequestParam(value = "sha1sum", required = false) final String sha1Sum, + @RequestParam(value = "sha256sum", required = false) final String sha256Sum) { if (file.isEmpty()) { return ResponseEntity.badRequest().build(); @@ -87,8 +88,8 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi { try (InputStream in = file.getInputStream()) { final Artifact result = artifactManagement.create(new ArtifactUpload(in, softwareModuleId, fileName, - md5Sum == null ? null : md5Sum.toLowerCase(), sha1Sum == null ? null : sha1Sum.toLowerCase(), false, - file.getContentType(), file.getSize())); + md5Sum == null ? null : md5Sum.toLowerCase(), sha1Sum == null ? null : sha1Sum.toLowerCase(), + sha256Sum == null ? null : sha256Sum.toLowerCase(), false, file.getContentType(), file.getSize())); final MgmtArtifact reponse = MgmtSoftwareModuleMapper.toResponse(result); MgmtSoftwareModuleMapper.addLinks(result, reponse); diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java index 7856f3379..1bdac9f3b 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java @@ -165,6 +165,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra final byte random[] = randomBytes(5 * 1024); final String md5sum = HashGeneratorUtils.generateMD5(random); final String sha1sum = HashGeneratorUtils.generateSHA1(random); + final String sha256sum = HashGeneratorUtils.generateSHA256(random); final MockMultipartFile file = new MockMultipartFile("file", "origFilename", null, random); // upload @@ -175,6 +176,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(jsonPath("$.hashes.md5", equalTo(md5sum))) .andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum))) + .andExpect(jsonPath("$.hashes.sha256", equalTo(sha256sum))) .andExpect(jsonPath("$.size", equalTo(random.length))) .andExpect(jsonPath("$.providedFilename", equalTo("origFilename"))).andReturn(); @@ -247,6 +249,9 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra assertThat(artifactManagement.getByFilename("origFilename").get().getMd5Hash()).as("Wrong md5 hash") .isEqualTo(HashGeneratorUtils.generateMD5(random)); + assertThat(artifactManagement.getByFilename("origFilename").get().getSha256Hash()).as("Wrong sha256 hash") + .isEqualTo(HashGeneratorUtils.generateSHA256(random)); + // metadata assertThat(softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getFilename()) .as("wrong metadata of the filename").isEqualTo("origFilename"); @@ -275,6 +280,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra final byte random[] = randomBytes(5 * 1024); final String md5sum = HashGeneratorUtils.generateMD5(random); final String sha1sum = HashGeneratorUtils.generateSHA1(random); + final String sha256sum = HashGeneratorUtils.generateSHA256(random); final MockMultipartFile file = new MockMultipartFile("file", "orig", null, random); mvc.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file) @@ -282,6 +288,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(jsonPath("$.hashes.md5", equalTo(md5sum))) .andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum))) + .andExpect(jsonPath("$.hashes.sha256", equalTo(sha256sum))) .andExpect(jsonPath("$.providedFilename", equalTo("orig"))).andExpect(status().isCreated()); mvc.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)) @@ -322,13 +329,14 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra final byte random[] = randomBytes(5 * 1024); final String md5sum = HashGeneratorUtils.generateMD5(random); final String sha1sum = HashGeneratorUtils.generateSHA1(random); + final String sha256sum = HashGeneratorUtils.generateSHA256(random); final MockMultipartFile file = new MockMultipartFile("file", "origFilename", null, random); // upload // wrong sha1 MvcResult mvcResult = mvc .perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file) - .param("md5sum", md5sum).param("sha1sum", "afsdff")) + .param("md5sum", md5sum).param("sha1sum", "afsdff").param("sha256sum", sha256sum)) .andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()).andReturn(); // check error result @@ -336,10 +344,21 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra assertThat(exceptionInfo.getErrorCode()).as("Exception contains wrong error code") .isEqualTo(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH.getKey()); + // wrong sha256 + mvcResult = mvc + .perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file) + .param("md5sum", md5sum).param("sha1sum", sha1sum).param("sha256sum", "jdshfsd")) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()).andReturn(); + + // check error result + exceptionInfo = ResourceUtility.convertException(mvcResult.getResponse().getContentAsString()); + assertThat(exceptionInfo.getErrorCode()).as("Exception contains wrong error code") + .isEqualTo(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA256_MATCH.getKey()); + // wrong md5 mvcResult = mvc .perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file) - .param("md5sum", "sdfsdfs").param("sha1sum", sha1sum)) + .param("md5sum", "sdfsdfs").param("sha1sum", sha1sum).param("sha256sum", sha256sum)) .andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()).andReturn(); // check error result @@ -366,6 +385,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra final byte random[] = randomBytes(5 * 1024); final String md5sum = HashGeneratorUtils.generateMD5(random); final String sha1sum = HashGeneratorUtils.generateSHA1(random); + final String sha256sum = HashGeneratorUtils.generateSHA256(random); final MockMultipartFile file = new MockMultipartFile("file", "origFilename" + i, null, random); // upload @@ -375,14 +395,13 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(jsonPath("$.hashes.md5", equalTo(md5sum))) .andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum))) + .andExpect(jsonPath("$.hashes.sha256", equalTo(sha256sum))) .andExpect(jsonPath("$.size", equalTo(random.length))) .andExpect(jsonPath("$.providedFilename", equalTo("origFilename" + i))).andReturn(); } // upload one more file to cause the quota to be exceeded final byte random[] = randomBytes(5 * 1024); - HashGeneratorUtils.generateMD5(random); - HashGeneratorUtils.generateSHA1(random); final MockMultipartFile file = new MockMultipartFile("file", "origFilename_final", null, random); // upload @@ -409,6 +428,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra final byte random[] = randomBytes(artifactSize); final String md5sum = HashGeneratorUtils.generateMD5(random); final String sha1sum = HashGeneratorUtils.generateSHA1(random); + final String sha256sum = HashGeneratorUtils.generateSHA256(random); final MockMultipartFile file = new MockMultipartFile("file", "origFilename" + i, null, random); // upload @@ -419,14 +439,13 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(jsonPath("$.hashes.md5", equalTo(md5sum))) .andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum))) + .andExpect(jsonPath("$.hashes.sha256", equalTo(sha256sum))) .andExpect(jsonPath("$.size", equalTo(random.length))) .andExpect(jsonPath("$.providedFilename", equalTo("origFilename" + i))).andReturn(); } // upload one more file to cause the quota to be exceeded final byte random[] = randomBytes(artifactSize); - HashGeneratorUtils.generateMD5(random); - HashGeneratorUtils.generateSHA1(random); final MockMultipartFile file = new MockMultipartFile("file", "origFilename_final", null, random); // upload @@ -490,6 +509,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra .andExpect(jsonPath("$.size", equalTo(random.length))) .andExpect(jsonPath("$.hashes.md5", equalTo(artifact.getMd5Hash()))) .andExpect(jsonPath("$.hashes.sha1", equalTo(artifact.getSha1Hash()))) + .andExpect(jsonPath("$.hashes.sha256", equalTo(artifact.getSha256Hash()))) .andExpect(jsonPath("$.providedFilename", equalTo("file1"))) .andExpect(jsonPath("$._links.download.href", equalTo("http://localhost/rest/v1/softwaremodules/" + sm.getId() + "/artifacts/" @@ -518,6 +538,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra .andExpect(jsonPath("$.[0].size", equalTo(random.length))) .andExpect(jsonPath("$.[0].hashes.md5", equalTo(artifact.getMd5Hash()))) .andExpect(jsonPath("$.[0].hashes.sha1", equalTo(artifact.getSha1Hash()))) + .andExpect(jsonPath("$.[0].hashes.sha256", equalTo(artifact.getSha256Hash()))) .andExpect(jsonPath("$.[0].providedFilename", equalTo("file1"))) .andExpect(jsonPath("$.[0]._links.self.href", equalTo("http://localhost/rest/v1/softwaremodules/" + sm.getId() + "/artifacts/" @@ -525,6 +546,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra .andExpect(jsonPath("$.[1].id", equalTo(artifact2.getId().intValue()))) .andExpect(jsonPath("$.[1].hashes.md5", equalTo(artifact2.getMd5Hash()))) .andExpect(jsonPath("$.[1].hashes.sha1", equalTo(artifact2.getSha1Hash()))) + .andExpect(jsonPath("$.[1].hashes.sha256", equalTo(artifact2.getSha256Hash()))) .andExpect(jsonPath("$.[1].providedFilename", equalTo("file2"))) .andExpect(jsonPath("$.[1]._links.self.href", equalTo( "http://localhost/rest/v1/softwaremodules/" + sm.getId() + "/artifacts/" + artifact2.getId()))); @@ -759,7 +781,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra } @Test - @Description("Verfies that the system answers as defined in case of a wnon extsing field used in filter. Expected result: BAD REQUEST with error description.") + @Description("Verfies that the system answers as defined in case of a non existing field used in filter. Expected result: BAD REQUEST with error description.") public void getSoftwareModulesWithUnknownFieldErrorFilterParameter() throws Exception { mvc.perform(get("/rest/v1/softwaremodules?q=wrongField==abc").accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()) diff --git a/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java index 4030a1fd4..e5448b36d 100644 --- a/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java +++ b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java @@ -57,6 +57,7 @@ public class ResponseExceptionHandler { ERROR_TO_HTTP_STATUS.put(SpServerError.SP_INSUFFICIENT_PERMISSION, HttpStatus.FORBIDDEN); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_UPLOAD_FAILED, HttpStatus.INTERNAL_SERVER_ERROR); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH, HttpStatus.BAD_REQUEST); + ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA256_MATCH, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_MD5_MATCH, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_DELETE_FAILED, HttpStatus.INTERNAL_SERVER_ERROR); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_LOAD_FAILED, HttpStatus.INTERNAL_SERVER_ERROR); @@ -118,9 +119,10 @@ public class ResponseExceptionHandler { /** * Method for handling exception of type HttpMessageNotReadableException and - * MethodArgumentNotValidException which are thrown in case the request body is - * not well formed (e.g. syntax failures, missing/invalid parameters) and cannot - * be deserialized. Called by the Spring-Framework for exception handling. + * MethodArgumentNotValidException which are thrown in case the request body + * is not well formed (e.g. syntax failures, missing/invalid parameters) and + * cannot be deserialized. Called by the Spring-Framework for exception + * handling. * * @param request * the Http request @@ -129,7 +131,7 @@ public class ResponseExceptionHandler { * @return the entity to be responded containing the exception information * as entity. */ - @ExceptionHandler({HttpMessageNotReadableException.class, MethodArgumentNotValidException.class}) + @ExceptionHandler({ HttpMessageNotReadableException.class, MethodArgumentNotValidException.class }) public ResponseEntity handleExceptionCausedByIncorrectRequestBody(final HttpServletRequest request, final Exception ex) { logRequest(request, ex); diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/MgmtApiModelProperties.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/MgmtApiModelProperties.java index 33339dc53..4bd414350 100644 --- a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/MgmtApiModelProperties.java +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/MgmtApiModelProperties.java @@ -47,6 +47,7 @@ public final class MgmtApiModelProperties { public static final String ARTIFACT_PROVIDED_FILENAME = "Filename of the artifact."; public static final String ARTIFACT_HASHES_SHA1 = "SHA1 hash of the artifact."; public static final String ARTIFACT_HASHES_MD5 = "MD5 hash of the artifact."; + public static final String ARTIFACT_HASHES_SHA256 = "SHA256 hash of the artifact."; public static final String ARTIFACT_DOWNLOAD_LINK = "Download link of the artifact."; diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/SoftwaremodulesDocumentationTest.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/SoftwaremodulesDocumentationTest.java index a84edd57a..778a1ce7e 100644 --- a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/SoftwaremodulesDocumentationTest.java +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/SoftwaremodulesDocumentationTest.java @@ -266,6 +266,8 @@ public class SoftwaremodulesDocumentationTest extends AbstractApiRestDocumentati fieldWithPath("[].hashes.md5").description(MgmtApiModelProperties.ARTIFACT_HASHES_MD5), fieldWithPath("[].hashes.sha1") .description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA1), + fieldWithPath("[].hashes.sha256") + .description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA256), fieldWithPath("[].providedFilename") .description(MgmtApiModelProperties.ARTIFACT_PROVIDED_FILENAME), fieldWithPath("[]._links.self").ignored()))); @@ -299,6 +301,8 @@ public class SoftwaremodulesDocumentationTest extends AbstractApiRestDocumentati .description(MgmtApiModelProperties.ARTIFACT_DOWNLOAD_LINK), fieldWithPath("hashes.md5").description(MgmtApiModelProperties.ARTIFACT_HASHES_MD5), fieldWithPath("hashes.sha1").description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA1), + fieldWithPath("hashes.sha256") + .description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA256), fieldWithPath("providedFilename") .description(MgmtApiModelProperties.ARTIFACT_PROVIDED_FILENAME))) @@ -374,6 +378,8 @@ public class SoftwaremodulesDocumentationTest extends AbstractApiRestDocumentati fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT), fieldWithPath("hashes.md5").description(MgmtApiModelProperties.ARTIFACT_HASHES_MD5), fieldWithPath("hashes.sha1").description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA1), + fieldWithPath("hashes.sha256") + .description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA256), fieldWithPath("providedFilename") .description(MgmtApiModelProperties.ARTIFACT_PROVIDED_FILENAME), fieldWithPath("_links.self").ignored(), fieldWithPath("_links.download") diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/AbstractFileTransferHandler.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/AbstractFileTransferHandler.java index d9e35018e..4f84d6a23 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/AbstractFileTransferHandler.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/AbstractFileTransferHandler.java @@ -297,7 +297,7 @@ public abstract class AbstractFileTransferHandler implements Serializable { private Artifact uploadArtifact(final String filename) { try { return artifactManagement.create(new ArtifactUpload(inputStream, fileUploadId.getSoftwareModuleId(), - filename, null, null, true, mimeType, -1)); + filename, null, null, null, true, mimeType, -1)); } catch (final ArtifactUploadFailedException | InvalidSHA1HashException | InvalidMD5HashException e) { throw new ArtifactUploadFailedException(e); }