SEBSERV-418 removed SEB config upload to Moodle and call set_exam_data on change instead
This commit is contained in:
parent
d291e21543
commit
01bd5c5558
8 changed files with 75 additions and 144 deletions
|
@ -31,7 +31,7 @@ public interface FullLmsIntegrationAPI {
|
|||
|
||||
Result<ExamData> applyExamData(ExamData examData);
|
||||
|
||||
Result<Exam> applyConnectionConfiguration(Exam exam, byte[] configData);
|
||||
//Result<Exam> applyConnectionConfiguration(Exam exam, byte[] configData);
|
||||
|
||||
Result<String> deleteConnectionDetails();
|
||||
|
||||
|
|
|
@ -8,10 +8,7 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -53,7 +50,6 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConnectionConfigu
|
|||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConnectionConfigurationService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamConfigUpdateEvent;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ScreenProctoringService;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -152,11 +148,9 @@ public class FullLmsIntegrationServiceImpl implements FullLmsIntegrationService
|
|||
return Result.tryCatch(() -> {
|
||||
if (hasFullIntegration(exam.lmsSetupId)) {
|
||||
this.applyExamData(exam, !exam.active);
|
||||
this.applyConnectionConfiguration(exam);
|
||||
}
|
||||
return exam;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -245,7 +239,7 @@ public class FullLmsIntegrationServiceImpl implements FullLmsIntegrationService
|
|||
.getOr(Collections.emptyList())
|
||||
.stream()
|
||||
.filter(exam -> this.needsConnectionConfigurationChange(exam, event.configId))
|
||||
.forEach(this::applyConnectionConfiguration);
|
||||
.forEach(exam -> applyExamData(exam, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -332,8 +326,7 @@ public class FullLmsIntegrationServiceImpl implements FullLmsIntegrationService
|
|||
.map(template -> getQuizData(template, courseId, quizId, examData))
|
||||
.map(createExam(examTemplateId, showQuitLink, quitPassword))
|
||||
.map(exam -> applyExamData(exam, false))
|
||||
.map(this::applySEBClientRestrictionIfRunning)
|
||||
.map(this::applyConnectionConfiguration);
|
||||
.map(this::applySEBClientRestrictionIfRunning);
|
||||
}
|
||||
|
||||
private Exam applySEBClientRestrictionIfRunning(final Exam exam) {
|
||||
|
@ -502,7 +495,6 @@ public class FullLmsIntegrationServiceImpl implements FullLmsIntegrationService
|
|||
.byModelId(examTemplateId)
|
||||
.getOrThrow();
|
||||
|
||||
|
||||
// import exam
|
||||
final POSTMapper post = new POSTMapper(null, null);
|
||||
post.putIfAbsent(Domain.EXAM.ATTR_EXAM_TEMPLATE_ID, examTemplateId);
|
||||
|
@ -526,12 +518,11 @@ public class FullLmsIntegrationServiceImpl implements FullLmsIntegrationService
|
|||
}
|
||||
|
||||
private Exam checkDeletion(final Exam exam) {
|
||||
// TODO check if Exam can be deleted according to the Spec
|
||||
|
||||
if (exam.status != Exam.ExamStatus.RUNNING) {
|
||||
return exam;
|
||||
}
|
||||
|
||||
// if exam is running and has active SEB client connections, it cannot be deleted
|
||||
final Integer active = this.clientConnectionDAO
|
||||
.getAllActiveConnectionTokens(exam.id)
|
||||
.map(Collection::size)
|
||||
|
@ -545,15 +536,6 @@ public class FullLmsIntegrationServiceImpl implements FullLmsIntegrationService
|
|||
throw new APIMessage.APIMessageException(
|
||||
APIMessage.ErrorMessage.INTEGRITY_VALIDATION
|
||||
.of("Exam currently has active SEB Client connections."));
|
||||
|
||||
// check if there are no active SEB client connections
|
||||
// if (this.examSessionService.hasActiveSEBClientConnections(exam.id)) {
|
||||
// throw new APIMessage.APIMessageException(
|
||||
// APIMessage.ErrorMessage.INTEGRITY_VALIDATION
|
||||
// .of("Exam currently has active SEB Client connections."));
|
||||
// }
|
||||
//
|
||||
// return exam;
|
||||
}
|
||||
|
||||
|
||||
|
@ -637,38 +619,37 @@ public class FullLmsIntegrationServiceImpl implements FullLmsIntegrationService
|
|||
}
|
||||
}
|
||||
|
||||
private Exam applyConnectionConfiguration(final Exam exam) {
|
||||
return lmsAPITemplateCacheService
|
||||
.getLmsAPITemplate(exam.lmsSetupId)
|
||||
.flatMap(template -> {
|
||||
final String connectionConfigId = getConnectionConfigurationId(exam);
|
||||
|
||||
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
final PipedOutputStream pout;
|
||||
final PipedInputStream pin;
|
||||
try {
|
||||
pout = new PipedOutputStream();
|
||||
pin = new PipedInputStream(pout);
|
||||
|
||||
this.connectionConfigurationService
|
||||
.exportSEBClientConfiguration(pout, connectionConfigId, exam.id);
|
||||
|
||||
out.flush();
|
||||
|
||||
IOUtils.copyLarge(pin, out);
|
||||
|
||||
// TODO check if this works as expected
|
||||
return template.applyConnectionConfiguration(exam, out.toByteArray());
|
||||
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException("Failed to stream output", e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(out);
|
||||
}
|
||||
})
|
||||
.onError(error -> log.error("Failed to apply ConnectionConfiguration for exam: {} error: ", exam, error))
|
||||
.getOr(exam);
|
||||
}
|
||||
// private Exam applyConnectionConfiguration(final Exam exam) {
|
||||
// return lmsAPITemplateCacheService
|
||||
// .getLmsAPITemplate(exam.lmsSetupId)
|
||||
// .flatMap(template -> {
|
||||
// final String connectionConfigId = getConnectionConfigurationId(exam);
|
||||
//
|
||||
// final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
// final PipedOutputStream pout;
|
||||
// final PipedInputStream pin;
|
||||
// try {
|
||||
// pout = new PipedOutputStream();
|
||||
// pin = new PipedInputStream(pout);
|
||||
//
|
||||
// this.connectionConfigurationService
|
||||
// .exportSEBClientConfiguration(pout, connectionConfigId, exam.id);
|
||||
//
|
||||
// out.flush();
|
||||
//
|
||||
// IOUtils.copyLarge(pin, out);
|
||||
//
|
||||
// return template.applyConnectionConfiguration(exam, out.toByteArray());
|
||||
//
|
||||
// } catch (final Exception e) {
|
||||
// throw new RuntimeException("Failed to stream output", e);
|
||||
// } finally {
|
||||
// IOUtils.closeQuietly(out);
|
||||
// }
|
||||
// })
|
||||
// .onError(error -> log.error("Failed to apply ConnectionConfiguration for exam: {} error: ", exam, error))
|
||||
// .getOr(exam);
|
||||
// }
|
||||
|
||||
private boolean hasFullIntegration(final Long lmsSetupId) {
|
||||
// no LMS
|
||||
|
|
|
@ -546,23 +546,6 @@ public class LmsAPITemplateAdapter implements LmsAPITemplate {
|
|||
.getOrThrow());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Exam> applyConnectionConfiguration(final Exam exam, final byte[] configData) {
|
||||
if (this.lmsIntegrationAPI == null) {
|
||||
return Result.ofError(
|
||||
new UnsupportedOperationException("LMS Integration API Not Supported For: " + getType().name()));
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Apply Connection Configuration for exam: {} for LMSSetup: {}", exam, lmsSetup());
|
||||
}
|
||||
|
||||
return this.examRequest.protectedRun(() -> this.lmsIntegrationAPI
|
||||
.applyConnectionConfiguration(exam, configData)
|
||||
.getOrThrow());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Result<String> deleteConnectionDetails() {
|
||||
if (this.lmsIntegrationAPI == null) {
|
||||
|
|
|
@ -444,11 +444,6 @@ public class AnsLmsAPITemplate extends AbstractCachedCourseAccess implements Lms
|
|||
return Result.ofRuntimeError("Not Supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Exam> applyConnectionConfiguration(final Exam exam, final byte[] configData) {
|
||||
return Result.ofRuntimeError("Not Supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<String> deleteConnectionDetails() {
|
||||
return Result.ofRuntimeError("Not Supported");
|
||||
|
|
|
@ -39,11 +39,6 @@ public class MockupFullIntegration implements FullLmsIntegrationAPI {
|
|||
return Result.ofRuntimeError("Not Supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Exam> applyConnectionConfiguration(final Exam exam, final byte[] configData) {
|
||||
return Result.ofRuntimeError("Not Supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<String> deleteConnectionDetails() {
|
||||
return Result.ofRuntimeError("TODO");
|
||||
|
|
|
@ -452,32 +452,12 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
|
|||
new HttpEntity<>(body, headers);
|
||||
|
||||
final ResponseEntity<String> exchange = super.exchange(
|
||||
uri.toString(),
|
||||
uri.append("?token=").append(this.accessToken).toString(),
|
||||
HttpMethod.POST,
|
||||
requestEntity,
|
||||
String.class);
|
||||
|
||||
return exchange.getBody();
|
||||
|
||||
// multiPartAttributes.add("token", this.accessToken.toString());
|
||||
//
|
||||
// queryAttributes.forEach((key, values) -> {
|
||||
// if (values.isEmpty()) {
|
||||
// return;
|
||||
// }
|
||||
// if (uri.toString().contains("?")) {
|
||||
// uri.append("&").append(key).append("=").append(values.get(0));
|
||||
// } else {
|
||||
// uri.append("?").append(key).append("=").append(values.get(0));
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// log.info("Upload to Moodle url: {}", uri.toString());
|
||||
//
|
||||
// return super.postForObject(
|
||||
// uri.toString(),
|
||||
// multiPartAttributes,
|
||||
// String.class);
|
||||
}
|
||||
|
||||
private String doRequest(
|
||||
|
|
|
@ -239,43 +239,43 @@ public class MoodlePluginFullIntegration implements FullLmsIntegrationAPI {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Exam> applyConnectionConfiguration(final Exam exam, final byte[] configData) {
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
final String quizId = MoodleUtils.getQuizId(exam.externalId);
|
||||
final String fileName = getConnectionConfigFileName(exam);
|
||||
|
||||
// final MultiValueMap<String, Object> multiPartAttributes = new LinkedMultiValueMap<>();
|
||||
// multiPartAttributes.add("quizid", quizId);
|
||||
// multiPartAttributes.add("name", fileName);
|
||||
// multiPartAttributes.add("filename", fileName);
|
||||
|
||||
// final MultiValueMap<String, String> queryAttributes = new LinkedMultiValueMap<>();
|
||||
// //queryAttributes.add("quizid", quizId);
|
||||
// final ByteArrayResource contentsAsResource = new ByteArrayResource(configData) {
|
||||
// @Override
|
||||
// public String getFilename() {
|
||||
// return fileName; // Filename has to be returned in order to be able to post.
|
||||
// }
|
||||
// };
|
||||
// @Override
|
||||
// public Result<Exam> applyConnectionConfiguration(final Exam exam, final byte[] configData) {
|
||||
// return Result.tryCatch(() -> {
|
||||
//
|
||||
// multiPartAttributes.add("file", contentsAsResource);
|
||||
|
||||
final MoodleAPIRestTemplate rest = getRestTemplate().getOrThrow();
|
||||
final String response = rest.uploadMultiPart(
|
||||
UPLOAD_ENDPOINT,
|
||||
quizId,
|
||||
fileName,
|
||||
configData);
|
||||
|
||||
if (response != null) {
|
||||
log.info("Upload Connection Configuration to Moodle: quizid: {}, fileName: {} response: {}", quizId, fileName, response );
|
||||
}
|
||||
|
||||
return exam;
|
||||
});
|
||||
}
|
||||
// final String quizId = MoodleUtils.getQuizId(exam.externalId);
|
||||
// final String fileName = getConnectionConfigFileName(exam);
|
||||
//
|
||||
//// final MultiValueMap<String, Object> multiPartAttributes = new LinkedMultiValueMap<>();
|
||||
//// multiPartAttributes.add("quizid", quizId);
|
||||
//// multiPartAttributes.add("name", fileName);
|
||||
//// multiPartAttributes.add("filename", fileName);
|
||||
//
|
||||
//// final MultiValueMap<String, String> queryAttributes = new LinkedMultiValueMap<>();
|
||||
//// //queryAttributes.add("quizid", quizId);
|
||||
//// final ByteArrayResource contentsAsResource = new ByteArrayResource(configData) {
|
||||
//// @Override
|
||||
//// public String getFilename() {
|
||||
//// return fileName; // Filename has to be returned in order to be able to post.
|
||||
//// }
|
||||
//// };
|
||||
////
|
||||
//// multiPartAttributes.add("file", contentsAsResource);
|
||||
//
|
||||
// final MoodleAPIRestTemplate rest = getRestTemplate().getOrThrow();
|
||||
// final String response = rest.uploadMultiPart(
|
||||
// UPLOAD_ENDPOINT,
|
||||
// quizId,
|
||||
// fileName,
|
||||
// configData);
|
||||
//
|
||||
// if (response != null) {
|
||||
// log.info("Upload Connection Configuration to Moodle: quizid: {}, fileName: {} response: {}", quizId, fileName, response );
|
||||
// }
|
||||
//
|
||||
// return exam;
|
||||
// });
|
||||
// }
|
||||
|
||||
private String getConnectionConfigFileName(final Exam exam) {
|
||||
return "SEBServerConnectionConfiguration-" + exam.id + ".seb";
|
||||
|
@ -317,7 +317,9 @@ public class MoodlePluginFullIntegration implements FullLmsIntegrationAPI {
|
|||
public Result<QuizData> getQuizDataForRemoteImport(final String examData) {
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
log.info("****** Try to parse import exam data sent by Moodle on Exam import: {}", examData);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Try to parse import exam data sent by Moodle on Exam import: {}", examData);
|
||||
}
|
||||
|
||||
final LmsSetup lmsSetup = this.restTemplateFactory.getApiTemplateDataSupplier().getLmsSetup();
|
||||
final String urlPrefix = (lmsSetup.lmsApiUrl.endsWith(Constants.URL_PATH_SEPARATOR))
|
||||
|
|
|
@ -431,11 +431,6 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm
|
|||
return Result.ofRuntimeError("Not Supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Exam> applyConnectionConfiguration(final Exam exam, final byte[] configData) {
|
||||
return Result.ofRuntimeError("Not Supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<String> deleteConnectionDetails() {
|
||||
return Result.ofRuntimeError("Not Supported");
|
||||
|
|
Loading…
Reference in a new issue