diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/Constants.java b/src/main/java/ch/ethz/seb/sebserver/gbl/Constants.java index f0c9c690..7940521c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/Constants.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/Constants.java @@ -35,6 +35,7 @@ public final class Constants { public static final long HOUR_IN_MILLIS = 60 * MINUTE_IN_MILLIS; public static final long DAY_IN_MILLIS = 24 * HOUR_IN_MILLIS; + public static final Character CARRIAGE_RETURN = '\n'; public static final Character CURLY_BRACE_OPEN = '{'; public static final Character CURLY_BRACE_CLOSE = '}'; public static final Character COLON = ':'; diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/OpenEdxSebRestriction.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/OpenEdxSebRestriction.java index 4b05dcaf..10c74f69 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/OpenEdxSebRestriction.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/OpenEdxSebRestriction.java @@ -93,7 +93,7 @@ public class OpenEdxSebRestriction { public final Collection permissionComponents; @JsonProperty(ATTR_USER_BANNING_ENABLED) - public final boolean banningEnabled; + public final Boolean banningEnabled; @JsonCreator OpenEdxSebRestriction( diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java index 085b16f4..5ee09d82 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java @@ -175,6 +175,56 @@ public final class Utils { .collect(Collectors.toList())); } + public static Collection getListOfLines(final String list) { + if (list == null) { + return Collections.emptyList(); + } + + return Arrays.asList(StringUtils.split( + streamlineCarriageReturn(list), + Constants.CARRIAGE_RETURN)); + } + + public static String convertCarriageReturnToListSeparator(final String value) { + if (value == null) { + return null; + } + + return streamlineCarriageReturn(value.trim()) + .replace(Constants.CARRIAGE_RETURN, Constants.LIST_SEPARATOR_CHAR); + } + + public static String convertListSeparatorToCarriageReturn(final String value) { + if (value == null) { + return null; + } + + return value + .trim() + .replace(Constants.LIST_SEPARATOR_CHAR, Constants.CARRIAGE_RETURN); + } + + public static String streamlineCarriageReturn(final String value) { + if (value == null) { + return null; + } + + return value.replace('\r', '\n') + .replace("\r\n", "\n"); + } + + public static Collection getListFromString(final String list) { + return getListFromString(list, Constants.LIST_SEPARATOR); + } + + public static Collection getListFromString(final String list, final String separator) { + if (list == null) { + return Collections.emptyList(); + } + + return Arrays.asList(StringUtils.split(list, separator)); + } + public static Result dateTimeStringToTimestamp(final String startTime) { return Result.tryCatch(() -> { return DateTime.parse(startTime, Constants.STANDARD_DATE_TIME_FORMATTER).getMillis(); 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 17327f7c..c787cde6 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 @@ -394,6 +394,8 @@ public class ExamForm implements TemplateComposer { // additional data in read-only view if (readonly && !importFromQuizData) { + this.widgetFactory.labelSeparator(content); + // List of SEB Configuration this.widgetFactory.labelLocalized( content, @@ -479,6 +481,8 @@ public class ExamForm implements TemplateComposer { .noEventPropagation() .publishIf(() -> userGrantCheck.r() && configurationTable.hasAnyContent()); + this.widgetFactory.labelSeparator(content); + // List of Indicators this.widgetFactory.labelLocalized( content, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamSebRestrictionSettings.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamSebRestrictionSettings.java index b523a79b..2cd0ba37 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamSebRestrictionSettings.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamSebRestrictionSettings.java @@ -8,6 +8,9 @@ package ch.ethz.seb.sebserver.gui.content; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; @@ -16,14 +19,14 @@ import java.util.function.Supplier; import org.apache.commons.lang3.StringUtils; import org.eclipse.swt.widgets.Composite; +import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.api.API; -import ch.ethz.seb.sebserver.gbl.api.JSONMapper; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSebRestriction; import ch.ethz.seb.sebserver.gbl.model.exam.SebRestriction; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType; import ch.ethz.seb.sebserver.gbl.util.Utils; -import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition; +import ch.ethz.seb.sebserver.gui.form.Form; import ch.ethz.seb.sebserver.gui.form.FormBuilder; import ch.ethz.seb.sebserver.gui.form.FormHandle; import ch.ethz.seb.sebserver.gui.service.ResourceService; @@ -54,6 +57,10 @@ public class ExamSebRestrictionSettings { new LocTextKey("sebserver.exam.form.sebrestriction.WHITELIST_PATHS"); private final static LocTextKey SEB_RESTRICTION_FORM_EDX_PERMISSIONS = new LocTextKey("sebserver.exam.form.sebrestriction.PERMISSION_COMPONENTS"); + private final static LocTextKey SEB_RESTRICTION_FORM_EDX_BLACKLIST_CHAPTERS = + new LocTextKey("sebserver.exam.form.sebrestriction.BLACKLIST_CHAPTERS"); + private final static LocTextKey SEB_RESTRICTION_FORM_EDX_USER_BANNING_ENABLED = + new LocTextKey("sebserver.exam.form.sebrestriction.USER_BANNING_ENABLED"); static final String PAGE_CONTEXT_ATTR_LMS_TYPE = "ATTR_LMS_TYPE"; @@ -66,7 +73,8 @@ public class ExamSebRestrictionSettings { new ModalInputDialog>( action.pageContext().getParent().getShell(), pageService.getWidgetFactory()) - .setVeryLargeDialogWidth(); + .setDialogWidth(740) + .setDialogHeight(400); final SebRestrictionPropertiesForm bindFormContext = new SebRestrictionPropertiesForm( pageService, @@ -96,19 +104,35 @@ public class ExamSebRestrictionSettings { final LmsType lmsType = getLmsType(pageContext); SebRestriction bodyValue = null; try { - final JSONMapper jsonMapper = pageService.getJSONMapper(); - if (lmsType == LmsType.OPEN_EDX) { - final OpenEdxSebRestriction edxProperties = jsonMapper.readValue( - formHandle.getFormBinding().getFormAsJson(), - OpenEdxSebRestriction.class); - bodyValue = SebRestriction.from(Long.parseLong(entityKey.modelId), edxProperties); - } else { - bodyValue = jsonMapper.readValue( - formHandle.getFormBinding().getFormAsJson(), - SebRestriction.class); - } - } catch (final Exception e) { + final Form form = formHandle.getForm(); + final Collection browserKeys = Utils.getListOfLines( + form.getFieldValue(SebRestriction.ATTR_BROWSER_KEYS)); + final Map additionalAttributes = new HashMap<>(); + if (lmsType == LmsType.OPEN_EDX) { + additionalAttributes.put( + OpenEdxSebRestriction.ATTR_PERMISSION_COMPONENTS, + form.getFieldValue(OpenEdxSebRestriction.ATTR_PERMISSION_COMPONENTS)); + additionalAttributes.put( + OpenEdxSebRestriction.ATTR_WHITELIST_PATHS, + form.getFieldValue(OpenEdxSebRestriction.ATTR_WHITELIST_PATHS)); + additionalAttributes.put( + OpenEdxSebRestriction.ATTR_USER_BANNING_ENABLED, + form.getFieldValue(OpenEdxSebRestriction.ATTR_USER_BANNING_ENABLED)); + additionalAttributes.put( + OpenEdxSebRestriction.ATTR_BLACKLIST_CHAPTERS, + Utils.convertCarriageReturnToListSeparator( + form.getFieldValue(OpenEdxSebRestriction.ATTR_BLACKLIST_CHAPTERS))); + } + + bodyValue = new SebRestriction( + Long.parseLong(entityKey.modelId), + null, + browserKeys, + additionalAttributes); + + } catch (final Exception e) { + e.printStackTrace(); } return !pageService @@ -116,17 +140,8 @@ public class ExamSebRestrictionSettings { .getBuilder(SaveSebRestriction.class) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .withBody(bodyValue) - //.withFormBinding(formHandle.getFormBinding()) .call() .onError(formHandle::handleError) - .map(mapping -> { - pageService.executePageAction( - pageService.pageActionBuilder(pageContext.clearEntityKeys()) - .newAction(ActionDefinition.EXAM_VIEW_FROM_LIST) - .withEntityKey(pageContext.getParentEntityKey()) - .create()); - return mapping; - }) .hasError(); } @@ -152,15 +167,22 @@ public class ExamSebRestrictionSettings { final EntityKey entityKey = this.pageContext.getEntityKey(); final LmsType lmsType = getLmsType(this.pageContext); + final Composite content = this.pageService + .getWidgetFactory() + .createPopupScrollComposite(parent); + final SebRestriction sebRestriction = restService .getBuilder(GetSebRestriction.class) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .call() .getOrThrow(); - final PageContext formContext = this.pageContext.clearEntityKeys(); + final PageContext formContext = this.pageContext + .copyOf(content) + .clearEntityKeys(); + final FormHandle formHandle = this.pageService.formBuilder( - formContext.copyOf(parent), 3) + formContext, 3) .withDefaultSpanEmptyCell(0) .withEmptyCellSeparation(false) .readonly(false) @@ -168,14 +190,14 @@ public class ExamSebRestrictionSettings { .addField(FormBuilder.text( SebRestriction.ATTR_CONFIG_KEYS, SEB_RESTRICTION_FORM_CONFIG_KEYS, - StringUtils.join(sebRestriction.getConfigKeys(), '\n')) - .asArea(25) + StringUtils.join(sebRestriction.getConfigKeys(), Constants.CARRIAGE_RETURN)) + .asArea(50) .readonly(true)) .addField(FormBuilder.text( SebRestriction.ATTR_BROWSER_KEYS, SEB_RESTRICTION_FORM_BROWSER_KEYS, - StringUtils.join(sebRestriction.getBrowserExamKeys(), '\n')) + StringUtils.join(sebRestriction.getBrowserExamKeys(), Constants.CARRIAGE_RETURN)) .asArea()) .addFieldIf( @@ -196,6 +218,26 @@ public class ExamSebRestrictionSettings { .get(OpenEdxSebRestriction.ATTR_PERMISSION_COMPONENTS), () -> resourceService.sebRestrictionPermissionResources())) + .addFieldIf( + () -> lmsType == LmsType.OPEN_EDX, + () -> FormBuilder.text( + OpenEdxSebRestriction.ATTR_BLACKLIST_CHAPTERS, + SEB_RESTRICTION_FORM_EDX_BLACKLIST_CHAPTERS, + Utils.convertListSeparatorToCarriageReturn( + sebRestriction + .getAdditionalProperties() + .get(OpenEdxSebRestriction.ATTR_BLACKLIST_CHAPTERS))) + .asArea()) + + .addFieldIf( + () -> lmsType == LmsType.OPEN_EDX, + () -> FormBuilder.checkbox( + OpenEdxSebRestriction.ATTR_USER_BANNING_ENABLED, + SEB_RESTRICTION_FORM_EDX_USER_BANNING_ENABLED, + sebRestriction + .getAdditionalProperties() + .get(OpenEdxSebRestriction.ATTR_USER_BANNING_ENABLED))) + .build(); return () -> formHandle; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigList.java index 233be02f..1ea19cac 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigList.java @@ -149,6 +149,7 @@ public class SebExamConfigList implements TemplateComposer { // configuration template table widgetFactory.label(content, ""); + widgetFactory.labelSeparator(content); widgetFactory.labelLocalizedTitle( content, TITLE_TEMPLATE_TEXT_KEY); @@ -192,7 +193,8 @@ public class SebExamConfigList implements TemplateComposer { .publishIf(examConfigGrant::iw) .newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP_FROM_LIST) - .withSelect(configTable::getSelection, PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY) + .withSelect(configTable::getSelection, PageAction::applySingleSelectionAsEntityKey, + EMPTY_SELECTION_TEXT_KEY) .publishIf(() -> configTable.hasAnyContent()) .newAction(ActionDefinition.SEB_EXAM_CONFIG_MODIFY_PROP_FROM_LIST) 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 0eb208fd..b6bff8e2 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 @@ -289,6 +289,7 @@ public class SebExamConfigPropForm implements TemplateComposer { if (isAttachedToExam) { + widgetFactory.labelSeparator(content); widgetFactory.labelLocalized( content, CustomVariant.TEXT_H3, 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 1097eb02..fc58e7b4 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 @@ -250,12 +250,12 @@ public enum ActionDefinition { ActionCategory.FORM), EXAM_ENABLE_SEB_RESTRICTION( new LocTextKey("sebserver.exam.action.sebrestriction.enable"), - ImageIcon.LOCK, + ImageIcon.UNLOCK, PageStateDefinitionImpl.EXAM_VIEW, ActionCategory.FORM), EXAM_DISABLE_SEB_RESTRICTION( new LocTextKey("sebserver.exam.action.sebrestriction.disable"), - ImageIcon.UNLOCK, + ImageIcon.LOCK, PageStateDefinitionImpl.EXAM_VIEW, ActionCategory.FORM), diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java index e2d6d154..fdc04b92 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java @@ -611,7 +611,7 @@ public class ResourceService { return Arrays.asList(WhiteListPath.values()) .stream() .map(type -> new Tuple<>( - type.name(), + type.key, this.i18nSupport.getText(SEB_RESTRICTION_WHITE_LIST_PREFIX + type.name(), type.key))) .sorted(RESOURCE_COMPARATOR) .collect(Collectors.toList()); @@ -621,7 +621,7 @@ public class ResourceService { return Arrays.asList(PermissionComponent.values()) .stream() .map(type -> new Tuple<>( - type.name(), + type.key, this.i18nSupport.getText(SEB_RESTRICTION_PERMISSIONS_PREFIX + type.name(), type.key))) .sorted(RESOURCE_COMPARATOR) .collect(Collectors.toList()); 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 436f271b..e59911e2 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 @@ -501,7 +501,7 @@ public class WidgetFactory { public Label labelSeparator(final Composite parent) { final Label label = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL); - final GridData data = new GridData(SWT.FILL, SWT.TOP, true, true); + final GridData data = new GridData(SWT.FILL, SWT.TOP, true, false); label.setLayoutData(data); return label; } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/AdditionalAttributesDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/AdditionalAttributesDAO.java index cdfdac8a..f9711e1f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/AdditionalAttributesDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/AdditionalAttributesDAO.java @@ -38,7 +38,7 @@ public interface AdditionalAttributesDAO { * @param entityId the entity identifier (primary key) * @param name the name of the attribute * @param value the value of the attribute */ - void saveAdditionalAttribute( + Result saveAdditionalAttribute( EntityType type, Long entityId, String name, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/AdditionalAttributesDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/AdditionalAttributesDAOImpl.java index 31b7a3fa..5f7804ab 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/AdditionalAttributesDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/AdditionalAttributesDAOImpl.java @@ -59,53 +59,60 @@ public class AdditionalAttributesDAOImpl implements AdditionalAttributesDAO { @Override @Transactional - public void saveAdditionalAttribute( + public Result saveAdditionalAttribute( final EntityType type, final Long entityId, final String name, final String value) { - if (value == null) { - this.delete(entityId, name); - return; - } + return Result.tryCatch(() -> { + if (value == null) { + Result.ofError(new IllegalArgumentException( + "value cannot be null. Use delete to delete an additional attribute")); + } - final Optional id = this.additionalAttributeRecordMapperer - .selectIdsByExample() - .where( - AdditionalAttributeRecordDynamicSqlSupport.entityType, - SqlBuilder.isEqualTo(type.name())) - .and( - AdditionalAttributeRecordDynamicSqlSupport.entityId, - SqlBuilder.isEqualTo(entityId)) - .and( - AdditionalAttributeRecordDynamicSqlSupport.name, - SqlBuilder.isEqualTo(name)) - .build() - .execute() - .stream() - .findFirst(); + final Optional id = this.additionalAttributeRecordMapperer + .selectIdsByExample() + .where( + AdditionalAttributeRecordDynamicSqlSupport.entityType, + SqlBuilder.isEqualTo(type.name())) + .and( + AdditionalAttributeRecordDynamicSqlSupport.entityId, + SqlBuilder.isEqualTo(entityId)) + .and( + AdditionalAttributeRecordDynamicSqlSupport.name, + SqlBuilder.isEqualTo(name)) + .build() + .execute() + .stream() + .findFirst(); - if (id.isPresent()) { - final AdditionalAttributeRecord rec = new AdditionalAttributeRecord( - id.get(), - type.name(), - entityId, - name, - value); - this.additionalAttributeRecordMapperer - .updateByPrimaryKeySelective(rec); - } else { - final AdditionalAttributeRecord rec = new AdditionalAttributeRecord( - null, - type.name(), - entityId, - name, - value); - this.additionalAttributeRecordMapperer - .insert(rec); - } + if (id.isPresent()) { + final AdditionalAttributeRecord rec = new AdditionalAttributeRecord( + id.get(), + type.name(), + entityId, + name, + value); + this.additionalAttributeRecordMapperer + .updateByPrimaryKeySelective(rec); + return this.additionalAttributeRecordMapperer + .selectByPrimaryKey(rec.getId()); + } else { + final AdditionalAttributeRecord rec = new AdditionalAttributeRecord( + null, + type.name(), + entityId, + name, + value); + this.additionalAttributeRecordMapperer + .insert(rec); + + return this.additionalAttributeRecordMapperer + .selectByPrimaryKey(rec.getId()); + } + }); } @Override diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java index dbb16633..ade4406b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java @@ -206,11 +206,17 @@ public class ExamDAOImpl implements ExamDAO { (exam.supporter != null) ? StringUtils.join(exam.supporter, Constants.LIST_SEPARATOR_CHAR) : null, - (exam.type != null) ? exam.type.name() : null, + (exam.type != null) + ? exam.type.name() + : null, exam.quitPassword, - null, // browser keys - (exam.status != null) ? exam.status.name() : null, - BooleanUtils.toIntegerObject(exam.lmsSebRestriction), + exam.browserExamKeys, + (exam.status != null) + ? exam.status.name() + : null, + (exam.lmsSebRestriction != null) + ? BooleanUtils.toIntegerObject(exam.lmsSebRestriction) + : null, null, // updating null, // lastUpdate null // active diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/SebRestrictionService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/SebRestrictionService.java index fa75a13f..934220e8 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/SebRestrictionService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/SebRestrictionService.java @@ -29,10 +29,9 @@ public interface SebRestrictionService { * and given additional restriction properties within the AdditionalAttrtibutes linked * to the given Exam. * - * - * @param exam - * @param sebRestriction - * @return */ + * @param exam the Exam instance to save the SEB restrictions for + * @param sebRestriction SebRestriction data containing generic and LMS specific restriction attributes + * @return Result refer to the given Exam instance or to an error if happened */ Result saveSebRestrictionToExam(Exam exam, SebRestriction sebRestriction); /** Used to apply SEB Client restriction within the LMS API for a specified Exam. diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/SebRestrictionServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/SebRestrictionServiceImpl.java index c48f51b2..f4ea9891 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/SebRestrictionServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/SebRestrictionServiceImpl.java @@ -118,7 +118,10 @@ public class SebRestrictionServiceImpl implements SebRestrictionService { final Collection browserExamKeys = sebRestriction.getBrowserExamKeys(); final Exam newExam = new Exam( exam.id, - null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, + exam.supporter, + exam.status, + exam.lmsSebRestriction, (browserExamKeys != null && !browserExamKeys.isEmpty()) ? StringUtils.join(browserExamKeys, Constants.LIST_SEPARATOR_CHAR) : StringUtils.EMPTY, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java index 6f614a1e..8dcfdbd9 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java @@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.webservice.weblayer.api; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -36,6 +37,7 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; 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; import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException; @@ -47,10 +49,12 @@ import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM; import ch.ethz.seb.sebserver.gbl.model.Page; import ch.ethz.seb.sebserver.gbl.model.PageSortOrder; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; +import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSebRestriction; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; import ch.ethz.seb.sebserver.gbl.model.exam.SebRestriction; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.Features; +import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType; import ch.ethz.seb.sebserver.gbl.model.user.UserRole; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Result; @@ -60,6 +64,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.Authorization import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.AdditionalAttributesDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; @@ -79,6 +84,7 @@ public class ExamAdministrationController extends EntityController { private final ExamDAO examDAO; private final UserDAO userDAO; + private final AdditionalAttributesDAO additionalAttributesDAO; private final LmsAPIService lmsAPIService; private final ExamConfigService sebExamConfigService; private final ExamSessionService examSessionService; @@ -95,7 +101,8 @@ public class ExamAdministrationController extends EntityController { final UserDAO userDAO, final ExamConfigService sebExamConfigService, final ExamSessionService examSessionService, - final SebRestrictionService sebRestrictionService) { + final SebRestrictionService sebRestrictionService, + final AdditionalAttributesDAO additionalAttributesDAO) { super(authorization, bulkActionService, @@ -106,6 +113,7 @@ public class ExamAdministrationController extends EntityController { this.examDAO = examDAO; this.userDAO = userDAO; + this.additionalAttributesDAO = additionalAttributesDAO; this.lmsAPIService = lmsAPIService; this.sebExamConfigService = sebExamConfigService; this.examSessionService = examSessionService; @@ -278,7 +286,6 @@ public class ExamAdministrationController extends EntityController { @PathVariable(API.PARAM_MODEL_ID) final Long examlId) { checkModifyPrivilege(institutionId); - return this.entityDAO.byPK(examlId) .flatMap(this.authorization::checkModify) .flatMap(exam -> this.applySebRestriction(exam, true)) @@ -328,6 +335,33 @@ public class ExamAdministrationController extends EntityController { .getOrThrow(); } + @Override + protected Result notifyCreated(final Exam entity) { + return Result.tryCatch(() -> { + + final LmsSetup lmsSetup = this.lmsAPIService.getLmsSetup(entity.lmsSetupId) + .getOrThrow(); + + // if we have an Open edX LMS involved, add additional initial SEB restriction attributes + if (lmsSetup.lmsType == LmsType.OPEN_EDX) { + final List permissions = Arrays.asList( + OpenEdxSebRestriction.PermissionComponent.ALWAYS_ALLOW_STUFF.key, + OpenEdxSebRestriction.PermissionComponent.CHECK_CONFIG_KEY.key); + + this.additionalAttributesDAO.saveAdditionalAttribute( + EntityType.EXAM, + entity.id, + SebRestrictionService.SEB_RESTRICTION_ADDITIONAL_PROPERTY_NAME_PREFIX + + OpenEdxSebRestriction.ATTR_PERMISSION_COMPONENTS, + StringUtils.join(permissions, Constants.LIST_SEPARATOR_CHAR)) + .getOrThrow(); + + } + + return entity; + }); + } + @Override protected Result validForCreate(final Exam entity) { return super.validForCreate(entity) @@ -381,10 +415,6 @@ public class ExamAdministrationController extends EntityController { "SEB Restriction feature not available for LMS type: " + lmsSetup.lmsType)); } - if (BooleanUtils.toBoolean(exam.lmsSebRestriction) == restrict) { - return Result.of(exam); - } - if (restrict) { if (!this.lmsAPIService .getLmsSetup(exam.lmsSetupId)