From c4edad2651189cd7e30bd7c4bf9a8c0690767084 Mon Sep 17 00:00:00 2001 From: anhefti Date: Tue, 3 Mar 2020 15:47:10 +0100 Subject: [PATCH 1/6] several fixes --- .../ch/ethz/seb/sebserver/gbl/api/API.java | 4 +- .../impl/ExamConfigurationServiceImpl.java | 6 +- ...ion.java => AttachDefaultOrientation.java} | 4 +- .../api/ConfigurationNodeController.java | 11 +- .../gui/integration/GuiIntegrationTest.java | 18 +-- .../integration/UseCasesIntegrationTest.java | 132 +++++++++++++++++- 6 files changed, 143 insertions(+), 32 deletions(-) rename src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/{AttchDefaultOrientation.java => AttachDefaultOrientation.java} (92%) diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java b/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java index 89d5c3d8..0075af09 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java @@ -141,8 +141,8 @@ public final class API { public static final String TEMPLATE_ATTRIBUTE_ENDPOINT = "/template-attribute"; public static final String TEMPLATE_ATTRIBUTE_RESET_VALUES = "/reset"; - public static final String TEMPLATE_ATTRIBUTE_REMOVE_ORIENTATION = "remove-orientation"; - public static final String TEMPLATE_ATTRIBUTE_ATTACH_DEFAULT_ORIENTATION = "attach-default-orientation"; + public static final String TEMPLATE_ATTRIBUTE_REMOVE_ORIENTATION = "/remove-orientation"; + public static final String TEMPLATE_ATTRIBUTE_ATTACH_DEFAULT_ORIENTATION = "/attach-default-orientation"; public static final String ORIENTATION_ENDPOINT = "/orientation"; public static final String VIEW_ENDPOINT = ORIENTATION_ENDPOINT + "/view"; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java index 1cafeb3b..11b3763d 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java @@ -52,7 +52,7 @@ import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCallError; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; -import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.AttchDefaultOrientation; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.AttachDefaultOrientation; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetConfigAttributes; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetConfigurationValues; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetOrientations; @@ -297,14 +297,14 @@ public class ExamConfigurationServiceImpl implements ExamConfigurationService { if (selection != null && !selection.isEmpty()) { selection.stream().forEach(entityKey -> { callTemplateAction( - AttchDefaultOrientation.class, + AttachDefaultOrientation.class, parentEntityKey.modelId, entityKey.modelId); }); } else { final EntityKey entityKey = action.getEntityKey(); callTemplateAction( - AttchDefaultOrientation.class, + AttachDefaultOrientation.class, parentEntityKey.modelId, entityKey.modelId); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/AttchDefaultOrientation.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/AttachDefaultOrientation.java similarity index 92% rename from src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/AttchDefaultOrientation.java rename to src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/AttachDefaultOrientation.java index f3f973de..a862b1d5 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/AttchDefaultOrientation.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/AttachDefaultOrientation.java @@ -24,9 +24,9 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; @Lazy @Component @GuiProfile -public class AttchDefaultOrientation extends RestCall { +public class AttachDefaultOrientation extends RestCall { - public AttchDefaultOrientation() { + public AttachDefaultOrientation() { super(new TypeKey<>( CallType.SAVE, EntityType.CONFIGURATION_NODE, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java index 71e2e8ec..47a958ce 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java @@ -276,7 +276,7 @@ public class ConfigurationNodeController extends EntityController( - attrs.size() / pageSize, - pageNumber, + attrs.size() / this.paginationService.getPageSize(pageSize), + this.paginationService.getPageNumber(pageNumber), sort, attrs.subList(start, end)); } diff --git a/src/test/java/ch/ethz/seb/sebserver/gui/integration/GuiIntegrationTest.java b/src/test/java/ch/ethz/seb/sebserver/gui/integration/GuiIntegrationTest.java index 0df19573..a21dd41c 100644 --- a/src/test/java/ch/ethz/seb/sebserver/gui/integration/GuiIntegrationTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/gui/integration/GuiIntegrationTest.java @@ -10,9 +10,6 @@ package ch.ethz.seb.sebserver.gui.integration; import static org.junit.Assert.assertNotNull; -import java.io.IOException; -import java.net.HttpURLConnection; - import javax.servlet.http.HttpSession; import org.junit.Before; @@ -22,7 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.security.web.FilterChainProxy; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringRunner; @@ -79,18 +76,7 @@ public abstract class GuiIntegrationTest { final ClientHttpRequestFactoryService clientHttpRequestFactoryService = Mockito .mock(ClientHttpRequestFactoryService.class); Mockito.when(clientHttpRequestFactoryService.getClientHttpRequestFactory()).thenReturn( - Result.of( - new SimpleClientHttpRequestFactory() { - - @Override - protected void prepareConnection( - final HttpURLConnection connection, - final String httpMethod) throws IOException { - - super.prepareConnection(connection, httpMethod); - connection.setInstanceFollowRedirects(false); - } - })); + Result.of(new HttpComponentsClientHttpRequestFactory())); return new OAuth2AuthorizationContextHolder( this.clientId, diff --git a/src/test/java/ch/ethz/seb/sebserver/gui/integration/UseCasesIntegrationTest.java b/src/test/java/ch/ethz/seb/sebserver/gui/integration/UseCasesIntegrationTest.java index d8d3b495..38628afa 100644 --- a/src/test/java/ch/ethz/seb/sebserver/gui/integration/UseCasesIntegrationTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/gui/integration/UseCasesIntegrationTest.java @@ -65,6 +65,7 @@ import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues.TableV import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation; import ch.ethz.seb.sebserver.gbl.model.sebconfig.SebClientConfig; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute; import ch.ethz.seb.sebserver.gbl.model.sebconfig.View; import ch.ethz.seb.sebserver.gbl.model.user.PasswordChange; import ch.ethz.seb.sebserver.gbl.model.user.UserInfo; @@ -104,6 +105,7 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig. import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig.GetClientConfigPage; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig.NewClientConfig; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig.SaveClientConfig; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.AttachDefaultOrientation; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.CopyConfiguration; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ExportPlainXML; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetConfigAttributes; @@ -125,6 +127,8 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.Ge import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ImportExamConfigOnExistingConfig; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ImportNewExamConfig; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.NewExamConfig; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.RemoveOrientation; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ResetTemplateValues; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfig; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfigHistory; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfigTableValues; @@ -1433,11 +1437,19 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest { .stream() .filter(attr -> "URLFilterEnable".equals(attr.name)) .findFirst() + .or(() -> { + fail("Expected one attribute"); + return null; + }) .ifPresent( attr -> { values.stream() .filter(cv -> cv.attributeId.equals(attr.id)) .findFirst() + .or(() -> { + fail("Expected one attribute"); + return null; + }) .ifPresent( val -> assertEquals(Constants.TRUE_STRING, val.value)); }); @@ -1446,18 +1458,30 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest { .stream() .filter(attr -> "URLFilterRules".equals(attr.name)) .findFirst() + .or(() -> { + fail("Expected one attribute"); + return null; + }) .ifPresent( parent -> { attributes.stream() .filter(attr -> parent.id.equals(attr.parentId) && "URLFilterRules.expression".equals(attr.name)) .findFirst() + .or(() -> { + fail("Expected one attribute"); + return null; + }) .ifPresent( tAttr -> { values.stream() .filter(tVal -> tVal.attributeId.equals(tAttr.id) && tVal.listIndex == 0) .findFirst() + .or(() -> { + fail("Expected one value"); + return null; + }) .ifPresent( firstTVal -> assertEquals("jrtjrtzj", firstTVal.value)); }); @@ -1544,8 +1568,12 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest { @Order(15) // ************************************* // Use Case 15: Login as examAdmin2 and get views and orientations - // - test Views API - // - create configuration template form existing configuration + // - Test Views API + // - Create configuration template form existing configuration + // - Check views and orientation created for template + // - Remove one template attribute from orientation + // - Change one template attribute value + // - Reset template values public void testUsecase15() throws IOException { final RestServiceImpl restService = createRestServiceForUser( "examAdmin2", @@ -1557,7 +1585,14 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest { new CopyConfiguration(), new GetTemplateAttributePage(), new GetExamConfigNodePage(), - new GetTemplateAttribute()); + new GetTemplateAttribute(), + new GetConfigurationValues(), + new GetConfigurationValuePage(), + new SaveExamConfigValue(), + new GetFollowupConfiguration(), + new RemoveOrientation(), + new AttachDefaultOrientation(), + new ResetTemplateValues()); final List views = restService .getBuilder(GetViews.class) @@ -1572,6 +1607,7 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest { .getBuilder(GetOrientations.class) .call() .getOrThrow(); + assertNotNull(orientations); orientations.forEach(o -> assertEquals(o.templateId, ConfigurationNode.DEFAULT_TEMPLATE_ID)); // get configuration page and first config from the page to copy as template @@ -1612,7 +1648,95 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest { assertNotNull(newTemplate); assertEquals("Config Template", newTemplate.name); - assertNotNull(orientations); + // check views for template where created + final List templateViews = restService + .getBuilder(GetViews.class) + .withQueryParam(View.FILTER_ATTR_TEMPLATE, String.valueOf(template.id)) + .call() + .getOrThrow(); + + assertNotNull(templateViews); + assertFalse(templateViews.isEmpty()); + assertEquals(11, templateViews.size()); + + // check orientations for template where created + final List templateTrientations = restService + .getBuilder(GetOrientations.class) + .withQueryParam(Orientation.FILTER_ATTR_TEMPLATE_ID, String.valueOf(template.id)) + .call() + .getOrThrow(); + assertNotNull(templateTrientations); + assertFalse(templateTrientations.isEmpty()); + assertEquals(192, templateTrientations.size()); + + // get template attributes page + final Page templateAttributes = restService + .getBuilder(GetTemplateAttributePage.class) + .withURIVariable(API.PARAM_PARENT_MODEL_ID, String.valueOf(template.id)) + .call() + .getOrThrow(); + + assertNotNull(templateAttributes); + assertFalse(templateAttributes.isEmpty()); + final TemplateAttribute templateAttr = templateAttributes.content.get(0); + assertEquals(template.id, templateAttr.templateId); + final Orientation orientation = templateAttr.getOrientation(); + assertNotNull(orientation); + + TemplateAttribute savedTAttribute = restService + .getBuilder(RemoveOrientation.class) + .withURIVariable(API.PARAM_PARENT_MODEL_ID, String.valueOf(template.id)) + .withURIVariable(API.PARAM_MODEL_ID, templateAttr.getModelId()) + .call() + .getOrThrow(); + + assertNotNull(savedTAttribute); + assertNull(savedTAttribute.getOrientation()); + + // Re-attach default orientation + savedTAttribute = restService + .getBuilder(AttachDefaultOrientation.class) + .withURIVariable(API.PARAM_PARENT_MODEL_ID, String.valueOf(template.id)) + .withURIVariable(API.PARAM_MODEL_ID, templateAttr.getModelId()) + .call() + .getOrThrow(); + + assertNotNull(savedTAttribute); + assertNotNull(savedTAttribute.getOrientation()); + assertEquals(orientation.viewId, savedTAttribute.getOrientation().viewId); + assertEquals(orientation.templateId, savedTAttribute.getOrientation().templateId); + assertEquals(orientation.attributeId, savedTAttribute.getOrientation().attributeId); + + // get first value and change it + final Configuration fallow_up = restService.getBuilder(GetFollowupConfiguration.class) + .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(template.id)) + .call() + .getOrThrow(); + assertNotNull(fallow_up); + + final List values = restService + .getBuilder(GetConfigurationValues.class) + .withQueryParam(ConfigurationValue.FILTER_ATTR_CONFIGURATION_ID, String.valueOf(fallow_up.id)) + .withQueryParam(ConfigurationValue.FILTER_ATTR_CONFIGURATION_ATTRIBUTE_ID, savedTAttribute.getModelId()) + .call() + .getOrThrow(); + + assertNotNull(values); + assertTrue(values.size() == 1); + final ConfigurationValue templateValue = values.get(0); + assertNull(templateValue.value); + + final ConfigurationValue newValue = new ConfigurationValue( + templateValue.id, templateValue.institutionId, savedTAttribute.getTemplateId(), + templateValue.attributeId, 0, "123"); + final ConfigurationValue newTemplValue = restService + .getBuilder(SaveExamConfigValue.class) + .withBody(newValue) + .call() + .getOrThrow(); + assertNotNull(newTemplValue); + assertEquals("123", newTemplValue.value); + } } From 697eff40558b3bc737ca49e3d90f1a0fed84dcc4 Mon Sep 17 00:00:00 2001 From: anhefti Date: Tue, 3 Mar 2020 15:51:50 +0100 Subject: [PATCH 2/6] fix for Java 8 --- .../gui/service/page/impl/PageServiceImpl.java | 14 +++++++------- .../sebserver/gui/widget/ImageUploadSelection.java | 5 ++++- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageServiceImpl.java index 73ebd521..90c6a5fd 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageServiceImpl.java @@ -20,7 +20,6 @@ import java.util.function.Supplier; import javax.servlet.http.HttpSession; -import ch.ethz.seb.sebserver.gbl.util.Cryptor; import org.eclipse.rap.rwt.RWT; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,6 +35,7 @@ import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.Page; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; +import ch.ethz.seb.sebserver.gbl.util.Cryptor; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gui.form.FormBuilder; import ch.ethz.seb.sebserver.gui.service.ResourceService; @@ -227,7 +227,7 @@ public class PageServiceImpl implements PageService { final int dependencies = (int) entities.stream() .flatMap(entity -> { final RestCall>.RestCallBuilder builder = - restService.getBuilder( + restService.> getBuilder( entity.entityType(), CallType.GET_DEPENDENCIES); @@ -254,7 +254,7 @@ public class PageServiceImpl implements PageService { public Function activationToggleActionFunction( final EntityTable table, final LocTextKey noSelectionText, - Function testBeforeActivation) { + final Function testBeforeActivation) { return action -> { final Set selectedROWData = table.getSelectedROWData(); @@ -269,7 +269,7 @@ public class PageServiceImpl implements PageService { for (final T entity : selectedROWData) { if (!entity.isActive()) { - RestCall.RestCallBuilder restCallBuilder = restService.getBuilder( + final RestCall.RestCallBuilder restCallBuilder = restService. getBuilder( entityType, CallType.ACTIVATION_ACTIVATE) .withURIVariable(API.PARAM_MODEL_ID, entity.getModelId()); @@ -280,7 +280,7 @@ public class PageServiceImpl implements PageService { restCallBuilder .call() .onError(errors::add); - } catch (Exception e) { + } catch (final Exception e) { errors.add(e); } } else { @@ -289,7 +289,7 @@ public class PageServiceImpl implements PageService { .onError(errors::add); } } else { - restService.getBuilder(entityType, CallType.ACTIVATION_DEACTIVATE) + restService. getBuilder(entityType, CallType.ACTIVATION_DEACTIVATE) .withURIVariable(API.PARAM_MODEL_ID, entity.getModelId()) .call() .onError(errors::add); @@ -347,7 +347,7 @@ public class PageServiceImpl implements PageService { @Override public FormBuilder formBuilder(final PageContext pageContext, final int rows) { - return new FormBuilder(this, pageContext, cryptor, rows); + return new FormBuilder(this, pageContext, this.cryptor, rows); } @Override diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/ImageUploadSelection.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/ImageUploadSelection.java index eec2cad2..6b7cf37e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/ImageUploadSelection.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/ImageUploadSelection.java @@ -48,7 +48,10 @@ public final class ImageUploadSelection extends Composite { private static final long serialVersionUID = 368264811155804533L; private static final Logger log = LoggerFactory.getLogger(ImageUploadSelection.class); - public static final Set SUPPORTED_IMAGE_FILES = Set.of(".png", ".jpg", ".jpeg"); + public static final Set SUPPORTED_IMAGE_FILES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList( + ".png", + ".jpg", + ".jpeg"))); private final ServerPushService serverPushService; From 3e3887a90cc15bc77e3bcca40605d484d2264345 Mon Sep 17 00:00:00 2001 From: anhefti Date: Tue, 3 Mar 2020 15:59:04 +0100 Subject: [PATCH 3/6] fixed for Java 8 --- .../integration/UseCasesIntegrationTest.java | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/src/test/java/ch/ethz/seb/sebserver/gui/integration/UseCasesIntegrationTest.java b/src/test/java/ch/ethz/seb/sebserver/gui/integration/UseCasesIntegrationTest.java index 38628afa..7d0a67a1 100644 --- a/src/test/java/ch/ethz/seb/sebserver/gui/integration/UseCasesIntegrationTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/gui/integration/UseCasesIntegrationTest.java @@ -1437,19 +1437,11 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest { .stream() .filter(attr -> "URLFilterEnable".equals(attr.name)) .findFirst() - .or(() -> { - fail("Expected one attribute"); - return null; - }) .ifPresent( attr -> { values.stream() .filter(cv -> cv.attributeId.equals(attr.id)) .findFirst() - .or(() -> { - fail("Expected one attribute"); - return null; - }) .ifPresent( val -> assertEquals(Constants.TRUE_STRING, val.value)); }); @@ -1458,30 +1450,18 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest { .stream() .filter(attr -> "URLFilterRules".equals(attr.name)) .findFirst() - .or(() -> { - fail("Expected one attribute"); - return null; - }) .ifPresent( parent -> { attributes.stream() .filter(attr -> parent.id.equals(attr.parentId) && "URLFilterRules.expression".equals(attr.name)) .findFirst() - .or(() -> { - fail("Expected one attribute"); - return null; - }) .ifPresent( tAttr -> { values.stream() .filter(tVal -> tVal.attributeId.equals(tAttr.id) && tVal.listIndex == 0) .findFirst() - .or(() -> { - fail("Expected one value"); - return null; - }) .ifPresent( firstTVal -> assertEquals("jrtjrtzj", firstTVal.value)); }); From abe1cc77d804f59ec0ab7a0764a3b1ef2c48a282 Mon Sep 17 00:00:00 2001 From: anhefti Date: Tue, 3 Mar 2020 16:23:43 +0100 Subject: [PATCH 4/6] code cleanup --- .../sebconfig/ClientConfigService.java | 6 +- .../impl/ClientConfigServiceImpl.java | 156 ++++++++---------- .../api/SebClientConfigController.java | 53 +++--- 3 files changed, 97 insertions(+), 118 deletions(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ClientConfigService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ClientConfigService.java index dda1369f..40f483b9 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ClientConfigService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ClientConfigService.java @@ -12,14 +12,11 @@ import java.io.OutputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; -import org.springframework.context.event.EventListener; import org.springframework.security.oauth2.provider.ClientDetails; import ch.ethz.seb.sebserver.gbl.model.sebconfig.SebClientConfig; import ch.ethz.seb.sebserver.gbl.util.Result; -import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkActionEvent; public interface ClientConfigService { @@ -63,7 +60,6 @@ public interface ClientConfigService { /** Internally used to check OAuth2 access for a active SebClientConfig. * * @param config the SebClientConfig to check access - * @return true if the system was able to gain an access token for the client. False otherwise - */ + * @return true if the system was able to gain an access token for the client. False otherwise */ boolean checkAccess(SebClientConfig config); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ClientConfigServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ClientConfigServiceImpl.java index f851615f..1a71dc21 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ClientConfigServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ClientConfigServiceImpl.java @@ -8,10 +8,41 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Collection; +import java.util.Collections; +import java.util.UUID; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Lazy; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + import ch.ethz.seb.sebserver.WebSecurityConfig; import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.api.API; -import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.institution.Institution; import ch.ethz.seb.sebserver.gbl.model.sebconfig.SebClientConfig; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; @@ -28,39 +59,6 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigEncrypti import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ZipService; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl.SebConfigEncryptionServiceImpl.EncryptionContext; import ch.ethz.seb.sebserver.webservice.weblayer.oauth.WebserviceResourceConfiguration; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Lazy; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.provider.ClientDetails; -import org.springframework.security.oauth2.provider.client.BaseClientDetails; -import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.stereotype.Service; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; -import java.nio.charset.StandardCharsets; -import java.util.Base64; -import java.util.Collection; -import java.util.Collections; -import java.util.UUID; @Lazy @Service @@ -71,35 +69,35 @@ public class ClientConfigServiceImpl implements ClientConfigService { private static final String SEB_CLIENT_CONFIG_TEMPLATE_XML = " \r\n" + - " sebMode\r\n" + - " 1\r\n" + - " sebConfigPurpose\r\n" + - " %s\r\n" + - " sebServerFallback\r\n" + - " <%s />\r\n" + - "%s" + - " sebServerURL\r\n" + - " %s\r\n" + - " sebServerConfiguration\r\n" + - " \r\n" + - " institution\r\n" + - " %s\r\n" + - " clientName\r\n" + - " %s\r\n" + - " clientSecret\r\n" + - " %s\r\n" + - " apiDiscovery\r\n" + - " %s\r\n" + - " \r\n" + - " \r\n"; + " sebMode\r\n" + + " 1\r\n" + + " sebConfigPurpose\r\n" + + " %s\r\n" + + " sebServerFallback\r\n" + + " <%s />\r\n" + + "%s" + + " sebServerURL\r\n" + + " %s\r\n" + + " sebServerConfiguration\r\n" + + " \r\n" + + " institution\r\n" + + " %s\r\n" + + " clientName\r\n" + + " %s\r\n" + + " clientSecret\r\n" + + " %s\r\n" + + " apiDiscovery\r\n" + + " %s\r\n" + + " \r\n" + + " \r\n"; private final static String SEB_CLIENT_CONFIG_INTEGER_TEMPLATE = " %s\r\n" + - " %s\r\n"; + " %s\r\n"; private final static String SEB_CLIENT_CONFIG_STRING_TEMPLATE = " %s\r\n" + - " %s\r\n"; + " %s\r\n"; private final InstitutionDAO institutionDAO; private final SebClientConfigDAO sebClientConfigDAO; @@ -107,7 +105,6 @@ public class ClientConfigServiceImpl implements ClientConfigService { private final SebConfigEncryptionService sebConfigEncryptionService; private final PasswordEncoder clientPasswordEncoder; private final ZipService zipService; - private final TokenStore tokenStore; private final WebserviceInfo webserviceInfo; protected ClientConfigServiceImpl( @@ -116,7 +113,6 @@ public class ClientConfigServiceImpl implements ClientConfigService { final ClientCredentialService clientCredentialService, final SebConfigEncryptionService sebConfigEncryptionService, final ZipService zipService, - final TokenStore tokenStore, @Qualifier(WebSecurityConfig.CLIENT_PASSWORD_ENCODER_BEAN_NAME) final PasswordEncoder clientPasswordEncoder, final WebserviceInfo webserviceInfo) { @@ -126,7 +122,6 @@ public class ClientConfigServiceImpl implements ClientConfigService { this.sebConfigEncryptionService = sebConfigEncryptionService; this.zipService = zipService; this.clientPasswordEncoder = clientPasswordEncoder; - this.tokenStore = tokenStore; this.webserviceInfo = webserviceInfo; } @@ -279,7 +274,7 @@ public class ClientConfigServiceImpl implements ClientConfigService { config.fallbackAttemptInterval); if (StringUtils.isNotBlank(config.fallbackPassword)) { - CharSequence decrypt = clientCredentialService.decrypt(config.fallbackPassword); + final CharSequence decrypt = this.clientCredentialService.decrypt(config.fallbackPassword); fallbackAddition += String.format( SEB_CLIENT_CONFIG_STRING_TEMPLATE, SebClientConfig.ATTR_FALLBACK_PASSWORD, @@ -287,7 +282,7 @@ public class ClientConfigServiceImpl implements ClientConfigService { } if (StringUtils.isNotBlank(config.quitPassword)) { - CharSequence decrypt = clientCredentialService.decrypt(config.quitPassword); + final CharSequence decrypt = this.clientCredentialService.decrypt(config.quitPassword); fallbackAddition += String.format( SEB_CLIENT_CONFIG_STRING_TEMPLATE, SebClientConfig.ATTR_QUIT_PASSWORD, @@ -323,34 +318,34 @@ public class ClientConfigServiceImpl implements ClientConfigService { } @Override - public boolean checkAccess(SebClientConfig config) { - if(!config.isActive()) { + public boolean checkAccess(final SebClientConfig config) { + if (!config.isActive()) { return false; } try { - RestTemplate restTemplate = new RestTemplate(); - String externalServerURL = webserviceInfo.getExternalServerURL() + + final RestTemplate restTemplate = new RestTemplate(); + final String externalServerURL = this.webserviceInfo.getExternalServerURL() + API.OAUTH_TOKEN_ENDPOINT; - MultiValueMap headers = new LinkedMultiValueMap<>(); + final MultiValueMap headers = new LinkedMultiValueMap<>(); headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE); - ClientCredentials credentials = sebClientConfigDAO + final ClientCredentials credentials = this.sebClientConfigDAO .getSebClientCredentials(config.getModelId()) .getOrThrow(); - CharSequence plainClientSecret = clientCredentialService.getPlainClientSecret(credentials); - String basicAuth = credentials.clientId + + final CharSequence plainClientSecret = this.clientCredentialService.getPlainClientSecret(credentials); + final String basicAuth = credentials.clientId + String.valueOf(Constants.COLON) + plainClientSecret; - String encoded = Base64.getEncoder() + final String encoded = Base64.getEncoder() .encodeToString(basicAuth.getBytes()); headers.add(HttpHeaders.AUTHORIZATION, "Basic " + encoded); - HttpEntity entity = new HttpEntity<>( + final HttpEntity entity = new HttpEntity<>( "grant_type=client_credentials&scope=read write", headers); - ResponseEntity exchange = restTemplate.exchange( + final ResponseEntity exchange = restTemplate.exchange( externalServerURL, HttpMethod.POST, entity, @@ -362,25 +357,12 @@ public class ClientConfigServiceImpl implements ClientConfigService { log.warn("Failed to check access SebClientConfig {} response: {}", config, exchange.getStatusCode()); return false; } - } catch (Exception e) { + } catch (final Exception e) { log.warn("Failed to check access for SebClientConfig: {} cause: {}", config, e.getMessage()); return false; } } - private void flushClientConfigData(final EntityKey key) { - try { - final String clientName = this.sebClientConfigDAO.getSebClientCredentials(key.modelId) - .getOrThrow() - .clientIdAsString(); - - final Collection tokensByClientId = this.tokenStore.findTokensByClientId(clientName); - tokensByClientId.forEach(this.tokenStore::removeAccessToken); - } catch (final Exception e) { - log.error("Unexpected error while trying to flush ClientConfig data for {}", key, e); - } - } - private void passwordEncryption( final OutputStream output, final CharSequence encryptionPassword, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/SebClientConfigController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/SebClientConfigController.java index 129085e8..f90ef1cb 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/SebClientConfigController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/SebClientConfigController.java @@ -8,6 +8,30 @@ package ch.ethz.seb.sebserver.webservice.weblayer.api; +import java.io.IOException; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.util.ArrayList; +import java.util.Collection; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.mybatis.dynamic.sql.SqlTable; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.APIMessage; @@ -25,29 +49,6 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.SebClientConfigDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ClientConfigService; import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.StringUtils; -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; -import org.mybatis.dynamic.sql.SqlTable; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.scheduling.annotation.EnableAsync; -import org.springframework.validation.FieldError; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.client.RestTemplate; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; -import java.util.ArrayList; -import java.util.Collection; @WebServiceProfile @RestController @@ -146,16 +147,16 @@ public class SebClientConfigController extends ActivatableEntityController notifySaved(SebClientConfig entity) { + protected Result notifySaved(final SebClientConfig entity) { if (entity.isActive()) { // try to get access token for SEB client - sebClientConfigService.checkAccess(entity); + this.sebClientConfigService.checkAccess(entity); } return super.notifySaved(entity); } private SebClientConfig checkPasswordMatch(final SebClientConfig entity) { - Collection errors = new ArrayList<>(); + final Collection errors = new ArrayList<>(); if (entity.hasEncryptionSecret() && !entity.encryptSecret.equals(entity.encryptSecretConfirm)) { errors.add(APIMessage.fieldValidationError( new FieldError( From 719aad380f51088a0c08ed1704144347c28f102f Mon Sep 17 00:00:00 2001 From: anhefti Date: Tue, 3 Mar 2020 16:25:05 +0100 Subject: [PATCH 5/6] prepared for version 0.6.2 --- pom.xml | 2 +- src/main/resources/config/application.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 77e9bb72..38d702a0 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ jar - 0.6.1 + 0.6.2 UTF-8 UTF-8 diff --git a/src/main/resources/config/application.properties b/src/main/resources/config/application.properties index fac4b640..2093a415 100644 --- a/src/main/resources/config/application.properties +++ b/src/main/resources/config/application.properties @@ -1,6 +1,6 @@ spring.application.name=SEB Server spring.profiles.active=dev -sebserver.version=0.6.1 (RC for v1.0) +sebserver.version=0.6.2 (RC for v1.0) ########################################################## ### Global Server Settings From ebe56c3af34659fbc66c7f37c4cc74fe4aa4522f Mon Sep 17 00:00:00 2001 From: anhefti Date: Wed, 4 Mar 2020 08:39:11 +0100 Subject: [PATCH 6/6] docs --- README.rst | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/README.rst b/README.rst index fda4782b..26fd9839 100644 --- a/README.rst +++ b/README.rst @@ -30,22 +30,12 @@ SEB Server provides a range of basic functionalities: - Automated SEB restriction on LMS side if the specified type of LMS supports the SEB restriction API - Monitoring and administration of SEB Client connections within a running exam -What is the SEB Server Setup repository? ----------------------------------------- - -The SEB Server Setup repository contains predefined, docker-based installation directories for different installation proposes like demo, testing or production. The repository is completely separated from the SEB Server source repository and contains only files for setup-configuration and installation of a SEB Server infrastructure. The idea is that this repository can be cloned from a Server/VM on that the SEB Server has to be installed. One can then navigate to the directory with the needed setup and adapt the configuration files if needed. Then just use Docker to build up the SEB Server. - Install SEB Server ------------------ For a complete guide to install SEB Server please go to `SEB Server Installation Guide `_ -Getting started with SEB Server -------------------------------- - -For a complete SEB Server user guide please go to `SEB Server User Guide `_ - Project Background ------------------ -TODO \ No newline at end of file +The SEB Server is currently build and maintained by the `Swiss MOOC Service `_ that is founded by leading Swiss universities EPFL, ETH, SUPSI, USI and HES-SO and is financially supported by the `Swissuniversities’ P5 program `_.