SEBSERV-351 unit tests and fixes
This commit is contained in:
parent
2af314b135
commit
c2a22b68a5
5 changed files with 200 additions and 25 deletions
|
@ -79,7 +79,7 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm
|
||||||
|
|
||||||
private OlatLmsRestTemplate cachedRestTemplate;
|
private OlatLmsRestTemplate cachedRestTemplate;
|
||||||
|
|
||||||
protected OlatLmsAPITemplate(
|
public OlatLmsAPITemplate(
|
||||||
final ClientHttpRequestFactoryService clientHttpRequestFactoryService,
|
final ClientHttpRequestFactoryService clientHttpRequestFactoryService,
|
||||||
final ClientCredentialService clientCredentialService,
|
final ClientCredentialService clientCredentialService,
|
||||||
final APITemplateDataSupplier apiTemplateDataSupplier,
|
final APITemplateDataSupplier apiTemplateDataSupplier,
|
||||||
|
@ -344,8 +344,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.quitLink = this.getQuitLink(restriction.examId);
|
||||||
post.quitSecret = restriction.getAdditionalProperties().getOrDefault(ADDITIONAL_ATTR_QUIT_SECRET, null);
|
post.quitSecret = this.getQuitSecret(restriction.examId);
|
||||||
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>());
|
||||||
|
@ -370,7 +370,6 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm
|
||||||
final Exam exam,
|
final Exam exam,
|
||||||
final SEBRestriction sebRestrictionData) {
|
final SEBRestriction sebRestrictionData) {
|
||||||
|
|
||||||
populateWithQuitLinkAndSecret(exam, sebRestrictionData);
|
|
||||||
return getRestTemplate()
|
return getRestTemplate()
|
||||||
.map(t -> this.setRestrictionForAssignmentId(t, exam.externalId, sebRestrictionData));
|
.map(t -> this.setRestrictionForAssignmentId(t, exam.externalId, sebRestrictionData));
|
||||||
}
|
}
|
||||||
|
@ -403,8 +402,13 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm
|
||||||
return res.getBody();
|
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 Class<R> responseType) {
|
||||||
|
|
||||||
final LmsSetup lmsSetup = this.apiTemplateDataSupplier.getLmsSetup();
|
final LmsSetup lmsSetup = this.apiTemplateDataSupplier.getLmsSetup();
|
||||||
final HttpHeaders httpHeaders = new HttpHeaders();
|
final HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.set("content-type", "application/json");
|
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 {
|
try {
|
||||||
|
|
||||||
final String quitLink = this.examConfigurationValueService.getMappedDefaultConfigAttributeValue(
|
final String quitSecretEncrypted = this.examConfigurationValueService.getMappedDefaultConfigAttributeValue(
|
||||||
exam.id,
|
examId,
|
||||||
CONFIG_ATTR_NAME_QUIT_LINK);
|
|
||||||
|
|
||||||
final String quitSecret = this.examConfigurationValueService.getMappedDefaultConfigAttributeValue(
|
|
||||||
exam.id,
|
|
||||||
CONFIG_ATTR_NAME_QUIT_SECRET);
|
CONFIG_ATTR_NAME_QUIT_SECRET);
|
||||||
|
|
||||||
if (StringUtils.isNotEmpty(quitLink)) {
|
if (StringUtils.isNotEmpty(quitSecretEncrypted)) {
|
||||||
sebRestrictionData.additionalProperties.put(ADDITIONAL_ATTR_QUIT_LINK, quitLink);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtils.isNotEmpty(quitSecret)) {
|
|
||||||
try {
|
try {
|
||||||
final String decryptedSecret = this.cryptor
|
|
||||||
.encrypt(quitSecret)
|
return this.cryptor
|
||||||
|
.decrypt(quitSecretEncrypted)
|
||||||
.getOrThrow()
|
.getOrThrow()
|
||||||
.toString();
|
.toString();
|
||||||
|
|
||||||
sebRestrictionData.additionalProperties.put(ADDITIONAL_ATTR_QUIT_SECRET, decryptedSecret);
|
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
log.error("Failed to decrypt quitSecret: ", 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) {
|
} 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ public final class OlatLmsData {
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
static final class RestrictionData {
|
public static final class RestrictionData {
|
||||||
/*
|
/*
|
||||||
* OLAT API example:
|
* OLAT API example:
|
||||||
* {
|
* {
|
||||||
|
@ -74,7 +74,7 @@ public final class OlatLmsData {
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
static final class RestrictionDataPost {
|
public static final class RestrictionDataPost {
|
||||||
/*
|
/*
|
||||||
* OLAT API example:
|
* OLAT API example:
|
||||||
* {
|
* {
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -539,7 +539,7 @@ INSERT IGNORE INTO configuration_value VALUES
|
||||||
(1,1,1,1,0,NULL),
|
(1,1,1,1,0,NULL),
|
||||||
(2,1,1,2,0,'true'),
|
(2,1,1,2,0,'true'),
|
||||||
(3,1,1,3,0,'false'),
|
(3,1,1,3,0,'false'),
|
||||||
(4,1,1,4,0,NULL),
|
(4,1,1,4,0,'e6494b842987b4e039a101f14d4a76acc338d33205336f2562c7d8071e3ed65886edbbe3b71a4a33cc09c6'),
|
||||||
(5,1,1,5,0,'2'),
|
(5,1,1,5,0,'2'),
|
||||||
(6,1,1,6,0,'10'),
|
(6,1,1,6,0,'10'),
|
||||||
(7,1,1,7,0,'5'),
|
(7,1,1,7,0,'5'),
|
||||||
|
@ -602,7 +602,7 @@ INSERT IGNORE INTO configuration_value VALUES
|
||||||
(64,1,1,64,0,'true'),
|
(64,1,1,64,0,'true'),
|
||||||
(65,1,1,65,0,'true'),
|
(65,1,1,65,0,'true'),
|
||||||
(66,1,1,66,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'),
|
(68,1,1,68,0,'true'),
|
||||||
(69,1,1,69,0,'false'),
|
(69,1,1,69,0,'false'),
|
||||||
(70,1,1,70,0,NULL),
|
(70,1,1,70,0,NULL),
|
||||||
|
|
Loading…
Reference in a new issue