Merge remote-tracking branch 'origin/master'

This commit is contained in:
anhefti 2020-03-04 09:47:08 +01:00
commit b9153ab223
14 changed files with 234 additions and 171 deletions

View file

@ -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 <https://seb-server-setup.readthedocs.io/en/latest/overview.html>`_
Getting started with SEB Server
-------------------------------
For a complete SEB Server user guide please go to `SEB Server User Guide <https://seb-server.readthedocs.io/en/latest/#>`_
Project Background
------------------
TODO
The SEB Server is currently build and maintained by the `Swiss MOOC Service <https://www.swissmooc.ch/>`_ that is founded by leading Swiss universities EPFL, ETH, SUPSI, USI and HES-SO and is financially supported by the `Swissuniversities P5 program <https://www.swissuniversities.ch/themen/digitalisierung/p-5-wissenschaftliche-information>`_.

View file

@ -18,7 +18,7 @@
<packaging>jar</packaging>
<properties>
<sebserver-version>0.6.1</sebserver-version>
<sebserver-version>0.6.2</sebserver-version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

View file

@ -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";

View file

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

View file

@ -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<Set<EntityKey>>.RestCallBuilder builder =
restService.getBuilder(
restService.<Set<EntityKey>> getBuilder(
entity.entityType(),
CallType.GET_DEPENDENCIES);
@ -254,7 +254,7 @@ public class PageServiceImpl implements PageService {
public <T extends Entity & Activatable> Function<PageAction, PageAction> activationToggleActionFunction(
final EntityTable<T> table,
final LocTextKey noSelectionText,
Function<PageAction, PageAction> testBeforeActivation) {
final Function<PageAction, PageAction> testBeforeActivation) {
return action -> {
final Set<T> selectedROWData = table.getSelectedROWData();
@ -269,7 +269,7 @@ public class PageServiceImpl implements PageService {
for (final T entity : selectedROWData) {
if (!entity.isActive()) {
RestCall<T>.RestCallBuilder restCallBuilder = restService.<T>getBuilder(
final RestCall<T>.RestCallBuilder restCallBuilder = restService.<T> 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.<T>getBuilder(entityType, CallType.ACTIVATION_DEACTIVATE)
restService.<T> 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

View file

@ -24,9 +24,9 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy
@Component
@GuiProfile
public class AttchDefaultOrientation extends RestCall<TemplateAttribute> {
public class AttachDefaultOrientation extends RestCall<TemplateAttribute> {
public AttchDefaultOrientation() {
public AttachDefaultOrientation() {
super(new TypeKey<>(
CallType.SAVE,
EntityType.CONFIGURATION_NODE,

View file

@ -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<String> SUPPORTED_IMAGE_FILES = Set.of(".png", ".jpg", ".jpeg");
public static final Set<String> SUPPORTED_IMAGE_FILES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
".png",
".jpg",
".jpeg")));
private final ServerPushService serverPushService;

View file

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

View file

@ -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 =
" <dict>\r\n" +
" <key>sebMode</key>\r\n" +
" <integer>1</integer>\r\n" +
" <key>sebConfigPurpose</key>\r\n" +
" <integer>%s</integer>\r\n" +
" <key>sebServerFallback</key>\r\n" +
" <%s />\r\n" +
"%s" +
" <key>sebServerURL</key>\r\n" +
" <string>%s</string>\r\n" +
" <key>sebServerConfiguration</key>\r\n" +
" <dict>\r\n" +
" <key>institution</key>\r\n" +
" <string>%s</string>\r\n" +
" <key>clientName</key>\r\n" +
" <string>%s</string>\r\n" +
" <key>clientSecret</key>\r\n" +
" <string>%s</string>\r\n" +
" <key>apiDiscovery</key>\r\n" +
" <string>%s</string>\r\n" +
" </dict>\r\n" +
" </dict>\r\n";
" <key>sebMode</key>\r\n" +
" <integer>1</integer>\r\n" +
" <key>sebConfigPurpose</key>\r\n" +
" <integer>%s</integer>\r\n" +
" <key>sebServerFallback</key>\r\n" +
" <%s />\r\n" +
"%s" +
" <key>sebServerURL</key>\r\n" +
" <string>%s</string>\r\n" +
" <key>sebServerConfiguration</key>\r\n" +
" <dict>\r\n" +
" <key>institution</key>\r\n" +
" <string>%s</string>\r\n" +
" <key>clientName</key>\r\n" +
" <string>%s</string>\r\n" +
" <key>clientSecret</key>\r\n" +
" <string>%s</string>\r\n" +
" <key>apiDiscovery</key>\r\n" +
" <string>%s</string>\r\n" +
" </dict>\r\n" +
" </dict>\r\n";
private final static String SEB_CLIENT_CONFIG_INTEGER_TEMPLATE =
" <key>%s</key>\r\n" +
" <integer>%s</integer>\r\n";
" <integer>%s</integer>\r\n";
private final static String SEB_CLIENT_CONFIG_STRING_TEMPLATE =
" <key>%s</key>\r\n" +
" <string>%s</string>\r\n";
" <string>%s</string>\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<String, String> headers = new LinkedMultiValueMap<>();
final MultiValueMap<String, String> 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<String> entity = new HttpEntity<>(
final HttpEntity<String> entity = new HttpEntity<>(
"grant_type=client_credentials&scope=read write",
headers);
ResponseEntity<String> exchange = restTemplate.exchange(
final ResponseEntity<String> 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<OAuth2AccessToken> 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,

View file

@ -276,7 +276,7 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
EntityType.CONFIGURATION_NODE))));
}
Configuration config = doImport
final Configuration config = doImport
.getOrThrow();
return this.configurationDAO
@ -353,15 +353,16 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
filterMap)
.getOrThrow();
final int start = (pageNumber - 1) * pageSize;
int end = start + pageSize;
final int start = (this.paginationService.getPageNumber(pageNumber) - 1) *
this.paginationService.getPageSize(pageSize);
int end = start + this.paginationService.getPageSize(pageSize);
if (attrs.size() < end) {
end = attrs.size();
}
return new Page<>(
attrs.size() / pageSize,
pageNumber,
attrs.size() / this.paginationService.getPageSize(pageSize),
this.paginationService.getPageNumber(pageNumber),
sort,
attrs.subList(start, end));
}

View file

@ -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<SebCl
}
@Override
protected Result<SebClientConfig> notifySaved(SebClientConfig entity) {
protected Result<SebClientConfig> 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<APIMessage> errors = new ArrayList<>();
final Collection<APIMessage> errors = new ArrayList<>();
if (entity.hasEncryptionSecret() && !entity.encryptSecret.equals(entity.encryptSecretConfirm)) {
errors.add(APIMessage.fieldValidationError(
new FieldError(

View file

@ -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

View file

@ -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,

View file

@ -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;
@ -1544,8 +1548,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 +1565,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<View> views = restService
.getBuilder(GetViews.class)
@ -1572,6 +1587,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 +1628,95 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest {
assertNotNull(newTemplate);
assertEquals("Config Template", newTemplate.name);
assertNotNull(orientations);
// check views for template where created
final List<View> 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<Orientation> 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<TemplateAttribute> 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<ConfigurationValue> 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);
}
}