SEBSERV-351 unit tests and fixes

This commit is contained in:
anhefti 2022-10-25 13:32:09 +02:00
parent 2af314b135
commit c2a22b68a5
5 changed files with 200 additions and 25 deletions

View file

@ -79,7 +79,7 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm
private OlatLmsRestTemplate cachedRestTemplate;
protected OlatLmsAPITemplate(
public OlatLmsAPITemplate(
final ClientHttpRequestFactoryService clientHttpRequestFactoryService,
final ClientCredentialService clientCredentialService,
final APITemplateDataSupplier apiTemplateDataSupplier,
@ -344,8 +344,8 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm
final RestrictionDataPost post = new RestrictionDataPost();
post.browserExamKeys = new ArrayList<>(restriction.browserExamKeys);
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);
post.quitLink = this.getQuitLink(restriction.examId);
post.quitSecret = this.getQuitSecret(restriction.examId);
final RestrictionData r =
this.apiPost(restTemplate, url, post, RestrictionDataPost.class, RestrictionData.class);
return new SEBRestriction(Long.valueOf(id), r.configKeys, r.browserExamKeys, new HashMap<String, String>());
@ -370,7 +370,6 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm
final Exam exam,
final SEBRestriction sebRestrictionData) {
populateWithQuitLinkAndSecret(exam, sebRestrictionData);
return getRestTemplate()
.map(t -> this.setRestrictionForAssignmentId(t, exam.externalId, sebRestrictionData));
}
@ -403,8 +402,13 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm
return res.getBody();
}
private <P, R> R apiPost(final RestTemplate restTemplate, final String url, final P post, final Class<P> postType,
private <P, R> R apiPost(
final RestTemplate restTemplate,
final String url,
final P post,
final Class<P> postType,
final Class<R> responseType) {
final LmsSetup lmsSetup = this.apiTemplateDataSupplier.getLmsSetup();
final HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("content-type", "application/json");
@ -459,36 +463,42 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm
});
}
private void populateWithQuitLinkAndSecret(final Exam exam, final SEBRestriction sebRestrictionData) {
private String getQuitSecret(final Long examId) {
try {
final String quitLink = this.examConfigurationValueService.getMappedDefaultConfigAttributeValue(
exam.id,
CONFIG_ATTR_NAME_QUIT_LINK);
final String quitSecret = this.examConfigurationValueService.getMappedDefaultConfigAttributeValue(
exam.id,
final String quitSecretEncrypted = this.examConfigurationValueService.getMappedDefaultConfigAttributeValue(
examId,
CONFIG_ATTR_NAME_QUIT_SECRET);
if (StringUtils.isNotEmpty(quitLink)) {
sebRestrictionData.additionalProperties.put(ADDITIONAL_ATTR_QUIT_LINK, quitLink);
}
if (StringUtils.isNotEmpty(quitSecret)) {
if (StringUtils.isNotEmpty(quitSecretEncrypted)) {
try {
final String decryptedSecret = this.cryptor
.encrypt(quitSecret)
return this.cryptor
.decrypt(quitSecretEncrypted)
.getOrThrow()
.toString();
sebRestrictionData.additionalProperties.put(ADDITIONAL_ATTR_QUIT_SECRET, decryptedSecret);
} catch (final Exception e) {
log.error("Failed to decrypt quitSecret: ", e);
}
}
} catch (final Exception e) {
log.error("Failed to get SEB restriction with quit secret: ", e);
}
return null;
}
private String getQuitLink(final Long examId) {
try {
return this.examConfigurationValueService.getMappedDefaultConfigAttributeValue(
examId,
CONFIG_ATTR_NAME_QUIT_LINK);
} catch (final Exception e) {
log.error("Failed to populate SEB restriction with quit link and quit secret: ", e);
log.error("Failed to get SEB restriction with quit link: ", e);
return null;
}
}

View file

@ -55,7 +55,7 @@ public final class OlatLmsData {
}
@JsonIgnoreProperties(ignoreUnknown = true)
static final class RestrictionData {
public static final class RestrictionData {
/*
* OLAT API example:
* {
@ -74,7 +74,7 @@ public final class OlatLmsData {
}
@JsonIgnoreProperties(ignoreUnknown = true)
static final class RestrictionDataPost {
public static final class RestrictionDataPost {
/*
* OLAT API example:
* {

View file

@ -0,0 +1,49 @@
/*
* 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.integration.api.admin;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.jdbc.Sql;
import ch.ethz.seb.sebserver.gbl.util.Cryptor;
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamConfigurationValueService;
@Sql(scripts = { "classpath:schema-test.sql", "classpath:data-test.sql", "classpath:data-test-additional.sql" })
public class ExamConfigurationValueServiceTest extends AdministrationAPIIntegrationTester {
@Autowired
private ExamConfigurationValueService examConfigurationValueService;
@Autowired
private Cryptor cryptor;
@Test
public void testGetConfigValues() {
final String allowQuit = this.examConfigurationValueService
.getMappedDefaultConfigAttributeValue(2L, "allowQuit");
assertNotNull(allowQuit);
assertEquals("true", allowQuit);
final String hashedQuitPassword = this.examConfigurationValueService
.getMappedDefaultConfigAttributeValue(2L, "hashedQuitPassword");
assertNotNull(hashedQuitPassword);
assertEquals(
"e6494b842987b4e039a101f14d4a76acc338d33205336f2562c7d8071e3ed65886edbbe3b71a4a33cc09c6",
hashedQuitPassword);
final CharSequence plainQuitPassword = this.cryptor.decrypt(hashedQuitPassword).getOrThrow();
assertEquals("123", plainQuitPassword);
}
}

View file

@ -0,0 +1,116 @@
/*
* 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.integration.api.admin;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.lang.reflect.Field;
import java.util.Arrays;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.http.HttpEntity;
import org.springframework.test.context.jdbc.Sql;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType;
import ch.ethz.seb.sebserver.gbl.model.exam.SEBRestriction;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
import ch.ethz.seb.sebserver.gbl.util.Cryptor;
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.impl.olat.OlatLmsAPITemplate;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.olat.OlatLmsData.RestrictionDataPost;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.olat.OlatLmsRestTemplate;
@Sql(scripts = { "classpath:schema-test.sql", "classpath:data-test.sql", "classpath:data-test-additional.sql" })
public class OlatLmsAPITemplateTest extends AdministrationAPIIntegrationTester {
@Autowired
private ExamConfigurationValueService examConfigurationValueService;
@Autowired
private Cryptor cryptor;
@Autowired
private CacheManager cacheManager;
@Test
public void testSetRestriction() throws Exception {
final OlatLmsRestTemplate restTemplateMock = Mockito.mock(OlatLmsRestTemplate.class);
final APITemplateDataSupplier apiTemplateDataSupplier = Mockito.mock(APITemplateDataSupplier.class);
Mockito.when(apiTemplateDataSupplier.getLmsSetup()).thenReturn(new LmsSetup(
1L, 1L, null, null, null, null, null, null, null, null, null, null, false, null));
final OlatLmsAPITemplate olatLmsAPITemplate = new OlatLmsAPITemplate(
null,
null,
apiTemplateDataSupplier,
this.examConfigurationValueService,
this.cryptor,
this.cacheManager);
Mockito.when(restTemplateMock.exchange(Mockito.any(), Mockito.any(), Mockito.any(),
(Class) Mockito.any(), (Object[]) Mockito.any())).then(new Answer() {
@Override
public Object answer(final InvocationOnMock invocation) throws Throwable {
final HttpEntity<RestrictionDataPost> argument2 = invocation.getArgument(2, HttpEntity.class);
assertNotNull(argument2);
final RestrictionDataPost body = argument2.getBody();
assertNotNull(body);
assertEquals("seb://quitlink.seb", body.quitLink);
assertEquals("123", body.quitSecret);
return null;
}
});
final Field field = OlatLmsAPITemplate.class.getDeclaredField("cachedRestTemplate");
field.setAccessible(true);
field.set(olatLmsAPITemplate, restTemplateMock);
final Exam exam = new Exam(
2L,
1L,
1L,
Constants.EMPTY_NOTE,
false,
Constants.EMPTY_NOTE,
null,
null,
ExamType.UNDEFINED,
null,
null,
ExamStatus.FINISHED,
Boolean.FALSE,
null,
Boolean.FALSE,
null,
null,
null,
null);
final SEBRestriction sebRestriction = new SEBRestriction(
2L,
Arrays.asList("configKey1", "configKey2"),
Arrays.asList("browserKey1", "browserKey2"),
null);
olatLmsAPITemplate.applySEBClientRestriction(exam, sebRestriction);
}
}

View file

@ -539,7 +539,7 @@ INSERT IGNORE INTO configuration_value VALUES
(1,1,1,1,0,NULL),
(2,1,1,2,0,'true'),
(3,1,1,3,0,'false'),
(4,1,1,4,0,NULL),
(4,1,1,4,0,'e6494b842987b4e039a101f14d4a76acc338d33205336f2562c7d8071e3ed65886edbbe3b71a4a33cc09c6'),
(5,1,1,5,0,'2'),
(6,1,1,6,0,'10'),
(7,1,1,7,0,'5'),
@ -602,7 +602,7 @@ INSERT IGNORE INTO configuration_value VALUES
(64,1,1,64,0,'true'),
(65,1,1,65,0,'true'),
(66,1,1,66,0,'true'),
(67,1,1,67,0,NULL),
(67,1,1,67,0,'seb://quitlink.seb'),
(68,1,1,68,0,'true'),
(69,1,1,69,0,'false'),
(70,1,1,70,0,NULL),