Feature mgmtapi add sha256 to softwaremodules (#918)

* Add sha256 hash to softwaremodules in mgmt api

Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com>

* Adapt rest docs

Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com>

* Edit comments

Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com>

* Add proper license header

Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com>
This commit is contained in:
Sebastian Firsching
2020-01-13 12:36:14 +01:00
committed by Dominic Schabel
parent 0e9caf3a88
commit 5feb5873c4
14 changed files with 134 additions and 33 deletions

View File

@@ -109,6 +109,12 @@ public enum SpServerError {
SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH("hawkbit.server.error.artifact.uploadFailed.checksum.sha1.match", 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."), "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 * 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 * error message, which describes that the action can not be canceled cause

View File

@@ -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);
}
}

View File

@@ -60,7 +60,7 @@ public class ArtifactUpload {
*/ */
public ArtifactUpload(final InputStream inputStream, final long moduleId, final String filename, public ArtifactUpload(final InputStream inputStream, final long moduleId, final String filename,
final boolean overrideExisting, final long filesize) { 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. * the size of the file in bytes.
*/ */
public ArtifactUpload(final InputStream inputStream, final long moduleId, final String filename, public ArtifactUpload(final InputStream inputStream, final long moduleId, final String filename,
final String providedMd5Sum, final String providedSha1Sum, final boolean overrideExisting, final String providedMd5Sum, final String providedSha1Sum, final String providedSha256Sum,
final String contentType, final long filesize) { final boolean overrideExisting, final String contentType, final long filesize) {
this.inputStream = inputStream; this.inputStream = inputStream;
this.moduleId = moduleId; this.moduleId = moduleId;
this.filename = filename; this.filename = filename;
this.providedMd5Sum = providedMd5Sum; this.providedMd5Sum = providedMd5Sum;
this.providedSha1Sum = providedSha1Sum; this.providedSha1Sum = providedSha1Sum;
this.providedSha256Sum = null; this.providedSha256Sum = providedSha256Sum;
this.overrideExisting = overrideExisting; this.overrideExisting = overrideExisting;
this.contentType = contentType; this.contentType = contentType;
this.filesize = filesize; this.filesize = filesize;

View File

@@ -25,11 +25,12 @@ import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.InvalidMD5HashException; import org.eclipse.hawkbit.repository.exception.InvalidMD5HashException;
import org.eclipse.hawkbit.repository.exception.InvalidSHA1HashException; 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.configuration.Constants;
import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact; import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; 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.FileSizeAndStorageQuotaCheckingInputStream;
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.ArtifactUpload; import org.eclipse.hawkbit.repository.model.ArtifactUpload;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
@@ -121,16 +122,17 @@ public class JpaArtifactManagement implements ArtifactManagement {
} }
private AbstractDbArtifact storeArtifact(final ArtifactUpload artifactUpload) { private AbstractDbArtifact storeArtifact(final ArtifactUpload artifactUpload) {
try(final InputStream quotaStream = wrapInQuotaStream(artifactUpload.getInputStream())) { try (final InputStream quotaStream = wrapInQuotaStream(artifactUpload.getInputStream())) {
return artifactRepository.store(tenantAware.getCurrentTenant(), quotaStream, return artifactRepository.store(tenantAware.getCurrentTenant(), quotaStream, artifactUpload.getFilename(),
artifactUpload.getFilename(), artifactUpload.getContentType(), artifactUpload.getContentType(), new DbArtifactHash(artifactUpload.getProvidedSha1Sum(),
new DbArtifactHash(artifactUpload.getProvidedSha1Sum(), artifactUpload.getProvidedMd5Sum(), artifactUpload.getProvidedMd5Sum(), artifactUpload.getProvidedSha256Sum()));
artifactUpload.getProvidedSha256Sum()));
} catch (final ArtifactStoreException | IOException e) { } catch (final ArtifactStoreException | IOException e) {
throw new ArtifactUploadFailedException(e); throw new ArtifactUploadFailedException(e);
} catch (final HashNotMatchException e) { } catch (final HashNotMatchException e) {
if (e.getHashFunction().equals(HashNotMatchException.SHA1)) { if (e.getHashFunction().equals(HashNotMatchException.SHA1)) {
throw new InvalidSHA1HashException(e.getMessage(), e); throw new InvalidSHA1HashException(e.getMessage(), e);
} else if (e.getHashFunction().equals(HashNotMatchException.SHA256)) {
throw new InvalidSHA256HashException(e.getMessage(), e);
} else { } else {
throw new InvalidMD5HashException(e.getMessage(), e); throw new InvalidMD5HashException(e.getMessage(), e);
} }
@@ -148,7 +150,8 @@ public class JpaArtifactManagement implements ArtifactManagement {
final long currentlyUsed = localArtifactRepository.getSumOfUndeletedArtifactSize().orElse(0L); final long currentlyUsed = localArtifactRepository.getSumOfUndeletedArtifactSize().orElse(0L);
final long maxArtifactSizeTotal = quotaManagement.getMaxArtifactStorage(); final long maxArtifactSizeTotal = quotaManagement.getMaxArtifactStorage();
return new FileSizeAndStorageQuotaCheckingInputStream(in, maxArtifactSize, maxArtifactSizeTotal - currentlyUsed); return new FileSizeAndStorageQuotaCheckingInputStream(in, maxArtifactSize,
maxArtifactSizeTotal - currentlyUsed);
} }
@Override @Override

View File

@@ -30,9 +30,9 @@ import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.event.remote.SoftwareModuleDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.SoftwareModuleDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; 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.FileSizeQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; 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.exception.StorageQuotaExceededException;
import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact; import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
@@ -84,12 +84,12 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
final int artifactSize = artifactData.length(); final int artifactSize = artifactData.length();
verifyThrownExceptionBy( verifyThrownExceptionBy(
() -> artifactManagement.create(new ArtifactUpload(IOUtils.toInputStream(artifactData, "UTF-8"), () -> 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"); "SoftwareModule");
verifyThrownExceptionBy( verifyThrownExceptionBy(
() -> artifactManagement.create(new ArtifactUpload(IOUtils.toInputStream(artifactData, "UTF-8"), () -> 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"); "SoftwareModule");
verifyThrownExceptionBy(() -> artifactManagement.delete(NOT_EXIST_IDL), "Artifact"); verifyThrownExceptionBy(() -> artifactManagement.delete(NOT_EXIST_IDL), "Artifact");

View File

@@ -23,6 +23,9 @@ public class MgmtArtifactHash {
@JsonProperty @JsonProperty
private String md5; private String md5;
@JsonProperty
private String sha256;
/** /**
* Default constructor. * Default constructor.
*/ */
@@ -33,9 +36,10 @@ public class MgmtArtifactHash {
/** /**
* Public constructor. * 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.sha1 = sha1;
this.md5 = md5; this.md5 = md5;
this.sha256 = sha256;
} }
public String getSha1() { public String getSha1() {
@@ -46,4 +50,8 @@ public class MgmtArtifactHash {
return md5; return md5;
} }
public String getSha256() {
return sha256;
}
} }

View File

@@ -52,6 +52,8 @@ public interface MgmtSoftwareModuleRestApi {
* checksum for uploaded content check * checksum for uploaded content check
* @param sha1Sum * @param sha1Sum
* checksum for uploaded content check * checksum for uploaded content check
* @param sha256Sum
* checksum for uploaded content check
* *
* @return In case all sets could successful be created the ResponseEntity * @return In case all sets could successful be created the ResponseEntity
* with status code 201 - Created but without ResponseBody. In any * with status code 201 - Created but without ResponseBody. In any
@@ -64,7 +66,8 @@ public interface MgmtSoftwareModuleRestApi {
@RequestPart("file") final MultipartFile file, @RequestPart("file") final MultipartFile file,
@RequestParam(value = "filename", required = false) final String optionalFileName, @RequestParam(value = "filename", required = false) final String optionalFileName,
@RequestParam(value = "md5sum", required = false) final String md5Sum, @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 * Handles the GET request of retrieving all meta data of artifacts assigned

View File

@@ -132,7 +132,8 @@ public final class MgmtSoftwareModuleMapper {
final MgmtArtifact artifactRest = new MgmtArtifact(); final MgmtArtifact artifactRest = new MgmtArtifact();
artifactRest.setArtifactId(artifact.getId()); artifactRest.setArtifactId(artifact.getId());
artifactRest.setSize(artifact.getSize()); 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()); artifactRest.setProvidedFilename(artifact.getFilename());

View File

@@ -74,7 +74,8 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi {
@RequestPart("file") final MultipartFile file, @RequestPart("file") final MultipartFile file,
@RequestParam(value = "filename", required = false) final String optionalFileName, @RequestParam(value = "filename", required = false) final String optionalFileName,
@RequestParam(value = "md5sum", required = false) final String md5Sum, @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()) { if (file.isEmpty()) {
return ResponseEntity.badRequest().build(); return ResponseEntity.badRequest().build();
@@ -87,8 +88,8 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi {
try (InputStream in = file.getInputStream()) { try (InputStream in = file.getInputStream()) {
final Artifact result = artifactManagement.create(new ArtifactUpload(in, softwareModuleId, fileName, final Artifact result = artifactManagement.create(new ArtifactUpload(in, softwareModuleId, fileName,
md5Sum == null ? null : md5Sum.toLowerCase(), sha1Sum == null ? null : sha1Sum.toLowerCase(), false, md5Sum == null ? null : md5Sum.toLowerCase(), sha1Sum == null ? null : sha1Sum.toLowerCase(),
file.getContentType(), file.getSize())); sha256Sum == null ? null : sha256Sum.toLowerCase(), false, file.getContentType(), file.getSize()));
final MgmtArtifact reponse = MgmtSoftwareModuleMapper.toResponse(result); final MgmtArtifact reponse = MgmtSoftwareModuleMapper.toResponse(result);
MgmtSoftwareModuleMapper.addLinks(result, reponse); MgmtSoftwareModuleMapper.addLinks(result, reponse);

View File

@@ -165,6 +165,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
final byte random[] = randomBytes(5 * 1024); final byte random[] = randomBytes(5 * 1024);
final String md5sum = HashGeneratorUtils.generateMD5(random); final String md5sum = HashGeneratorUtils.generateMD5(random);
final String sha1sum = HashGeneratorUtils.generateSHA1(random); final String sha1sum = HashGeneratorUtils.generateSHA1(random);
final String sha256sum = HashGeneratorUtils.generateSHA256(random);
final MockMultipartFile file = new MockMultipartFile("file", "origFilename", null, random); final MockMultipartFile file = new MockMultipartFile("file", "origFilename", null, random);
// upload // upload
@@ -175,6 +176,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(jsonPath("$.hashes.md5", equalTo(md5sum))) .andExpect(jsonPath("$.hashes.md5", equalTo(md5sum)))
.andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum))) .andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum)))
.andExpect(jsonPath("$.hashes.sha256", equalTo(sha256sum)))
.andExpect(jsonPath("$.size", equalTo(random.length))) .andExpect(jsonPath("$.size", equalTo(random.length)))
.andExpect(jsonPath("$.providedFilename", equalTo("origFilename"))).andReturn(); .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") assertThat(artifactManagement.getByFilename("origFilename").get().getMd5Hash()).as("Wrong md5 hash")
.isEqualTo(HashGeneratorUtils.generateMD5(random)); .isEqualTo(HashGeneratorUtils.generateMD5(random));
assertThat(artifactManagement.getByFilename("origFilename").get().getSha256Hash()).as("Wrong sha256 hash")
.isEqualTo(HashGeneratorUtils.generateSHA256(random));
// metadata // metadata
assertThat(softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getFilename()) assertThat(softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getFilename())
.as("wrong metadata of the filename").isEqualTo("origFilename"); .as("wrong metadata of the filename").isEqualTo("origFilename");
@@ -275,6 +280,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
final byte random[] = randomBytes(5 * 1024); final byte random[] = randomBytes(5 * 1024);
final String md5sum = HashGeneratorUtils.generateMD5(random); final String md5sum = HashGeneratorUtils.generateMD5(random);
final String sha1sum = HashGeneratorUtils.generateSHA1(random); final String sha1sum = HashGeneratorUtils.generateSHA1(random);
final String sha256sum = HashGeneratorUtils.generateSHA256(random);
final MockMultipartFile file = new MockMultipartFile("file", "orig", null, random); final MockMultipartFile file = new MockMultipartFile("file", "orig", null, random);
mvc.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file) 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(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(jsonPath("$.hashes.md5", equalTo(md5sum))) .andExpect(jsonPath("$.hashes.md5", equalTo(md5sum)))
.andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum))) .andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum)))
.andExpect(jsonPath("$.hashes.sha256", equalTo(sha256sum)))
.andExpect(jsonPath("$.providedFilename", equalTo("orig"))).andExpect(status().isCreated()); .andExpect(jsonPath("$.providedFilename", equalTo("orig"))).andExpect(status().isCreated());
mvc.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)) 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 byte random[] = randomBytes(5 * 1024);
final String md5sum = HashGeneratorUtils.generateMD5(random); final String md5sum = HashGeneratorUtils.generateMD5(random);
final String sha1sum = HashGeneratorUtils.generateSHA1(random); final String sha1sum = HashGeneratorUtils.generateSHA1(random);
final String sha256sum = HashGeneratorUtils.generateSHA256(random);
final MockMultipartFile file = new MockMultipartFile("file", "origFilename", null, random); final MockMultipartFile file = new MockMultipartFile("file", "origFilename", null, random);
// upload // upload
// wrong sha1 // wrong sha1
MvcResult mvcResult = mvc MvcResult mvcResult = mvc
.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file) .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(); .andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()).andReturn();
// check error result // check error result
@@ -336,10 +344,21 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
assertThat(exceptionInfo.getErrorCode()).as("Exception contains wrong error code") assertThat(exceptionInfo.getErrorCode()).as("Exception contains wrong error code")
.isEqualTo(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH.getKey()); .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 // wrong md5
mvcResult = mvc mvcResult = mvc
.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file) .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(); .andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()).andReturn();
// check error result // check error result
@@ -366,6 +385,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
final byte random[] = randomBytes(5 * 1024); final byte random[] = randomBytes(5 * 1024);
final String md5sum = HashGeneratorUtils.generateMD5(random); final String md5sum = HashGeneratorUtils.generateMD5(random);
final String sha1sum = HashGeneratorUtils.generateSHA1(random); final String sha1sum = HashGeneratorUtils.generateSHA1(random);
final String sha256sum = HashGeneratorUtils.generateSHA256(random);
final MockMultipartFile file = new MockMultipartFile("file", "origFilename" + i, null, random); final MockMultipartFile file = new MockMultipartFile("file", "origFilename" + i, null, random);
// upload // upload
@@ -375,14 +395,13 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(jsonPath("$.hashes.md5", equalTo(md5sum))) .andExpect(jsonPath("$.hashes.md5", equalTo(md5sum)))
.andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum))) .andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum)))
.andExpect(jsonPath("$.hashes.sha256", equalTo(sha256sum)))
.andExpect(jsonPath("$.size", equalTo(random.length))) .andExpect(jsonPath("$.size", equalTo(random.length)))
.andExpect(jsonPath("$.providedFilename", equalTo("origFilename" + i))).andReturn(); .andExpect(jsonPath("$.providedFilename", equalTo("origFilename" + i))).andReturn();
} }
// upload one more file to cause the quota to be exceeded // upload one more file to cause the quota to be exceeded
final byte random[] = randomBytes(5 * 1024); final byte random[] = randomBytes(5 * 1024);
HashGeneratorUtils.generateMD5(random);
HashGeneratorUtils.generateSHA1(random);
final MockMultipartFile file = new MockMultipartFile("file", "origFilename_final", null, random); final MockMultipartFile file = new MockMultipartFile("file", "origFilename_final", null, random);
// upload // upload
@@ -409,6 +428,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
final byte random[] = randomBytes(artifactSize); final byte random[] = randomBytes(artifactSize);
final String md5sum = HashGeneratorUtils.generateMD5(random); final String md5sum = HashGeneratorUtils.generateMD5(random);
final String sha1sum = HashGeneratorUtils.generateSHA1(random); final String sha1sum = HashGeneratorUtils.generateSHA1(random);
final String sha256sum = HashGeneratorUtils.generateSHA256(random);
final MockMultipartFile file = new MockMultipartFile("file", "origFilename" + i, null, random); final MockMultipartFile file = new MockMultipartFile("file", "origFilename" + i, null, random);
// upload // upload
@@ -419,14 +439,13 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(jsonPath("$.hashes.md5", equalTo(md5sum))) .andExpect(jsonPath("$.hashes.md5", equalTo(md5sum)))
.andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum))) .andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum)))
.andExpect(jsonPath("$.hashes.sha256", equalTo(sha256sum)))
.andExpect(jsonPath("$.size", equalTo(random.length))) .andExpect(jsonPath("$.size", equalTo(random.length)))
.andExpect(jsonPath("$.providedFilename", equalTo("origFilename" + i))).andReturn(); .andExpect(jsonPath("$.providedFilename", equalTo("origFilename" + i))).andReturn();
} }
// upload one more file to cause the quota to be exceeded // upload one more file to cause the quota to be exceeded
final byte random[] = randomBytes(artifactSize); final byte random[] = randomBytes(artifactSize);
HashGeneratorUtils.generateMD5(random);
HashGeneratorUtils.generateSHA1(random);
final MockMultipartFile file = new MockMultipartFile("file", "origFilename_final", null, random); final MockMultipartFile file = new MockMultipartFile("file", "origFilename_final", null, random);
// upload // upload
@@ -490,6 +509,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
.andExpect(jsonPath("$.size", equalTo(random.length))) .andExpect(jsonPath("$.size", equalTo(random.length)))
.andExpect(jsonPath("$.hashes.md5", equalTo(artifact.getMd5Hash()))) .andExpect(jsonPath("$.hashes.md5", equalTo(artifact.getMd5Hash())))
.andExpect(jsonPath("$.hashes.sha1", equalTo(artifact.getSha1Hash()))) .andExpect(jsonPath("$.hashes.sha1", equalTo(artifact.getSha1Hash())))
.andExpect(jsonPath("$.hashes.sha256", equalTo(artifact.getSha256Hash())))
.andExpect(jsonPath("$.providedFilename", equalTo("file1"))) .andExpect(jsonPath("$.providedFilename", equalTo("file1")))
.andExpect(jsonPath("$._links.download.href", .andExpect(jsonPath("$._links.download.href",
equalTo("http://localhost/rest/v1/softwaremodules/" + sm.getId() + "/artifacts/" 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].size", equalTo(random.length)))
.andExpect(jsonPath("$.[0].hashes.md5", equalTo(artifact.getMd5Hash()))) .andExpect(jsonPath("$.[0].hashes.md5", equalTo(artifact.getMd5Hash())))
.andExpect(jsonPath("$.[0].hashes.sha1", equalTo(artifact.getSha1Hash()))) .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].providedFilename", equalTo("file1")))
.andExpect(jsonPath("$.[0]._links.self.href", .andExpect(jsonPath("$.[0]._links.self.href",
equalTo("http://localhost/rest/v1/softwaremodules/" + sm.getId() + "/artifacts/" 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].id", equalTo(artifact2.getId().intValue())))
.andExpect(jsonPath("$.[1].hashes.md5", equalTo(artifact2.getMd5Hash()))) .andExpect(jsonPath("$.[1].hashes.md5", equalTo(artifact2.getMd5Hash())))
.andExpect(jsonPath("$.[1].hashes.sha1", equalTo(artifact2.getSha1Hash()))) .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].providedFilename", equalTo("file2")))
.andExpect(jsonPath("$.[1]._links.self.href", equalTo( .andExpect(jsonPath("$.[1]._links.self.href", equalTo(
"http://localhost/rest/v1/softwaremodules/" + sm.getId() + "/artifacts/" + artifact2.getId()))); "http://localhost/rest/v1/softwaremodules/" + sm.getId() + "/artifacts/" + artifact2.getId())));
@@ -759,7 +781,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
} }
@Test @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 { public void getSoftwareModulesWithUnknownFieldErrorFilterParameter() throws Exception {
mvc.perform(get("/rest/v1/softwaremodules?q=wrongField==abc").accept(MediaType.APPLICATION_JSON)) mvc.perform(get("/rest/v1/softwaremodules?q=wrongField==abc").accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()) .andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest())

View File

@@ -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_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, 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_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_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_DELETE_FAILED, HttpStatus.INTERNAL_SERVER_ERROR);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_LOAD_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 * Method for handling exception of type HttpMessageNotReadableException and
* MethodArgumentNotValidException which are thrown in case the request body is * MethodArgumentNotValidException which are thrown in case the request body
* not well formed (e.g. syntax failures, missing/invalid parameters) and cannot * is not well formed (e.g. syntax failures, missing/invalid parameters) and
* be deserialized. Called by the Spring-Framework for exception handling. * cannot be deserialized. Called by the Spring-Framework for exception
* handling.
* *
* @param request * @param request
* the Http request * the Http request
@@ -129,7 +131,7 @@ public class ResponseExceptionHandler {
* @return the entity to be responded containing the exception information * @return the entity to be responded containing the exception information
* as entity. * as entity.
*/ */
@ExceptionHandler({HttpMessageNotReadableException.class, MethodArgumentNotValidException.class}) @ExceptionHandler({ HttpMessageNotReadableException.class, MethodArgumentNotValidException.class })
public ResponseEntity<ExceptionInfo> handleExceptionCausedByIncorrectRequestBody(final HttpServletRequest request, public ResponseEntity<ExceptionInfo> handleExceptionCausedByIncorrectRequestBody(final HttpServletRequest request,
final Exception ex) { final Exception ex) {
logRequest(request, ex); logRequest(request, ex);

View File

@@ -47,6 +47,7 @@ public final class MgmtApiModelProperties {
public static final String ARTIFACT_PROVIDED_FILENAME = "Filename of the artifact."; 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_SHA1 = "SHA1 hash of the artifact.";
public static final String ARTIFACT_HASHES_MD5 = "MD5 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."; public static final String ARTIFACT_DOWNLOAD_LINK = "Download link of the artifact.";

View File

@@ -266,6 +266,8 @@ public class SoftwaremodulesDocumentationTest extends AbstractApiRestDocumentati
fieldWithPath("[].hashes.md5").description(MgmtApiModelProperties.ARTIFACT_HASHES_MD5), fieldWithPath("[].hashes.md5").description(MgmtApiModelProperties.ARTIFACT_HASHES_MD5),
fieldWithPath("[].hashes.sha1") fieldWithPath("[].hashes.sha1")
.description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA1), .description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA1),
fieldWithPath("[].hashes.sha256")
.description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA256),
fieldWithPath("[].providedFilename") fieldWithPath("[].providedFilename")
.description(MgmtApiModelProperties.ARTIFACT_PROVIDED_FILENAME), .description(MgmtApiModelProperties.ARTIFACT_PROVIDED_FILENAME),
fieldWithPath("[]._links.self").ignored()))); fieldWithPath("[]._links.self").ignored())));
@@ -299,6 +301,8 @@ public class SoftwaremodulesDocumentationTest extends AbstractApiRestDocumentati
.description(MgmtApiModelProperties.ARTIFACT_DOWNLOAD_LINK), .description(MgmtApiModelProperties.ARTIFACT_DOWNLOAD_LINK),
fieldWithPath("hashes.md5").description(MgmtApiModelProperties.ARTIFACT_HASHES_MD5), fieldWithPath("hashes.md5").description(MgmtApiModelProperties.ARTIFACT_HASHES_MD5),
fieldWithPath("hashes.sha1").description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA1), fieldWithPath("hashes.sha1").description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA1),
fieldWithPath("hashes.sha256")
.description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA256),
fieldWithPath("providedFilename") fieldWithPath("providedFilename")
.description(MgmtApiModelProperties.ARTIFACT_PROVIDED_FILENAME))) .description(MgmtApiModelProperties.ARTIFACT_PROVIDED_FILENAME)))
@@ -374,6 +378,8 @@ public class SoftwaremodulesDocumentationTest extends AbstractApiRestDocumentati
fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT), fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT),
fieldWithPath("hashes.md5").description(MgmtApiModelProperties.ARTIFACT_HASHES_MD5), fieldWithPath("hashes.md5").description(MgmtApiModelProperties.ARTIFACT_HASHES_MD5),
fieldWithPath("hashes.sha1").description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA1), fieldWithPath("hashes.sha1").description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA1),
fieldWithPath("hashes.sha256")
.description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA256),
fieldWithPath("providedFilename") fieldWithPath("providedFilename")
.description(MgmtApiModelProperties.ARTIFACT_PROVIDED_FILENAME), .description(MgmtApiModelProperties.ARTIFACT_PROVIDED_FILENAME),
fieldWithPath("_links.self").ignored(), fieldWithPath("_links.download") fieldWithPath("_links.self").ignored(), fieldWithPath("_links.download")

View File

@@ -297,7 +297,7 @@ public abstract class AbstractFileTransferHandler implements Serializable {
private Artifact uploadArtifact(final String filename) { private Artifact uploadArtifact(final String filename) {
try { try {
return artifactManagement.create(new ArtifactUpload(inputStream, fileUploadId.getSoftwareModuleId(), 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) { } catch (final ArtifactUploadFailedException | InvalidSHA1HashException | InvalidMD5HashException e) {
throw new ArtifactUploadFailedException(e); throw new ArtifactUploadFailedException(e);
} }