improved SEB Restriction handling error handling and logging
This commit is contained in:
		
							parent
							
								
									0544d7a799
								
							
						
					
					
						commit
						fc310597e6
					
				
					 19 changed files with 77 additions and 139 deletions
				
			
		|  | @ -177,9 +177,7 @@ public final class CircuitBreaker<T> { | ||||||
| 
 | 
 | ||||||
|                 this.state = State.HALF_OPEN; |                 this.state = State.HALF_OPEN; | ||||||
|                 this.failingCount.set(0); |                 this.failingCount.set(0); | ||||||
|                 return Result.ofError(new RuntimeException( |                 return result; | ||||||
|                         "Set CircuitBeaker to half-open state. Cause: " + result.getError(), |  | ||||||
|                         result.getError())); |  | ||||||
|             } else { |             } else { | ||||||
|                 // try again |                 // try again | ||||||
|                 return protectedRun(supplier); |                 return protectedRun(supplier); | ||||||
|  | @ -258,7 +256,7 @@ public final class CircuitBreaker<T> { | ||||||
|             return Result.ofError(e); |             return Result.ofError(e); | ||||||
|         } catch (final ExecutionException e) { |         } catch (final ExecutionException e) { | ||||||
|             future.cancel(false); |             future.cancel(false); | ||||||
|             if (log.isWarnEnabled()) { |             if (log.isDebugEnabled()) { | ||||||
|                 log.warn("Attempt error: {}, {}", e.getMessage(), this.state); |                 log.warn("Attempt error: {}, {}", e.getMessage(), this.state); | ||||||
|             } |             } | ||||||
|             final Throwable cause = e.getCause(); |             final Throwable cause = e.getCause(); | ||||||
|  |  | ||||||
|  | @ -142,7 +142,8 @@ public final class Result<T> { | ||||||
|             if (this.error instanceof RuntimeException) { |             if (this.error instanceof RuntimeException) { | ||||||
|                 throw (RuntimeException) this.error; |                 throw (RuntimeException) this.error; | ||||||
|             } else { |             } else { | ||||||
|                 throw new RuntimeException("RuntimeExceptionWrapper cause: " + this.error.getMessage(), this.error); |                 String cause = this.error.getMessage() != null ? this.error.getMessage() : this.error.toString(); | ||||||
|  |                 throw new RuntimeException("RuntimeExceptionWrapper cause: " + cause, this.error); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -238,7 +238,7 @@ public class ExamForm implements TemplateComposer { | ||||||
|                 .withURIVariable(API.PARAM_MODEL_ID, exam.getModelId()) |                 .withURIVariable(API.PARAM_MODEL_ID, exam.getModelId()) | ||||||
|                 .call() |                 .call() | ||||||
|                 .onError(e -> log.error("Unexpected error while trying to verify seb restriction settings: ", e)) |                 .onError(e -> log.error("Unexpected error while trying to verify seb restriction settings: ", e)) | ||||||
|                 .getOr(false); |                 .getOr(exam.sebRestriction); | ||||||
|         final boolean sebRestrictionMismatch = readonly && |         final boolean sebRestrictionMismatch = readonly && | ||||||
|                 sebRestrictionAvailable && |                 sebRestrictionAvailable && | ||||||
|                 isRestricted != exam.sebRestriction && |                 isRestricted != exam.sebRestriction && | ||||||
|  | @ -525,7 +525,6 @@ public class ExamForm implements TemplateComposer { | ||||||
|         final boolean newExam = exam.id == null; |         final boolean newExam = exam.id == null; | ||||||
|         final boolean hasLMS = exam.lmsSetupId != null; |         final boolean hasLMS = exam.lmsSetupId != null; | ||||||
|         final boolean importFromLMS = newExam && hasLMS; |         final boolean importFromLMS = newExam && hasLMS; | ||||||
|         final DateTimeZone timeZone = this.pageService.getCurrentUser().get().timeZone; |  | ||||||
|         final LocTextKey statusTitle = new LocTextKey("sebserver.exam.status." + exam.status.name()); |         final LocTextKey statusTitle = new LocTextKey("sebserver.exam.status." + exam.status.name()); | ||||||
| 
 | 
 | ||||||
|         return this.pageService.formBuilder(formContext.copyOf(content)) |         return this.pageService.formBuilder(formContext.copyOf(content)) | ||||||
|  | @ -585,9 +584,7 @@ public class ExamForm implements TemplateComposer { | ||||||
|                                 exam.getDescription()) |                                 exam.getDescription()) | ||||||
|                         .asArea() |                         .asArea() | ||||||
|                         .readonly(hasLMS)) |                         .readonly(hasLMS)) | ||||||
|                 .withAdditionalValueMapping( |                 .withAdditionalValueMapping(QuizData.QUIZ_ATTR_DESCRIPTION) | ||||||
|                         QuizData.QUIZ_ATTR_DESCRIPTION, |  | ||||||
|                         QuizData.QUIZ_ATTR_DESCRIPTION) |  | ||||||
| 
 | 
 | ||||||
|                 .addField(FormBuilder.dateTime( |                 .addField(FormBuilder.dateTime( | ||||||
|                                 Domain.EXAM.ATTR_QUIZ_START_TIME, |                                 Domain.EXAM.ATTR_QUIZ_START_TIME, | ||||||
|  | @ -599,11 +596,8 @@ public class ExamForm implements TemplateComposer { | ||||||
|                 .addField(FormBuilder.dateTime( |                 .addField(FormBuilder.dateTime( | ||||||
|                                 Domain.EXAM.ATTR_QUIZ_END_TIME, |                                 Domain.EXAM.ATTR_QUIZ_END_TIME, | ||||||
|                                 FORM_END_TIME_TEXT_KEY, |                                 FORM_END_TIME_TEXT_KEY, | ||||||
|                                 exam.endTime != null |                                 exam.endTime) | ||||||
|                                         ? exam.endTime |                         .readonly(hasLMS)) | ||||||
|                                         : DateTime.now(timeZone).plusHours(1)) |  | ||||||
|                         .readonly(hasLMS) |  | ||||||
|                         .mandatory(!hasLMS)) |  | ||||||
| 
 | 
 | ||||||
|                 .addField(FormBuilder.text( |                 .addField(FormBuilder.text( | ||||||
|                                 QuizData.QUIZ_ATTR_START_URL, |                                 QuizData.QUIZ_ATTR_START_URL, | ||||||
|  | @ -611,9 +605,7 @@ public class ExamForm implements TemplateComposer { | ||||||
|                                 exam.getStartURL()) |                                 exam.getStartURL()) | ||||||
|                         .readonly(hasLMS) |                         .readonly(hasLMS) | ||||||
|                         .mandatory(!hasLMS)) |                         .mandatory(!hasLMS)) | ||||||
|                 .withAdditionalValueMapping( |                 .withAdditionalValueMapping(QuizData.QUIZ_ATTR_START_URL) | ||||||
|                         QuizData.QUIZ_ATTR_START_URL, |  | ||||||
|                         QuizData.QUIZ_ATTR_START_URL) |  | ||||||
| 
 | 
 | ||||||
|                 .addField(FormBuilder.singleSelection( |                 .addField(FormBuilder.singleSelection( | ||||||
|                                 Domain.EXAM.ATTR_TYPE, |                                 Domain.EXAM.ATTR_TYPE, | ||||||
|  | @ -636,6 +628,7 @@ public class ExamForm implements TemplateComposer { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private Exam newExamNoLMS() { |     private Exam newExamNoLMS() { | ||||||
|  |         final DateTimeZone timeZone = this.pageService.getCurrentUser().get().timeZone; | ||||||
|         return new Exam( |         return new Exam( | ||||||
|             null, |             null, | ||||||
|             this.pageService.getCurrentUser().get().institutionId, |             this.pageService.getCurrentUser().get().institutionId, | ||||||
|  | @ -643,8 +636,8 @@ public class ExamForm implements TemplateComposer { | ||||||
|             UUID.randomUUID().toString(), |             UUID.randomUUID().toString(), | ||||||
|             true, |             true, | ||||||
|             null, |             null, | ||||||
|             null, |                 DateTime.now(timeZone), | ||||||
|             null, |                 DateTime.now(timeZone).plusHours(1), | ||||||
|             Exam.ExamType.UNDEFINED, |             Exam.ExamType.UNDEFINED, | ||||||
|             null, |             null, | ||||||
|             null, |             null, | ||||||
|  |  | ||||||
|  | @ -23,10 +23,11 @@ public class DateTimeSelectorFieldBuilder extends FieldBuilder<DateTime> { | ||||||
|         final Composite fieldGrid = createFieldGrid(builder.formParent, this.spanInput); |         final Composite fieldGrid = createFieldGrid(builder.formParent, this.spanInput); | ||||||
| 
 | 
 | ||||||
|         if (readonly) { |         if (readonly) { | ||||||
|             final Text label = new Text(fieldGrid, SWT.NONE); |             final Text readonlyLabel = builder.widgetFactory.textInput(fieldGrid, this.label); | ||||||
|             label.setText(builder.i18nSupport.formatDisplayDateTime(value) + " " + builder.i18nSupport.getUsersTimeZoneTitleSuffix()); |             readonlyLabel.setEditable(false); | ||||||
|             label.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, true)); |             readonlyLabel.setText(builder.i18nSupport.formatDisplayDateWithTimeZone(value)); | ||||||
|             builder.form.putReadonlyField(this.name, titleLabel, label); |             readonlyLabel.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, true)); | ||||||
|  |             builder.form.putReadonlyField(this.name, titleLabel, readonlyLabel); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -16,7 +16,6 @@ import java.util.function.Predicate; | ||||||
| 
 | 
 | ||||||
| import ch.ethz.seb.sebserver.gbl.api.API; | import ch.ethz.seb.sebserver.gbl.api.API; | ||||||
| import ch.ethz.seb.sebserver.gui.widget.*; | import ch.ethz.seb.sebserver.gui.widget.*; | ||||||
| import com.fasterxml.jackson.databind.JsonNode; |  | ||||||
| import org.apache.commons.lang3.BooleanUtils; | import org.apache.commons.lang3.BooleanUtils; | ||||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||||
| import org.eclipse.rap.rwt.RWT; | import org.eclipse.rap.rwt.RWT; | ||||||
|  | @ -105,6 +104,10 @@ public final class Form implements FormBinding { | ||||||
|         this.additionalAttributeMapping.put(fieldName, attrName); |         this.additionalAttributeMapping.put(fieldName, attrName); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public void putAdditionalValueMapping(final String fieldName) { | ||||||
|  |         this.additionalAttributeMapping.put(fieldName, fieldName); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public String getStaticValue(final String name) { |     public String getStaticValue(final String name) { | ||||||
|         return this.staticValues.get(name); |         return this.staticValues.get(name); | ||||||
|     } |     } | ||||||
|  | @ -188,7 +191,7 @@ public final class Form implements FormBinding { | ||||||
|     Form removeField(final String name) { |     Form removeField(final String name) { | ||||||
|         if (this.formFields.containsKey(name)) { |         if (this.formFields.containsKey(name)) { | ||||||
|             final List<FormFieldAccessor> list = this.formFields.remove(name); |             final List<FormFieldAccessor> list = this.formFields.remove(name); | ||||||
|             list.forEach(ffa -> ffa.dispose()); |             list.forEach(FormFieldAccessor::dispose); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return this; |         return this; | ||||||
|  | @ -318,7 +321,7 @@ public final class Form implements FormBinding { | ||||||
|                     additionalAttrs.put(entry.getValue(), fieldValue); |                     additionalAttrs.put(entry.getValue(), fieldValue); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if (additionalAttrs != null) { |             if (!additionalAttrs.isEmpty()) { | ||||||
|                 this.objectRoot.putIfAbsent( |                 this.objectRoot.putIfAbsent( | ||||||
|                         API.PARAM_ADDITIONAL_ATTRIBUTES, |                         API.PARAM_ADDITIONAL_ATTRIBUTES, | ||||||
|                         jsonMapper.valueToTree(additionalAttrs)); |                         jsonMapper.valueToTree(additionalAttrs)); | ||||||
|  |  | ||||||
|  | @ -152,6 +152,21 @@ public class FormBuilder { | ||||||
|         return this; |         return this; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public FormBuilder withAdditionalValueMapping(final String fieldName) { | ||||||
|  |         this.form.putAdditionalValueMapping(fieldName); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public FormBuilder withAdditionalValueMappingIf( | ||||||
|  |             final BooleanSupplier condition, | ||||||
|  |             final Supplier<String> fieldNameSupplier) { | ||||||
|  | 
 | ||||||
|  |         if (condition.getAsBoolean()) { | ||||||
|  |             this.form.putAdditionalValueMapping(fieldNameSupplier.get()); | ||||||
|  |         } | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public FormBuilder addFieldIf( |     public FormBuilder addFieldIf( | ||||||
|             final BooleanSupplier condition, |             final BooleanSupplier condition, | ||||||
|             final Supplier<FieldBuilder<?>> templateSupplier) { |             final Supplier<FieldBuilder<?>> templateSupplier) { | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.gui.service.i18n; | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.Locale; | import java.util.Locale; | ||||||
| 
 | 
 | ||||||
|  | import org.apache.commons.lang3.StringUtils; | ||||||
| import org.joda.time.DateTime; | import org.joda.time.DateTime; | ||||||
| 
 | 
 | ||||||
| import ch.ethz.seb.sebserver.gbl.util.Utils; | import ch.ethz.seb.sebserver.gbl.util.Utils; | ||||||
|  | @ -61,7 +62,9 @@ public interface I18nSupport { | ||||||
|      * @param date the DateTime instance |      * @param date the DateTime instance | ||||||
|      * @return date formatted date String to display */ |      * @return date formatted date String to display */ | ||||||
|     default String formatDisplayDateWithTimeZone(final DateTime date) { |     default String formatDisplayDateWithTimeZone(final DateTime date) { | ||||||
|         return formatDisplayDateTime(date) + " " + this.getUsersTimeZoneTitleSuffix(); |         return formatDisplayDateTime(date) + (date != null | ||||||
|  |                 ? " " + this.getUsersTimeZoneTitleSuffix() | ||||||
|  |                 : StringUtils.EMPTY); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** Format a time-stamp (milliseconds) to a text format to display. |     /** Format a time-stamp (milliseconds) to a text format to display. | ||||||
|  |  | ||||||
|  | @ -124,7 +124,7 @@ public class ExamAdminServiceImpl implements ExamAdminService { | ||||||
|                     EntityType.EXAM, |                     EntityType.EXAM, | ||||||
|                     examId, |                     examId, | ||||||
|                     Exam.ADDITIONAL_ATTR_SIGNATURE_KEY_SALT, |                     Exam.ADDITIONAL_ATTR_SIGNATURE_KEY_SALT, | ||||||
|                     KeyGenerators.string().generateKey().toString()); |                     KeyGenerators.string().generateKey()); | ||||||
| 
 | 
 | ||||||
|             return exam; |             return exam; | ||||||
|         }).flatMap(this::initAdditionalAttributesForMoodleExams); |         }).flatMap(this::initAdditionalAttributesForMoodleExams); | ||||||
|  | @ -204,7 +204,7 @@ public class ExamAdminServiceImpl implements ExamAdminService { | ||||||
|         return this.lmsAPIService |         return this.lmsAPIService | ||||||
|                 .getLmsAPITemplate(exam.lmsSetupId) |                 .getLmsAPITemplate(exam.lmsSetupId) | ||||||
|                 .map(lmsAPI -> lmsAPI.hasSEBClientRestriction(exam)) |                 .map(lmsAPI -> lmsAPI.hasSEBClientRestriction(exam)) | ||||||
|                 .onError(error -> log.error("Failed to check SEB restriction: ", error)); |                 .onError(error -> log.warn("Failed to check SEB restriction: {}", error.getMessage())); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  | @ -301,7 +301,7 @@ public class ExamAdminServiceImpl implements ExamAdminService { | ||||||
| 
 | 
 | ||||||
|         return getProctoringServiceSettings(exam.id) |         return getProctoringServiceSettings(exam.id) | ||||||
|                 .map(settings -> { |                 .map(settings -> { | ||||||
|                     ProctoringServiceSettings resetSettings; |                     final ProctoringServiceSettings resetSettings; | ||||||
|                     if (exam.examTemplateId != null) { |                     if (exam.examTemplateId != null) { | ||||||
|                         // get settings from origin template |                         // get settings from origin template | ||||||
|                         resetSettings = this.proctoringAdminService |                         resetSettings = this.proctoringAdminService | ||||||
|  | @ -401,7 +401,7 @@ public class ExamAdminServiceImpl implements ExamAdminService { | ||||||
|                     .stream() |                     .stream() | ||||||
|                     .forEach(configNodeId -> { |                     .forEach(configNodeId -> { | ||||||
|                         if (this.examConfigurationMapDAO.checkNoActiveExamReferences(configNodeId).getOr(false)) { |                         if (this.examConfigurationMapDAO.checkNoActiveExamReferences(configNodeId).getOr(false)) { | ||||||
|                             log.debug("Also set exam configuration to archived: ", configNodeId); |                             log.debug("Also set exam configuration to archived: {}", configNodeId); | ||||||
|                             this.configurationNodeDAO.save( |                             this.configurationNodeDAO.save( | ||||||
|                                     new ConfigurationNode( |                                     new ConfigurationNode( | ||||||
|                                             configNodeId, null, null, null, null, null, |                                             configNodeId, null, null, null, null, null, | ||||||
|  |  | ||||||
|  | @ -23,18 +23,18 @@ public interface SEBRestrictionAPI { | ||||||
|      * @return {@link LmsSetupTestResult } instance with the test result report */ |      * @return {@link LmsSetupTestResult } instance with the test result report */ | ||||||
|     LmsSetupTestResult testCourseRestrictionAPI(); |     LmsSetupTestResult testCourseRestrictionAPI(); | ||||||
| 
 | 
 | ||||||
|     /** Get SEB restriction data from LMS within a {@link SEBRestrictionData } instance. The available restriction |     /** Get SEB restriction data from LMS within a {@link SEBRestriction } instance. The available restriction | ||||||
|      * details |      * details | ||||||
|      * depends on the type of LMS but shall at least contains the config-key(s) and the browser-exam-key(s). |      * depends on the type of LMS but shall at least contains the config-key(s) and the browser-exam-key(s). | ||||||
|      * |      * | ||||||
|      * @param exam the exam to get the SEB restriction data for |      * @param exam the exam to get the SEB restriction data for | ||||||
|      * @return Result refer to the {@link SEBRestrictionData } instance or to an ResourceNotFoundException if the |      * @return Result refer to the {@link SEBRestriction } instance or to an ResourceNotFoundException if the | ||||||
|      *         restriction is |      *         restriction is | ||||||
|      *         missing or to another exception on unexpected error case */ |      *         missing or to another exception on unexpected error case */ | ||||||
|     Result<SEBRestriction> getSEBClientRestriction(Exam exam); |     Result<SEBRestriction> getSEBClientRestriction(Exam exam); | ||||||
| 
 | 
 | ||||||
|     /** Use this to check if there is a SEB restriction available on the LMS for the specified exam. |     /** Use this to check if there is a SEB restriction available on the LMS for the specified exam. | ||||||
|      * |      * <p> | ||||||
|      * A SEB Restriction is available if it can get from LMS and if there is either a Config-Key |      * A SEB Restriction is available if it can get from LMS and if there is either a Config-Key | ||||||
|      * or a BrowserExam-Key set or both. If none of this keys is set, the SEB Restriction is been |      * or a BrowserExam-Key set or both. If none of this keys is set, the SEB Restriction is been | ||||||
|      * considered to not set on the LMS. |      * considered to not set on the LMS. | ||||||
|  | @ -42,12 +42,7 @@ public interface SEBRestrictionAPI { | ||||||
|      * @param exam exam the exam to get the SEB restriction data for |      * @param exam exam the exam to get the SEB restriction data for | ||||||
|      * @return true if there is a SEB restriction set on the LMS for the exam or false otherwise */ |      * @return true if there is a SEB restriction set on the LMS for the exam or false otherwise */ | ||||||
|     default boolean hasSEBClientRestriction(final Exam exam) { |     default boolean hasSEBClientRestriction(final Exam exam) { | ||||||
|         final Result<SEBRestriction> sebClientRestriction = getSEBClientRestriction(exam); |         return hasSEBClientRestriction(getSEBClientRestriction(exam).getOrThrow()); | ||||||
|         if (sebClientRestriction.hasError()) { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         return hasSEBClientRestriction(sebClientRestriction.get()); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     default boolean hasSEBClientRestriction(final SEBRestriction sebRestriction) { |     default boolean hasSEBClientRestriction(final SEBRestriction sebRestriction) { | ||||||
|  | @ -58,7 +53,7 @@ public interface SEBRestrictionAPI { | ||||||
|      * |      * | ||||||
|      * @param exam The exam to apply the restriction for |      * @param exam The exam to apply the restriction for | ||||||
|      * @param sebRestrictionData containing all data for SEB Client restriction to apply to the LMS |      * @param sebRestrictionData containing all data for SEB Client restriction to apply to the LMS | ||||||
|      * @return Result refer to the given {@link SEBRestrictionData } if restriction was successful or to an error if |      * @return Result refer to the given {@link SEBRestriction } if restriction was successful or to an error if | ||||||
|      *         not */ |      *         not */ | ||||||
|     Result<SEBRestriction> applySEBClientRestriction( |     Result<SEBRestriction> applySEBClientRestriction( | ||||||
|             Exam exam, |             Exam exam, | ||||||
|  |  | ||||||
|  | @ -153,8 +153,11 @@ public class LmsAPIServiceImpl implements LmsAPIService { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (template.lmsSetup().getLmsType().features.contains(LmsSetup.Features.SEB_RESTRICTION)) { |         if (template.lmsSetup().getLmsType().features.contains(LmsSetup.Features.SEB_RESTRICTION)) { | ||||||
|             this.cache.remove(new CacheKey(template.lmsSetup().getModelId(), 0)); |             final LmsSetupTestResult lmsSetupTestResult = template.testCourseRestrictionAPI(); | ||||||
|             return template.testCourseRestrictionAPI(); |             if (!lmsSetupTestResult.isOk()) { | ||||||
|  |                 this.cache.remove(new CacheKey(template.lmsSetup().getModelId(), 0)); | ||||||
|  |             } | ||||||
|  |             return lmsSetupTestResult; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return LmsSetupTestResult.ofOkay(template.lmsSetup().getLmsType()); |         return LmsSetupTestResult.ofOkay(template.lmsSetup().getLmsType()); | ||||||
|  |  | ||||||
|  | @ -386,18 +386,12 @@ public class LmsAPITemplateAdapter implements LmsAPITemplate { | ||||||
| 
 | 
 | ||||||
|         return this.restrictionRequest.protectedRun(() -> this.sebRestrictionAPI |         return this.restrictionRequest.protectedRun(() -> this.sebRestrictionAPI | ||||||
|                 .getSEBClientRestriction(exam) |                 .getSEBClientRestriction(exam) | ||||||
|                 .onError(error -> log.error("Failed to get SEB restrictions: {}", error.getMessage())) |  | ||||||
|                 .getOrThrow()); |                 .getOrThrow()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public boolean hasSEBClientRestriction(final Exam exam) { |     public boolean hasSEBClientRestriction(final Exam exam) { | ||||||
|         final Result<SEBRestriction> sebClientRestriction = getSEBClientRestriction(exam); |         return this.sebRestrictionAPI.hasSEBClientRestriction(getSEBClientRestriction(exam).getOrThrow()); | ||||||
|         if (sebClientRestriction.hasError()) { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         return this.sebRestrictionAPI.hasSEBClientRestriction(sebClientRestriction.get()); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  |  | ||||||
|  | @ -18,6 +18,7 @@ import java.util.Map; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||||
| 
 | 
 | ||||||
|  | import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.AdditionalAttributeRecord; | ||||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  | @ -102,7 +103,7 @@ public class SEBRestrictionServiceImpl implements SEBRestrictionService { | ||||||
|                     .getOrThrow(); |                     .getOrThrow(); | ||||||
| 
 | 
 | ||||||
|             configKeys.addAll(generatedKeys); |             configKeys.addAll(generatedKeys); | ||||||
|             if (generatedKeys != null && !generatedKeys.isEmpty()) { |             if (!generatedKeys.isEmpty()) { | ||||||
|                 configKeys.addAll(this.lmsAPIService |                 configKeys.addAll(this.lmsAPIService | ||||||
|                         .getLmsAPITemplate(exam.lmsSetupId) |                         .getLmsAPITemplate(exam.lmsSetupId) | ||||||
|                         .flatMap(lmsTemplate -> lmsTemplate.getSEBClientRestriction(exam)) |                         .flatMap(lmsTemplate -> lmsTemplate.getSEBClientRestriction(exam)) | ||||||
|  | @ -130,8 +131,8 @@ public class SEBRestrictionServiceImpl implements SEBRestrictionService { | ||||||
|                         .collect(Collectors.toMap( |                         .collect(Collectors.toMap( | ||||||
|                                 attr -> attr.getName().replace( |                                 attr -> attr.getName().replace( | ||||||
|                                         SEB_RESTRICTION_ADDITIONAL_PROPERTY_NAME_PREFIX, |                                         SEB_RESTRICTION_ADDITIONAL_PROPERTY_NAME_PREFIX, | ||||||
|                                         ""), |                                         StringUtils.EMPTY), | ||||||
|                                 attr -> attr.getValue()))); |                                 AdditionalAttributeRecord::getValue))); | ||||||
|             } catch (final Exception e) { |             } catch (final Exception e) { | ||||||
|                 log.error( |                 log.error( | ||||||
|                         "Failed to load additional SEB restriction properties from AdditionalAttributes of the Exam: {}", |                         "Failed to load additional SEB restriction properties from AdditionalAttributes of the Exam: {}", | ||||||
|  |  | ||||||
|  | @ -8,6 +8,10 @@ | ||||||
| 
 | 
 | ||||||
| package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.mockup; | package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.mockup; | ||||||
| 
 | 
 | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.concurrent.ConcurrentHashMap; | ||||||
|  | 
 | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
| 
 | 
 | ||||||
|  | @ -23,6 +27,8 @@ 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<>(); | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     public LmsSetupTestResult testCourseRestrictionAPI() { |     public LmsSetupTestResult testCourseRestrictionAPI() { | ||||||
|         return LmsSetupTestResult.ofOkay(LmsType.MOCKUP); |         return LmsSetupTestResult.ofOkay(LmsType.MOCKUP); | ||||||
|  | @ -31,15 +37,6 @@ 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); | ||||||
| //        if (BooleanUtils.toBoolean(exam.sebRestriction)) { |  | ||||||
| //            return Result.of(new SEBRestriction( |  | ||||||
| //                    exam.id, |  | ||||||
| //                    Stream.of("configKey").collect(Collectors.toList()), |  | ||||||
| //                    Collections.emptyList(), |  | ||||||
| //                    Collections.emptyMap())); |  | ||||||
| //        } else { |  | ||||||
| //            return Result.ofError(new NoSEBRestrictionException()); |  | ||||||
| //        } |  | ||||||
|         return Result.ofError(new NoSEBRestrictionException()); |         return Result.ofError(new NoSEBRestrictionException()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -164,7 +164,6 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory | ||||||
|     public Result<MoodleAPIRestTemplate> createRestTemplate(final String service, final String accessTokenPath) { |     public Result<MoodleAPIRestTemplate> createRestTemplate(final String service, final String accessTokenPath) { | ||||||
| 
 | 
 | ||||||
|         final LmsSetup lmsSetup = this.apiTemplateDataSupplier.getLmsSetup(); |         final LmsSetup lmsSetup = this.apiTemplateDataSupplier.getLmsSetup(); | ||||||
| 
 |  | ||||||
|         return Result.tryCatch(() -> { |         return Result.tryCatch(() -> { | ||||||
|             final ClientCredentials credentials = this.apiTemplateDataSupplier.getLmsClientCredentials(); |             final ClientCredentials credentials = this.apiTemplateDataSupplier.getLmsClientCredentials(); | ||||||
|             final ProxyData proxyData = this.apiTemplateDataSupplier.getProxyData(); |             final ProxyData proxyData = this.apiTemplateDataSupplier.getProxyData(); | ||||||
|  | @ -319,7 +318,7 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             final boolean usePOST = queryAttributes != null && !queryAttributes.isEmpty(); |             final boolean usePOST = queryAttributes != null && !queryAttributes.isEmpty(); | ||||||
|             HttpEntity<?> functionReqEntity; |             final HttpEntity<?> functionReqEntity; | ||||||
|             if (usePOST) { |             if (usePOST) { | ||||||
|                 final HttpHeaders headers = new HttpHeaders(); |                 final HttpHeaders headers = new HttpHeaders(); | ||||||
|                 headers.set( |                 headers.set( | ||||||
|  | @ -401,8 +400,7 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory | ||||||
|                     if (moodleToken == null || moodleToken.token == null) { |                     if (moodleToken == null || moodleToken.token == null) { | ||||||
|                         throw new RuntimeException("Access Token request with 200 but no or invalid token body"); |                         throw new RuntimeException("Access Token request with 200 but no or invalid token body"); | ||||||
|                     } else { |                     } else { | ||||||
|                         log.info("Successfully get access token from Moodle: {}", |                         log.info("Successfully get access token from Moodle: {}", lmsSetup.name); | ||||||
|                                 lmsSetup); |  | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                     this.accessToken = moodleToken.token; |                     this.accessToken = moodleToken.token; | ||||||
|  |  | ||||||
|  | @ -1,68 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) 2022 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.lms.impl.moodle.plugin; |  | ||||||
| 
 |  | ||||||
| import org.slf4j.Logger; |  | ||||||
| import org.slf4j.LoggerFactory; |  | ||||||
| import org.springframework.context.annotation.Lazy; |  | ||||||
| import org.springframework.stereotype.Service; |  | ||||||
| 
 |  | ||||||
| import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult; |  | ||||||
| import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; |  | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleAPIRestTemplate; |  | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleRestTemplateFactory; |  | ||||||
| 
 |  | ||||||
| @Lazy |  | ||||||
| @Service |  | ||||||
| @WebServiceProfile |  | ||||||
| public class MoodlePluginCheck { |  | ||||||
| 
 |  | ||||||
|     private static final Logger log = LoggerFactory.getLogger(MoodlePluginCheck.class); |  | ||||||
| 
 |  | ||||||
|     /** Used to check if the moodle SEB Server plugin is available for a given LMSSetup. |  | ||||||
|      * |  | ||||||
|      * @param lmsSetup The LMS Setup |  | ||||||
|      * @return true if the SEB Server plugin is available */ |  | ||||||
|     public boolean checkPluginAvailable(final MoodleRestTemplateFactory restTemplateFactory) { |  | ||||||
|         try { |  | ||||||
| 
 |  | ||||||
|             log.info("Check Moodle SEB Server Plugin available..."); |  | ||||||
| 
 |  | ||||||
|             final LmsSetupTestResult test = restTemplateFactory.test(); |  | ||||||
| 
 |  | ||||||
|             if (!test.isOk()) { |  | ||||||
|                 log.warn("Failed to check Moodle SEB Server Plugin because of invalid LMS Setup: ", test); |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             final MoodleAPIRestTemplate restTemplate = restTemplateFactory |  | ||||||
|                     .createRestTemplate(MooldePluginLmsAPITemplateFactory.SEB_SERVER_SERVICE_NAME) |  | ||||||
|                     .getOrThrow(); |  | ||||||
| 
 |  | ||||||
|             try { |  | ||||||
|                 restTemplate.testAPIConnection( |  | ||||||
|                         MoodlePluginCourseAccess.COURSES_API_FUNCTION_NAME, |  | ||||||
|                         MoodlePluginCourseAccess.USERS_API_FUNCTION_NAME); |  | ||||||
|             } catch (final Exception e) { |  | ||||||
|                 log.info("Moodle SEB Server Plugin not available: {}", e.getMessage()); |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             log.info("Moodle SEB Server Plugin not available for: {}", |  | ||||||
|                     restTemplateFactory.getApiTemplateDataSupplier().getLmsSetup()); |  | ||||||
| 
 |  | ||||||
|             return true; |  | ||||||
| 
 |  | ||||||
|         } catch (final Exception e) { |  | ||||||
|             log.error("Failed to check Moodle SEB Server Plugin because of unexpected error: ", e); |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -109,6 +109,7 @@ public class MoodlePluginCourseAccess extends AbstractCachedCourseAccess impleme | ||||||
|             final boolean applyNameCriteria) { |             final boolean applyNameCriteria) { | ||||||
| 
 | 
 | ||||||
|         super(cacheManager); |         super(cacheManager); | ||||||
|  | 
 | ||||||
|         this.jsonMapper = jsonMapper; |         this.jsonMapper = jsonMapper; | ||||||
|         this.restTemplateFactory = restTemplateFactory; |         this.restTemplateFactory = restTemplateFactory; | ||||||
|         this.applyNameCriteria = applyNameCriteria; |         this.applyNameCriteria = applyNameCriteria; | ||||||
|  | @ -594,7 +595,9 @@ public class MoodlePluginCourseAccess extends AbstractCachedCourseAccess impleme | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private Result<MoodleAPIRestTemplate> getRestTemplate() { |     private Result<MoodleAPIRestTemplate> getRestTemplate() { | ||||||
|  | 
 | ||||||
|         if (this.restTemplate == null) { |         if (this.restTemplate == null) { | ||||||
|  | 
 | ||||||
|             final Result<MoodleAPIRestTemplate> templateRequest = this.restTemplateFactory |             final Result<MoodleAPIRestTemplate> templateRequest = this.restTemplateFactory | ||||||
|                     .createRestTemplate(MooldePluginLmsAPITemplateFactory.SEB_SERVER_SERVICE_NAME); |                     .createRestTemplate(MooldePluginLmsAPITemplateFactory.SEB_SERVER_SERVICE_NAME); | ||||||
|             if (templateRequest.hasError()) { |             if (templateRequest.hasError()) { | ||||||
|  |  | ||||||
|  | @ -283,13 +283,13 @@ public class MoodlePluginCourseRestriction implements SEBRestrictionAPI { | ||||||
| 
 | 
 | ||||||
|     private Result<MoodleAPIRestTemplate> getRestTemplate() { |     private Result<MoodleAPIRestTemplate> getRestTemplate() { | ||||||
|         if (this.restTemplate == null) { |         if (this.restTemplate == null) { | ||||||
|  | 
 | ||||||
|             final Result<MoodleAPIRestTemplate> templateRequest = this.restTemplateFactory |             final Result<MoodleAPIRestTemplate> templateRequest = this.restTemplateFactory | ||||||
|                     .createRestTemplate(MooldePluginLmsAPITemplateFactory.SEB_SERVER_SERVICE_NAME); |                     .createRestTemplate(MooldePluginLmsAPITemplateFactory.SEB_SERVER_SERVICE_NAME); | ||||||
|             if (templateRequest.hasError()) { |             if (templateRequest.hasError()) { | ||||||
|                 return templateRequest; |                 return templateRequest; | ||||||
|             } else { |             } else { | ||||||
|                 final MoodleAPIRestTemplate moodleAPIRestTemplate = templateRequest.get(); |                 this.restTemplate = templateRequest.get(); | ||||||
|                 this.restTemplate = moodleAPIRestTemplate; |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -337,7 +337,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> { | ||||||
|         return this.examDAO |         return this.examDAO | ||||||
|                 .byPK(modelId) |                 .byPK(modelId) | ||||||
|                 .flatMap(this.examAdminService::isRestricted) |                 .flatMap(this.examAdminService::isRestricted) | ||||||
|                 .getOrThrow(); |                 .getOr(false); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @RequestMapping( |     @RequestMapping( | ||||||
|  | @ -376,7 +376,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> { | ||||||
|         return this.entityDAO.byPK(examId) |         return this.entityDAO.byPK(examId) | ||||||
|                 .flatMap(this.authorization::checkModify) |                 .flatMap(this.authorization::checkModify) | ||||||
|                 .flatMap(exam -> this.sebRestrictionService.saveSEBRestrictionToExam(exam, sebRestriction)) |                 .flatMap(exam -> this.sebRestrictionService.saveSEBRestrictionToExam(exam, sebRestriction)) | ||||||
|                 .flatMap(exam -> this.examAdminService.isRestricted(exam).getOrThrow() |                 .flatMap(exam -> this.examAdminService.isRestricted(exam).getOr(false) | ||||||
|                         ? this.applySEBRestriction(exam, true) |                         ? this.applySEBRestriction(exam, true) | ||||||
|                         : Result.of(exam)) |                         : Result.of(exam)) | ||||||
|                 .getOrThrow(); |                 .getOrThrow(); | ||||||
|  |  | ||||||
|  | @ -33,6 +33,7 @@ public class MoodlePluginCourseRestrictionTest { | ||||||
| 
 | 
 | ||||||
|     @Test |     @Test | ||||||
|     public void testSetup() { |     public void testSetup() { | ||||||
|  | 
 | ||||||
|         final MoodlePluginCourseRestriction candidate = crateMockup(); |         final MoodlePluginCourseRestriction candidate = crateMockup(); | ||||||
| 
 | 
 | ||||||
|         assertEquals("MoodlePluginCourseRestriction [restTemplate=null]", candidate.toTestString()); |         assertEquals("MoodlePluginCourseRestriction [restTemplate=null]", candidate.toTestString()); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 anhefti
						anhefti