SEBSERV-72 implementation and config fixes

This commit is contained in:
anhefti 2019-10-17 16:53:33 +02:00
parent c96901472b
commit 2f29f14dc2
24 changed files with 606 additions and 135 deletions

View file

@ -11,7 +11,6 @@ package ch.ethz.seb.sebserver;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.net.HttpURLConnection;
import java.security.KeyManagementException; import java.security.KeyManagementException;
import java.security.KeyStoreException; import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@ -39,7 +38,6 @@ import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.ResourceUtils; import org.springframework.util.ResourceUtils;
@ -95,11 +93,18 @@ public class ClientHttpRequestFactoryService {
final HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); final HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setHttpClient(this.createProxiedClient(proxy, null)); factory.setHttpClient(this.createProxiedClient(proxy, null));
factory.setBufferRequestBody(false);
return factory; return factory;
} else { } else {
final DevClientHttpRequestFactory devClientHttpRequestFactory = new DevClientHttpRequestFactory(); final HttpComponentsClientHttpRequestFactory devClientHttpRequestFactory =
devClientHttpRequestFactory.setOutputStreaming(false); new HttpComponentsClientHttpRequestFactory();
devClientHttpRequestFactory.setBufferRequestBody(false);
// final HttpClient httpClient = devClientHttpRequestFactory.getHttpClient();
// httpClient.setInstanceFollowRedirects(false);
// httpClient.setOutputStreaming(false);
return devClientHttpRequestFactory; return devClientHttpRequestFactory;
} }
} }
@ -204,17 +209,17 @@ public class ClientHttpRequestFactoryService {
} }
// TODO set connection and read timeout!? configurable!? // TODO set connection and read timeout!? configurable!?
private static class DevClientHttpRequestFactory extends SimpleClientHttpRequestFactory { // private static class DevClientHttpRequestFactory extends HttpComponentsClientHttpRequestFactory {
//
@Override // @Override
protected void prepareConnection( // protected void prepareConnection(
final HttpURLConnection connection, // final HttpURLConnection connection,
final String httpMethod) throws IOException { // final String httpMethod) throws IOException {
//
super.prepareConnection(connection, httpMethod); // super.prepareConnection(connection, httpMethod);
super.setBufferRequestBody(false); // super.setBufferRequestBody(false);
connection.setInstanceFollowRedirects(false); // connection.setInstanceFollowRedirects(false);
} // }
} // }
} }

View file

@ -27,6 +27,7 @@ public final class API {
public static final String PARAM_ENTITY_TYPE = "entityType"; public static final String PARAM_ENTITY_TYPE = "entityType";
public static final String PARAM_BULK_ACTION_TYPE = "bulkActionType"; public static final String PARAM_BULK_ACTION_TYPE = "bulkActionType";
public static final String PARAM_CLIENT_CONFIG_SECRET = "client_config_secret"; public static final String PARAM_CLIENT_CONFIG_SECRET = "client_config_secret";
public static final String PARAM_VIEW_ID = "viewId";
public static final String DEFAULT_CONFIG_TEMPLATE_ID = String.valueOf(ConfigurationNode.DEFAULT_TEMPLATE_ID); public static final String DEFAULT_CONFIG_TEMPLATE_ID = String.valueOf(ConfigurationNode.DEFAULT_TEMPLATE_ID);
public static final String INSTITUTION_VAR_PATH_SEGMENT = "/{" + PARAM_INSTITUTION_ID + "}"; public static final String INSTITUTION_VAR_PATH_SEGMENT = "/{" + PARAM_INSTITUTION_ID + "}";
@ -128,6 +129,9 @@ public final class API {
public static final String IMPORT_FILE_ATTR_NAME = "importFile"; public static final String IMPORT_FILE_ATTR_NAME = "importFile";
public static final String TEMPLATE_ATTRIBUTE_ENDPOINT = "/template-attribute"; 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_DEFAUL_ORIENTATION = "attach-default-orientation";
public static final String ORIENTATION_ENDPOINT = "/orientation"; public static final String ORIENTATION_ENDPOINT = "/orientation";
public static final String VIEW_ENDPOINT = ORIENTATION_ENDPOINT + "/view"; public static final String VIEW_ENDPOINT = ORIENTATION_ENDPOINT + "/view";

View file

@ -23,6 +23,7 @@ import ch.ethz.seb.sebserver.gbl.model.Entity;
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class Orientation implements Entity { public final class Orientation implements Entity {
public static final String FILTER_ATTR_ATTRIBUTE_ID = "attributeId";
public static final String FILTER_ATTR_TEMPLATE_ID = "templateId"; public static final String FILTER_ATTR_TEMPLATE_ID = "templateId";
public static final String FILTER_ATTR_VIEW_ID = "viewId"; public static final String FILTER_ATTR_VIEW_ID = "viewId";
public static final String FILTER_ATTR_GROUP_ID = "groupId"; public static final String FILTER_ATTR_GROUP_ID = "groupId";

View file

@ -10,6 +10,9 @@ package ch.ethz.seb.sebserver.gui.content;
import java.util.Arrays; import java.util.Arrays;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Composite;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -36,13 +39,13 @@ import ch.ethz.seb.sebserver.gui.service.examconfig.impl.ViewContext;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.PageContext; import ch.ethz.seb.sebserver.gui.service.page.PageContext;
import ch.ethz.seb.sebserver.gui.service.page.PageService; import ch.ethz.seb.sebserver.gui.service.page.PageService;
import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer; import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetConfigurations; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetConfigurations;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetTemplateAttribute; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetTemplateAttribute;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser; import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
@Lazy @Lazy
@Component @Component
@ -142,10 +145,17 @@ public class ConfigTemplateAttributeForm implements TemplateComposer {
attribute.getGroupId())) attribute.getGroupId()))
.build(); .build();
widgetFactory.labelLocalizedTitle( widgetFactory.labelLocalized(
content, content,
CustomVariant.TEXT_H2,
FORM_VALUE_TEXT_KEY); FORM_VALUE_TEXT_KEY);
final Composite grid = new Composite(content, SWT.NONE);
grid.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
grid.setLayout(new GridLayout(6, true));
final PageContext valueContext = formContext.copyOf(grid);
final InputFieldBuilder inputFieldBuilder = this.examConfigurationService.getInputFieldBuilder( final InputFieldBuilder inputFieldBuilder = this.examConfigurationService.getInputFieldBuilder(
attribute.getConfigAttribute(), attribute.getConfigAttribute(),
attribute.getOrientation()); attribute.getOrientation());
@ -154,7 +164,7 @@ public class ConfigTemplateAttributeForm implements TemplateComposer {
.getOrThrow(); .getOrThrow();
final ViewContext viewContext = this.examConfigurationService.createViewContext( final ViewContext viewContext = this.examConfigurationService.createViewContext(
formContext, valueContext,
configuration, configuration,
new View(-1L, "template", 10, 0, templateId), new View(-1L, "template", 10, 0, templateId),
attributeMapping, attributeMapping,
@ -171,9 +181,7 @@ public class ConfigTemplateAttributeForm implements TemplateComposer {
configuration.id, configuration.id,
Arrays.asList(viewContext)); Arrays.asList(viewContext));
final PageActionBuilder pageActionBuilder = this.pageService this.pageService.pageActionBuilder(formContext.clearEntityKeys())
.pageActionBuilder(formContext.clearEntityKeys());
pageActionBuilder
.newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_FORM_SET_DEFAULT) .newAction(ActionDefinition.SEB_EXAM_CONFIG_TEMPLATE_ATTR_FORM_SET_DEFAULT)
.withEntityKey(attributeKey) .withEntityKey(attributeKey)

View file

@ -282,7 +282,7 @@ public class ConfigTemplateForm implements TemplateComposer {
final PageAction action, final PageAction action,
final EntityTable<TemplateAttribute> attrTable) { final EntityTable<TemplateAttribute> attrTable) {
final PageAction removeFormView = this.examConfigurationService.removeFormView(action); final PageAction removeFormView = this.examConfigurationService.removeFromView(action);
// reload the list // reload the list
attrTable.applyFilter(); attrTable.applyFilter();
return removeFormView; return removeFormView;

View file

@ -61,7 +61,9 @@ public interface ExamConfigurationService {
PageAction resetToDefaults(PageAction action); PageAction resetToDefaults(PageAction action);
PageAction removeFormView(PageAction action); PageAction removeFromView(PageAction action);
PageAction attachToDefaultView(final PageAction action);
static String attributeNameKey(final ConfigurationAttribute attribute) { static String attributeNameKey(final ConfigurationAttribute attribute) {
if (attribute == null) { if (attribute == null) {

View file

@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.gui.service.examconfig.impl;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.tomcat.util.buf.StringUtils; import org.apache.tomcat.util.buf.StringUtils;
@ -46,12 +47,16 @@ import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.FieldValidationError; import ch.ethz.seb.sebserver.gui.service.page.FieldValidationError;
import ch.ethz.seb.sebserver.gui.service.page.PageContext; import ch.ethz.seb.sebserver.gui.service.page.PageContext;
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction; 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.RestCallError;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; 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.GetConfigAttributes; 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.GetConfigurationValues;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetOrientations; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetOrientations;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetViewList; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetViewList;
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.SaveExamConfigTableValues; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfigTableValues;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfigValue; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfigValue;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
@ -213,21 +218,82 @@ public class ExamConfigurationServiceImpl implements ExamConfigurationService {
@Override @Override
public final PageAction resetToDefaults(final PageAction action) { public final PageAction resetToDefaults(final PageAction action) {
final EntityKey singleSelection = action.getSingleSelection(); final EntityKey parentEntityKey = action.pageContext().getParentEntityKey();
final Set<EntityKey> selection = action.getMultiSelection();
if (selection != null && !selection.isEmpty()) {
selection.stream().forEach(entityKey -> {
callTemplateAction(
ResetTemplateValues.class,
parentEntityKey.modelId,
entityKey.modelId);
});
} else {
final EntityKey entityKey = action.getEntityKey();
callTemplateAction(
ResetTemplateValues.class,
parentEntityKey.modelId,
entityKey.modelId);
}
// TODO
return action; return action;
} }
@Override @Override
public final PageAction removeFormView(final PageAction action) { public final PageAction removeFromView(final PageAction action) {
final EntityKey singleSelection = action.getSingleSelection(); final EntityKey parentEntityKey = action.pageContext().getParentEntityKey();
final Set<EntityKey> selection = action.getMultiSelection();
// TODO if (selection != null && !selection.isEmpty()) {
selection.stream().forEach(entityKey -> {
callTemplateAction(
RemoveOrientation.class,
parentEntityKey.modelId,
entityKey.modelId);
});
} else {
final EntityKey entityKey = action.getEntityKey();
callTemplateAction(
RemoveOrientation.class,
parentEntityKey.modelId,
entityKey.modelId);
}
return action; return action;
} }
@Override
public final PageAction attachToDefaultView(final PageAction action) {
final EntityKey parentEntityKey = action.pageContext().getParentEntityKey();
final Set<EntityKey> selection = action.getMultiSelection();
if (selection != null && !selection.isEmpty()) {
selection.stream().forEach(entityKey -> {
callTemplateAction(
AttchDefaultOrientation.class,
parentEntityKey.modelId,
entityKey.modelId);
});
} else {
final EntityKey entityKey = action.getEntityKey();
callTemplateAction(
AttchDefaultOrientation.class,
parentEntityKey.modelId,
entityKey.modelId);
}
return action;
}
private void callTemplateAction(
final Class<? extends RestCall<?>> actionType,
final String templateId,
final String attributeId) {
this.restService.getBuilder(actionType)
.withURIVariable(API.PARAM_PARENT_MODEL_ID, templateId)
.withURIVariable(API.PARAM_MODEL_ID, attributeId)
.call()
.getOrThrow();
}
private static final class ValueChangeListenerImpl implements ValueChangeListener { private static final class ValueChangeListenerImpl implements ValueChangeListener {
public static final String VALIDATION_ERROR_KEY_PREFIX = "sebserver.examconfig.props.validation."; public static final String VALIDATION_ERROR_KEY_PREFIX = "sebserver.examconfig.props.validation.";

View file

@ -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.gui.service.remote.webservice.api.seb.examconfig;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class AttchDefaultOrientation extends RestCall<TemplateAttribute> {
public AttchDefaultOrientation() {
super(new TypeKey<>(
CallType.SAVE,
EntityType.CONFIGURATION_NODE,
new TypeReference<TemplateAttribute>() {
}),
HttpMethod.PATCH,
MediaType.APPLICATION_FORM_URLENCODED,
API.CONFIGURATION_NODE_ENDPOINT
+ API.PARENT_MODEL_ID_VAR_PATH_SEGMENT
+ API.TEMPLATE_ATTRIBUTE_ENDPOINT
+ API.MODEL_ID_VAR_PATH_SEGMENT
+ API.TEMPLATE_ATTRIBUTE_ATTACH_DEFAUL_ORIENTATION);
}
}

View file

@ -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.gui.service.remote.webservice.api.seb.examconfig;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class RemoveOrientation extends RestCall<TemplateAttribute> {
public RemoveOrientation() {
super(new TypeKey<>(
CallType.SAVE,
EntityType.CONFIGURATION_NODE,
new TypeReference<TemplateAttribute>() {
}),
HttpMethod.PATCH,
MediaType.APPLICATION_FORM_URLENCODED,
API.CONFIGURATION_NODE_ENDPOINT
+ API.PARENT_MODEL_ID_VAR_PATH_SEGMENT
+ API.TEMPLATE_ATTRIBUTE_ENDPOINT
+ API.MODEL_ID_VAR_PATH_SEGMENT
+ API.TEMPLATE_ATTRIBUTE_REMOVE_ORIENTATION);
}
}

View file

@ -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.gui.service.remote.webservice.api.seb.examconfig;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class ResetTemplateValues extends RestCall<TemplateAttribute> {
public ResetTemplateValues() {
super(new TypeKey<>(
CallType.SAVE,
EntityType.CONFIGURATION_NODE,
new TypeReference<TemplateAttribute>() {
}),
HttpMethod.PATCH,
MediaType.APPLICATION_FORM_URLENCODED,
API.CONFIGURATION_NODE_ENDPOINT
+ API.PARENT_MODEL_ID_VAR_PATH_SEGMENT
+ API.TEMPLATE_ATTRIBUTE_ENDPOINT
+ API.MODEL_ID_VAR_PATH_SEGMENT
+ API.TEMPLATE_ATTRIBUTE_RESET_VALUES);
}
}

View file

@ -36,6 +36,7 @@ public class WebserviceInfo {
private static final String WEB_SERVICE_TEST_PROPERTY = "sebserver.test.property"; private static final String WEB_SERVICE_TEST_PROPERTY = "sebserver.test.property";
private static final String WEB_SERVICE_SERVER_NAME_KEY = "sebserver.webservice.http.server.name"; private static final String WEB_SERVICE_SERVER_NAME_KEY = "sebserver.webservice.http.server.name";
private static final String WEB_SERVICE_HTTP_SCHEME_KEY = "sebserver.webservice.http.scheme"; private static final String WEB_SERVICE_HTTP_SCHEME_KEY = "sebserver.webservice.http.scheme";
private static final String WEB_SERVICE_HTTP_PORT = "sebserver.webservice.http.port";
private static final String WEB_SERVICE_HOST_ADDRESS_KEY = "server.address"; private static final String WEB_SERVICE_HOST_ADDRESS_KEY = "server.address";
private static final String WEB_SERVICE_SERVER_PORT_KEY = "server.port"; private static final String WEB_SERVICE_SERVER_PORT_KEY = "server.port";
private static final String WEB_SERVICE_EXAM_API_DISCOVERY_ENDPOINT_KEY = private static final String WEB_SERVICE_EXAM_API_DISCOVERY_ENDPOINT_KEY =
@ -45,8 +46,9 @@ public class WebserviceInfo {
private final String testProperty; private final String testProperty;
private final String httpScheme; private final String httpScheme;
private final String hostAddress; // internal private final String hostAddress; // internal
private final String serverName; // external private final String webserverName; // external
private final String serverPort; private final String serverPort; // internal
private final String webserverPort; // external
private final String discoveryEndpoint; private final String discoveryEndpoint;
private final String serverURLPrefix; private final String serverURLPrefix;
@ -58,17 +60,21 @@ public class WebserviceInfo {
this.testProperty = environment.getProperty(WEB_SERVICE_TEST_PROPERTY, "NOT_AVAILABLE"); this.testProperty = environment.getProperty(WEB_SERVICE_TEST_PROPERTY, "NOT_AVAILABLE");
this.httpScheme = environment.getRequiredProperty(WEB_SERVICE_HTTP_SCHEME_KEY); this.httpScheme = environment.getRequiredProperty(WEB_SERVICE_HTTP_SCHEME_KEY);
this.hostAddress = environment.getRequiredProperty(WEB_SERVICE_HOST_ADDRESS_KEY); this.hostAddress = environment.getRequiredProperty(WEB_SERVICE_HOST_ADDRESS_KEY);
this.serverName = environment.getProperty(WEB_SERVICE_SERVER_NAME_KEY, ""); this.webserverName = environment.getProperty(WEB_SERVICE_SERVER_NAME_KEY, "");
this.serverPort = environment.getRequiredProperty(WEB_SERVICE_SERVER_PORT_KEY); this.serverPort = environment.getRequiredProperty(WEB_SERVICE_SERVER_PORT_KEY);
this.webserverPort = environment.getProperty(WEB_SERVICE_HTTP_PORT);
this.discoveryEndpoint = environment.getRequiredProperty(WEB_SERVICE_EXAM_API_DISCOVERY_ENDPOINT_KEY); this.discoveryEndpoint = environment.getRequiredProperty(WEB_SERVICE_EXAM_API_DISCOVERY_ENDPOINT_KEY);
this.serverURLPrefix = UriComponentsBuilder.newInstance() final UriComponentsBuilder builder = UriComponentsBuilder.newInstance()
.scheme(this.httpScheme) .scheme(this.httpScheme)
.host((StringUtils.isNotBlank(this.serverName)) .host((StringUtils.isNotBlank(this.webserverName))
? this.serverName ? this.webserverName
: this.hostAddress) : this.hostAddress);
.port(this.serverPort) if (StringUtils.isNotBlank(this.webserverPort)) {
.toUriString(); builder.port(this.webserverPort);
}
this.serverURLPrefix = builder.toUriString();
this.isDistributed = BooleanUtils.toBoolean(environment.getProperty( this.isDistributed = BooleanUtils.toBoolean(environment.getProperty(
"sebserver.webservice.distributed", "sebserver.webservice.distributed",
@ -106,14 +112,18 @@ public class WebserviceInfo {
return this.hostAddress; return this.hostAddress;
} }
public String getServerName() { public String getWebserviceDomainName() {
return this.serverName; return this.webserverName;
} }
public String getServerPort() { public String getServerPort() {
return this.serverPort; return this.serverPort;
} }
public String getServerExternalPort() {
return this.webserverPort;
}
public String getDiscoveryEndpoint() { public String getDiscoveryEndpoint() {
return this.discoveryEndpoint; return this.discoveryEndpoint;
} }
@ -183,18 +193,20 @@ public class WebserviceInfo {
builder.append(this.httpScheme); builder.append(this.httpScheme);
builder.append(", hostAddress="); builder.append(", hostAddress=");
builder.append(this.hostAddress); builder.append(this.hostAddress);
builder.append(", serverName="); builder.append(", webserverName=");
builder.append(this.serverName); builder.append(this.webserverName);
builder.append(", serverPort="); builder.append(", serverPort=");
builder.append(this.serverPort); builder.append(this.serverPort);
builder.append(", webserverPort=");
builder.append(this.webserverPort);
builder.append(", discoveryEndpoint="); builder.append(", discoveryEndpoint=");
builder.append(this.discoveryEndpoint); builder.append(this.discoveryEndpoint);
builder.append(", externalAddressAlias=");
builder.append(this.externalAddressAlias);
builder.append(", serverURLPrefix="); builder.append(", serverURLPrefix=");
builder.append(this.serverURLPrefix); builder.append(this.serverURLPrefix);
builder.append(", isDistributed="); builder.append(", isDistributed=");
builder.append(this.isDistributed); builder.append(this.isDistributed);
builder.append(", externalAddressAlias=");
builder.append(this.externalAddressAlias);
builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
} }

View file

@ -8,6 +8,8 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.dao; package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
import java.util.Arrays;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
@ -119,6 +121,10 @@ public class FilterMap extends POSTMapper {
return getLong(Orientation.FILTER_ATTR_TEMPLATE_ID); return getLong(Orientation.FILTER_ATTR_TEMPLATE_ID);
} }
public Long getOrientationAttributeId() {
return getLong(Orientation.FILTER_ATTR_ATTRIBUTE_ID);
}
public Long getOrientationViewId() { public Long getOrientationViewId() {
return getLong(Orientation.FILTER_ATTR_VIEW_ID); return getLong(Orientation.FILTER_ATTR_VIEW_ID);
} }
@ -284,4 +290,23 @@ public class FilterMap extends POSTMapper {
return null; return null;
} }
public static final class Builder {
private final FilterMap filterMap = new FilterMap();
public Builder add(final String name, final String value) {
this.filterMap.params.add(name, value);
return this;
}
public Builder put(final String name, final String value) {
this.filterMap.params.put(name, Arrays.asList(value));
return this;
}
public FilterMap create() {
return new FilterMap(this.filterMap.params);
}
}
} }

View file

@ -8,6 +8,7 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.dao; package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
import java.util.List;
import java.util.Map; import java.util.Map;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
@ -18,4 +19,8 @@ public interface ViewDAO extends EntityDAO<View, View> {
Result<Map<Long, Long>> copyDefaultViewsForTemplate(ConfigurationNode node); Result<Map<Long, Long>> copyDefaultViewsForTemplate(ConfigurationNode node);
Result<List<View>> getDefaultTemplateViews();
Result<View> getDefaultViewForTemplate(Long templateId, Long defaultViewId);
} }

View file

@ -91,6 +91,9 @@ public class OrientationDAOImpl implements OrientationDAO {
.where( .where(
OrientationRecordDynamicSqlSupport.templateId, OrientationRecordDynamicSqlSupport.templateId,
SqlBuilder.isEqualToWhenPresent(filterMap.getOrientationTemplateId())) SqlBuilder.isEqualToWhenPresent(filterMap.getOrientationTemplateId()))
.and(
OrientationRecordDynamicSqlSupport.configAttributeId,
SqlBuilder.isEqualToWhenPresent(filterMap.getOrientationAttributeId()))
.and( .and(
OrientationRecordDynamicSqlSupport.viewId, OrientationRecordDynamicSqlSupport.viewId,
SqlBuilder.isEqualToWhenPresent(filterMap.getOrientationViewId())) SqlBuilder.isEqualToWhenPresent(filterMap.getOrientationViewId()))

View file

@ -100,6 +100,47 @@ public class ViewDAOImpl implements ViewDAO {
.collect(Collectors.toList())); .collect(Collectors.toList()));
} }
@Override
@Transactional(readOnly = true)
public Result<List<View>> getDefaultTemplateViews() {
return Result.tryCatch(() -> this.viewRecordMapper
.selectByExample()
.where(
ViewRecordDynamicSqlSupport.templateId,
SqlBuilder.isEqualTo(ConfigurationNode.DEFAULT_TEMPLATE_ID))
.build()
.execute()
.stream()
.map(ViewDAOImpl::toDomainModel)
.flatMap(DAOLoggingSupport::logAndSkipOnError)
.collect(Collectors.toList()));
}
@Override
@Transactional(readOnly = true)
public Result<View> getDefaultViewForTemplate(final Long templateId, final Long defaultViewId) {
return Result.tryCatch(() -> {
// get all views of template
final List<ViewRecord> templateViews = this.viewRecordMapper
.selectByExample()
.where(
ViewRecordDynamicSqlSupport.templateId,
SqlBuilder.isEqualTo(templateId))
.build()
.execute();
// get default view
final ViewRecord defView = this.viewRecordMapper.selectByPrimaryKey(defaultViewId);
final ViewRecord result = templateViews
.stream()
.filter(view -> view.getName().equals(defView.getName()))
.findFirst()
.orElseThrow();
return result;
})
.flatMap(ViewDAOImpl::toDomainModel);
}
@Override @Override
@Transactional @Transactional
public Result<View> createNew(final View data) { public Result<View> createNew(final View data) {

View file

@ -9,9 +9,7 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig; package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig;
import java.util.List; import java.util.List;
import java.util.Set;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute; import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
@ -29,9 +27,20 @@ public interface SebExamConfigTemplateService {
final Long templateId, final Long templateId,
final Long attributeId); final Long attributeId);
Result<Set<EntityKey>> setDefaultValues( Result<TemplateAttribute> setDefaultValues(
final Long institutionId, final Long institutionId,
final Long templateId, final Long templateId,
final Long attributeId); final Long attributeId);
Result<TemplateAttribute> removeOrientation(
final Long institutionId,
final Long templateId,
final Long attributeId);
Result<TemplateAttribute> attachDefaultOrientation(
final Long institutionId,
final Long templateId,
final Long attributeId,
Long viewId);
} }

View file

@ -8,33 +8,34 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl; package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.PageSortOrder; import ch.ethz.seb.sebserver.gbl.model.PageSortOrder;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute; import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationAttributeDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationAttributeDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationNodeDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationValueDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationValueDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.OrientationDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.OrientationDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ViewDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ViewDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebExamConfigService;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebExamConfigTemplateService; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebExamConfigTemplateService;
@Lazy @Lazy
@ -42,28 +43,26 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebExamConfigTemp
@WebServiceProfile @WebServiceProfile
public class SebExamConfigTemplateServiceImpl implements SebExamConfigTemplateService { public class SebExamConfigTemplateServiceImpl implements SebExamConfigTemplateService {
private final ConfigurationNodeDAO ConfigurationNodeDAO; private static final Logger log = LoggerFactory.getLogger(SebExamConfigTemplateServiceImpl.class);
private final ConfigurationDAO configurationDAO;
private final ViewDAO viewDAO; private final ViewDAO viewDAO;
private final ConfigurationDAO configurationDAO;
private final OrientationDAO orientationDAO; private final OrientationDAO orientationDAO;
private final ConfigurationAttributeDAO configurationAttributeDAO; private final ConfigurationAttributeDAO configurationAttributeDAO;
private final ConfigurationValueDAO configurationValueDAO; private final ConfigurationValueDAO configurationValueDAO;
private final SebExamConfigService sebExamConfigService;
protected SebExamConfigTemplateServiceImpl( protected SebExamConfigTemplateServiceImpl(
final ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationNodeDAO configurationNodeDAO, final ViewDAO viewDAO,
final ConfigurationDAO configurationDAO, final ViewDAO viewDAO, final OrientationDAO orientationDAO, final ConfigurationDAO configurationDAO,
final OrientationDAO orientationDAO,
final ConfigurationAttributeDAO configurationAttributeDAO, final ConfigurationAttributeDAO configurationAttributeDAO,
final ConfigurationValueDAO configurationValueDAO, final ConfigurationValueDAO configurationValueDAO) {
final SebExamConfigService sebExamConfigService) {
super();
this.ConfigurationNodeDAO = configurationNodeDAO;
this.configurationDAO = configurationDAO;
this.viewDAO = viewDAO; this.viewDAO = viewDAO;
this.configurationDAO = configurationDAO;
this.orientationDAO = orientationDAO; this.orientationDAO = orientationDAO;
this.configurationAttributeDAO = configurationAttributeDAO; this.configurationAttributeDAO = configurationAttributeDAO;
this.configurationValueDAO = configurationValueDAO; this.configurationValueDAO = configurationValueDAO;
this.sebExamConfigService = sebExamConfigService;
} }
@Override @Override
@ -127,7 +126,7 @@ public class SebExamConfigTemplateServiceImpl implements SebExamConfigTemplateSe
} }
@Override @Override
public Result<Set<EntityKey>> setDefaultValues( public Result<TemplateAttribute> setDefaultValues(
final Long institutionId, final Long institutionId,
final Long templateId, final Long templateId,
final Long attributeId) { final Long attributeId) {
@ -137,7 +136,102 @@ public class SebExamConfigTemplateServiceImpl implements SebExamConfigTemplateSe
.setDefaultValues( .setDefaultValues(
institutionId, institutionId,
config.id, config.id,
attributeId))
.flatMap(vals -> getAttribute(
institutionId,
templateId,
attributeId)); attributeId));
} }
@Override
public Result<TemplateAttribute> removeOrientation(
final Long institutionId,
final Long templateId,
final Long attributeId) {
return Result.tryCatch(() -> {
final Orientation orientation = getOrientation(templateId, attributeId);
this.orientationDAO.delete(new HashSet<>(Arrays.asList(orientation.getEntityKey())))
.getOrThrow();
final TemplateAttribute attribute = getAttribute(institutionId, templateId, attributeId)
.getOrThrow();
if (attribute.getOrientation() != null) {
throw new IllegalStateException(
"Failed to remove Orientation, expecting no Orientatoin for attribute: " + attribute);
}
return attribute;
});
}
@Override
public Result<TemplateAttribute> attachDefaultOrientation(
final Long institutionId,
final Long templateId,
final Long attributeId,
final Long viewId) {
return Result.tryCatch(() -> {
final Orientation orientation = getOrientation(templateId, attributeId);
final Orientation devOrientation = getOrientation(ConfigurationNode.DEFAULT_TEMPLATE_ID, attributeId);
if (orientation != null) {
this.orientationDAO.delete(new HashSet<>(Arrays.asList(orientation.getEntityKey())))
.getOrThrow();
}
final Long _viewId;
if (viewId == null) {
_viewId = this.viewDAO.getDefaultViewForTemplate(templateId, devOrientation.viewId)
.getOrThrow().id;
} else {
_viewId = viewId;
}
final Orientation newOrientation = new Orientation(
null,
attributeId,
templateId,
_viewId,
devOrientation.groupId,
devOrientation.xPosition,
devOrientation.yPosition,
devOrientation.width,
devOrientation.height,
devOrientation.title);
this.orientationDAO.save(newOrientation)
.getOrThrow();
final TemplateAttribute attribute = getAttribute(institutionId, templateId, attributeId)
.getOrThrow();
if (attribute.getOrientation() == null) {
throw new IllegalStateException(
"Failed to attach default Orientation, expecting Orientatoin for attribute: " + attribute);
}
return attribute;
});
}
private Orientation getOrientation(final Long templateId, final Long attributeId) {
final FilterMap filterMap = new FilterMap.Builder()
.put(Orientation.FILTER_ATTR_TEMPLATE_ID, String.valueOf(templateId))
.put(Orientation.FILTER_ATTR_ATTRIBUTE_ID, String.valueOf(attributeId))
.create();
return this.orientationDAO.allMatching(filterMap)
.get(error -> {
log.warn("Unexpecrted error while get Orientation: ", error);
return Collections.emptyList();
})
.stream()
.findFirst()
.orElse(null);
}
} }

View file

@ -14,6 +14,7 @@ import java.util.UUID;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.boot.logging.LogLevel;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -31,6 +32,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.PingHandlingStrategy; import ch.ethz.seb.sebserver.webservice.servicelayer.session.PingHandlingStrategy;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SebClientConnectionService; import ch.ethz.seb.sebserver.webservice.servicelayer.session.SebClientConnectionService;
import ch.ethz.seb.sebserver.webservice.weblayer.api.APIConstraintViolationException; import ch.ethz.seb.sebserver.webservice.weblayer.api.APIConstraintViolationException;
import ch.ethz.seb.sebserver.webservice.weblayer.api.OnlyMessageLogExceptionWrapper;
@Lazy @Lazy
@Service @Service
@ -392,7 +394,9 @@ public class SebClientConnectionServiceImpl implements SebClientConnectionServic
if (activeClientConnection != null) { if (activeClientConnection != null) {
if (activeClientConnection.clientConnection.status != ConnectionStatus.ESTABLISHED) { if (activeClientConnection.clientConnection.status != ConnectionStatus.ESTABLISHED) {
throw new IllegalStateException("No established SEB client connection"); throw new OnlyMessageLogExceptionWrapper(
new IllegalStateException("No established SEB client connection"),
LogLevel.WARN);
} }
// store event // store event
@ -404,6 +408,8 @@ public class SebClientConnectionServiceImpl implements SebClientConnectionServic
activeClientConnection.getindicatorMapping(event.eventType) activeClientConnection.getindicatorMapping(event.eventType)
.stream() .stream()
.forEach(indicator -> indicator.notifyValueChange(event)); .forEach(indicator -> indicator.notifyValueChange(event));
} else {
log.warn("No active ClientConnection found for connectionToken: {}", connectionToken);
} }
} }

View file

@ -53,6 +53,9 @@ public class APIExceptionHandler extends ResponseEntityExceptionHandler {
if (ex instanceof AccessDeniedException) { if (ex instanceof AccessDeniedException) {
log.warn("Access denied: ", ex); log.warn("Access denied: ", ex);
} else if (ex instanceof OnlyMessageLogExceptionWrapper) {
((OnlyMessageLogExceptionWrapper) ex).log(log);
return new ResponseEntity<>(status);
} else { } else {
log.error("Unexpected generic error catched at the API endpoint: ", ex); log.error("Unexpected generic error catched at the API endpoint: ", ex);
} }
@ -83,6 +86,15 @@ public class APIExceptionHandler extends ResponseEntityExceptionHandler {
HttpStatus.BAD_REQUEST); HttpStatus.BAD_REQUEST);
} }
@ExceptionHandler(OnlyMessageLogExceptionWrapper.class)
public ResponseEntity<Object> onlyMessageLogExceptionWrapper(
final OnlyMessageLogExceptionWrapper ex,
final WebRequest request) {
ex.log(log);
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(OAuth2Exception.class) @ExceptionHandler(OAuth2Exception.class)
public ResponseEntity<Object> handleOAuth2Exception( public ResponseEntity<Object> handleOAuth2Exception(
final OAuth2Exception ex, final OAuth2Exception ex,

View file

@ -13,7 +13,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Set;
import javax.servlet.ServletOutputStream; import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -39,13 +38,13 @@ import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.api.POSTMapper; import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType; import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM; import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.Page; import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigKey; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigKey;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute; import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute;
import ch.ethz.seb.sebserver.gbl.model.user.UserLogActivityType;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.gbl.util.Utils;
@ -305,11 +304,12 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
@RequestMapping( @RequestMapping(
path = API.PARENT_MODEL_ID_VAR_PATH_SEGMENT path = API.PARENT_MODEL_ID_VAR_PATH_SEGMENT
+ API.TEMPLATE_ATTRIBUTE_ENDPOINT + API.TEMPLATE_ATTRIBUTE_ENDPOINT
+ API.MODEL_ID_VAR_PATH_SEGMENT, + API.MODEL_ID_VAR_PATH_SEGMENT
method = RequestMethod.POST, + API.TEMPLATE_ATTRIBUTE_RESET_VALUES,
method = RequestMethod.PATCH,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE) produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Set<EntityKey> resetTemplateAttribute( public TemplateAttribute resetTemplateAttributeValues(
@PathVariable(name = API.PARAM_PARENT_MODEL_ID, required = true) final Long parentModelId, @PathVariable(name = API.PARAM_PARENT_MODEL_ID, required = true) final Long parentModelId,
@PathVariable(name = API.PARAM_MODEL_ID, required = true) final Long modelId, @PathVariable(name = API.PARAM_MODEL_ID, required = true) final Long modelId,
@RequestParam( @RequestParam(
@ -323,6 +323,62 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
institutionId, institutionId,
parentModelId, parentModelId,
modelId) modelId)
.flatMap(entity -> this.userActivityLogDAO.log(UserLogActivityType.MODIFY, entity))
.getOrThrow();
}
@RequestMapping(
path = API.PARENT_MODEL_ID_VAR_PATH_SEGMENT
+ API.TEMPLATE_ATTRIBUTE_ENDPOINT
+ API.MODEL_ID_VAR_PATH_SEGMENT
+ API.TEMPLATE_ATTRIBUTE_ATTACH_DEFAUL_ORIENTATION,
method = RequestMethod.PATCH,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public TemplateAttribute attachDefaultTemplateAttributeOrientation(
@PathVariable(name = API.PARAM_PARENT_MODEL_ID, required = true) final Long parentModelId,
@PathVariable(name = API.PARAM_MODEL_ID, required = true) final Long modelId,
@RequestParam(
name = API.PARAM_INSTITUTION_ID,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@RequestParam(name = API.PARAM_VIEW_ID) final Long viewId) {
checkModifyPrivilege(institutionId);
return this.sebExamConfigTemplateService
.attachDefaultOrientation(
institutionId,
parentModelId,
modelId,
viewId)
.flatMap(entity -> this.userActivityLogDAO.log(UserLogActivityType.MODIFY, entity))
.getOrThrow();
}
@RequestMapping(
path = API.PARENT_MODEL_ID_VAR_PATH_SEGMENT
+ API.TEMPLATE_ATTRIBUTE_ENDPOINT
+ API.MODEL_ID_VAR_PATH_SEGMENT
+ API.TEMPLATE_ATTRIBUTE_REMOVE_ORIENTATION,
method = RequestMethod.PATCH,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public TemplateAttribute removeTemplateAttributeOrientation(
@PathVariable(name = API.PARAM_PARENT_MODEL_ID, required = true) final Long parentModelId,
@PathVariable(name = API.PARAM_MODEL_ID, required = true) final Long modelId,
@RequestParam(
name = API.PARAM_INSTITUTION_ID,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId) {
checkModifyPrivilege(institutionId);
return this.sebExamConfigTemplateService
.removeOrientation(
institutionId,
parentModelId,
modelId)
.flatMap(entity -> this.userActivityLogDAO.log(UserLogActivityType.MODIFY, entity))
.getOrThrow(); .getOrThrow();
} }

View file

@ -326,7 +326,8 @@ public class ExamAPI_V1_Controller {
@RequestHeader(name = API.EXAM_API_SEB_CONNECTION_TOKEN, required = true) final String connectionToken, @RequestHeader(name = API.EXAM_API_SEB_CONNECTION_TOKEN, required = true) final String connectionToken,
@RequestBody(required = true) final ClientEvent event) { @RequestBody(required = true) final ClientEvent event) {
this.sebClientConnectionService.notifyClientEvent(connectionToken, event); this.sebClientConnectionService
.notifyClientEvent(connectionToken, event);
} }
private Long getInstitutionId(final Principal principal) { private Long getInstitutionId(final Principal principal) {

View file

@ -0,0 +1,51 @@
/*
* 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.webservice.weblayer.api;
import org.slf4j.Logger;
import org.springframework.boot.logging.LogLevel;
public class OnlyMessageLogExceptionWrapper extends RuntimeException {
private static final long serialVersionUID = 4177915563660228494L;
public final LogLevel logLevel;
public OnlyMessageLogExceptionWrapper(final Exception cause) {
super(cause);
this.logLevel = LogLevel.WARN;
}
public OnlyMessageLogExceptionWrapper(final Exception cause, final LogLevel logLevel) {
super(cause);
this.logLevel = logLevel;
}
public final void log(final Logger logger) {
final String message = this.getCause().getMessage();
switch (this.logLevel) {
case ERROR:
case FATAL:
logger.error(message);
break;
case INFO:
logger.info(message);
break;
case TRACE:
logger.trace(message);
break;
case WARN:
logger.warn(message);
break;
default:
logger.debug(message);
break;
}
}
}

View file

@ -1,62 +0,0 @@
# overall server configuration
server.address=0.0.0.0
server.port=8080
server.servlet.context-path=/
server.servlet.session.cookie.http-only=true
server.servlet.session.tracking-modes=cookie
# database server
datastore.mariadb.server.address=seb-server-mariadb
datastore.mariadb.server.port=3306
# data source configuration
spring.datasource.username=root
spring.datasource.initialize=true
spring.datasource.initialization-mode=always
spring.datasource.url=jdbc:mariadb://${datastore.mariadb.server.address}:${datastore.mariadb.server.port}/SEBServer?useSSL=false&createDatabaseIfNotExist=true
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.platform=demo
spring.datasource.hikari.initializationFailTimeout=30000
spring.datasource.hikari.connectionTimeout=30000
spring.datasource.hikari.idleTimeout=600000
spring.datasource.hikari.maxLifetime=1800000
# webservice configuration
sebserver.test.property=DEMO SOURCE CONFIG
sebserver.webservice.distributed=false
sebserver.webservice.http.scheme=http
sebserver.webservice.http.server.name=ralph.ethz.ch
sebserver.webservice.http.redirect.gui=${sebserver.gui.entrypoint}
sebserver.webservice.api.admin.clientId=guiClient
sebserver.webservice.api.admin.endpoint=/admin-api/v1
sebserver.webservice.api.admin.accessTokenValiditySeconds=3600
sebserver.webservice.api.admin.refreshTokenValiditySeconds=-1
sebserver.webservice.api.exam.endpoint=/exam-api
sebserver.webservice.api.exam.endpoint.discovery=${sebserver.webservice.api.exam.endpoint}/discovery
sebserver.webservice.api.exam.endpoint.v1=${sebserver.webservice.api.exam.endpoint}/v1
sebserver.webservice.api.exam.accessTokenValiditySeconds=86400
sebserver.webservice.api.pagination.maxPageSize=500
# comma separated list of known possible OpenEdX API access token request endpoints
sebserver.webservice.lms.openedx.api.token.request.paths=/oauth2/access_token
# write logs to
logging.file=log/sebserver.log
# actuator configuration
management.endpoints.web.base-path=/actuator
management.endpoints.web.exposure.include=logfile,loggers
# GUI server configuration
sebserver.gui.entrypoint=/gui
sebserver.gui.webservice.protocol=http
sebserver.gui.webservice.address=${server.address}
sebserver.gui.webservice.port=8080
sebserver.gui.webservice.apipath=/admin-api/v1
sebserver.gui.theme=css/sebserver.css
sebserver.gui.list.page.size=20
sebserver.gui.date.displayformat=MM/dd/yyyy HH:mm
sebserver.gui.date.displayformat.timezone=|ZZ
sebserver.gui.multilingual=false
sebserver.gui.languages=en
sebserver.gui.seb.client.config.download.filename=SEBClientSettings.seb
sebserver.gui.seb.exam.config.download.filename=SEBExamSettings.seb

View file

@ -22,7 +22,7 @@ spring.quartz.properties.org.quartz.threadPool.threadCount=2
sebserver.webservice.distributed=false sebserver.webservice.distributed=false
sebserver.webservice.http.scheme=http sebserver.webservice.http.scheme=http
sebserver.webservice.http.server.name=${server.address} sebserver.webservice.http.server.name=${server.address}
sebserver.webservice.http.port=${server.port}
sebserver.webservice.http.redirect.gui=/gui sebserver.webservice.http.redirect.gui=/gui
sebserver.webservice.api.admin.endpoint=/admin-api/v1 sebserver.webservice.api.admin.endpoint=/admin-api/v1
sebserver.webservice.api.admin.accessTokenValiditySeconds=3600 sebserver.webservice.api.admin.accessTokenValiditySeconds=3600