Skip to content

Commit

Permalink
SEBSERV-586 LMS deactivation fix and better logging
Browse files Browse the repository at this point in the history
  • Loading branch information
anhefti committed Sep 19, 2024
1 parent 1a1069b commit d34b3e4
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

package ch.ethz.seb.sebserver.webservice.servicelayer.lms;

import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult;
Expand All @@ -30,9 +29,7 @@ public interface FullLmsIntegrationAPI {
Result<IntegrationData> applyConnectionDetails(IntegrationData data);

Result<ExamData> applyExamData(ExamData examData);

//Result<Exam> applyConnectionConfiguration(Exam exam, byte[] configData);


Result<String> deleteConnectionDetails();

Result<QuizData> getQuizDataForRemoteImport(String examData);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AdHocAccountData;
Expand All @@ -28,9 +29,9 @@

public interface FullLmsIntegrationService {

@EventListener
@EventListener(LmsSetupChangeEvent.class)
void notifyLmsSetupChange(final LmsSetupChangeEvent event);
@EventListener
@EventListener(ExamTemplateChangeEvent.class)
void notifyExamTemplateChange(final ExamTemplateChangeEvent event);
@EventListener(ConnectionConfigurationChangeEvent.class)
void notifyConnectionConfigurationChange(ConnectionConfigurationChangeEvent event);
Expand All @@ -46,6 +47,8 @@ public interface FullLmsIntegrationService {

Result<IntegrationData> applyFullLmsIntegration(Long lmsSetupId);

Result<IntegrationData> applyFullLmsIntegration(LmsSetup lmsSetup);

Result<Boolean> deleteFullLmsIntegration(Long lmsSetupId);

Result<Exam> importExam(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplateCacheService;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.SEBRestrictionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleResponseException;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleUtils;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConnectionConfigurationChangeEvent;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConnectionConfigurationService;
Expand Down Expand Up @@ -183,34 +184,44 @@ public void notifyExamConfigChange(final ExamConfigUpdateEvent event) {

@Override
public void notifyLmsSetupChange(final LmsSetupChangeEvent event) {

final LmsSetup lmsSetup = event.getLmsSetup();
if (!hasFullIntegration(lmsSetup.id)) {
return;
}

if (event.activation == Activatable.ActivationAction.NONE) {
if (!lmsSetup.integrationActive) {

try {
if (event.activation == Activatable.ActivationAction.NONE) {
if (!lmsSetup.integrationActive) {
applyFullLmsIntegration(lmsSetup.id)
.onError(error -> log.warn(
"Failed to update LMS integration for: {} error {}", lmsSetup, error.getMessage()))
.onSuccess(data -> log.debug(
"Successfully updated LMS integration for: {} data: {}", lmsSetup, data));
}
} else if (event.activation == Activatable.ActivationAction.ACTIVATE) {
applyFullLmsIntegration(lmsSetup.id)
.map(data -> reapplyExistingExams(data, lmsSetup))
.onError(error -> log.warn(
"Failed to update LMS integration for: {} error {}", lmsSetup, error.getMessage()))
.onSuccess(data -> log.debug(
"Successfully updated LMS integration for: {} data: {}", lmsSetup, data));
} else if (event.activation == Activatable.ActivationAction.DEACTIVATE) {

log.info("Deactivate full integration for LMS: {}", lmsSetup);

// remove all active exam data for involved exams before deactivate them
this.examDAO
.allActiveForLMSSetup(Arrays.asList(lmsSetup.id))
.getOrThrow()
.forEach(exam -> applyExamData(exam, true))
;
// delete full integration on Moodle side due to deactivation
this.deleteFullLmsIntegration(lmsSetup.id)
.getOrThrow();
}
} else if (event.activation == Activatable.ActivationAction.ACTIVATE) {
applyFullLmsIntegration(lmsSetup.id)
.map(data -> reapplyExistingExams(data,lmsSetup))
.onError(error -> log.warn(
"Failed to update LMS integration for: {} error {}", lmsSetup, error.getMessage()))
.onSuccess(data -> log.debug(
"Successfully updated LMS integration for: {} data: {}", lmsSetup, data));
} else if (event.activation == Activatable.ActivationAction.DEACTIVATE) {
// remove all active exam data for involved exams before deactivate them
this.examDAO
.allActiveForLMSSetup(Arrays.asList(lmsSetup.id))
.getOrThrow();
// delete full integration on Moodle side due to deactivation
this.deleteFullLmsIntegration(lmsSetup.id)
.getOrThrow();
} catch (final Exception e) {
log.error("Failed to apply LMS Setup change for full LMS integration for: {}", lmsSetup, e);
}
}

Expand Down Expand Up @@ -253,39 +264,46 @@ public void notifyConnectionConfigurationChange(final ConnectionConfigurationCha
public Result<IntegrationData> applyFullLmsIntegration(final Long lmsSetupId) {
return lmsSetupDAO
.byPK(lmsSetupId)
.map(lmsSetup -> {
String connectionId = lmsSetup.getConnectionId();
if (connectionId == null) {
connectionId = lmsSetupDAO.save(lmsSetup).getOrThrow().connectionId;
}
if (connectionId == null) {
throw new IllegalStateException("No LMS Setup connectionId available for: " + lmsSetup);
}
.flatMap(this::applyFullLmsIntegration);
}

@Override
public Result<IntegrationData> applyFullLmsIntegration(final LmsSetup lmsSetup) {
return Result.tryCatch(() -> {
final Long lmsSetupId = lmsSetup.id;
final String connectionId = lmsSetup.getConnectionId();
// if (connectionId == null) {
// connectionId = lmsSetupDAO.save(lmsSetup).getOrThrow().connectionId;
// }
if (connectionId == null) {
throw new RuntimeException("Illegal state", new MoodleResponseException(
"The Assessment Tool Setup must be saved first before full integration can be tested and applied.","none"));
}

// reset old token to get actual one
resource.setScope(Arrays.asList(String.valueOf(lmsSetupId)));
restTemplate.getOAuth2ClientContext().setAccessToken(null);
final String accessToken = restTemplate.getAccessToken().getValue();
// reset old token to get actual one
resource.setScope(Arrays.asList(String.valueOf(lmsSetupId)));
restTemplate.getOAuth2ClientContext().setAccessToken(null);
final String accessToken = restTemplate.getAccessToken().getValue();

final IntegrationData data = new IntegrationData(
connectionId,
lmsSetup.name,
getAPIRootURL(),
accessToken,
this.getIntegrationTemplates(lmsSetup.institutionId)
);
final IntegrationData data = new IntegrationData(
connectionId,
lmsSetup.name,
getAPIRootURL(),
accessToken,
this.getIntegrationTemplates(lmsSetup.institutionId)
);

return lmsAPITemplateCacheService.getLmsAPITemplate(lmsSetupId)
.getOrThrow()
.applyConnectionDetails(data)
.onError(error -> lmsSetupDAO
.setIntegrationActive(lmsSetupId, false)
.onError(er -> log.error("Failed to mark LMS integration inactive", er)))
.onSuccess( d -> lmsSetupDAO
.setIntegrationActive(lmsSetupId, true)
.onError(er -> log.error("Failed to mark LMS integration active", er)))
.getOrThrow();
});
return lmsAPITemplateCacheService.getLmsAPITemplate(lmsSetupId)
.getOrThrow()
.applyConnectionDetails(data)
.onError(error -> lmsSetupDAO
.setIntegrationActive(lmsSetupId, false)
.onError(er -> log.error("Failed to mark LMS integration inactive", er)))
.onSuccess(d -> lmsSetupDAO
.setIntegrationActive(lmsSetupId, true)
.onError(er -> log.error("Failed to mark LMS integration active", er)))
.getOrThrow();
});
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,14 @@ private LmsSetupTestResult fullIntegrationTest(final LmsAPITemplate template) {
} else {

final Result<FullLmsIntegrationService.IntegrationData> integrationDataResult = fullLmsIntegrationService
.applyFullLmsIntegration(template.lmsSetup().id);
.applyFullLmsIntegration(template.lmsSetup());

if (integrationDataResult.hasError()) {
Throwable error = integrationDataResult.getError();
if (error instanceof RuntimeException) {
error = error.getCause();
}
if (error != null && error instanceof MoodleResponseException) {
if (error instanceof MoodleResponseException) {
return LmsSetupTestResult.ofFullIntegrationAPIError(
template.lmsSetup().lmsType,
error.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,49 +239,10 @@ public Result<ExamData> applyExamData(final ExamData examData) {
});
}

// @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.
//// }
//// };
////
//// 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";
}



@Override
public Result<String> deleteConnectionDetails() {
return Result.tryCatch(() -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,36 +170,6 @@ protected Result<LmsSetup> notifySaved(final LmsSetup entity, final Activatable.
return super.notifySaved(entity, activation);
}

// @Override
// protected Result<LmsSetup> validForActivation(final LmsSetup entity, final boolean activation) {
// return super.validForActivation(entity, activation)
// .map(lmsSetup -> {
// if (!activation) {
// // on deactivation remove all SEB restrictions and delete full integration if in place
// return sebRestrictionService
// .applyLMSSetupDeactivation(lmsSetup)
// .onErrorDo(error -> {
// log.warn("Failed to apply LMSSetup deactivation for SEB Restriction: ", error);
// return lmsSetup;
// })
// .flatMap(fullLmsIntegrationService::applyLMSSetupDeactivation)
// .onErrorDo(error -> {
// log.warn("Failed to apply LMSSetup deactivation for LMS full integration: ", error);
// return lmsSetup;
// })
// .flatMap(screenProctoringService::applyLMSSetupDeactivation)
// .onErrorDo(error -> {
// log.warn("Failed to apply LMSSetup deactivation for Screen Proctoring: ", error);
// return lmsSetup;
// })
// .getOrThrow();
// } else {
//
// }
// return entity;
// });
// }

@Override
protected Result<LmsSetup> validForDelete(final LmsSetup entity) {
return Result.tryCatch(() -> {
Expand Down

0 comments on commit d34b3e4

Please sign in to comment.