SEBSERV-105 GUI implementation and bug-fix
This commit is contained in:
parent
151b6b734a
commit
45fb04955b
16 changed files with 236 additions and 91 deletions
|
@ -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 = ':';
|
||||
|
|
|
@ -93,7 +93,7 @@ public class OpenEdxSebRestriction {
|
|||
public final Collection<String> permissionComponents;
|
||||
|
||||
@JsonProperty(ATTR_USER_BANNING_ENABLED)
|
||||
public final boolean banningEnabled;
|
||||
public final Boolean banningEnabled;
|
||||
|
||||
@JsonCreator
|
||||
OpenEdxSebRestriction(
|
||||
|
|
|
@ -175,6 +175,56 @@ public final class Utils {
|
|||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
public static Collection<String> 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<String> getListFromString(final String list) {
|
||||
return getListFromString(list, Constants.LIST_SEPARATOR);
|
||||
}
|
||||
|
||||
public static Collection<String> getListFromString(final String list, final String separator) {
|
||||
if (list == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return Arrays.asList(StringUtils.split(list, separator));
|
||||
}
|
||||
|
||||
public static Result<Long> dateTimeStringToTimestamp(final String startTime) {
|
||||
return Result.tryCatch(() -> {
|
||||
return DateTime.parse(startTime, Constants.STANDARD_DATE_TIME_FORMATTER).getMillis();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<FormHandle<?>>(
|
||||
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<String> browserKeys = Utils.getListOfLines(
|
||||
form.getFieldValue(SebRestriction.ATTR_BROWSER_KEYS));
|
||||
|
||||
final Map<String, String> 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<SebRestriction> 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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -289,6 +289,7 @@ public class SebExamConfigPropForm implements TemplateComposer {
|
|||
|
||||
if (isAttachedToExam) {
|
||||
|
||||
widgetFactory.labelSeparator(content);
|
||||
widgetFactory.labelLocalized(
|
||||
content,
|
||||
CustomVariant.TEXT_H3,
|
||||
|
|
|
@ -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),
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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<AdditionalAttributeRecord> saveAdditionalAttribute(
|
||||
EntityType type,
|
||||
Long entityId,
|
||||
String name,
|
||||
|
|
|
@ -59,53 +59,60 @@ public class AdditionalAttributesDAOImpl implements AdditionalAttributesDAO {
|
|||
|
||||
@Override
|
||||
@Transactional
|
||||
public void saveAdditionalAttribute(
|
||||
public Result<AdditionalAttributeRecord> 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<Long> 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<Long> 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<Exam> saveSebRestrictionToExam(Exam exam, SebRestriction sebRestriction);
|
||||
|
||||
/** Used to apply SEB Client restriction within the LMS API for a specified Exam.
|
||||
|
|
|
@ -118,7 +118,10 @@ public class SebRestrictionServiceImpl implements SebRestrictionService {
|
|||
final Collection<String> 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,
|
||||
|
|
|
@ -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<Exam, Exam> {
|
|||
|
||||
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<Exam, Exam> {
|
|||
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<Exam, Exam> {
|
|||
|
||||
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<Exam, Exam> {
|
|||
@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<Exam, Exam> {
|
|||
.getOrThrow();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result<Exam> 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<String> 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<Exam> validForCreate(final Exam entity) {
|
||||
return super.validForCreate(entity)
|
||||
|
@ -381,10 +415,6 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
|||
"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)
|
||||
|
|
Loading…
Reference in a new issue