diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java b/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java index 09216565..2dc2b710 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java @@ -108,6 +108,7 @@ public final class API { public static final String CONFIGURATION_NODE_ENDPOINT = "/configuration_node"; public static final String CONFIGURATION_FOLLOWUP_PATH_SEGMENT = "/followup"; + public static final String CONFIGURATION_CONFIG_KEY_PATH_SEGMENT = "/configkey"; public static final String CONFIGURATION_ENDPOINT = "/configuration"; public static final String CONFIGURATION_SAVE_TO_HISTORY_PATH_SEGMENT = "/save_to_history"; public static final String CONFIGURATION_UNDO_PATH_SEGMENT = "/undo"; diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/ConfigKey.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/ConfigKey.java new file mode 100644 index 00000000..60c6186b --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/ConfigKey.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.gbl.model.sebconfig; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public final class ConfigKey { + + public static final String ATTR_KEY = "key"; + + @JsonProperty(ATTR_KEY) + public final String key; + + @JsonCreator + public ConfigKey(@JsonProperty(ATTR_KEY) final String key) { + this.key = key; + } + + public String getKey() { + return this.key; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((this.key == null) ? 0 : this.key.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final ConfigKey other = (ConfigKey) obj; + if (this.key == null) { + if (other.key != null) + return false; + } else if (!this.key.equals(other.key)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("ConfigKey [key="); + builder.append(this.key); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java index fbe345c9..d86efd8c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java @@ -385,7 +385,13 @@ public class ExamForm implements TemplateComposer { indicatorTable::getSelection, this::deleteSelectedIndicator, INDICATOR_EMPTY_SELECTION_TEXT_KEY) - .publishIf(() -> modifyGrant && indicatorTable.hasAnyContent() && editable); + .publishIf(() -> modifyGrant && indicatorTable.hasAnyContent() && editable) + + .newAction(ActionDefinition.SEB_EXAM_CONFIG_GET_CONFIG_KEY) + .withEntityKey(entityKey) + .withExec(SebExamConfigPropForm.getConfigKeyFunction(this.pageService)) + .publishIf(() -> userGrantCheck.r()); + ; } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigPropForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigPropForm.java index 438736c8..edfd7e24 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigPropForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigPropForm.java @@ -8,9 +8,13 @@ package ch.ethz.seb.sebserver.gui.content; +import java.util.function.Function; + import org.eclipse.rap.rwt.RWT; import org.eclipse.rap.rwt.client.service.UrlLauncher; +import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -20,6 +24,7 @@ import org.springframework.stereotype.Component; import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.EntityKey; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigKey; 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.user.UserInfo; @@ -32,15 +37,19 @@ 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.PageService; import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer; +import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog; +import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction; import ch.ethz.seb.sebserver.gui.service.remote.DownloadService; import ch.ethz.seb.sebserver.gui.service.remote.SebExamConfigDownload; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ExportConfigKey; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode; 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.SaveExamConfig; import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser; import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck; import ch.ethz.seb.sebserver.gui.widget.WidgetFactory; +import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant; @Lazy @Component @@ -60,6 +69,9 @@ public class SebExamConfigPropForm implements TemplateComposer { private static final LocTextKey FORM_STATUS_TEXT_KEY = new LocTextKey("sebserver.examconfig.form.status"); + private static final LocTextKey CONFIG_KEY_TITLE_TEXT_KEY = + new LocTextKey("sebserver.examconfig.form.config-key.title"); + private final PageService pageService; private final RestService restService; private final CurrentUser currentUser; @@ -183,6 +195,11 @@ public class SebExamConfigPropForm implements TemplateComposer { }) .publishIf(() -> readGrant && isReadonly) + .newAction(ActionDefinition.SEB_EXAM_CONFIG_GET_CONFIG_KEY) + .withEntityKey(entityKey) + .withExec(SebExamConfigPropForm.getConfigKeyFunction(this.pageService)) + .publishIf(() -> readGrant && isReadonly) + .newAction(ActionDefinition.SEB_EXAM_CONFIG_SAVE) .withEntityKey(entityKey) .withExec(formHandle::processFormSave) @@ -198,4 +215,37 @@ public class SebExamConfigPropForm implements TemplateComposer { } + public static Function getConfigKeyFunction(final PageService pageService) { + final RestService restService = pageService.getResourceService().getRestService(); + return action -> { + final ConfigKey configKey = restService.getBuilder(ExportConfigKey.class) + .withURIVariable(API.PARAM_MODEL_ID, action.getEntityKey().modelId) + .call() + .getOrThrow(); + + final WidgetFactory widgetFactory = pageService.getWidgetFactory(); + final ModalInputDialog dialog = new ModalInputDialog<>( + action.pageContext().getParent().getShell(), + widgetFactory); + + dialog.open( + CONFIG_KEY_TITLE_TEXT_KEY, + action.pageContext(), + pc -> { + final Composite content = widgetFactory.defaultPageLayout( + pc.getParent()); + + widgetFactory.labelLocalized( + content, + CustomVariant.TEXT_H3, + CONFIG_KEY_TITLE_TEXT_KEY); + + final Text text = new Text(content, SWT.NONE); + text.setEditable(false); + text.setText(configKey.key); + }); + return action; + }; + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigSettingsForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigSettingsForm.java index 4844751c..95b8859e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigSettingsForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigSettingsForm.java @@ -167,6 +167,10 @@ public class SebExamConfigSettingsForm implements TemplateComposer { .withSuccess(KEY_UNDO_SUCCESS) .publishIf(() -> examConfigGrant.iw()) + .newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP) + .withEntityKey(entityKey) + .publish() + ; } catch (final Exception e) { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java index 9bc806c2..9f0680b5 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java @@ -177,7 +177,6 @@ public enum ActionDefinition { QUIZ_DISCOVERY_SHOW_DETAILS( new LocTextKey("sebserver.quizdiscovery.action.details"), ImageIcon.SHOW, - null, ActionCategory.QUIZ_LIST), QUIZ_DISCOVERY_EXAM_IMPORT( new LocTextKey("sebserver.quizdiscovery.action.import"), @@ -340,6 +339,12 @@ public enum ActionDefinition { ImageIcon.SHOW, PageStateDefinition.SEB_EXAM_CONFIG_VIEW, ActionCategory.SEB_EXAM_CONFIG_LIST), + SEB_EXAM_CONFIG_VIEW_PROP( + new LocTextKey("sebserver.examconfig.action.view"), + ImageIcon.SHOW, + PageStateDefinition.SEB_EXAM_CONFIG_VIEW, + ActionCategory.FORM), + SEB_EXAM_CONFIG_MODIFY_PROP_FROM_LIST( new LocTextKey("sebserver.examconfig.action.list.modify.properties"), ImageIcon.EDIT, @@ -370,6 +375,10 @@ public enum ActionDefinition { ImageIcon.EXPORT, PageStateDefinition.SEB_EXAM_CONFIG_VIEW, ActionCategory.FORM), + SEB_EXAM_CONFIG_GET_CONFIG_KEY( + new LocTextKey("sebserver.examconfig.action.get-config-key"), + ImageIcon.SECURE, + ActionCategory.FORM), SEB_EXAM_CONFIG_MODIFY_FROM_LIST( new LocTextKey("sebserver.examconfig.action.list.modify"), @@ -381,12 +390,12 @@ public enum ActionDefinition { new LocTextKey("sebserver.examconfig.action.saveToHistory"), ImageIcon.SAVE, PageStateDefinition.SEB_EXAM_CONFIG_EDIT, - ActionCategory.SEB_EXAM_CONFIG_LIST), + ActionCategory.FORM), SEB_EXAM_CONFIG_UNDO( new LocTextKey("sebserver.examconfig.action.undo"), ImageIcon.UNDO, PageStateDefinition.SEB_EXAM_CONFIG_EDIT, - ActionCategory.SEB_EXAM_CONFIG_LIST), + ActionCategory.FORM), RUNNING_EXAM_VIEW_LIST( new LocTextKey("sebserver.monitoring.action.list"), @@ -422,6 +431,14 @@ public enum ActionDefinition { this(title, icon, targetState, ActionCategory.VARIA); } + private ActionDefinition( + final LocTextKey title, + final ImageIcon icon, + final ActionCategory category) { + + this(title, icon, null, category); + } + private ActionDefinition( final LocTextKey title, final ImageIcon icon, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ExportConfigKey.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ExportConfigKey.java new file mode 100644 index 00000000..6b7486fb --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ExportConfigKey.java @@ -0,0 +1,42 @@ +/* + * 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.ConfigKey; +import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; + +@Lazy +@Component +@GuiProfile +public class ExportConfigKey extends RestCall { + + public ExportConfigKey() { + super(new TypeKey<>( + CallType.UNDEFINED, + EntityType.CONFIGURATION_NODE, + new TypeReference() { + }), + HttpMethod.GET, + MediaType.APPLICATION_FORM_URLENCODED, + API.CONFIGURATION_NODE_ENDPOINT + + API.MODEL_ID_VAR_PATH_SEGMENT + + API.CONFIGURATION_CONFIG_KEY_PATH_SEGMENT); + } + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ExportPlainXML.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ExportPlainXML.java index 3999c335..e43fab7e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ExportPlainXML.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/seb/examconfig/ExportPlainXML.java @@ -34,8 +34,8 @@ public class ExportPlainXML extends AbstractExportCall { HttpMethod.GET, MediaType.APPLICATION_FORM_URLENCODED, API.CONFIGURATION_NODE_ENDPOINT - + API.CONFIGURATION_PLAIN_XML_DOWNLOAD_PATH_SEGMENT - + API.MODEL_ID_VAR_PATH_SEGMENT); + + API.MODEL_ID_VAR_PATH_SEGMENT + + API.CONFIGURATION_PLAIN_XML_DOWNLOAD_PATH_SEGMENT); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java index 0d3abffb..13926b3a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java @@ -78,6 +78,7 @@ public class WidgetFactory { NO("no.png"), SAVE("save.png"), EXPORT("export.png"), + SECURE("secure.png"), NEW("new.png"), DELETE("delete.png"), SEARCH("lens.png"), diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ConfigurationFormat.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ConfigurationFormat.java new file mode 100644 index 00000000..61ac3064 --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ConfigurationFormat.java @@ -0,0 +1,14 @@ +/* + * 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.servicelayer.sebconfig; + +public enum ConfigurationFormat { + XML, + JSON +} diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebExamConfigService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebExamConfigService.java index 906569a3..5ea8769e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebExamConfigService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/SebExamConfigService.java @@ -13,6 +13,7 @@ import java.io.OutputStream; import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue; +import ch.ethz.seb.sebserver.gbl.util.Result; /** The base interface and service for all SEB Exam Configuration related functionality. */ public interface SebExamConfigService { @@ -40,13 +41,25 @@ public interface SebExamConfigService { * @param configurationNodeId the identifier of the ConfigurationNode to export */ void exportPlainXML(OutputStream out, Long institutionId, Long configurationNodeId); + /** Used to export a specified SEB Exam Configuration as plain JSON + * This exports the values of the follow-up configuration defined by a given + * ConfigurationNode (configurationNodeId) and sorts the attributes recording to + * the SEB configuration JSON specification to create a Config-Key as + * described here: https://www.safeexambrowser.org/developer/seb-config-key.html + * + * @param out The output stream to write the plain JSON text to. + * @param institutionId The identifier of the institution of the requesting user + * @param configurationNodeId the identifier of the ConfigurationNode to export */ + void exportPlainJSON(OutputStream out, Long institutionId, Long configurationNodeId); + /** Used to export the default SEB Exam Configuration for a given exam identifier. * either with encryption if defined or as plain text within the SEB Configuration format * as described here: https://www.safeexambrowser.org/developer/seb-file-format.html * * @param out The output stream to write the export data to * @param institutionId The identifier of the institution of the requesting user - * @param examId the exam identifier */ + * @param examId the exam identifier + * @return The configuration node identifier (PK) */ default Long exportForExam(final OutputStream out, final Long institutionId, final Long examId) { return exportForExam(out, institutionId, examId, null); } @@ -58,10 +71,11 @@ public interface SebExamConfigService { * @param out The output stream to write the export data to * @param institutionId The identifier of the institution of the requesting user * @param examId the exam identifier - * @param userId the user identifier if a specific user based configuration shall be exported */ + * @param userId the user identifier if a specific user based configuration shall be exported + * @return The configuration node identifier (PK) */ Long exportForExam(OutputStream out, Long institutionId, Long examId, String userId); /** TODO */ - String generateConfigKey(Long configurationNodeId); + Result generateConfigKey(Long institutionId, Long configurationNodeId); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigIO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigIO.java index a900a95a..4421a430 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigIO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigIO.java @@ -11,9 +11,11 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.function.Function; +import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -35,6 +37,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationValueDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueConverter; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueConverterService; +import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConfigurationFormat; @Lazy @Component @@ -49,6 +52,9 @@ public class ExamConfigIO { private static final byte[] XML_PLIST_END_UTF_8 = Utils.toByteArray(Constants.XML_PLIST_END); private static final byte[] XML_DICT_START_UTF_8 = Utils.toByteArray(Constants.XML_DICT_START); private static final byte[] XML_DICT_END_UTF_8 = Utils.toByteArray(Constants.XML_DICT_END); + private static final byte[] JSON_START = Utils.toByteArray("{"); + private static final byte[] JSON_END = Utils.toByteArray("}"); + private static final byte[] JSON_SEPARATOR = Utils.toByteArray(Constants.LIST_SEPARATOR); private final ConfigurationAttributeDAO configurationAttributeDAO; private final ConfigurationValueDAO configurationValueDAO; @@ -68,7 +74,8 @@ public class ExamConfigIO { } @Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME) - void exportPlainXML( + void exportPlain( + final ConfigurationFormat exportFormat, final OutputStream out, final Long institutionId, final Long configurationNodeId) { @@ -82,6 +89,7 @@ public class ExamConfigIO { .getOrThrow() .stream() .flatMap(this::convertAttribute) + .filter(exportFormatBasedAttributeFilter(exportFormat)) .sorted() .collect(Collectors.toList()); @@ -94,25 +102,39 @@ public class ExamConfigIO { getConfigurationValueSupplier(institutionId, configurationId); try { - // write headers - out.write(XML_VERSION_HEADER_UTF_8); - out.write(XML_DOCTYPE_HEADER_UTF_8); - // plist open - out.write(XML_PLIST_START_V1_UTF_8); - out.write(XML_DICT_START_UTF_8); + writeHeader(exportFormat, out); // write attributes - for (final ConfigurationAttribute attribute : sortedAttributes) { - this.attributeValueConverterService.getAttributeValueConverter(attribute).convertToXML( - out, - attribute, - configurationValueSupplier); + final Iterator iterator = sortedAttributes.iterator(); + while (iterator.hasNext()) { + + final ConfigurationAttribute attribute = iterator.next(); + final AttributeValueConverter attributeValueConverter = + this.attributeValueConverterService.getAttributeValueConverter(attribute); + + switch (exportFormat) { + case XML: { + attributeValueConverter.convertToXML( + out, + attribute, + configurationValueSupplier); + break; + } + case JSON: { + attributeValueConverter.convertToJSON( + out, + attribute, + configurationValueSupplier); + if (iterator.hasNext()) { + out.write(JSON_SEPARATOR); + } + break; + } + } } - // plist close - out.write(XML_DICT_END_UTF_8); - out.write(XML_PLIST_END_UTF_8); + writeFooter(exportFormat, out); out.flush(); if (log.isDebugEnabled()) { @@ -131,6 +153,49 @@ public class ExamConfigIO { } } + private Predicate exportFormatBasedAttributeFilter(final ConfigurationFormat format) { + // Filter originatorVersion according to: https://www.safeexambrowser.org/developer/seb-config-key.html + return attr -> !("originatorVersion".equals(attr.getName()) && format == ConfigurationFormat.JSON); + } + + private void writeFooter( + final ConfigurationFormat exportFormat, + final OutputStream out) throws IOException { + + if (exportFormat == ConfigurationFormat.XML) { + // plist close + out.write(XML_DICT_END_UTF_8); + out.write(XML_PLIST_END_UTF_8); + } else { + out.write(JSON_END); + } + } + + private void writeHeader( + final ConfigurationFormat exportFormat, + final OutputStream out) throws IOException { + + if (exportFormat == ConfigurationFormat.XML) { + writeXMLHeaderInformation(out); + } else { + writeJSONHeaderInformation(out); + } + } + + private void writeJSONHeaderInformation(final OutputStream out) throws IOException { + out.write(JSON_START); + } + + private void writeXMLHeaderInformation(final OutputStream out) throws IOException { + // write headers + out.write(XML_VERSION_HEADER_UTF_8); + out.write(XML_DOCTYPE_HEADER_UTF_8); + + // plist open + out.write(XML_PLIST_START_V1_UTF_8); + out.write(XML_DICT_START_UTF_8); + } + private Stream convertAttribute(final ConfigurationAttribute attr) { final AttributeValueConverter attributeValueConverter = this.attributeValueConverterService.getAttributeValueConverter(attr); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebExamConfigServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebExamConfigServiceImpl.java index bd773b64..d3ce36fb 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebExamConfigServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebExamConfigServiceImpl.java @@ -13,7 +13,11 @@ import java.io.OutputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -21,6 +25,8 @@ import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; +import ch.ethz.seb.sebserver.gbl.api.APIMessage; +import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException; import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues; @@ -29,6 +35,7 @@ import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; 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.ExamConfigurationMapDAO; +import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConfigurationFormat; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConfigurationValueValidator; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebExamConfigService; @@ -77,8 +84,28 @@ public class SebExamConfigServiceImpl implements SebExamConfigService { @Override public void validate(final ConfigurationTableValues tableValue) throws FieldValidationException { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("TODO"); + final List errors = tableValue.values.stream() + .map(tv -> new ConfigurationValue( + null, + tableValue.institutionId, + tableValue.configurationId, + tv.attributeId, + tv.listIndex, + tv.value)) + .flatMap(cv -> { + try { + validate(cv); + return Stream.empty(); + } catch (final FieldValidationException fve) { + return Stream.of(fve); + } + }) + .map(fve -> fve.apiMessage) + .collect(Collectors.toList()); + + if (!errors.isEmpty()) { + throw new APIMessageException(errors); + } } @Override @@ -87,48 +114,16 @@ public class SebExamConfigServiceImpl implements SebExamConfigService { final Long institutionId, final Long configurationNodeId) { - if (log.isDebugEnabled()) { - log.debug("Start to stream plain text SEB clonfiguration data"); - } + this.exportPlain(ConfigurationFormat.XML, out, institutionId, configurationNodeId); + } - PipedOutputStream pout = null; - PipedInputStream pin = null; - try { - pout = new PipedOutputStream(); - pin = new PipedInputStream(pout); - - this.examConfigIO.exportPlainXML( - pout, - institutionId, - configurationNodeId); - - IOUtils.copyLarge(pin, out); - - pout.flush(); - pout.close(); - pin.close(); - - } catch (final IOException e) { - log.error("Error while stream plain text SEB clonfiguration data: ", e); - } finally { - try { - if (pin != null) - pin.close(); - } catch (final IOException e1) { - log.error("Failed to close PipedInputStream: ", e1); - } - try { - if (pout != null) - pout.close(); - } catch (final IOException e1) { - log.error("Failed to close PipedOutputStream: ", e1); - } - - if (log.isDebugEnabled()) { - log.debug("Finished to stream plain text SEB clonfiguration data"); - } - } + @Override + public void exportPlainJSON( + final OutputStream out, + final Long institutionId, + final Long configurationNodeId) { + this.exportPlain(ConfigurationFormat.JSON, out, institutionId, configurationNodeId); } public Result getDefaultConfigurationIdForExam(final Long examId) { @@ -160,12 +155,125 @@ public class SebExamConfigServiceImpl implements SebExamConfigService { } @Override - public String generateConfigKey(final Long configurationNodeId) { + public Result generateConfigKey( + final Long institutionId, + final Long configurationNodeId) { - //DigestUtils.sha1Hex(data) + if (log.isDebugEnabled()) { + log.debug("Start to stream plain JSON SEB clonfiguration data for Config-Key generation"); + } - // TODO https://www.safeexambrowser.org/developer/seb-config-key.html - throw new UnsupportedOperationException("TODO"); + if (log.isTraceEnabled()) { + PipedOutputStream pout = null; + PipedInputStream pin = null; + try { + pout = new PipedOutputStream(); + pin = new PipedInputStream(pout); + this.examConfigIO.exportPlain( + ConfigurationFormat.JSON, + pout, + institutionId, + configurationNodeId); + + final String json = IOUtils.toString(pin, "UTF-8"); + + log.trace("SEB Configuration JSON to create Config-Key: {}", json); + } catch (final Exception e) { + log.error("Failed to trace SEB Configuration JSON: ", e); + } + } + + PipedOutputStream pout = null; + PipedInputStream pin = null; + try { + pout = new PipedOutputStream(); + pin = new PipedInputStream(pout); + + this.examConfigIO.exportPlain( + ConfigurationFormat.JSON, + pout, + institutionId, + configurationNodeId); + + final String configKey = DigestUtils.sha256Hex(pin); + + pout.flush(); + pout.close(); + pin.close(); + + return Result.of(configKey); + + } catch (final IOException e) { + log.error("Error while stream plain JSON SEB clonfiguration data for Config-Key generation: ", e); + return Result.ofError(e); + } finally { + try { + if (pin != null) + pin.close(); + } catch (final IOException e1) { + log.error("Failed to close PipedInputStream: ", e1); + } + try { + if (pout != null) + pout.close(); + } catch (final IOException e1) { + log.error("Failed to close PipedOutputStream: ", e1); + } + + if (log.isDebugEnabled()) { + log.debug("Finished to stream plain JSON SEB clonfiguration data for Config-Key generation"); + } + } + } + + private void exportPlain( + final ConfigurationFormat exportFormat, + final OutputStream out, + final Long institutionId, + final Long configurationNodeId) { + + if (log.isDebugEnabled()) { + log.debug("Start to stream plain text SEB clonfiguration data"); + } + + PipedOutputStream pout = null; + PipedInputStream pin = null; + try { + pout = new PipedOutputStream(); + pin = new PipedInputStream(pout); + + this.examConfigIO.exportPlain( + exportFormat, + pout, + institutionId, + configurationNodeId); + + IOUtils.copyLarge(pin, out); + + pout.flush(); + pout.close(); + pin.close(); + + } catch (final IOException e) { + log.error("Error while stream plain text SEB clonfiguration data: ", e); + } finally { + try { + if (pin != null) + pin.close(); + } catch (final IOException e1) { + log.error("Failed to close PipedInputStream: ", e1); + } + try { + if (pout != null) + pout.close(); + } catch (final IOException e1) { + log.error("Failed to close PipedOutputStream: ", e1); + } + + if (log.isDebugEnabled()) { + log.debug("Finished to stream plain text SEB clonfiguration data"); + } + } } } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/converter/IntegerConverter.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/converter/IntegerConverter.java index b9aae121..315f9f22 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/converter/IntegerConverter.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/converter/IntegerConverter.java @@ -10,9 +10,6 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl.converter; import java.io.IOException; import java.io.OutputStream; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; import java.util.Set; import java.util.function.Function; @@ -35,16 +32,24 @@ public class IntegerConverter implements AttributeValueConverter { private static final Logger log = LoggerFactory.getLogger(IntegerConverter.class); - public static final Set SUPPORTED_TYPES = Collections.unmodifiableSet( - new HashSet<>(Arrays.asList( - AttributeType.INTEGER, - AttributeType.SLIDER, - AttributeType.SINGLE_SELECTION, - AttributeType.RADIO_SELECTION))); + public static final Set SUPPORTED_ATTR_NAMES = Utils.immutableSetOf( + "taskBarHeight", + "allowedDisplaysMaxNumber"); + + public static final Set SUPPORTED_TYPES = Utils.immutableSetOf( + AttributeType.INTEGER, + AttributeType.SLIDER, + AttributeType.SINGLE_SELECTION, + AttributeType.RADIO_SELECTION); private static final String XML_TEMPLATE = "%s%s"; private static final String JSON_TEMPLATE = "\"%s\":%s"; + @Override + public Set names() { + return SUPPORTED_ATTR_NAMES; + } + @Override public Set types() { return SUPPORTED_TYPES; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/converter/StringConverter.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/converter/StringConverter.java index a6875882..132a4c94 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/converter/StringConverter.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/converter/StringConverter.java @@ -44,7 +44,7 @@ public class StringConverter implements AttributeValueConverter { private static final String XML_TEMPLATE_EMPTY = "%s"; private static final String JSON_TEMPLATE = "\"%s\":\"%s\""; - private static final String JSON_TEMPLATE_EMPTY = "\"%s\":"; + private static final String JSON_TEMPLATE_EMPTY = "\"%s\":\"\""; @Override public Set types() { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/APIExceptionHandler.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/APIExceptionHandler.java index 128dc671..e7317b2f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/APIExceptionHandler.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/APIExceptionHandler.java @@ -78,7 +78,7 @@ public class APIExceptionHandler extends ResponseEntityExceptionHandler { } @ExceptionHandler(OAuth2Exception.class) - public ResponseEntity handleBeanValidationException( + public ResponseEntity handleOAuth2Exception( final OAuth2Exception ex, final WebRequest request) { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java index df39df78..c0ec1f44 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java @@ -22,6 +22,7 @@ import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBo import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.POSTMapper; import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM; +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.ConfigurationNode; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; @@ -84,20 +85,42 @@ public class ConfigurationNodeController extends EntityController downloadPlainXMLConfig( @@ -108,7 +131,7 @@ public class ConfigurationNodeController extends EntityController this.sebExamConfigService .exportPlainXML(out, institutionId, modelId); diff --git a/src/main/resources/data-demo.sql b/src/main/resources/data-demo.sql index 03bfddf4..8bb8c644 100644 --- a/src/main/resources/data-demo.sql +++ b/src/main/resources/data-demo.sql @@ -215,7 +215,7 @@ INSERT IGNORE INTO configuration_attribute VALUES (259, 'SOCKSPassword', 'TEXT_FIELD', 220, null, null, 'groupId=socks,createDefaultValue=true', null), (260, 'RTSPEnable', 'CHECKBOX', 220, null, null, 'groupId=rtsp,createDefaultValue=true', 'false'), (261, 'RTSPProxy', 'TEXT_FIELD', 220, null, null, 'groupId=rtsp,createDefaultValue=true', null), - (262, 'RTSPPort', 'INTEGER', 220, null, null, 'groupId=rtsp,createDefaultValue=true', '1080'), + (262, 'RTSPPort', 'INTEGER', 220, null, null, 'groupId=rtsp,createDefaultValue=true', '554'), (263, 'RTSPRequiresPassword', 'CHECKBOX', 220, null, null, 'groupId=rtsp,createDefaultValue=true', 'false'), (264, 'RTSPUsername', 'TEXT_FIELD', 220, null, null, 'groupId=rtsp,createDefaultValue=true', null), (265, 'RTSPPassword', 'TEXT_FIELD', 220, null, null, 'groupId=rtsp,createDefaultValue=true', null), @@ -228,7 +228,7 @@ INSERT IGNORE INTO configuration_attribute VALUES (304, 'enablePrivateClipboard', 'CHECKBOX', null, null, null, null, 'true'), (305, 'enableLogging', 'CHECKBOX', null, null, null, null, 'false'), (306, 'logDirectoryWin', 'TEXT_FIELD', null, null, null, null, ''), - (307, 'logDirectoryOSX', 'TEXT_FIELD', null, null, null, null, '~/Documents'), + (307, 'logDirectoryOSX', 'TEXT_FIELD', null, null, null, null, 'NSTemporaryDirectory'), (308, 'minMacOSVersion', 'SINGLE_SELECTION', null, '0,1,2,3,4,5,6,7', null, null, '0'), (309, 'enableAppSwitcherCheck', 'CHECKBOX', null, null, null, null, 'true'), (310, 'forceAppFolderInstall', 'CHECKBOX', null, null, null, null, 'true'), diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml index 30fe5caa..15ccd15d 100644 --- a/src/main/resources/logback-spring.xml +++ b/src/main/resources/logback-spring.xml @@ -33,6 +33,7 @@ + diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 8a53f70e..27ce5e32 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -392,6 +392,7 @@ sebserver.examconfig.action.list.new=New Exam Configuration sebserver.examconfig.action.list.view=View Configuration sebserver.examconfig.action.list.modify=Edit Settings sebserver.examconfig.action.list.modify.properties=Edit Configuration +sebserver.examconfig.action.view=View Configuration sebserver.examconfig.action.modify=Edit Settings sebserver.examconfig.action.modify.properties=Edit Configuration sebserver.examconfig.action.save=Save @@ -400,12 +401,14 @@ sebserver.examconfig.action.saveToHistory.success=Successfully saved in history sebserver.examconfig.action.undo=Undo sebserver.examconfig.action.undo.success=Successfully reverted to last saved state sebserver.examconfig.action.export.plainxml=Export XML +sebserver.examconfig.action.get-config-key=Export Config-Key sebserver.examconfig.form.title.new=New Exam Configuration sebserver.examconfig.form.title=Exam Configuration sebserver.examconfig.form.name=Name sebserver.examconfig.form.description=Description sebserver.examconfig.form.status=Status +sebserver.examconfig.form.config-key.title=Config Key sebserver.examconfig.status.CONSTRUCTION=Under Construction sebserver.examconfig.status.READY_TO_USE=Ready To Use diff --git a/src/main/resources/static/images/secure.png b/src/main/resources/static/images/secure.png new file mode 100644 index 00000000..ce731f05 Binary files /dev/null and b/src/main/resources/static/images/secure.png differ diff --git a/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/exam/SebExamConfigurationRequestTest.java b/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/exam/SebExamConfigurationRequestTest.java index d72880bf..c62dc8f2 100644 --- a/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/exam/SebExamConfigurationRequestTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/exam/SebExamConfigurationRequestTest.java @@ -58,7 +58,7 @@ public class SebExamConfigurationRequestTest extends ExamAPIIntegrationTester { final String contentAsString = configResponse.getContentAsString(); assertEquals( - "allowAudioCaptureallowBrowsingBackForwardallowDictionaryLookupallowDisplayMirroringallowDownUploadsallowedDisplayBuiltinallowedDisplaysMaxNumber1allowFlashFullscreenallowPDFPlugInallowQuitallowScreenSharingallowSiriallowSpellCheckallowSpellCheckDictionaryda-DKen-AUen-GBen-USes-ESfr-FRpt-PTsv-SEsv-FIallowSwitchToApplicationsallowUserAppFolderInstallallowVideoCaptureallowVirtualMachineaudioControlEnabledaudioMuteaudioSetVolumeLevelaudioVolumeLevel25blockPopUpWindowsbrowserUserAgentbrowserUserAgentMac0browserUserAgentMacCustombrowserUserAgentWinDesktopMode0browserUserAgentWinDesktopModeCustombrowserUserAgentWinTouchMode0browserUserAgentWinTouchModeCustombrowserViewMode0browserWindowAllowReloadbrowserWindowTitleSuffixchooseFileToUploadPolicy0createNewDesktopdetectStoppedProcessdownloadAndOpenSebConfigdownloadDirectoryOSXdownloadDirectoryWindownloadPDFFilesenableAltEscenableAltF4enableAltMouseWheelenableAltTabenableAppSwitcherCheckenableBrowserWindowToolbarenableCtrlEscenableEscenableF1enableF10enableF11enableF12enableF2enableF3enableF4enableF5enableF6enableF7enableF8enableF9enableJavaenableJavaScriptenableLoggingenablePlugInsenablePrintScreenenablePrivateClipboardenableRightMouseenableSebBrowserenableStartMenuenableTouchExitenableZoomPageenableZoomTextexitKey12exitKey210exitKey35forceAppFolderInstallhashedAdminPasswordhashedQuitPasswordhideBrowserWindowToolbarignoreExitKeysinsideSebEnableChangeAPasswordinsideSebEnableEaseOfAccessinsideSebEnableLockThisComputerinsideSebEnableLogOffinsideSebEnableNetworkConnectionSelectorinsideSebEnableShutDowninsideSebEnableStartTaskManagerinsideSebEnableSwitchUserinsideSebEnableVmWareClientShadekillExplorerShelllogDirectoryOSX~/DocumentslogDirectoryWinmainBrowserWindowHeight100%mainBrowserWindowPositioning1mainBrowserWindowWidth100%minMacOSVersion0newBrowserWindowAllowReloadnewBrowserWindowByLinkBlockForeignnewBrowserWindowByLinkHeight100%newBrowserWindowByLinkPolicy2newBrowserWindowByLinkPositioning2newBrowserWindowByLinkWidth100%newBrowserWindowNavigationnewBrowserWindowShowReloadWarningopenDownloadsoriginatorVersionSEB_Server_0.3.0permittedProcessesprohibitedProcessesproxiesAutoConfigurationEnabledAutoConfigurationJavaScriptAutoConfigurationURLAutoDiscoveryEnabledExceptionsListExcludeSimpleHostnamesFTPEnableFTPPassiveFTPPasswordFTPPort21FTPProxyFTPRequiresPasswordFTPUsernameHTTPEnableHTTPPasswordHTTPPort80HTTPProxyHTTPRequiresPasswordHTTPSEnableHTTPSPasswordHTTPSPort443HTTPSProxyHTTPSRequiresPasswordHTTPSUsernameHTTPUsernameRTSPEnableRTSPPasswordRTSPPort1080RTSPProxyRTSPRequiresPasswordRTSPUsernameSOCKSEnableSOCKSPasswordSOCKSPort1080SOCKSProxySOCKSRequiresPasswordSOCKSUsernameproxySettingsPolicy0quitURLquitURLConfirmremoveBrowserProfileremoveLocalStoragerestartExamPasswordProtectedrestartExamTextrestartExamURLrestartExamUseStartURLsebConfigPurpose0sebServicePolicy2showInputLanguageshowMenuBarshowReloadButtonshowReloadWarningshowTaskBarshowTimetaskBarHeight40URLFilterEnableURLFilterEnableContentFilterURLFilterRuleszoomMode0", + "allowAudioCaptureallowBrowsingBackForwardallowDictionaryLookupallowDisplayMirroringallowDownUploadsallowedDisplayBuiltinallowedDisplaysMaxNumber1allowFlashFullscreenallowPDFPlugInallowQuitallowScreenSharingallowSiriallowSpellCheckallowSpellCheckDictionaryda-DKen-AUen-GBen-USes-ESfr-FRpt-PTsv-SEsv-FIallowSwitchToApplicationsallowUserAppFolderInstallallowVideoCaptureallowVirtualMachineaudioControlEnabledaudioMuteaudioSetVolumeLevelaudioVolumeLevel25blockPopUpWindowsbrowserUserAgentbrowserUserAgentMac0browserUserAgentMacCustombrowserUserAgentWinDesktopMode0browserUserAgentWinDesktopModeCustombrowserUserAgentWinTouchMode0browserUserAgentWinTouchModeCustombrowserViewMode0browserWindowAllowReloadbrowserWindowTitleSuffixchooseFileToUploadPolicy0createNewDesktopdetectStoppedProcessdownloadAndOpenSebConfigdownloadDirectoryOSXdownloadDirectoryWindownloadPDFFilesenableAltEscenableAltF4enableAltMouseWheelenableAltTabenableAppSwitcherCheckenableBrowserWindowToolbarenableCtrlEscenableEscenableF1enableF10enableF11enableF12enableF2enableF3enableF4enableF5enableF6enableF7enableF8enableF9enableJavaenableJavaScriptenableLoggingenablePlugInsenablePrintScreenenablePrivateClipboardenableRightMouseenableSebBrowserenableStartMenuenableTouchExitenableZoomPageenableZoomTextexitKey12exitKey210exitKey35forceAppFolderInstallhashedAdminPasswordhashedQuitPasswordhideBrowserWindowToolbarignoreExitKeysinsideSebEnableChangeAPasswordinsideSebEnableEaseOfAccessinsideSebEnableLockThisComputerinsideSebEnableLogOffinsideSebEnableNetworkConnectionSelectorinsideSebEnableShutDowninsideSebEnableStartTaskManagerinsideSebEnableSwitchUserinsideSebEnableVmWareClientShadekillExplorerShelllogDirectoryOSX~/DocumentslogDirectoryWinmainBrowserWindowHeight100%mainBrowserWindowPositioning1mainBrowserWindowWidth100%minMacOSVersion0newBrowserWindowAllowReloadnewBrowserWindowByLinkBlockForeignnewBrowserWindowByLinkHeight100%newBrowserWindowByLinkPolicy2newBrowserWindowByLinkPositioning2newBrowserWindowByLinkWidth100%newBrowserWindowNavigationnewBrowserWindowShowReloadWarningopenDownloadsoriginatorVersionSEB_Server_0.3.0permittedProcessesprohibitedProcessesproxiesAutoConfigurationEnabledAutoConfigurationJavaScriptAutoConfigurationURLAutoDiscoveryEnabledExceptionsListExcludeSimpleHostnamesFTPEnableFTPPassiveFTPPasswordFTPPort21FTPProxyFTPRequiresPasswordFTPUsernameHTTPEnableHTTPPasswordHTTPPort80HTTPProxyHTTPRequiresPasswordHTTPSEnableHTTPSPasswordHTTPSPort443HTTPSProxyHTTPSRequiresPasswordHTTPSUsernameHTTPUsernameRTSPEnableRTSPPasswordRTSPPort1080RTSPProxyRTSPRequiresPasswordRTSPUsernameSOCKSEnableSOCKSPasswordSOCKSPort1080SOCKSProxySOCKSRequiresPasswordSOCKSUsernameproxySettingsPolicy0quitURLquitURLConfirmremoveBrowserProfileremoveLocalStoragerestartExamPasswordProtectedrestartExamTextrestartExamURLrestartExamUseStartURLsebConfigPurpose0sebServicePolicy2showInputLanguageshowMenuBarshowReloadButtonshowReloadWarningshowTaskBarshowTimetaskBarHeight40URLFilterEnableURLFilterEnableContentFilterURLFilterRuleszoomMode0", contentAsString); // check cache diff --git a/src/test/resources/data-test-additional.sql b/src/test/resources/data-test-additional.sql index c1998eb7..4a2bdc7c 100644 --- a/src/test/resources/data-test-additional.sql +++ b/src/test/resources/data-test-additional.sql @@ -183,7 +183,7 @@ INSERT IGNORE INTO configuration_attribute VALUES (259, 'SOCKSPassword', 'TEXT_FIELD', 220, null, null, 'groupId=socks,createDefaultValue=true', null), (260, 'RTSPEnable', 'CHECKBOX', 220, null, null, 'groupId=rtsp,createDefaultValue=true', 'false'), (261, 'RTSPProxy', 'TEXT_FIELD', 220, null, null, 'groupId=rtsp,createDefaultValue=true', null), - (262, 'RTSPPort', 'INTEGER', 220, null, null, 'groupId=rtsp,createDefaultValue=true', '1080'), + (262, 'RTSPPort', 'INTEGER', 220, null, null, 'groupId=rtsp,createDefaultValue=true', '554'), (263, 'RTSPRequiresPassword', 'CHECKBOX', 220, null, null, 'groupId=rtsp,createDefaultValue=true', 'false'), (264, 'RTSPUsername', 'TEXT_FIELD', 220, null, null, 'groupId=rtsp,createDefaultValue=true', null), (265, 'RTSPPassword', 'TEXT_FIELD', 220, null, null, 'groupId=rtsp,createDefaultValue=true', null), @@ -196,7 +196,7 @@ INSERT IGNORE INTO configuration_attribute VALUES (304, 'enablePrivateClipboard', 'CHECKBOX', null, null, null, null, 'true'), (305, 'enableLogging', 'CHECKBOX', null, null, null, null, 'false'), (306, 'logDirectoryWin', 'TEXT_FIELD', null, null, null, null, ''), - (307, 'logDirectoryOSX', 'TEXT_FIELD', null, null, null, null, '~/Documents'), + (307, 'logDirectoryOSX', 'TEXT_FIELD', null, null, null, null, 'NSTemporaryDirectory'), (308, 'minMacOSVersion', 'SINGLE_SELECTION', null, '0,1,2,3,4,5,6,7', null, null, '0'), (309, 'enableAppSwitcherCheck', 'CHECKBOX', null, null, null, null, 'true'), (310, 'forceAppFolderInstall', 'CHECKBOX', null, null, null, null, 'true'),