diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/api/APIMessage.java b/src/main/java/ch/ethz/seb/sebserver/gbl/api/APIMessage.java index 6cc76981..1a07b3e2 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/api/APIMessage.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/api/APIMessage.java @@ -23,6 +23,7 @@ import org.springframework.web.util.HtmlUtils; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.util.Utils; /** This class defines API error messages that are created and responded on error and/or exceptional @@ -201,39 +202,13 @@ public class APIMessage implements Serializable { final StringBuilder builder = new StringBuilder(); builder.append("Failure: ").append("

").append(errorMessage).append("

"); builder.append("Detail Messages:

"); - messages.stream() - .forEach(message -> { - builder - .append("  code : ") - .append(message.messageCode) - .append("
") - .append("  system message : ") - .append(HtmlUtils.htmlEscape(message.systemMessage)) - .append("
") - .append("  details : ") - .append(HtmlUtils.htmlEscape(StringUtils.abbreviate(message.details, 100))) - .append("

"); - }); - return builder.toString(); + return buildHTML(messages, builder); } public static String toHTML(final Collection messages) { final StringBuilder builder = new StringBuilder(); builder.append("Messages:

"); - messages.stream() - .forEach(message -> { - builder - .append("  code : ") - .append(message.messageCode) - .append("
") - .append("  system message : ") - .append(HtmlUtils.htmlEscape(message.systemMessage)) - .append("
") - .append("  details : ") - .append(HtmlUtils.htmlEscape(StringUtils.abbreviate(message.details, 100))) - .append("

"); - }); - return builder.toString(); + return buildHTML(messages, builder); } /** This exception can be internal used to wrap a created APIMessage @@ -257,12 +232,12 @@ public class APIMessage implements Serializable { } public APIMessageException(final ErrorMessage errorMessage) { - super(); + super(errorMessage.systemMessage); this.apiMessages = Arrays.asList(errorMessage.of()); } public APIMessageException(final ErrorMessage errorMessage, final String detail, final String... attributes) { - super(); + super(errorMessage.systemMessage); this.apiMessages = Arrays.asList(errorMessage.of(detail, attributes)); } @@ -286,4 +261,23 @@ public class APIMessage implements Serializable { } } + private static String buildHTML(final Collection messages, final StringBuilder builder) { + messages.stream() + .forEach(message -> { + builder + .append("  code : ") + .append(message.messageCode) + .append("
") + .append("  system message : ") + .append(HtmlUtils.htmlEscape(message.systemMessage)) + .append("
") + .append("  details : ") + .append((message.details != null) + ? HtmlUtils.htmlEscape(StringUtils.abbreviate(message.details, 100)) + : Constants.EMPTY_NOTE) + .append("

"); + }); + return builder.toString(); + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/api/authorization/PrivilegeType.java b/src/main/java/ch/ethz/seb/sebserver/gbl/api/authorization/PrivilegeType.java index 81c54d7c..e4bc9c20 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/api/authorization/PrivilegeType.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/api/authorization/PrivilegeType.java @@ -36,8 +36,6 @@ public enum PrivilegeType { } switch (this) { - case NONE: - return false; case READ: return type == READ; case MODIFY: diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/WebserviceConfig.java b/src/main/java/ch/ethz/seb/sebserver/webservice/WebserviceConfig.java index a30dd3d1..c1f79837 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/WebserviceConfig.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/WebserviceConfig.java @@ -10,21 +10,15 @@ package ch.ethz.seb.sebserver.webservice; import org.cryptonode.jncryptor.AES256JNCryptor; import org.cryptonode.jncryptor.JNCryptor; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Lazy; import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; -//TODO check if DataSourceAutoConfiguration and TokenStore bean definition is really needed here -//or if it is possible to move them to the WebServiceSecurityConfig. -//test with starting web and gui separately as well as together @Configuration @WebServiceProfile -@Import(DataSourceAutoConfiguration.class) public class WebserviceConfig { @Lazy diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/PasswordEncryptor.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/PasswordEncryptor.java index 7f540dbb..df7d76a7 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/PasswordEncryptor.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/PasswordEncryptor.java @@ -17,10 +17,10 @@ import java.io.SequenceInputStream; import java.util.Set; import org.apache.tomcat.util.http.fileupload.IOUtils; -import org.cryptonode.jncryptor.AES256JNCryptor; import org.cryptonode.jncryptor.AES256JNCryptorInputStream; import org.cryptonode.jncryptor.AES256JNCryptorOutputStream; import org.cryptonode.jncryptor.CryptorException; +import org.cryptonode.jncryptor.JNCryptor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; @@ -44,6 +44,12 @@ public class PasswordEncryptor implements SebConfigCryptor { Strategy.PASSWORD_PSWD, Strategy.PASSWORD_PWCC); + private final JNCryptor cryptor; + + protected PasswordEncryptor(final JNCryptor cryptor) { + this.cryptor = cryptor; + } + @Override public Set strategies() { return STRATEGIES; @@ -139,9 +145,9 @@ public class PasswordEncryptor implements SebConfigCryptor { final ByteArrayOutputStream out = new ByteArrayOutputStream(); IOUtils.copy(sequenceInputStream, out); final byte[] ciphertext = out.toByteArray(); - final AES256JNCryptor cryptor = new AES256JNCryptor(); - cryptor.setPBKDFIterations(Constants.JN_CRYPTOR_ITERATIONS); - final byte[] decryptData = cryptor.decryptData(ciphertext, Utils.toCharArray(password)); + + //cryptor.setPBKDFIterations(Constants.JN_CRYPTOR_ITERATIONS); + final byte[] decryptData = this.cryptor.decryptData(ciphertext, Utils.toCharArray(password)); final ByteArrayInputStream decryptedIn = new ByteArrayInputStream(decryptData); IOUtils.copyLarge(decryptedIn, output); diff --git a/src/test/java/ch/ethz/seb/sebserver/TestUtils.java b/src/test/java/ch/ethz/seb/sebserver/TestUtils.java new file mode 100644 index 00000000..98e2cc9d --- /dev/null +++ b/src/test/java/ch/ethz/seb/sebserver/TestUtils.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public final class TestUtils { + + private static final Object SOME_OBJECT = new Object(); + + public static final void genericObjectTest(final T testObject) { + assertFalse(testObject.equals(null)); + assertFalse(testObject.equals(SOME_OBJECT)); + assertTrue(testObject.equals(testObject)); + } + + public static final void genericObjectTest(final T testObject, final T other) { + genericObjectTest(testObject); + assertFalse(testObject.equals(other)); + } + +} diff --git a/src/test/java/ch/ethz/seb/sebserver/gbl/api/APIMessageTest.java b/src/test/java/ch/ethz/seb/sebserver/gbl/api/APIMessageTest.java new file mode 100644 index 00000000..7fe6d038 --- /dev/null +++ b/src/test/java/ch/ethz/seb/sebserver/gbl/api/APIMessageTest.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.gbl.api; + +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException; + +public class APIMessageTest { + + @Test + public void testInit() { + final APIMessage message = APIMessage.ErrorMessage.GENERIC.of(); + assertEquals( + "APIMessage [messageCode=0, systemMessage=Generic error message, details=null, attributes=[]]", + message.toString()); + + assertTrue(APIMessage.ErrorMessage.GENERIC.isOf(message)); + + final APIMessage message2 = APIMessage.ErrorMessage.GENERIC.of( + new RuntimeException("Some Exception"), + "attribute1", + "attribute2"); + + assertEquals( + "APIMessage [messageCode=0, systemMessage=Generic error message, details=Some Exception, attributes=[attribute1, attribute2]]", + message2.toString()); + + final APIMessage message3 = new APIMessage("test", "test"); + assertEquals( + "APIMessage [messageCode=test, systemMessage=test, details=null, attributes=[]]", + message3.toString()); + } + + @Test + public void testCreateErrorResponse() { + final ResponseEntity> errorResponse = APIMessage.ErrorMessage.GENERIC.createErrorResponse(); + assertTrue(errorResponse.getStatusCode() == HttpStatus.INTERNAL_SERVER_ERROR); + final List body = errorResponse.getBody(); + assertNotNull(body); + assertFalse(body.isEmpty()); + assertTrue(body.size() == 1); + assertEquals( + "APIMessage [messageCode=0, systemMessage=Generic error message, details=null, attributes=[]]", + body.get(0).toString()); + + } + + @Test + public void testToHTML() { + final List messages = Arrays.asList( + APIMessage.ErrorMessage.GENERIC.of(), + APIMessage.ErrorMessage.ILLEGAL_API_ARGUMENT.of()); + + final String html = APIMessage.toHTML("title message", messages); + assertEquals( + "Failure:

title message

Detail Messages:

  code : 0
  system message : Generic error message
  details : --

  code : 1010
  system message : Illegal API request argument
  details : --

", + html); + + final String html2 = APIMessage.toHTML(messages); + assertEquals( + "Messages:

  code : 0
  system message : Generic error message
  details : --

  code : 1010
  system message : Illegal API request argument
  details : --

", + html2); + } + + @Test + public void testAPIMessageException() { + final APIMessageException apiMessageException = + new APIMessage.APIMessageException(APIMessage.ErrorMessage.FORBIDDEN); + + assertEquals("FORBIDDEN", apiMessageException.getMessage()); + Collection apiMessages = apiMessageException.getAPIMessages(); + assertNotNull(apiMessages); + assertFalse(apiMessages.isEmpty()); + assertTrue(apiMessages.size() == 1); + + final APIMessageException apiMessageException2 = + new APIMessage.APIMessageException(APIMessage.ErrorMessage.FORBIDDEN, "detail", "attribute1", + "attribute2"); + + assertEquals("FORBIDDEN", apiMessageException2.getMessage()); + apiMessages = apiMessageException2.getAPIMessages(); + assertNotNull(apiMessages); + assertFalse(apiMessages.isEmpty()); + assertTrue(apiMessages.size() == 1); + assertEquals( + "APIMessage [messageCode=1001, systemMessage=FORBIDDEN, details=detail, attributes=[attribute1, attribute2]]", + apiMessages.iterator().next().toString()); + } + +} diff --git a/src/test/java/ch/ethz/seb/sebserver/gbl/api/ExamAPIDiscoveryTest.java b/src/test/java/ch/ethz/seb/sebserver/gbl/api/ExamAPIDiscoveryTest.java new file mode 100644 index 00000000..fb263a34 --- /dev/null +++ b/src/test/java/ch/ethz/seb/sebserver/gbl/api/ExamAPIDiscoveryTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.gbl.api; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.Arrays; + +import org.junit.Test; + +public class ExamAPIDiscoveryTest { + + @Test + public void testCreation() throws IOException { + final JSONMapper jsonMapper = new JSONMapper(); + final ExamAPIDiscovery examAPIDiscovery = new ExamAPIDiscovery( + "title", + "description", + "serverURL", + new ExamAPIDiscovery.ExamAPIVersion( + "v1", + Arrays.asList(new ExamAPIDiscovery.Endpoint("name", "desc", "loc", "auth"))), + new ExamAPIDiscovery.ExamAPIVersion( + "v2", + Arrays.asList(new ExamAPIDiscovery.Endpoint("name", "desc", "loc", "auth")))); + + final String asString = jsonMapper.writeValueAsString(examAPIDiscovery); + + assertEquals( + "{\"title\":\"title\",\"description\":\"description\",\"server-location\":\"serverURL\",\"api-versions\":[{\"name\":\"v1\",\"endpoints\":[{\"name\":\"name\",\"description\":\"desc\",\"location\":\"loc\",\"authorization\":\"auth\"}]},{\"name\":\"v2\",\"endpoints\":[{\"name\":\"name\",\"description\":\"desc\",\"location\":\"loc\",\"authorization\":\"auth\"}]}]}", + asString); + + final ExamAPIDiscovery examAPIDiscovery2 = jsonMapper.readValue(asString, ExamAPIDiscovery.class); + assertEquals(asString, jsonMapper.writeValueAsString(examAPIDiscovery2)); + } + +} diff --git a/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/PasswordEncryptorTest.java b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/PasswordEncryptorTest.java index 5858bf11..56852cad 100644 --- a/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/PasswordEncryptorTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/PasswordEncryptorTest.java @@ -64,7 +64,8 @@ public class PasswordEncryptorTest { @Test public void test2() throws IOException { - final PasswordEncryptor encryptor = new PasswordEncryptor(); + final JNCryptor cryptor = new AES256JNCryptor(); + final PasswordEncryptor encryptor = new PasswordEncryptor(cryptor); final String config = ""; final String pwd = "password"; diff --git a/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebConfigEncryptionServiceImplTest.java b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebConfigEncryptionServiceImplTest.java index 41f33447..6db5d6ca 100644 --- a/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebConfigEncryptionServiceImplTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebConfigEncryptionServiceImplTest.java @@ -18,6 +18,8 @@ import java.util.Arrays; import java.util.List; import org.apache.commons.io.IOUtils; +import org.cryptonode.jncryptor.AES256JNCryptor; +import org.cryptonode.jncryptor.JNCryptor; import org.junit.Test; import ch.ethz.seb.sebserver.gbl.util.Utils; @@ -95,8 +97,9 @@ public class SebConfigEncryptionServiceImplTest { } private SebConfigEncryptionServiceImpl sebConfigEncryptionServiceImpl() { + final JNCryptor cryptor = new AES256JNCryptor(); final List encryptors = Arrays.asList( - new PasswordEncryptor(), + new PasswordEncryptor(cryptor), new NoneEncryptor()); return new SebConfigEncryptionServiceImpl(encryptors); }