Merge pull request #4 from SafeExamBrowser/development

Development
This commit is contained in:
Andreas Hefti 2020-05-06 12:12:46 +02:00 committed by GitHub
commit bce5ea7f58
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 83 additions and 76 deletions

View file

@ -46,7 +46,6 @@ public final class Exam implements GrantEntity {
ExamType.UNDEFINED, ExamType.UNDEFINED,
null, null,
null, null,
null,
ExamStatus.FINISHED, ExamStatus.FINISHED,
// Boolean.FALSE, // Boolean.FALSE,
null, null,
@ -104,9 +103,6 @@ public final class Exam implements GrantEntity {
@NotNull @NotNull
public final ExamType type; public final ExamType type;
@JsonProperty(EXAM.ATTR_QUIT_PASSWORD)
public final String quitPassword;
@JsonProperty(EXAM.ATTR_OWNER) @JsonProperty(EXAM.ATTR_OWNER)
public final String owner; public final String owner;
@ -138,7 +134,6 @@ public final class Exam implements GrantEntity {
@JsonProperty(QuizData.QUIZ_ATTR_END_TIME) final DateTime endTime, @JsonProperty(QuizData.QUIZ_ATTR_END_TIME) final DateTime endTime,
@JsonProperty(QuizData.QUIZ_ATTR_START_URL) final String startURL, @JsonProperty(QuizData.QUIZ_ATTR_START_URL) final String startURL,
@JsonProperty(EXAM.ATTR_TYPE) final ExamType type, @JsonProperty(EXAM.ATTR_TYPE) final ExamType type,
@JsonProperty(EXAM.ATTR_QUIT_PASSWORD) final String quitPassword,
@JsonProperty(EXAM.ATTR_OWNER) final String owner, @JsonProperty(EXAM.ATTR_OWNER) final String owner,
@JsonProperty(EXAM.ATTR_SUPPORTER) final Collection<String> supporter, @JsonProperty(EXAM.ATTR_SUPPORTER) final Collection<String> supporter,
@JsonProperty(EXAM.ATTR_STATUS) final ExamStatus status, @JsonProperty(EXAM.ATTR_STATUS) final ExamStatus status,
@ -156,7 +151,6 @@ public final class Exam implements GrantEntity {
this.endTime = endTime; this.endTime = endTime;
this.startURL = startURL; this.startURL = startURL;
this.type = type; this.type = type;
this.quitPassword = quitPassword;
this.owner = owner; this.owner = owner;
this.status = (status != null) ? status : getStatusFromDate(startTime, endTime); this.status = (status != null) ? status : getStatusFromDate(startTime, endTime);
this.browserExamKeys = browserExamKeys; this.browserExamKeys = browserExamKeys;
@ -180,7 +174,6 @@ public final class Exam implements GrantEntity {
this.endTime = quizData.endTime; this.endTime = quizData.endTime;
this.startURL = quizData.startURL; this.startURL = quizData.startURL;
this.type = mapper.getEnum(EXAM.ATTR_TYPE, ExamType.class, ExamType.UNDEFINED); this.type = mapper.getEnum(EXAM.ATTR_TYPE, ExamType.class, ExamType.UNDEFINED);
this.quitPassword = mapper.getString(EXAM.ATTR_QUIT_PASSWORD);
this.owner = mapper.getString(EXAM.ATTR_OWNER); this.owner = mapper.getString(EXAM.ATTR_OWNER);
this.status = mapper.getEnum( this.status = mapper.getEnum(
EXAM.ATTR_STATUS, EXAM.ATTR_STATUS,
@ -208,7 +201,6 @@ public final class Exam implements GrantEntity {
this.endTime = null; this.endTime = null;
this.startURL = null; this.startURL = null;
this.type = null; this.type = null;
this.quitPassword = null;
this.owner = null; this.owner = null;
this.status = (status != null) ? status : getStatusFromDate(this.startTime, this.endTime); this.status = (status != null) ? status : getStatusFromDate(this.startTime, this.endTime);
this.browserExamKeys = null; this.browserExamKeys = null;
@ -300,10 +292,6 @@ public final class Exam implements GrantEntity {
return this.startURL; return this.startURL;
} }
public String getQuitPassword() {
return this.quitPassword;
}
public ExamStatus getStatus() { public ExamStatus getStatus() {
return this.status; return this.status;
} }
@ -339,8 +327,6 @@ public final class Exam implements GrantEntity {
builder.append(this.startURL); builder.append(this.startURL);
builder.append(", type="); builder.append(", type=");
builder.append(this.type); builder.append(this.type);
builder.append(", quitPassword=");
builder.append(this.quitPassword);
builder.append(", owner="); builder.append(", owner=");
builder.append(this.owner); builder.append(this.owner);
builder.append(", supporter="); builder.append(", supporter=");

View file

@ -36,7 +36,7 @@ public final class Institution implements GrantEntity, Activatable {
public final String name; public final String name;
@JsonProperty(INSTITUTION.ATTR_URL_SUFFIX) @JsonProperty(INSTITUTION.ATTR_URL_SUFFIX)
@Pattern(regexp = "(^$|.{3,255})", message = "institution:urlSuffix:size:3:255:${validatedValue}") @Pattern(regexp = "(^$|.{3,45})", message = "institution:urlSuffix:size:3:45:${validatedValue}")
public final String urlSuffix; public final String urlSuffix;
@JsonProperty(INSTITUTION.ATTR_LOGO_IMAGE) @JsonProperty(INSTITUTION.ATTR_LOGO_IMAGE)

View file

@ -186,7 +186,7 @@ public class LmsSetupList implements TemplateComposer {
action -> LmsSetupForm.testLmsSetup(action, null, restService)), action -> LmsSetupForm.testLmsSetup(action, null, restService)),
EMPTY_SELECTION_TEXT_KEY) EMPTY_SELECTION_TEXT_KEY)
.withConfirm(this.pageService.confirmDeactivation(table)) .withConfirm(this.pageService.confirmDeactivation(table))
.publishIf(() -> userGrant.im() && table.hasAnyContent(), false); .publishIf(() -> userGrant.iw() && table.hasAnyContent(), false);
} }

View file

@ -137,11 +137,11 @@ public class MonitoringRunningExam implements TemplateComposer {
clientTable clientTable
.withDefaultAction( .withDefaultAction(
actionBuilder actionBuilder
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION) .newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION)
.withParentEntityKey(entityKey) .withParentEntityKey(entityKey)
.create(), .create(),
this.pageService) this.pageService)
.withSelectionListener(this.pageService.getSelectionPublisher( .withSelectionListener(this.pageService.getSelectionPublisher(
pageContext, pageContext,
ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION, ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION,
@ -324,6 +324,7 @@ public class MonitoringRunningExam implements TemplateComposer {
action.pageContext()); action.pageContext());
clientTable.removeSelection(); clientTable.removeSelection();
clientTable.forceUpdateAll();
return action; return action;
} }
@ -340,6 +341,7 @@ public class MonitoringRunningExam implements TemplateComposer {
action.pageContext()); action.pageContext());
clientTable.removeSelection(); clientTable.removeSelection();
clientTable.forceUpdateAll();
return action; return action;
} }

View file

@ -8,17 +8,10 @@
package ch.ethz.seb.sebserver.gui.content.action; package ch.ethz.seb.sebserver.gui.content.action;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; import java.util.ArrayList;
import ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService; import java.util.HashMap;
import ch.ethz.seb.sebserver.gui.service.page.PageContext; import java.util.Map;
import ch.ethz.seb.sebserver.gui.service.page.PageService;
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
import ch.ethz.seb.sebserver.gui.service.page.event.ActionActivationEventListener;
import ch.ethz.seb.sebserver.gui.service.page.event.ActionPublishEventListener;
import ch.ethz.seb.sebserver.gui.service.page.event.PageEventListener;
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.eclipse.rap.rwt.RWT; import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.template.ImageCell; import org.eclipse.rap.rwt.template.ImageCell;
@ -38,9 +31,17 @@ import org.eclipse.swt.widgets.TreeItem;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.ArrayList; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import java.util.HashMap; import ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService;
import java.util.Map; 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.TemplateComposer;
import ch.ethz.seb.sebserver.gui.service.page.event.ActionActivationEventListener;
import ch.ethz.seb.sebserver.gui.service.page.event.ActionPublishEventListener;
import ch.ethz.seb.sebserver.gui.service.page.event.PageEventListener;
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
@Lazy @Lazy
@Component @Component
@ -52,8 +53,6 @@ public class ActionPane implements TemplateComposer {
private final PageService pageService; private final PageService pageService;
private final WidgetFactory widgetFactory; private final WidgetFactory widgetFactory;
private final Map<String, Tree> actionTrees = new HashMap<>();
protected ActionPane(final PageService pageService) { protected ActionPane(final PageService pageService) {
this.pageService = pageService; this.pageService = pageService;
this.widgetFactory = pageService.getWidgetFactory(); this.widgetFactory = pageService.getWidgetFactory();
@ -61,7 +60,7 @@ public class ActionPane implements TemplateComposer {
@Override @Override
public void compose(final PageContext pageContext) { public void compose(final PageContext pageContext) {
final Map<String, Tree> actionTrees = new HashMap<>();
final Label label = this.widgetFactory.labelLocalized( final Label label = this.widgetFactory.labelLocalized(
pageContext.getParent(), pageContext.getParent(),
CustomVariant.TEXT_H2, CustomVariant.TEXT_H2,
@ -79,7 +78,7 @@ public class ActionPane implements TemplateComposer {
PageEventListener.LISTENER_ATTRIBUTE_KEY, PageEventListener.LISTENER_ATTRIBUTE_KEY,
(ActionPublishEventListener) event -> { (ActionPublishEventListener) event -> {
final Composite parent = pageContext.getParent(); final Composite parent = pageContext.getParent();
final Tree treeForGroup = getTreeForGroup(parent, event.action.definition, true); final Tree treeForGroup = getTreeForGroup(actionTrees, parent, event.action.definition, true);
final TreeItem actionItem = ActionPane.this.widgetFactory.treeItemLocalized( final TreeItem actionItem = ActionPane.this.widgetFactory.treeItemLocalized(
treeForGroup, treeForGroup,
event.action.definition.title); event.action.definition.title);
@ -110,7 +109,7 @@ public class ActionPane implements TemplateComposer {
(ActionActivationEventListener) event -> { (ActionActivationEventListener) event -> {
final Composite parent = pageContext.getParent(); final Composite parent = pageContext.getParent();
for (final ActionDefinition ad : event.actions) { for (final ActionDefinition ad : event.actions) {
final TreeItem actionItem = findAction(parent, ad); final TreeItem actionItem = findAction(actionTrees, parent, ad);
if (actionItem == null) { if (actionItem == null) {
continue; continue;
} }
@ -128,7 +127,7 @@ public class ActionPane implements TemplateComposer {
} }
if (event.decoration != null) { if (event.decoration != null) {
final TreeItem actionItemToDecorate = findAction(parent, event.decoration._1); final TreeItem actionItemToDecorate = findAction(actionTrees, parent, event.decoration._1);
if (actionItemToDecorate != null && event.decoration._2 != null) { if (actionItemToDecorate != null && event.decoration._2 != null) {
actionItemToDecorate.setImage(0, actionItemToDecorate.setImage(0,
event.decoration._2.icon.getImage(parent.getDisplay())); event.decoration._2.icon.getImage(parent.getDisplay()));
@ -140,8 +139,11 @@ public class ActionPane implements TemplateComposer {
}); });
} }
private TreeItem findAction(final Composite parent, final ActionDefinition actionDefinition) { private TreeItem findAction(
final Tree treeForGroup = getTreeForGroup(parent, actionDefinition, false); final Map<String, Tree> actionTrees,
final Composite parent,
final ActionDefinition actionDefinition) {
final Tree treeForGroup = getTreeForGroup(actionTrees, parent, actionDefinition, false);
if (treeForGroup == null) { if (treeForGroup == null) {
return null; return null;
} }
@ -166,19 +168,20 @@ public class ActionPane implements TemplateComposer {
} }
private Tree getTreeForGroup( private Tree getTreeForGroup(
final Map<String, Tree> actionTrees,
final Composite parent, final Composite parent,
final ActionDefinition actionDefinition, final ActionDefinition actionDefinition,
boolean create) { final boolean create) {
clearDisposedTrees(); clearDisposedTrees(actionTrees);
final ActionCategory category = actionDefinition.category; final ActionCategory category = actionDefinition.category;
if (!this.actionTrees.containsKey(category.name()) && create) { if (!actionTrees.containsKey(category.name()) && create) {
final Tree actionTree = createActionTree(parent, actionDefinition.category); final Tree actionTree = createActionTree(parent, actionDefinition.category);
this.actionTrees.put(category.name(), actionTree); actionTrees.put(category.name(), actionTree);
} }
return this.actionTrees.get(category.name()); return actionTrees.get(category.name());
} }
private Tree createActionTree(final Composite parent, final ActionCategory category) { private Tree createActionTree(final Composite parent, final ActionCategory category) {
@ -257,19 +260,19 @@ public class ActionPane implements TemplateComposer {
return actions; return actions;
} }
private void clearDisposedTrees() { private void clearDisposedTrees(final Map<String, Tree> actionTrees) {
new ArrayList<>(this.actionTrees.entrySet()) new ArrayList<>(actionTrees.entrySet())
.forEach(entry -> { .forEach(entry -> {
final Control c = entry.getValue(); final Control c = entry.getValue();
// of tree is already disposed.. remove it // of tree is already disposed.. remove it
if (c.isDisposed()) { if (c.isDisposed()) {
this.actionTrees.remove(entry.getKey()); actionTrees.remove(entry.getKey());
} }
// check access from current thread // check access from current thread
try { try {
c.getBounds(); c.getBounds();
} catch (final Exception e) { } catch (final Exception e) {
this.actionTrees.remove(entry.getKey()); actionTrees.remove(entry.getKey());
} }
}); });
} }

View file

@ -191,8 +191,8 @@ public abstract class RestCall<T> {
} }
log.debug( log.debug(
"Webservice answered with well defined error- or validation-failure-response: ", "Webservice answered with well defined error- or validation-failure-response: {}",
restCallError); restCallError.toString());
return Result.ofError(restCallError); return Result.ofError(restCallError);
} }

View file

@ -106,6 +106,8 @@ public final class ClientConnectionTable {
private final Color darkFontColor; private final Color darkFontColor;
private final Color lightFontColor; private final Color lightFontColor;
private boolean forceUpdateAll = false;
public ClientConnectionTable( public ClientConnectionTable(
final PageService pageService, final PageService pageService,
final Composite tableRoot, final Composite tableRoot,
@ -289,13 +291,17 @@ public final class ClientConnectionTable {
updatableTableItem.connectionData.clientConnection.connectionToken); updatableTableItem.connectionData.clientConnection.connectionToken);
} }
public void forceUpdateAll() {
this.forceUpdateAll = true;
}
public void updateValues() { public void updateValues() {
if (this.statusFilterChanged) { if (this.statusFilterChanged) {
this.toDelete.clear(); this.toDelete.clear();
this.toDelete.addAll(this.tableMapping.keySet()); this.toDelete.addAll(this.tableMapping.keySet());
} }
this.restCallBuilder this.restCallBuilder
.withHeader(API.EXAM_MONITORING_STATE_FILTER, this.statusFilterParam) .withHeader(API.EXAM_MONITORING_STATE_FILTER, (this.forceUpdateAll) ? "" : this.statusFilterParam)
.call() .call()
.get(error -> { .get(error -> {
log.error("Error poll connection data: ", error); log.error("Error poll connection data: ", error);
@ -321,6 +327,8 @@ public final class ClientConnectionTable {
}); });
this.statusFilterChanged = false; this.statusFilterChanged = false;
} }
this.forceUpdateAll = false;
} }
public void updateGUI() { public void updateGUI() {
@ -554,7 +562,7 @@ public final class ClientConnectionTable {
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
final UpdatableTableItem other = (UpdatableTableItem) obj; final UpdatableTableItem other = (UpdatableTableItem) obj;
if (!getOuterType().equals(other.getOuterType())) if (getOuterType() != other.getOuterType())
return false; return false;
return compareTo(other) == 0; return compareTo(other) == 0;
} }

View file

@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.webservice;
import org.cryptonode.jncryptor.AES256JNCryptor; import org.cryptonode.jncryptor.AES256JNCryptor;
import org.cryptonode.jncryptor.JNCryptor; import org.cryptonode.jncryptor.JNCryptor;
import org.flywaydb.core.Flyway; import org.flywaydb.core.Flyway;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.flyway.FlywayMigrationStrategy; import org.springframework.boot.autoconfigure.flyway.FlywayMigrationStrategy;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -24,6 +25,9 @@ import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
@WebServiceProfile @WebServiceProfile
public class WebserviceConfig { public class WebserviceConfig {
@Value("${sebserver.webservice.clean-db-on-startup:false}")
boolean cleanDBOnStartup;
@Lazy @Lazy
@Bean @Bean
public JNCryptor jnCryptor() { public JNCryptor jnCryptor() {
@ -42,7 +46,9 @@ public class WebserviceConfig {
final FlywayMigrationStrategy strategy = new FlywayMigrationStrategy() { final FlywayMigrationStrategy strategy = new FlywayMigrationStrategy() {
@Override @Override
public void migrate(final Flyway flyway) { public void migrate(final Flyway flyway) {
flyway.clean(); if (WebserviceConfig.this.cleanDBOnStartup) {
flyway.clean();
}
flyway.migrate(); flyway.migrate();
} }
}; };

View file

@ -53,7 +53,15 @@ public interface PaginationService {
/** Get a Page of specified domain models from given pagination attributes within collection supplier delegate. /** Get a Page of specified domain models from given pagination attributes within collection supplier delegate.
* *
* * NOTE: Paging always depends on SQL level. It depends on the collection given by the SQL select statement
* that is executed within MyBatis by using the MyBatis page service.
* Be aware that if the delegate that is given here applies an additional filter to the filtering done
* on SQL level, this will lead to paging with not fully filled pages or even to empty pages if the filter
* filters a lot of the entries given by the SQL statement away.
* So we recommend to apply as much of the filtering as possible on the SQL level and only if necessary and
* not avoidable, apply a additional filter on software-level that eventually filter one or two entities
* for a page.
*
* @param pageNumber the current page number * @param pageNumber the current page number
* @param pageSize the (full) size of the page * @param pageSize the (full) size of the page
* @param sort the name of the sort column with a leading '-' for descending sort order * @param sort the name of the sort column with a leading '-' for descending sort order

View file

@ -224,7 +224,7 @@ public class ExamDAOImpl implements ExamDAO {
(exam.type != null) (exam.type != null)
? exam.type.name() ? exam.type.name()
: null, : null,
exam.quitPassword, null,
exam.browserExamKeys, exam.browserExamKeys,
(exam.status != null) (exam.status != null)
? exam.status.name() ? exam.status.name()
@ -769,11 +769,9 @@ public class ExamDAOImpl implements ExamDAO {
(quizData != null) ? quizData.endTime : null, (quizData != null) ? quizData.endTime : null,
(quizData != null) ? quizData.startURL : Constants.EMPTY_NOTE, (quizData != null) ? quizData.startURL : Constants.EMPTY_NOTE,
ExamType.valueOf(record.getType()), ExamType.valueOf(record.getType()),
record.getQuitPassword(),
record.getOwner(), record.getOwner(),
supporter, supporter,
status, status,
// BooleanUtils.toBooleanObject((quizData != null) ? record.getLmsSebRestriction() : null),
record.getBrowserKeys(), record.getBrowserKeys(),
BooleanUtils.toBooleanObject((quizData != null) ? record.getActive() : null), BooleanUtils.toBooleanObject((quizData != null) ? record.getActive() : null),
record.getLastupdate()); record.getLastupdate());

View file

@ -294,7 +294,7 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
return all( return all(
filterMap.getInstitutionId(), filterMap.getInstitutionId(),
filterMap.getString(UserActivityLog.FILTER_ATTR_USER_NAME), filterMap.getSQLWildcard(UserActivityLog.FILTER_ATTR_USER_NAME),
filterMap.getUserLogFrom(), filterMap.getUserLogFrom(),
filterMap.getUserLofTo(), filterMap.getUserLofTo(),
filterMap.getString(UserActivityLog.FILTER_ATTR_ACTIVITY_TYPES), filterMap.getString(UserActivityLog.FILTER_ATTR_ACTIVITY_TYPES),
@ -321,14 +321,6 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
? Arrays.asList(StringUtils.split(entityTypes, Constants.LIST_SEPARATOR)) ? Arrays.asList(StringUtils.split(entityTypes, Constants.LIST_SEPARATOR))
: null; : null;
Predicate<UserActivityLog> _predicate = (predicate != null)
? predicate
: model -> true;
if (StringUtils.isNotBlank(userName)) {
_predicate = _predicate.and(model -> model.getUsername().contains(userName));
}
final List<UserActivityLogRecord> records = this.userLogRecordMapper final List<UserActivityLogRecord> records = this.userLogRecordMapper
.selectByExample() .selectByExample()
.leftJoin(UserRecordDynamicSqlSupport.userRecord) .leftJoin(UserRecordDynamicSqlSupport.userRecord)
@ -338,6 +330,9 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
.where( .where(
UserRecordDynamicSqlSupport.institutionId, UserRecordDynamicSqlSupport.institutionId,
SqlBuilder.isEqualToWhenPresent(institutionId)) SqlBuilder.isEqualToWhenPresent(institutionId))
.and(
UserRecordDynamicSqlSupport.username,
SqlBuilder.isLikeWhenPresent(userName))
.and( .and(
UserActivityLogRecordDynamicSqlSupport.timestamp, UserActivityLogRecordDynamicSqlSupport.timestamp,
SqlBuilder.isGreaterThanOrEqualToWhenPresent(from)) SqlBuilder.isGreaterThanOrEqualToWhenPresent(from))
@ -355,7 +350,7 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
return this.toDomainModel(institutionId, records) return this.toDomainModel(institutionId, records)
.stream() .stream()
.filter(_predicate) .filter(predicate)
.collect(Collectors.toList()); .collect(Collectors.toList());
}); });
} }

View file

@ -131,7 +131,7 @@ public class SebRestrictionServiceImpl implements SebRestrictionService {
final Collection<String> browserExamKeys = sebRestriction.getBrowserExamKeys(); final Collection<String> browserExamKeys = sebRestriction.getBrowserExamKeys();
final Exam newExam = new Exam( final Exam newExam = new Exam(
exam.id, exam.id,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
exam.supporter, exam.supporter,
exam.status, exam.status,
(browserExamKeys != null && !browserExamKeys.isEmpty()) (browserExamKeys != null && !browserExamKeys.isEmpty())

View file

@ -10,7 +10,7 @@ spring.datasource.url=jdbc:mariadb://localhost:3306/SEBServer?createDatabaseIfNo
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.flyway.enabled=true spring.flyway.enabled=true
spring.flyway.locations=classpath:config/sql/base,classpath:config/sql/dev spring.flyway.locations=classpath:config/sql/base,classpath:config/sql/dev
spring.flyway.baselineOnMigrate=true spring.flyway.cleanDisabled=false
spring.datasource.hikari.initializationFailTimeout=30000 spring.datasource.hikari.initializationFailTimeout=30000
spring.datasource.hikari.connectionTimeout=30000 spring.datasource.hikari.connectionTimeout=30000
spring.datasource.hikari.idleTimeout=600000 spring.datasource.hikari.idleTimeout=600000
@ -20,6 +20,8 @@ sebserver.http.client.connect-timeout=15000
sebserver.http.client.connection-request-timeout=10000 sebserver.http.client.connection-request-timeout=10000
sebserver.http.client.read-timeout=20000 sebserver.http.client.read-timeout=20000
sebserver.webservice.clean-db-on-startup=false
# webservice configuration # webservice configuration
sebserver.init.adminaccount.gen-on-init=false sebserver.init.adminaccount.gen-on-init=false
sebserver.webservice.distributed=false sebserver.webservice.distributed=false

View file

@ -72,6 +72,7 @@ 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.url=jdbc:mariadb://${datastore.mariadb.server.address}:${datastore.mariadb.server.port}/SEBServer?useSSL=false&createDatabaseIfNotExist=true
spring.flyway.enabled=true spring.flyway.enabled=true
spring.flyway.locations=classpath:config/sql/base spring.flyway.locations=classpath:config/sql/base
spring.flyway.cleanDisabled=true
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.hikari.initializationFailTimeout=3000 spring.datasource.hikari.initializationFailTimeout=3000
spring.datasource.hikari.connectionTimeout=30000 spring.datasource.hikari.connectionTimeout=30000

View file

@ -806,7 +806,7 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest {
newExam.endTime, newExam.endTime,
newExam.startURL, newExam.startURL,
ExamType.MANAGED, ExamType.MANAGED,
null, null, null,
Utils.immutableCollectionOf(userId), Utils.immutableCollectionOf(userId),
ExamStatus.RUNNING, ExamStatus.RUNNING,
null, null,

View file

@ -61,7 +61,6 @@ public class ExamAPITest extends AdministrationAPIIntegrationTester {
exam.endTime, exam.endTime,
exam.startURL, exam.startURL,
exam.type, exam.type,
exam.quitPassword,
exam.owner, exam.owner,
Arrays.asList("user5"), Arrays.asList("user5"),
null, null,
@ -92,7 +91,6 @@ public class ExamAPITest extends AdministrationAPIIntegrationTester {
exam.endTime, exam.endTime,
exam.startURL, exam.startURL,
exam.type, exam.type,
exam.quitPassword,
exam.owner, exam.owner,
Arrays.asList("user2"), Arrays.asList("user2"),
null, null,