SEBSERV-457 finished implementation
This commit is contained in:
parent
fc310597e6
commit
cb9900a16d
13 changed files with 109 additions and 36 deletions
|
@ -228,8 +228,7 @@ public class ExamForm implements TemplateComposer {
|
||||||
final EntityGrantCheck entityGrantCheck = currentUser.entityGrantCheck(exam);
|
final EntityGrantCheck entityGrantCheck = currentUser.entityGrantCheck(exam);
|
||||||
final boolean modifyGrant = entityGrantCheck.m();
|
final boolean modifyGrant = entityGrantCheck.m();
|
||||||
final boolean writeGrant = entityGrantCheck.w();
|
final boolean writeGrant = entityGrantCheck.w();
|
||||||
final boolean editable = modifyGrant &&
|
final boolean editable = modifyGrant && (exam.getStatus() == ExamStatus.UP_COMING || exam.getStatus() == ExamStatus.RUNNING);
|
||||||
(exam.getStatus() == ExamStatus.UP_COMING || exam.getStatus() == ExamStatus.RUNNING);
|
|
||||||
final boolean signatureKeyCheckEnabled = BooleanUtils.toBoolean(
|
final boolean signatureKeyCheckEnabled = BooleanUtils.toBoolean(
|
||||||
exam.additionalAttributes.get(Exam.ADDITIONAL_ATTR_SIGNATURE_KEY_CHECK_ENABLED));
|
exam.additionalAttributes.get(Exam.ADDITIONAL_ATTR_SIGNATURE_KEY_CHECK_ENABLED));
|
||||||
final boolean sebRestrictionAvailable = readonly && testSEBRestrictionAPI(exam);
|
final boolean sebRestrictionAvailable = readonly && testSEBRestrictionAPI(exam);
|
||||||
|
@ -294,7 +293,8 @@ public class ExamForm implements TemplateComposer {
|
||||||
|
|
||||||
final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(formContext
|
final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(formContext
|
||||||
.clearEntityKeys()
|
.clearEntityKeys()
|
||||||
.removeAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA));
|
.removeAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA)
|
||||||
|
.removeAttribute(AttributeKeys.NEW_EXAM_NO_LMS));
|
||||||
|
|
||||||
|
|
||||||
// propagate content actions to action-pane
|
// propagate content actions to action-pane
|
||||||
|
@ -302,7 +302,8 @@ public class ExamForm implements TemplateComposer {
|
||||||
|
|
||||||
.newAction(ActionDefinition.EXAM_MODIFY)
|
.newAction(ActionDefinition.EXAM_MODIFY)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
.publishIf(() -> modifyGrant && readonly && editable)
|
.publishIf(() -> modifyGrant && readonly &&
|
||||||
|
(editable || (exam.getStatus() == ExamStatus.FINISHED && exam.lmsSetupId == null)))
|
||||||
|
|
||||||
.newAction(ActionDefinition.EXAM_DELETE)
|
.newAction(ActionDefinition.EXAM_DELETE)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
|
@ -316,7 +317,7 @@ public class ExamForm implements TemplateComposer {
|
||||||
.publishIf(() -> writeGrant && readonly && exam.status == ExamStatus.FINISHED)
|
.publishIf(() -> writeGrant && readonly && exam.status == ExamStatus.FINISHED)
|
||||||
|
|
||||||
.newAction(ActionDefinition.EXAM_SAVE)
|
.newAction(ActionDefinition.EXAM_SAVE)
|
||||||
.withExec(action -> (importFromQuizData)
|
.withExec(action -> importFromQuizData
|
||||||
? importExam(action, formHandle, sebRestrictionAvailable && exam.status == ExamStatus.RUNNING)
|
? importExam(action, formHandle, sebRestrictionAvailable && exam.status == ExamStatus.RUNNING)
|
||||||
: formHandle.processFormSave(action))
|
: formHandle.processFormSave(action))
|
||||||
.ignoreMoveAwayFromEdit()
|
.ignoreMoveAwayFromEdit()
|
||||||
|
@ -493,7 +494,7 @@ public class ExamForm implements TemplateComposer {
|
||||||
QuizData.QUIZ_ATTR_DESCRIPTION,
|
QuizData.QUIZ_ATTR_DESCRIPTION,
|
||||||
FORM_DESCRIPTION_TEXT_KEY,
|
FORM_DESCRIPTION_TEXT_KEY,
|
||||||
exam.getDescription())
|
exam.getDescription())
|
||||||
.asHTML(50)
|
.asHTMLOrArea(50, exam.lmsSetupId != null)
|
||||||
.readonly(true)
|
.readonly(true)
|
||||||
.withInputSpan(7)
|
.withInputSpan(7)
|
||||||
.withEmptyCellSeparation(false))
|
.withEmptyCellSeparation(false))
|
||||||
|
|
|
@ -94,6 +94,14 @@ public final class TextFieldBuilder extends FieldBuilder<String> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TextFieldBuilder asHTMLOrArea(final int minHeight, final boolean html) {
|
||||||
|
if (html) {
|
||||||
|
return this.asHTML(minHeight);
|
||||||
|
} else {
|
||||||
|
return this.asArea(minHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public TextFieldBuilder asMarkupLabel() {
|
public TextFieldBuilder asMarkupLabel() {
|
||||||
this.isMarkupLabel = true;
|
this.isMarkupLabel = true;
|
||||||
return this;
|
return this;
|
||||||
|
@ -187,4 +195,5 @@ public final class TextFieldBuilder extends FieldBuilder<String> {
|
||||||
+ HTML_TEXT_BLOCK_END;
|
+ HTML_TEXT_BLOCK_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -222,7 +222,7 @@ public final class PageAction {
|
||||||
} catch (final FormPostException e) {
|
} catch (final FormPostException e) {
|
||||||
if (e.getCause() instanceof RestCallError) {
|
if (e.getCause() instanceof RestCallError) {
|
||||||
final RestCallError cause = (RestCallError) e.getCause();
|
final RestCallError cause = (RestCallError) e.getCause();
|
||||||
if (cause.isUnexpectedError()) {
|
if (cause.isUnexpectedError() || log.isDebugEnabled()) {
|
||||||
log.error("Failed to execute action: {} | error: {} | cause: {}",
|
log.error("Failed to execute action: {} | error: {} | cause: {}",
|
||||||
PageAction.this.getName(),
|
PageAction.this.getName(),
|
||||||
cause.getMessage(),
|
cause.getMessage(),
|
||||||
|
|
|
@ -535,8 +535,9 @@ public class WidgetFactory {
|
||||||
final LocTextKey ariaLabel) {
|
final LocTextKey ariaLabel) {
|
||||||
|
|
||||||
final Text input = readonly
|
final Text input = readonly
|
||||||
? new Text(content, SWT.LEFT | SWT.MULTI)
|
? new Text(content, SWT.LEFT | SWT.MULTI | SWT.WRAP)
|
||||||
: new Text(content, SWT.LEFT | SWT.BORDER | SWT.MULTI);
|
: new Text(content, SWT.LEFT | SWT.BORDER | SWT.MULTI | SWT.WRAP);
|
||||||
|
|
||||||
if (ariaLabel != null) {
|
if (ariaLabel != null) {
|
||||||
WidgetFactory.setARIALabel(input, this.i18nSupport.getText(ariaLabel));
|
WidgetFactory.setARIALabel(input, this.i18nSupport.getText(ariaLabel));
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.mybatis.dynamic.sql.SqlBuilder;
|
import org.mybatis.dynamic.sql.SqlBuilder;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -147,7 +148,11 @@ public class ConfigurationValueDAOImpl implements ConfigurationValueDAO {
|
||||||
attrId);
|
attrId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return records.get(0).getValue();
|
final String value = records.get(0).getValue();
|
||||||
|
if (value == null) {
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -270,7 +270,7 @@ public class ExamRecordDAO {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exam.status != null && !exam.status.name().equals(oldRecord.getStatus())) {
|
if (exam.status != null && !exam.status.name().equals(oldRecord.getStatus())) {
|
||||||
log.warn("Exam state change on save. Exam. {}, Old state: {}, new state: {}",
|
log.info("Exam state change on save. Exam. {}, Old state: {}, new state: {}",
|
||||||
exam.externalId,
|
exam.externalId,
|
||||||
oldRecord.getStatus(),
|
oldRecord.getStatus(),
|
||||||
exam.status);
|
exam.status);
|
||||||
|
|
|
@ -67,7 +67,7 @@ public interface ExamAdminService {
|
||||||
* @return Result refer to the created exam or to an error when happened */
|
* @return Result refer to the created exam or to an error when happened */
|
||||||
Result<Exam> applyAdditionalSEBRestrictions(Exam exam);
|
Result<Exam> applyAdditionalSEBRestrictions(Exam exam);
|
||||||
|
|
||||||
/** Indicates whether a specific exam is been restricted with SEB restriction feature on the LMS or not.
|
/** Indicates whether a specific exam is being restricted with SEB restriction feature on the LMS or not.
|
||||||
*
|
*
|
||||||
* @param exam The exam instance
|
* @param exam The exam instance
|
||||||
* @return Result refer to the restriction flag or to an error when happened */
|
* @return Result refer to the restriction flag or to an error when happened */
|
||||||
|
@ -164,14 +164,23 @@ public interface ExamAdminService {
|
||||||
void notifyExamSaved(Exam exam);
|
void notifyExamSaved(Exam exam);
|
||||||
|
|
||||||
static void newExamFieldValidation(final POSTMapper postParams) {
|
static void newExamFieldValidation(final POSTMapper postParams) {
|
||||||
final Collection<APIMessage> validationErrors = new ArrayList<>();
|
noLMSFieldValidation(new Exam(postParams));
|
||||||
|
}
|
||||||
|
|
||||||
if (!postParams.contains(Domain.EXAM.ATTR_QUIZ_NAME)) {
|
static Exam noLMSFieldValidation(final Exam exam) {
|
||||||
|
|
||||||
|
// This only applies to exams that has no LMS
|
||||||
|
if (exam.lmsSetupId != null) {
|
||||||
|
return exam;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Collection<APIMessage> validationErrors = new ArrayList<>();
|
||||||
|
if (StringUtils.isBlank(exam.name)) {
|
||||||
validationErrors.add(APIMessage.fieldValidationError(
|
validationErrors.add(APIMessage.fieldValidationError(
|
||||||
Domain.EXAM.ATTR_QUIZ_NAME,
|
Domain.EXAM.ATTR_QUIZ_NAME,
|
||||||
"exam:quizName:notNull"));
|
"exam:quizName:notNull"));
|
||||||
} else {
|
} else {
|
||||||
final int length = postParams.getString(Domain.EXAM.ATTR_QUIZ_NAME).length();
|
final int length = exam.name.length();
|
||||||
if (length < 3 || length > 255) {
|
if (length < 3 || length > 255) {
|
||||||
validationErrors.add(APIMessage.fieldValidationError(
|
validationErrors.add(APIMessage.fieldValidationError(
|
||||||
Domain.EXAM.ATTR_QUIZ_NAME,
|
Domain.EXAM.ATTR_QUIZ_NAME,
|
||||||
|
@ -179,13 +188,13 @@ public interface ExamAdminService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!postParams.contains(QuizData.QUIZ_ATTR_START_URL)) {
|
if (StringUtils.isBlank(exam.getStartURL())) {
|
||||||
validationErrors.add(APIMessage.fieldValidationError(
|
validationErrors.add(APIMessage.fieldValidationError(
|
||||||
QuizData.QUIZ_ATTR_START_URL,
|
QuizData.QUIZ_ATTR_START_URL,
|
||||||
"exam:quiz_start_url:notNull"));
|
"exam:quiz_start_url:notNull"));
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
new URL(postParams.getString(QuizData.QUIZ_ATTR_START_URL)).toURI();
|
new URL(exam.getStartURL()).toURI();
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
validationErrors.add(APIMessage.fieldValidationError(
|
validationErrors.add(APIMessage.fieldValidationError(
|
||||||
QuizData.QUIZ_ATTR_START_URL,
|
QuizData.QUIZ_ATTR_START_URL,
|
||||||
|
@ -193,13 +202,13 @@ public interface ExamAdminService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!postParams.contains(Domain.EXAM.ATTR_QUIZ_START_TIME)) {
|
if (exam.startTime == null) {
|
||||||
validationErrors.add(APIMessage.fieldValidationError(
|
validationErrors.add(APIMessage.fieldValidationError(
|
||||||
Domain.EXAM.ATTR_QUIZ_START_TIME,
|
Domain.EXAM.ATTR_QUIZ_START_TIME,
|
||||||
"exam:quizStartTime:notNull"));
|
"exam:quizStartTime:notNull"));
|
||||||
} else if (postParams.contains(Domain.EXAM.ATTR_QUIZ_END_TIME)) {
|
} else if (exam.endTime != null) {
|
||||||
if (postParams.getDateTime(Domain.EXAM.ATTR_QUIZ_START_TIME)
|
if (exam.startTime
|
||||||
.isAfter(postParams.getDateTime(Domain.EXAM.ATTR_QUIZ_END_TIME))) {
|
.isAfter(exam.endTime)) {
|
||||||
validationErrors.add(APIMessage.fieldValidationError(
|
validationErrors.add(APIMessage.fieldValidationError(
|
||||||
Domain.EXAM.ATTR_QUIZ_END_TIME,
|
Domain.EXAM.ATTR_QUIZ_END_TIME,
|
||||||
"exam:quizEndTime:endBeforeStart"));
|
"exam:quizEndTime:endBeforeStart"));
|
||||||
|
@ -209,6 +218,8 @@ public interface ExamAdminService {
|
||||||
if (!validationErrors.isEmpty()) {
|
if (!validationErrors.isEmpty()) {
|
||||||
throw new APIMessageException(validationErrors);
|
throw new APIMessageException(validationErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return exam;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Used to check threshold consistency for a given list of thresholds.
|
/** Used to check threshold consistency for a given list of thresholds.
|
||||||
|
@ -326,4 +337,5 @@ public interface ExamAdminService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,6 +166,11 @@ public class ExamAdminServiceImpl implements ExamAdminService {
|
||||||
public Result<Exam> applyAdditionalSEBRestrictions(final Exam exam) {
|
public Result<Exam> applyAdditionalSEBRestrictions(final Exam exam) {
|
||||||
return Result.tryCatch(() -> {
|
return Result.tryCatch(() -> {
|
||||||
|
|
||||||
|
// this only applies to exams that are attached to an LMS
|
||||||
|
if (exam.lmsSetupId == null) {
|
||||||
|
return exam;
|
||||||
|
}
|
||||||
|
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Apply additional SEB restrictions for exam: {}",
|
log.debug("Apply additional SEB restrictions for exam: {}",
|
||||||
exam.externalId);
|
exam.externalId);
|
||||||
|
@ -325,6 +330,11 @@ public class ExamAdminServiceImpl implements ExamAdminService {
|
||||||
|
|
||||||
private Result<Exam> initAdditionalAttributesForMoodleExams(final Exam exam) {
|
private Result<Exam> initAdditionalAttributesForMoodleExams(final Exam exam) {
|
||||||
return Result.tryCatch(() -> {
|
return Result.tryCatch(() -> {
|
||||||
|
|
||||||
|
if (exam.lmsSetupId == null) {
|
||||||
|
return exam;
|
||||||
|
}
|
||||||
|
|
||||||
final LmsAPITemplate lmsTemplate = this.lmsAPIService
|
final LmsAPITemplate lmsTemplate = this.lmsAPIService
|
||||||
.getLmsAPITemplate(exam.lmsSetupId)
|
.getLmsAPITemplate(exam.lmsSetupId)
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
|
|
@ -84,9 +84,7 @@ public class SEBRestrictionServiceImpl implements SEBRestrictionService {
|
||||||
|
|
||||||
// check only if SEB_RESTRICTION feature is on
|
// check only if SEB_RESTRICTION feature is on
|
||||||
if (lmsSetup != null && lmsSetup.lmsType.features.contains(Features.SEB_RESTRICTION)) {
|
if (lmsSetup != null && lmsSetup.lmsType.features.contains(Features.SEB_RESTRICTION)) {
|
||||||
if (!exam.sebRestriction) {
|
return exam.sebRestriction;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -97,12 +95,11 @@ public class SEBRestrictionServiceImpl implements SEBRestrictionService {
|
||||||
public Result<SEBRestriction> getSEBRestrictionFromExam(final Exam exam) {
|
public Result<SEBRestriction> getSEBRestrictionFromExam(final Exam exam) {
|
||||||
return Result.tryCatch(() -> {
|
return Result.tryCatch(() -> {
|
||||||
// load the config keys from restriction and merge with new generated config keys
|
// load the config keys from restriction and merge with new generated config keys
|
||||||
final Set<String> configKeys = new HashSet<>();
|
|
||||||
final Collection<String> generatedKeys = this.examConfigService
|
final Collection<String> generatedKeys = this.examConfigService
|
||||||
.generateConfigKeys(exam.institutionId, exam.id)
|
.generateConfigKeys(exam.institutionId, exam.id)
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
|
||||||
configKeys.addAll(generatedKeys);
|
final Set<String> configKeys = new HashSet<>(generatedKeys);
|
||||||
if (!generatedKeys.isEmpty()) {
|
if (!generatedKeys.isEmpty()) {
|
||||||
configKeys.addAll(this.lmsAPIService
|
configKeys.addAll(this.lmsAPIService
|
||||||
.getLmsAPITemplate(exam.lmsSetupId)
|
.getLmsAPITemplate(exam.lmsSetupId)
|
||||||
|
@ -210,6 +207,11 @@ public class SEBRestrictionServiceImpl implements SEBRestrictionService {
|
||||||
@EventListener(ExamStartedEvent.class)
|
@EventListener(ExamStartedEvent.class)
|
||||||
public void notifyExamStarted(final ExamStartedEvent event) {
|
public void notifyExamStarted(final ExamStartedEvent event) {
|
||||||
|
|
||||||
|
// This affects only exams with LMS binding...
|
||||||
|
if (event.exam.lmsSetupId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("ExamStartedEvent received, process applySEBClientRestriction...");
|
log.debug("ExamStartedEvent received, process applySEBClientRestriction...");
|
||||||
}
|
}
|
||||||
|
@ -225,6 +227,11 @@ public class SEBRestrictionServiceImpl implements SEBRestrictionService {
|
||||||
@EventListener(ExamFinishedEvent.class)
|
@EventListener(ExamFinishedEvent.class)
|
||||||
public void notifyExamFinished(final ExamFinishedEvent event) {
|
public void notifyExamFinished(final ExamFinishedEvent event) {
|
||||||
|
|
||||||
|
// This affects only exams with LMS binding...
|
||||||
|
if (event.exam.lmsSetupId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("ExamFinishedEvent received, process releaseSEBClientRestriction...");
|
log.debug("ExamFinishedEvent received, process releaseSEBClientRestriction...");
|
||||||
}
|
}
|
||||||
|
@ -260,6 +267,11 @@ public class SEBRestrictionServiceImpl implements SEBRestrictionService {
|
||||||
@Override
|
@Override
|
||||||
public Result<Exam> applySEBClientRestriction(final Exam exam) {
|
public Result<Exam> applySEBClientRestriction(final Exam exam) {
|
||||||
return Result.tryCatch(() -> {
|
return Result.tryCatch(() -> {
|
||||||
|
if (exam.lmsSetupId == null) {
|
||||||
|
log.info("No LMS for Exam: {}", exam.name);
|
||||||
|
return exam;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.lmsAPIService
|
if (!this.lmsAPIService
|
||||||
.getLmsSetup(exam.lmsSetupId)
|
.getLmsSetup(exam.lmsSetupId)
|
||||||
.getOrThrow().lmsType.features.contains(Features.SEB_RESTRICTION)) {
|
.getOrThrow().lmsType.features.contains(Features.SEB_RESTRICTION)) {
|
||||||
|
|
|
@ -27,7 +27,7 @@ public class MockSEBRestrictionAPI implements SEBRestrictionAPI {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(MockSEBRestrictionAPI.class);
|
private static final Logger log = LoggerFactory.getLogger(MockSEBRestrictionAPI.class);
|
||||||
|
|
||||||
//private Map<Long, Boolean> restrictionDB = new ConcurrentHashMap<>();
|
private Map<Long, SEBRestriction> restrictionDB = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LmsSetupTestResult testCourseRestrictionAPI() {
|
public LmsSetupTestResult testCourseRestrictionAPI() {
|
||||||
|
@ -37,7 +37,11 @@ public class MockSEBRestrictionAPI implements SEBRestrictionAPI {
|
||||||
@Override
|
@Override
|
||||||
public Result<SEBRestriction> getSEBClientRestriction(final Exam exam) {
|
public Result<SEBRestriction> getSEBClientRestriction(final Exam exam) {
|
||||||
log.info("Get SEB Client restriction for Exam: {}", exam);
|
log.info("Get SEB Client restriction for Exam: {}", exam);
|
||||||
return Result.ofError(new NoSEBRestrictionException());
|
if (!restrictionDB.containsKey(exam.id)) {
|
||||||
|
return Result.ofError(new NoSEBRestrictionException());
|
||||||
|
} else {
|
||||||
|
return Result.of(restrictionDB.get(exam.id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -46,13 +50,24 @@ public class MockSEBRestrictionAPI implements SEBRestrictionAPI {
|
||||||
final SEBRestriction sebRestrictionData) {
|
final SEBRestriction sebRestrictionData) {
|
||||||
|
|
||||||
log.info("Apply SEB Client restriction: {}", sebRestrictionData);
|
log.info("Apply SEB Client restriction: {}", sebRestrictionData);
|
||||||
//return Result.ofError(new NoSEBRestrictionException());
|
restrictionDB.put(exam.id, sebRestrictionData);
|
||||||
return Result.of(sebRestrictionData);
|
return Result.of(sebRestrictionData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result<Exam> releaseSEBClientRestriction(final Exam exam) {
|
public Result<Exam> releaseSEBClientRestriction(final Exam exam) {
|
||||||
log.info("Release SEB Client restriction for Exam: {}", exam);
|
log.info("Release SEB Client restriction for Exam: {}", exam);
|
||||||
|
if (restrictionDB.containsKey(exam.id)) {
|
||||||
|
SEBRestriction sebRestriction = restrictionDB.get(exam.id);
|
||||||
|
restrictionDB.put(
|
||||||
|
exam.id,
|
||||||
|
new SEBRestriction(
|
||||||
|
exam.id,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
sebRestriction.additionalProperties,
|
||||||
|
sebRestriction.warningMessage));
|
||||||
|
}
|
||||||
return Result.of(exam);
|
return Result.of(exam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,7 @@ public class ExamConfigUpdateServiceImpl implements ExamConfigUpdateService {
|
||||||
log.debug("Update-Lock successfully placed for all involved exams: {}", examsIds);
|
log.debug("Update-Lock successfully placed for all involved exams: {}", examsIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check running exam integrity again after lock to ensure there where no SEB Client connection attempts in the meantime
|
// check running exam integrity again after lock to ensure there were no SEB Client connection attempts in the meantime
|
||||||
final Collection<Long> examIdsSecondCheck = checkRunningExamIntegrity(configurationNodeId)
|
final Collection<Long> examIdsSecondCheck = checkRunningExamIntegrity(configurationNodeId)
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ public class ExamConfigUpdateServiceImpl implements ExamConfigUpdateService {
|
||||||
|
|
||||||
// generate the new Config Key and update the Config Key within the LMSSetup API for each exam (delete old Key and add new Key)
|
// generate the new Config Key and update the Config Key within the LMSSetup API for each exam (delete old Key and add new Key)
|
||||||
for (final Exam exam : exams) {
|
for (final Exam exam : exams) {
|
||||||
if (exam.getStatus() == ExamStatus.RUNNING) {
|
if (exam.getStatus() == ExamStatus.RUNNING && exam.lmsSetupId != null) {
|
||||||
|
|
||||||
this.examUpdateHandler
|
this.examUpdateHandler
|
||||||
.getSEBRestrictionService()
|
.getSEBRestrictionService()
|
||||||
|
|
|
@ -172,7 +172,9 @@ public class RemoteProctoringRoomServiceImpl implements RemoteProctoringRoomServ
|
||||||
@EventListener
|
@EventListener
|
||||||
public void notifyExamFinished(final ExamFinishedEvent event) {
|
public void notifyExamFinished(final ExamFinishedEvent event) {
|
||||||
|
|
||||||
log.info("ExamFinishedEvent received, process disposeRoomsForExam...");
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("ExamFinishedEvent received, process disposeRoomsForExam...");
|
||||||
|
}
|
||||||
|
|
||||||
disposeRoomsForExam(event.exam)
|
disposeRoomsForExam(event.exam)
|
||||||
.onError(error -> log.error("Failed to dispose rooms for finished exam: {}", event.exam, error));
|
.onError(error -> log.error("Failed to dispose rooms for finished exam: {}", event.exam, error));
|
||||||
|
@ -183,12 +185,14 @@ public class RemoteProctoringRoomServiceImpl implements RemoteProctoringRoomServ
|
||||||
|
|
||||||
return Result.tryCatch(() -> {
|
return Result.tryCatch(() -> {
|
||||||
|
|
||||||
log.info("Dispose and deleting proctoring rooms for exam: {}", exam.externalId);
|
|
||||||
|
|
||||||
final ProctoringServiceSettings proctoringSettings = this.examAdminService
|
final ProctoringServiceSettings proctoringSettings = this.examAdminService
|
||||||
.getProctoringServiceSettings(exam.id)
|
.getProctoringServiceSettings(exam.id)
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
|
||||||
|
if (proctoringSettings.enableProctoring) {
|
||||||
|
log.info("Dispose and deleting proctoring rooms for exam: {}", exam.externalId);
|
||||||
|
}
|
||||||
|
|
||||||
this.proctoringAdminService
|
this.proctoringAdminService
|
||||||
.getExamProctoringService(proctoringSettings.serverType)
|
.getExamProctoringService(proctoringSettings.serverType)
|
||||||
.flatMap(service -> service.disposeServiceRoomsForExam(exam.id, proctoringSettings))
|
.flatMap(service -> service.disposeServiceRoomsForExam(exam.id, proctoringSettings))
|
||||||
|
|
|
@ -539,7 +539,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
||||||
+ API.EXAM_ADMINISTRATION_SCREEN_PROCTORING_PATH_SEGMENT,
|
+ API.EXAM_ADMINISTRATION_SCREEN_PROCTORING_PATH_SEGMENT,
|
||||||
method = RequestMethod.GET,
|
method = RequestMethod.GET,
|
||||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
public ScreenProctoringSettings getScreenProctoringeSettings(
|
public ScreenProctoringSettings getScreenProctoringSettings(
|
||||||
@RequestParam(
|
@RequestParam(
|
||||||
name = API.PARAM_INSTITUTION_ID,
|
name = API.PARAM_INSTITUTION_ID,
|
||||||
required = true,
|
required = true,
|
||||||
|
@ -655,6 +655,9 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
||||||
errors.add(0, ErrorMessage.EXAM_IMPORT_ERROR_AUTO_SETUP.of(
|
errors.add(0, ErrorMessage.EXAM_IMPORT_ERROR_AUTO_SETUP.of(
|
||||||
entity.getModelId(),
|
entity.getModelId(),
|
||||||
API.PARAM_MODEL_ID + Constants.FORM_URL_ENCODED_NAME_VALUE_SEPARATOR + entity.getModelId()));
|
API.PARAM_MODEL_ID + Constants.FORM_URL_ENCODED_NAME_VALUE_SEPARATOR + entity.getModelId()));
|
||||||
|
|
||||||
|
log.warn("Exam successfully created but some initialization did go wrong: {}", errors);
|
||||||
|
|
||||||
throw new APIMessageException(errors);
|
throw new APIMessageException(errors);
|
||||||
} else {
|
} else {
|
||||||
return this.examDAO.byPK(entity.id);
|
return this.examDAO.byPK(entity.id);
|
||||||
|
@ -679,7 +682,8 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
||||||
@Override
|
@Override
|
||||||
protected Result<Exam> validForSave(final Exam entity) {
|
protected Result<Exam> validForSave(final Exam entity) {
|
||||||
return super.validForSave(entity)
|
return super.validForSave(entity)
|
||||||
.map(this::checkExamSupporterRole);
|
.map(this::checkExamSupporterRole)
|
||||||
|
.map(ExamAdminService::noLMSFieldValidation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in a new issue