SEBSERV-351 implementation (no tests yet)
This commit is contained in:
		
							parent
							
								
									f131276bdd
								
							
						
					
					
						commit
						bb0c834676
					
				
					 17 changed files with 226 additions and 20 deletions
				
			
		|  | @ -28,4 +28,10 @@ public interface ConfigurationAttributeDAO extends EntityDAO<ConfigurationAttrib | ||||||
|      * @return Result refer to a collection of child ConfigurationAttribute or to an error if happened */ |      * @return Result refer to a collection of child ConfigurationAttribute or to an error if happened */ | ||||||
|     Result<Collection<ConfigurationAttribute>> allChildAttributes(final Long parentId); |     Result<Collection<ConfigurationAttribute>> allChildAttributes(final Long parentId); | ||||||
| 
 | 
 | ||||||
|  |     /** Use this to geht an attribute identifier by attribute name | ||||||
|  |      * | ||||||
|  |      * @param configAttributeName the attribute name | ||||||
|  |      * @return Result refer to the attribute identifier or to an error if happened */ | ||||||
|  |     Result<Long> getAttributeIdByName(String configAttributeName); | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -71,4 +71,11 @@ public interface ConfigurationValueDAO extends EntityDAO<ConfigurationValue, Con | ||||||
|             Long configurationId, |             Long configurationId, | ||||||
|             Long attributeId); |             Long attributeId); | ||||||
| 
 | 
 | ||||||
|  |     /** Use this to get a specific SEB Settings attribute value. | ||||||
|  |      * | ||||||
|  |      * @param configId the configuration identifier for the value | ||||||
|  |      * @param attrId the attribute identifier | ||||||
|  |      * @return the String value of the SEB setting attribute */ | ||||||
|  |     Result<String> getConfigAttributeValue(Long configId, Long attrId); | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -93,6 +93,19 @@ public class ConfigurationAttributeDAOImpl implements ConfigurationAttributeDAO | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|  |     @Transactional(readOnly = true) | ||||||
|  |     public Result<Long> getAttributeIdByName(final String attributeName) { | ||||||
|  |         return Result.tryCatch(() -> this.configurationAttributeRecordMapper | ||||||
|  |                 .selectByExample() | ||||||
|  |                 .where( | ||||||
|  |                         ConfigurationAttributeRecordDynamicSqlSupport.name, | ||||||
|  |                         SqlBuilder.isEqualTo(attributeName)) | ||||||
|  |                 .build() | ||||||
|  |                 .execute() | ||||||
|  |                 .get(0).getId()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     @Transactional(readOnly = true) |     @Transactional(readOnly = true) | ||||||
|     public Result<Collection<ConfigurationAttribute>> allMatching( |     public Result<Collection<ConfigurationAttribute>> allMatching( | ||||||
|  |  | ||||||
|  | @ -19,6 +19,7 @@ import java.util.HashMap; | ||||||
| import java.util.HashSet; | import java.util.HashSet; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
|  | import java.util.NoSuchElementException; | ||||||
| import java.util.Objects; | import java.util.Objects; | ||||||
| import java.util.Optional; | import java.util.Optional; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
|  | @ -122,6 +123,34 @@ public class ConfigurationValueDAOImpl implements ConfigurationValueDAO { | ||||||
|                 .collect(Collectors.toList())); |                 .collect(Collectors.toList())); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|  |     public Result<String> getConfigAttributeValue(final Long configId, final Long attrId) { | ||||||
|  |         return Result.tryCatch(() -> { | ||||||
|  | 
 | ||||||
|  |             final List<ConfigurationValueRecord> records = this.configurationValueRecordMapper.selectByExample() | ||||||
|  |                     .where( | ||||||
|  |                             ConfigurationValueRecordDynamicSqlSupport.configurationId, | ||||||
|  |                             isEqualTo(configId)) | ||||||
|  | 
 | ||||||
|  |                     .and( | ||||||
|  |                             ConfigurationValueRecordDynamicSqlSupport.configurationAttributeId, | ||||||
|  |                             SqlBuilder.isEqualTo(attrId)) | ||||||
|  |                     .build() | ||||||
|  |                     .execute(); | ||||||
|  | 
 | ||||||
|  |             if (records == null) { | ||||||
|  |                 throw new NoSuchElementException( | ||||||
|  |                         "No SEB setting attribute value found for configId: " + configId + " attrId: " + attrId); | ||||||
|  |             } | ||||||
|  |             if (records.size() > 1) { | ||||||
|  |                 log.warn("Found more then one attribute value for configId: {}, attrId:{} select first one.", configId, | ||||||
|  |                         attrId); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return records.get(0).getValue(); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     @Transactional(readOnly = true) |     @Transactional(readOnly = true) | ||||||
|     public Result<Collection<ConfigurationValue>> allOf(final Set<Long> pks) { |     public Result<Collection<ConfigurationValue>> allOf(final Set<Long> pks) { | ||||||
|  |  | ||||||
|  | @ -0,0 +1,21 @@ | ||||||
|  | /* | ||||||
|  |  * 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.exam; | ||||||
|  | 
 | ||||||
|  | public interface ExamConfigurationValueService { | ||||||
|  | 
 | ||||||
|  |     /** Get the actual SEB settings attribute value for the exam configuration mapped as default configuration | ||||||
|  |      * to the given exam | ||||||
|  |      * | ||||||
|  |      * @param examId The exam identifier | ||||||
|  |      * @param configAttributeName The name of the SEB settings attribute | ||||||
|  |      * @return The current value of the above SEB settings attribute and given exam. */ | ||||||
|  |     String getMappedDefaultConfigAttributeValue(Long examId, String configAttributeName); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,69 @@ | ||||||
|  | /* | ||||||
|  |  * 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.exam.impl; | ||||||
|  | 
 | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  | import org.springframework.stereotype.Service; | ||||||
|  | 
 | ||||||
|  | import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationAttributeDAO; | ||||||
|  | import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationDAO; | ||||||
|  | import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationValueDAO; | ||||||
|  | import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamConfigurationMapDAO; | ||||||
|  | import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamConfigurationValueService; | ||||||
|  | 
 | ||||||
|  | @Service | ||||||
|  | public class ExamConfigurationValueServiceImpl implements ExamConfigurationValueService { | ||||||
|  | 
 | ||||||
|  |     private static final Logger log = LoggerFactory.getLogger(ExamConfigurationValueServiceImpl.class); | ||||||
|  | 
 | ||||||
|  |     private final ExamConfigurationMapDAO examConfigurationMapDAO; | ||||||
|  |     private final ConfigurationDAO configurationDAO; | ||||||
|  |     private final ConfigurationAttributeDAO configurationAttributeDAO; | ||||||
|  |     private final ConfigurationValueDAO configurationValueDAO; | ||||||
|  | 
 | ||||||
|  |     public ExamConfigurationValueServiceImpl( | ||||||
|  |             final ExamConfigurationMapDAO examConfigurationMapDAO, | ||||||
|  |             final ConfigurationDAO configurationDAO, | ||||||
|  |             final ConfigurationAttributeDAO configurationAttributeDAO, | ||||||
|  |             final ConfigurationValueDAO configurationValueDAO) { | ||||||
|  | 
 | ||||||
|  |         this.examConfigurationMapDAO = examConfigurationMapDAO; | ||||||
|  |         this.configurationDAO = configurationDAO; | ||||||
|  |         this.configurationAttributeDAO = configurationAttributeDAO; | ||||||
|  |         this.configurationValueDAO = configurationValueDAO; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String getMappedDefaultConfigAttributeValue(final Long examId, final String configAttributeName) { | ||||||
|  |         try { | ||||||
|  | 
 | ||||||
|  |             final Long configId = this.examConfigurationMapDAO | ||||||
|  |                     .getDefaultConfigurationNode(examId) | ||||||
|  |                     .flatMap(nodeId -> this.configurationDAO.getConfigurationLastStableVersion(nodeId)) | ||||||
|  |                     .map(config -> config.id) | ||||||
|  |                     .getOrThrow(); | ||||||
|  | 
 | ||||||
|  |             final Long attrId = this.configurationAttributeDAO | ||||||
|  |                     .getAttributeIdByName(configAttributeName) | ||||||
|  |                     .onError(error -> log.error("Failed to get attribute id with name: {} for exam: {}", | ||||||
|  |                             configAttributeName, examId, error)) | ||||||
|  |                     .getOr(null); | ||||||
|  | 
 | ||||||
|  |             return this.configurationValueDAO | ||||||
|  |                     .getConfigAttributeValue(configId, attrId) | ||||||
|  |                     .getOrThrow(); | ||||||
|  | 
 | ||||||
|  |         } catch (final Exception e) { | ||||||
|  |             log.error("Unexpected error while trying to extract SEB settings attribute value:", e); | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -56,12 +56,12 @@ public interface SEBRestrictionAPI { | ||||||
| 
 | 
 | ||||||
|     /** Applies SEB Client restrictions to the LMS with the given attributes. |     /** Applies SEB Client restrictions to the LMS with the given attributes. | ||||||
|      * |      * | ||||||
|      * @param externalExamId The exam/course identifier from LMS side (Exam.externalId) |      * @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 SEBRestrictionData } if restriction was successful or to an error if | ||||||
|      *         not */ |      *         not */ | ||||||
|     Result<SEBRestriction> applySEBClientRestriction( |     Result<SEBRestriction> applySEBClientRestriction( | ||||||
|             String externalExamId, |             Exam exam, | ||||||
|             SEBRestriction sebRestrictionData); |             SEBRestriction sebRestrictionData); | ||||||
| 
 | 
 | ||||||
|     /** Releases an already applied SEB Client restriction within the LMS for a given Exam. |     /** Releases an already applied SEB Client restriction within the LMS for a given Exam. | ||||||
|  |  | ||||||
|  | @ -409,7 +409,7 @@ public class LmsAPITemplateAdapter implements LmsAPITemplate { | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Result<SEBRestriction> applySEBClientRestriction( |     public Result<SEBRestriction> applySEBClientRestriction( | ||||||
|             final String externalExamId, |             final Exam exam, | ||||||
|             final SEBRestriction sebRestrictionData) { |             final SEBRestriction sebRestrictionData) { | ||||||
| 
 | 
 | ||||||
|         if (this.sebRestrictionAPI == null) { |         if (this.sebRestrictionAPI == null) { | ||||||
|  | @ -418,11 +418,11 @@ public class LmsAPITemplateAdapter implements LmsAPITemplate { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (log.isDebugEnabled()) { |         if (log.isDebugEnabled()) { | ||||||
|             log.debug("Apply course restriction: {} for LMSSetup: {}", externalExamId, lmsSetup()); |             log.debug("Apply course restriction: {} for LMSSetup: {}", exam, lmsSetup()); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return this.restrictionRequest.protectedRun(() -> this.sebRestrictionAPI |         return this.restrictionRequest.protectedRun(() -> this.sebRestrictionAPI | ||||||
|                 .applySEBClientRestriction(externalExamId, sebRestrictionData) |                 .applySEBClientRestriction(exam, sebRestrictionData) | ||||||
|                 .onError(error -> log.error( |                 .onError(error -> log.error( | ||||||
|                         "Failed to apply SEB restrictions: {}", |                         "Failed to apply SEB restrictions: {}", | ||||||
|                         error.getMessage())) |                         error.getMessage())) | ||||||
|  |  | ||||||
|  | @ -237,7 +237,7 @@ public class SEBRestrictionServiceImpl implements SEBRestrictionService { | ||||||
|                         return this.lmsAPIService |                         return this.lmsAPIService | ||||||
|                                 .getLmsAPITemplate(exam.lmsSetupId) |                                 .getLmsAPITemplate(exam.lmsSetupId) | ||||||
|                                 .flatMap(lmsTemplate -> lmsTemplate.applySEBClientRestriction( |                                 .flatMap(lmsTemplate -> lmsTemplate.applySEBClientRestriction( | ||||||
|                                         exam.externalId, |                                         exam, | ||||||
|                                         sebRestrictionData)) |                                         sebRestrictionData)) | ||||||
|                                 .map(data -> exam) |                                 .map(data -> exam) | ||||||
|                                 .getOrThrow(); |                                 .getOrThrow(); | ||||||
|  |  | ||||||
|  | @ -56,8 +56,8 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.lms.APITemplateDataSupplier | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.AbstractCachedCourseAccess; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.AbstractCachedCourseAccess; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.ans.AnsLmsData.SEBServerData; |  | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.ans.AnsLmsData.AssignmentData; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.ans.AnsLmsData.AssignmentData; | ||||||
|  | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.ans.AnsLmsData.SEBServerData; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.ans.AnsLmsData.UserData; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.ans.AnsLmsData.UserData; | ||||||
| 
 | 
 | ||||||
| public class AnsLmsAPITemplate extends AbstractCachedCourseAccess implements LmsAPITemplate { | public class AnsLmsAPITemplate extends AbstractCachedCourseAccess implements LmsAPITemplate { | ||||||
|  | @ -371,10 +371,10 @@ public class AnsLmsAPITemplate extends AbstractCachedCourseAccess implements Lms | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Result<SEBRestriction> applySEBClientRestriction( |     public Result<SEBRestriction> applySEBClientRestriction( | ||||||
|             final String externalExamId, |             final Exam exam, | ||||||
|             final SEBRestriction sebRestrictionData) { |             final SEBRestriction sebRestrictionData) { | ||||||
|         return getRestTemplate() |         return getRestTemplate() | ||||||
|                 .map(t -> this.setRestrictionForAssignmentId(t, externalExamId, sebRestrictionData)); |                 .map(t -> this.setRestrictionForAssignmentId(t, exam.externalId, sebRestrictionData)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  |  | ||||||
|  | @ -148,16 +148,16 @@ public class OpenEdxCourseRestriction implements SEBRestrictionAPI { | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Result<SEBRestriction> applySEBClientRestriction( |     public Result<SEBRestriction> applySEBClientRestriction( | ||||||
|             final String externalExamId, |             final Exam exam, | ||||||
|             final SEBRestriction sebRestrictionData) { |             final SEBRestriction sebRestrictionData) { | ||||||
| 
 | 
 | ||||||
|         if (log.isDebugEnabled()) { |         if (log.isDebugEnabled()) { | ||||||
|             log.debug("PUT SEB Client restriction on course: {} : {}", externalExamId, sebRestrictionData); |             log.debug("PUT SEB Client restriction on course: {} : {}", exam.externalId, sebRestrictionData); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return Result.tryCatch(() -> { |         return Result.tryCatch(() -> { | ||||||
|             final LmsSetup lmsSetup = this.openEdxRestTemplateFactory.apiTemplateDataSupplier.getLmsSetup(); |             final LmsSetup lmsSetup = this.openEdxRestTemplateFactory.apiTemplateDataSupplier.getLmsSetup(); | ||||||
|             final String url = lmsSetup.lmsApiUrl + getSEBRestrictionUrl(externalExamId); |             final String url = lmsSetup.lmsApiUrl + getSEBRestrictionUrl(exam.externalId); | ||||||
|             final HttpHeaders httpHeaders = new HttpHeaders(); |             final HttpHeaders httpHeaders = new HttpHeaders(); | ||||||
|             httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); |             httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); | ||||||
|             httpHeaders.add(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, must-revalidate"); |             httpHeaders.add(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, must-revalidate"); | ||||||
|  | @ -172,7 +172,7 @@ public class OpenEdxCourseRestriction implements SEBRestrictionAPI { | ||||||
|                     .getBody(); |                     .getBody(); | ||||||
| 
 | 
 | ||||||
|             if (log.isDebugEnabled()) { |             if (log.isDebugEnabled()) { | ||||||
|                 log.debug("Successfully PUT SEB Client restriction on course: {} : {}", externalExamId, body); |                 log.debug("Successfully PUT SEB Client restriction on course: {} : {}", exam.externalId, body); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             return sebRestrictionData; |             return sebRestrictionData; | ||||||
|  |  | ||||||
|  | @ -36,7 +36,7 @@ public class MockSEBRestrictionAPI implements SEBRestrictionAPI { | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Result<SEBRestriction> applySEBClientRestriction( |     public Result<SEBRestriction> applySEBClientRestriction( | ||||||
|             final String externalExamId, |             final Exam exam, | ||||||
|             final SEBRestriction sebRestrictionData) { |             final SEBRestriction sebRestrictionData) { | ||||||
| 
 | 
 | ||||||
|         log.info("Apply SEB Client restriction: {}", sebRestrictionData); |         log.info("Apply SEB Client restriction: {}", sebRestrictionData); | ||||||
|  |  | ||||||
|  | @ -126,11 +126,11 @@ public class MoodleCourseRestriction implements SEBRestrictionAPI { | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Result<SEBRestriction> applySEBClientRestriction( |     public Result<SEBRestriction> applySEBClientRestriction( | ||||||
|             final String externalExamId, |             final Exam exam, | ||||||
|             final SEBRestriction sebRestrictionData) { |             final SEBRestriction sebRestrictionData) { | ||||||
| 
 | 
 | ||||||
|         return this.updateSEBRestriction( |         return this.updateSEBRestriction( | ||||||
|                 externalExamId, |                 exam.externalId, | ||||||
|                 MoodleSEBRestriction.from(sebRestrictionData)) |                 MoodleSEBRestriction.from(sebRestrictionData)) | ||||||
|                 .map(result -> sebRestrictionData); |                 .map(result -> sebRestrictionData); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -29,8 +29,10 @@ public class MoodlePluginCourseRestriction implements SEBRestrictionAPI { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Result<SEBRestriction> applySEBClientRestriction(final String externalExamId, |     public Result<SEBRestriction> applySEBClientRestriction( | ||||||
|  |             final Exam exam, | ||||||
|             final SEBRestriction sebRestrictionData) { |             final SEBRestriction sebRestrictionData) { | ||||||
|  | 
 | ||||||
|         // TODO Auto-generated method stub |         // TODO Auto-generated method stub | ||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -49,6 +49,7 @@ import ch.ethz.seb.sebserver.gbl.model.user.ExamineeAccountDetails; | ||||||
| import ch.ethz.seb.sebserver.gbl.util.Result; | import ch.ethz.seb.sebserver.gbl.util.Result; | ||||||
| import ch.ethz.seb.sebserver.gbl.util.Utils; | import ch.ethz.seb.sebserver.gbl.util.Utils; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; | import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; | ||||||
|  | import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamConfigurationValueService; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.APITemplateDataSupplier; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.APITemplateDataSupplier; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate; | ||||||
|  | @ -62,9 +63,16 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm | ||||||
| 
 | 
 | ||||||
|     private static final Logger log = LoggerFactory.getLogger(OlatLmsAPITemplate.class); |     private static final Logger log = LoggerFactory.getLogger(OlatLmsAPITemplate.class); | ||||||
| 
 | 
 | ||||||
|  |     private static final String ADDITIONAL_ATTR_QUIT_LINK = "ADDITIONAL_ATTR_QUIT_LINK"; | ||||||
|  |     private static final String ADDITIONAL_ATTR_QUIT_SECRET = "ADDITIONAL_ATTR_QUIT_SECRET"; | ||||||
|  | 
 | ||||||
|  |     private static final String CONFIG_ATTR_NAME_QUIT_LINK = "quitURL"; | ||||||
|  |     private static final String CONFIG_ATTR_NAME_QUIT_SECRET = "hashedQuitPassword"; | ||||||
|  | 
 | ||||||
|     private final ClientHttpRequestFactoryService clientHttpRequestFactoryService; |     private final ClientHttpRequestFactoryService clientHttpRequestFactoryService; | ||||||
|     private final ClientCredentialService clientCredentialService; |     private final ClientCredentialService clientCredentialService; | ||||||
|     private final APITemplateDataSupplier apiTemplateDataSupplier; |     private final APITemplateDataSupplier apiTemplateDataSupplier; | ||||||
|  |     private final ExamConfigurationValueService examConfigurationValueService; | ||||||
|     private final Long lmsSetupId; |     private final Long lmsSetupId; | ||||||
| 
 | 
 | ||||||
|     private OlatLmsRestTemplate cachedRestTemplate; |     private OlatLmsRestTemplate cachedRestTemplate; | ||||||
|  | @ -73,6 +81,7 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm | ||||||
|             final ClientHttpRequestFactoryService clientHttpRequestFactoryService, |             final ClientHttpRequestFactoryService clientHttpRequestFactoryService, | ||||||
|             final ClientCredentialService clientCredentialService, |             final ClientCredentialService clientCredentialService, | ||||||
|             final APITemplateDataSupplier apiTemplateDataSupplier, |             final APITemplateDataSupplier apiTemplateDataSupplier, | ||||||
|  |             final ExamConfigurationValueService examConfigurationValueService, | ||||||
|             final CacheManager cacheManager) { |             final CacheManager cacheManager) { | ||||||
| 
 | 
 | ||||||
|         super(cacheManager); |         super(cacheManager); | ||||||
|  | @ -80,6 +89,7 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm | ||||||
|         this.clientHttpRequestFactoryService = clientHttpRequestFactoryService; |         this.clientHttpRequestFactoryService = clientHttpRequestFactoryService; | ||||||
|         this.clientCredentialService = clientCredentialService; |         this.clientCredentialService = clientCredentialService; | ||||||
|         this.apiTemplateDataSupplier = apiTemplateDataSupplier; |         this.apiTemplateDataSupplier = apiTemplateDataSupplier; | ||||||
|  |         this.examConfigurationValueService = examConfigurationValueService; | ||||||
|         this.lmsSetupId = apiTemplateDataSupplier.getLmsSetup().id; |         this.lmsSetupId = apiTemplateDataSupplier.getLmsSetup().id; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -310,7 +320,15 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm | ||||||
|     private SEBRestriction getRestrictionForAssignmentId(final RestTemplate restTemplate, final String id) { |     private SEBRestriction getRestrictionForAssignmentId(final RestTemplate restTemplate, final String id) { | ||||||
|         final String url = String.format("/restapi/assessment_modes/%s/seb_restriction", id); |         final String url = String.format("/restapi/assessment_modes/%s/seb_restriction", id); | ||||||
|         final RestrictionData r = this.apiGet(restTemplate, url, RestrictionData.class); |         final RestrictionData r = this.apiGet(restTemplate, url, RestrictionData.class); | ||||||
|         return new SEBRestriction(Long.valueOf(id), r.configKeys, r.browserExamKeys, new HashMap<String, String>()); |         final HashMap<String, String> additionalAttributes = new HashMap<>(); | ||||||
|  |         if (StringUtils.isNotBlank(r.quitLink)) { | ||||||
|  |             additionalAttributes.put(ADDITIONAL_ATTR_QUIT_LINK, r.quitLink); | ||||||
|  |         } | ||||||
|  |         if (StringUtils.isNotBlank(r.quitSecret)) { | ||||||
|  |             additionalAttributes.put(ADDITIONAL_ATTR_QUIT_SECRET, r.quitSecret); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return new SEBRestriction(Long.valueOf(id), r.configKeys, r.browserExamKeys, additionalAttributes); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private SEBRestriction setRestrictionForAssignmentId( |     private SEBRestriction setRestrictionForAssignmentId( | ||||||
|  | @ -322,6 +340,8 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm | ||||||
|         final RestrictionDataPost post = new RestrictionDataPost(); |         final RestrictionDataPost post = new RestrictionDataPost(); | ||||||
|         post.browserExamKeys = new ArrayList<>(restriction.browserExamKeys); |         post.browserExamKeys = new ArrayList<>(restriction.browserExamKeys); | ||||||
|         post.configKeys = new ArrayList<>(restriction.configKeys); |         post.configKeys = new ArrayList<>(restriction.configKeys); | ||||||
|  |         post.quitLink = restriction.getAdditionalProperties().getOrDefault(ADDITIONAL_ATTR_QUIT_LINK, null); | ||||||
|  |         post.quitSecret = restriction.getAdditionalProperties().getOrDefault(ADDITIONAL_ATTR_QUIT_SECRET, null); | ||||||
|         final RestrictionData r = |         final RestrictionData r = | ||||||
|                 this.apiPost(restTemplate, url, post, RestrictionDataPost.class, RestrictionData.class); |                 this.apiPost(restTemplate, url, post, RestrictionDataPost.class, RestrictionData.class); | ||||||
|         return new SEBRestriction(Long.valueOf(id), r.configKeys, r.browserExamKeys, new HashMap<String, String>()); |         return new SEBRestriction(Long.valueOf(id), r.configKeys, r.browserExamKeys, new HashMap<String, String>()); | ||||||
|  | @ -343,10 +363,12 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Result<SEBRestriction> applySEBClientRestriction( |     public Result<SEBRestriction> applySEBClientRestriction( | ||||||
|             final String externalExamId, |             final Exam exam, | ||||||
|             final SEBRestriction sebRestrictionData) { |             final SEBRestriction sebRestrictionData) { | ||||||
|  | 
 | ||||||
|  |         populateWithQuitLinkAndSecret(exam, sebRestrictionData); | ||||||
|         return getRestTemplate() |         return getRestTemplate() | ||||||
|                 .map(t -> this.setRestrictionForAssignmentId(t, externalExamId, sebRestrictionData)); |                 .map(t -> this.setRestrictionForAssignmentId(t, exam.externalId, sebRestrictionData)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  | @ -433,4 +455,28 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private void populateWithQuitLinkAndSecret(final Exam exam, final SEBRestriction sebRestrictionData) { | ||||||
|  |         try { | ||||||
|  | 
 | ||||||
|  |             final String quitLink = this.examConfigurationValueService.getMappedDefaultConfigAttributeValue( | ||||||
|  |                     exam.id, | ||||||
|  |                     CONFIG_ATTR_NAME_QUIT_LINK); | ||||||
|  | 
 | ||||||
|  |             final String quitSecret = this.examConfigurationValueService.getMappedDefaultConfigAttributeValue( | ||||||
|  |                     exam.id, | ||||||
|  |                     CONFIG_ATTR_NAME_QUIT_SECRET); | ||||||
|  | 
 | ||||||
|  |             if (StringUtils.isNotEmpty(quitLink)) { | ||||||
|  |                 sebRestrictionData.additionalProperties.put(ADDITIONAL_ATTR_QUIT_LINK, quitLink); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (StringUtils.isNotEmpty(quitSecret)) { | ||||||
|  |                 sebRestrictionData.additionalProperties.put(ADDITIONAL_ATTR_QUIT_SECRET, quitSecret); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |         } catch (final Exception e) { | ||||||
|  |             log.error("Failed to populate SEB restriction with quit link and quit secret: ", e); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -19,6 +19,7 @@ import ch.ethz.seb.sebserver.gbl.client.ClientCredentialService; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType; | import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType; | ||||||
| import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; | import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; | ||||||
| import ch.ethz.seb.sebserver.gbl.util.Result; | import ch.ethz.seb.sebserver.gbl.util.Result; | ||||||
|  | import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamConfigurationValueService; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.APITemplateDataSupplier; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.APITemplateDataSupplier; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplateFactory; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplateFactory; | ||||||
|  | @ -38,6 +39,7 @@ public class OlatLmsAPITemplateFactory implements LmsAPITemplateFactory { | ||||||
| 
 | 
 | ||||||
|     private final ClientHttpRequestFactoryService clientHttpRequestFactoryService; |     private final ClientHttpRequestFactoryService clientHttpRequestFactoryService; | ||||||
|     private final ClientCredentialService clientCredentialService; |     private final ClientCredentialService clientCredentialService; | ||||||
|  |     private final ExamConfigurationValueService examConfigurationValueService; | ||||||
|     private final AsyncService asyncService; |     private final AsyncService asyncService; | ||||||
|     private final Environment environment; |     private final Environment environment; | ||||||
|     private final CacheManager cacheManager; |     private final CacheManager cacheManager; | ||||||
|  | @ -45,12 +47,14 @@ public class OlatLmsAPITemplateFactory implements LmsAPITemplateFactory { | ||||||
|     public OlatLmsAPITemplateFactory( |     public OlatLmsAPITemplateFactory( | ||||||
|             final ClientHttpRequestFactoryService clientHttpRequestFactoryService, |             final ClientHttpRequestFactoryService clientHttpRequestFactoryService, | ||||||
|             final ClientCredentialService clientCredentialService, |             final ClientCredentialService clientCredentialService, | ||||||
|  |             final ExamConfigurationValueService examConfigurationValueService, | ||||||
|             final AsyncService asyncService, |             final AsyncService asyncService, | ||||||
|             final Environment environment, |             final Environment environment, | ||||||
|             final CacheManager cacheManager) { |             final CacheManager cacheManager) { | ||||||
| 
 | 
 | ||||||
|         this.clientHttpRequestFactoryService = clientHttpRequestFactoryService; |         this.clientHttpRequestFactoryService = clientHttpRequestFactoryService; | ||||||
|         this.clientCredentialService = clientCredentialService; |         this.clientCredentialService = clientCredentialService; | ||||||
|  |         this.examConfigurationValueService = examConfigurationValueService; | ||||||
|         this.asyncService = asyncService; |         this.asyncService = asyncService; | ||||||
|         this.environment = environment; |         this.environment = environment; | ||||||
|         this.cacheManager = cacheManager; |         this.cacheManager = cacheManager; | ||||||
|  | @ -68,6 +72,7 @@ public class OlatLmsAPITemplateFactory implements LmsAPITemplateFactory { | ||||||
|                     this.clientHttpRequestFactoryService, |                     this.clientHttpRequestFactoryService, | ||||||
|                     this.clientCredentialService, |                     this.clientCredentialService, | ||||||
|                     apiTemplateDataSupplier, |                     apiTemplateDataSupplier, | ||||||
|  |                     this.examConfigurationValueService, | ||||||
|                     this.cacheManager); |                     this.cacheManager); | ||||||
|             return new LmsAPITemplateAdapter( |             return new LmsAPITemplateAdapter( | ||||||
|                     this.asyncService, |                     this.asyncService, | ||||||
|  |  | ||||||
|  | @ -61,12 +61,16 @@ public final class OlatLmsData { | ||||||
|          * { |          * { | ||||||
|          * "browserExamKeys": [ "1" ], |          * "browserExamKeys": [ "1" ], | ||||||
|          * "configKeys": null, |          * "configKeys": null, | ||||||
|  |          * "quitLink": "<the quit link from Exam Configuration>", | ||||||
|  |          * "quitSecret": "<the quit password from Exam Configuration (base64 encoded)>", | ||||||
|          * "key": 8028160 |          * "key": 8028160 | ||||||
|          * } |          * } | ||||||
|          */ |          */ | ||||||
|         public long key; |         public long key; | ||||||
|         public List<String> browserExamKeys; |         public List<String> browserExamKeys; | ||||||
|         public List<String> configKeys; |         public List<String> configKeys; | ||||||
|  |         public String quitLink; | ||||||
|  |         public String quitSecret; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @JsonIgnoreProperties(ignoreUnknown = true) |     @JsonIgnoreProperties(ignoreUnknown = true) | ||||||
|  | @ -76,10 +80,14 @@ public final class OlatLmsData { | ||||||
|          * { |          * { | ||||||
|          * "configKeys": ["a", "b"], |          * "configKeys": ["a", "b"], | ||||||
|          * "browserExamKeys": ["1", "2"] |          * "browserExamKeys": ["1", "2"] | ||||||
|  |          * "quitLink": "<the quit link from Exam Configuration>", | ||||||
|  |          * "quitSecret": "<the quit password from Exam Configuration (base64 encoded)>", | ||||||
|          * } |          * } | ||||||
|          */ |          */ | ||||||
|         public List<String> browserExamKeys; |         public List<String> browserExamKeys; | ||||||
|         public List<String> configKeys; |         public List<String> configKeys; | ||||||
|  |         public String quitLink; | ||||||
|  |         public String quitSecret; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 anhefti
						anhefti