Merge remote-tracking branch 'origin/dev-1.2' into development
Conflicts: src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/ExamAdminService.java src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/ExamAdminServiceImpl.java
This commit is contained in:
commit
b1181bb97a
7 changed files with 73 additions and 8 deletions
|
@ -30,6 +30,7 @@ import org.joda.time.DateTime;
|
|||
import org.mybatis.dynamic.sql.SqlBuilder;
|
||||
import org.mybatis.dynamic.sql.select.MyBatis3SelectModelAdapter;
|
||||
import org.mybatis.dynamic.sql.select.QueryExpressionDSL;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
|
@ -78,17 +79,20 @@ public class ExamDAOImpl implements ExamDAO {
|
|||
private final ExamRecordMapper examRecordMapper;
|
||||
private final ClientConnectionRecordMapper clientConnectionRecordMapper;
|
||||
private final AdditionalAttributeRecordMapper additionalAttributeRecordMapper;
|
||||
private final ApplicationEventPublisher applicationEventPublisher;
|
||||
private final LmsAPIService lmsAPIService;
|
||||
|
||||
public ExamDAOImpl(
|
||||
final ExamRecordMapper examRecordMapper,
|
||||
final ClientConnectionRecordMapper clientConnectionRecordMapper,
|
||||
final AdditionalAttributeRecordMapper additionalAttributeRecordMapper,
|
||||
final ApplicationEventPublisher applicationEventPublisher,
|
||||
final LmsAPIService lmsAPIService) {
|
||||
|
||||
this.examRecordMapper = examRecordMapper;
|
||||
this.clientConnectionRecordMapper = clientConnectionRecordMapper;
|
||||
this.additionalAttributeRecordMapper = additionalAttributeRecordMapper;
|
||||
this.applicationEventPublisher = applicationEventPublisher;
|
||||
this.lmsAPIService = lmsAPIService;
|
||||
}
|
||||
|
||||
|
@ -651,6 +655,9 @@ public class ExamDAOImpl implements ExamDAO {
|
|||
|
||||
final List<Long> ids = extractListOfPKs(all);
|
||||
|
||||
// notify exam deletition listener about following deletion, to cleanup stuff before deletion
|
||||
this.applicationEventPublisher.publishEvent(new ExamDeletionEvent(ids));
|
||||
|
||||
this.examRecordMapper.deleteByExample()
|
||||
.where(ExamRecordDynamicSqlSupport.id, isIn(ids))
|
||||
.build()
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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.dao.impl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
|
||||
public class ExamDeletionEvent extends ApplicationEvent {
|
||||
|
||||
private static final long serialVersionUID = -8910368901893082365L;
|
||||
|
||||
public final List<Long> ids;
|
||||
|
||||
public ExamDeletionEvent(final List<Long> ids) {
|
||||
super(ids);
|
||||
this.ids = Utils.immutableListOf(ids);
|
||||
}
|
||||
|
||||
}
|
|
@ -246,11 +246,17 @@ public class RemoteProctoringRoomDAOImpl implements RemoteProctoringRoomDAO {
|
|||
@Transactional
|
||||
public Result<Collection<EntityKey>> deleteRooms(final Long examId) {
|
||||
final Result<Collection<EntityKey>> tryCatch = Result.tryCatch(() -> {
|
||||
final List<Long> ids = this.remoteProctoringRoomRecordMapper.selectIdsByExample()
|
||||
final List<Long> ids = this.remoteProctoringRoomRecordMapper
|
||||
.selectIdsByExample()
|
||||
.where(RemoteProctoringRoomRecordDynamicSqlSupport.examId, isEqualTo(examId))
|
||||
.build()
|
||||
.execute();
|
||||
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
log.info("No proctoring rooms found for exam to delete: {}", examId);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
this.remoteProctoringRoomRecordMapper.deleteByExample()
|
||||
.where(RemoteProctoringRoomRecordDynamicSqlSupport.id, isIn(ids))
|
||||
.build()
|
||||
|
|
|
@ -16,6 +16,12 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamProctoringServi
|
|||
|
||||
public interface ExamAdminService {
|
||||
|
||||
/** Get the exam domain object for the exam identifier (PK).
|
||||
*
|
||||
* @param examId the exam identifier
|
||||
* @return Result refer to the domain object or to an error when happened */
|
||||
Result<Exam> examForPK(Long examId);
|
||||
|
||||
/** Saves additional attributes for the exam that are specific to a type of LMS
|
||||
*
|
||||
* @param exam The Exam to add the LMS specific attributes
|
||||
|
|
|
@ -76,7 +76,11 @@ public class ExamAdminServiceImpl implements ExamAdminService {
|
|||
this.cryptor = cryptor;
|
||||
this.examProctoringServiceFactory = examProctoringServiceFactory;
|
||||
this.remoteProctoringRoomDAO = remoteProctoringRoomDAO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Exam> examForPK(final Long examId) {
|
||||
return this.examDAO.byPK(examId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -21,12 +21,12 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
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.ProctoringRoomConnection;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
||||
|
@ -38,6 +38,7 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
|
|||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.RemoteProctoringRoomDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl.ExamDeletionEvent;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamProctoringRoomService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamProctoringService;
|
||||
|
@ -137,16 +138,28 @@ public class ExamProctoringRoomServiceImpl implements ExamProctoringRoomService
|
|||
}
|
||||
}
|
||||
|
||||
@EventListener(ExamDeletionEvent.class)
|
||||
public void notifyExamDeletionEvent(final ExamDeletionEvent event) {
|
||||
event.ids.forEach(examId -> {
|
||||
try {
|
||||
|
||||
this.examAdminService.examForPK(examId)
|
||||
.flatMap(this::disposeRoomsForExam)
|
||||
.getOrThrow();
|
||||
|
||||
} catch (final Exception e) {
|
||||
log.error("Failed to delete depending proctoring data for exam: {}", examId, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Exam> disposeRoomsForExam(final Exam exam) {
|
||||
if (exam.status != ExamStatus.FINISHED) {
|
||||
log.warn("The exam has not been finished yet. No proctoring rooms will be deleted: {} / {}",
|
||||
exam.name,
|
||||
exam.externalId);
|
||||
}
|
||||
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
log.info("Dispose and deleting proctoring rooms for exam: {}", exam.externalId);
|
||||
|
||||
final ProctoringServiceSettings proctoringSettings = this.examAdminService
|
||||
.getProctoringServiceSettings(exam.id)
|
||||
.getOrThrow();
|
||||
|
|
|
@ -685,6 +685,7 @@ public class ZoomProctoringService implements ExamProctoringService {
|
|||
|
||||
private final static class ZoomRestTemplate {
|
||||
|
||||
private static final int LIZENSED_USER = 2;
|
||||
private static final String API_TEST_ENDPOINT = "v2/users";
|
||||
private static final String API_CREATE_USER_ENDPOINT = "v2/users";
|
||||
private static final String API_DELETE_USER_ENDPOINT = "v2/users/{userid}?action=delete";
|
||||
|
@ -749,7 +750,7 @@ public class ZoomProctoringService implements ExamProctoringService {
|
|||
API_USER_CUST_CREATE,
|
||||
new CreateUserRequest.UserInfo(
|
||||
roomName + "@" + host,
|
||||
1,
|
||||
LIZENSED_USER,
|
||||
roomName,
|
||||
API_ZOOM_ROOM_USER));
|
||||
|
||||
|
|
Loading…
Reference in a new issue