Merge branch 'rel-1.4.1'

This commit is contained in:
anhefti 2022-11-10 15:28:32 +01:00
commit e704bde073
11 changed files with 91 additions and 31 deletions

View file

@ -18,7 +18,7 @@
<packaging>jar</packaging> <packaging>jar</packaging>
<properties> <properties>
<sebserver-version>1.4.0</sebserver-version> <sebserver-version>1.4.1</sebserver-version>
<build-version>${sebserver-version}</build-version> <build-version>${sebserver-version}</build-version>
<revision>${sebserver-version}</revision> <revision>${sebserver-version}</revision>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

View file

@ -757,4 +757,18 @@ public final class Utils {
} }
} }
public static boolean isEqualsWithEmptyCheck(final String s1, final String s2) {
// checks equal strings and both null
if (Objects.equals(s1, s2)) {
return true;
}
// check null and empty string
if (StringUtils.isBlank(s1) && StringUtils.isBlank(s2)) {
return true;
}
return false;
}
} }

View file

@ -742,14 +742,20 @@ public class ExamDAOImpl implements ExamDAO {
private QuizData saveAdditionalQuizAttributes(final Long examId, final QuizData quizData) { private QuizData saveAdditionalQuizAttributes(final Long examId, final QuizData quizData) {
final Map<String, String> additionalAttributes = new HashMap<>(quizData.getAdditionalAttributes()); final Map<String, String> additionalAttributes = new HashMap<>(quizData.getAdditionalAttributes());
additionalAttributes.put(QuizData.QUIZ_ATTR_DESCRIPTION, quizData.description); if (StringUtils.isNotBlank(quizData.description)) {
additionalAttributes.put(QuizData.QUIZ_ATTR_START_URL, quizData.startURL); additionalAttributes.put(QuizData.QUIZ_ATTR_DESCRIPTION, quizData.description);
}
if (StringUtils.isNotBlank(quizData.startURL)) {
additionalAttributes.put(QuizData.QUIZ_ATTR_START_URL, quizData.startURL);
}
this.additionalAttributesDAO.saveAdditionalAttributes( if (!additionalAttributes.isEmpty()) {
EntityType.EXAM, this.additionalAttributesDAO.saveAdditionalAttributes(
examId, EntityType.EXAM,
additionalAttributes) examId,
.getOrThrow(); additionalAttributes)
.getOrThrow();
}
return quizData; return quizData;
} }

View file

@ -135,8 +135,6 @@ public class UserDAOImpl implements UserDAO {
this.userRecordMapper this.userRecordMapper
.selectByExample() .selectByExample()
.where(UserRecordDynamicSqlSupport.username, isEqualTo(username)) .where(UserRecordDynamicSqlSupport.username, isEqualTo(username))
.and(UserRecordDynamicSqlSupport.active,
isEqualTo(BooleanUtils.toInteger(true)))
.build() .build()
.execute()) .execute())
.flatMap(this::sebServerUserFromRecord); .flatMap(this::sebServerUserFromRecord);

View file

@ -35,7 +35,7 @@ public interface SEBRestrictionAPI {
/** Use this to check if there is a SEB restriction available on the LMS for the specified exam. /** Use this to check if there is a SEB restriction available on the LMS for the specified exam.
* *
* A SEB Restriction is available if there it can get from LMS and if there is either a Config-Key * A SEB Restriction is available if it can get from LMS and if there is either a Config-Key
* or a BrowserExam-Key set or both. If none of this keys is set, the SEB Restriction is been * or a BrowserExam-Key set or both. If none of this keys is set, the SEB Restriction is been
* considered to not set on the LMS. * considered to not set on the LMS.
* *

View file

@ -197,6 +197,7 @@ public class SEBRestrictionServiceImpl implements SEBRestrictionService {
log.info("ExamStartedEvent received, process applySEBClientRestriction..."); log.info("ExamStartedEvent received, process applySEBClientRestriction...");
applySEBClientRestriction(event.exam) applySEBClientRestriction(event.exam)
.flatMap(e -> this.examDAO.setSEBRestriction(e.id, true))
.onError(error -> log.error( .onError(error -> log.error(
"Failed to apply SEB restrictions for started exam: {}", "Failed to apply SEB restrictions for started exam: {}",
event.exam, event.exam,

View file

@ -29,7 +29,6 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamConfigurationMapDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamConfigurationMapDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamConfigUpdateService; import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamConfigUpdateService;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService; import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService;
@ -45,22 +44,19 @@ public class ExamConfigUpdateServiceImpl implements ExamConfigUpdateService {
private final ExamConfigurationMapDAO examConfigurationMapDAO; private final ExamConfigurationMapDAO examConfigurationMapDAO;
private final ExamSessionService examSessionService; private final ExamSessionService examSessionService;
private final ExamUpdateHandler examUpdateHandler; private final ExamUpdateHandler examUpdateHandler;
private final ExamAdminService examAdminService;
protected ExamConfigUpdateServiceImpl( protected ExamConfigUpdateServiceImpl(
final ExamDAO examDAO, final ExamDAO examDAO,
final ConfigurationDAO configurationDAO, final ConfigurationDAO configurationDAO,
final ExamConfigurationMapDAO examConfigurationMapDAO, final ExamConfigurationMapDAO examConfigurationMapDAO,
final ExamSessionService examSessionService, final ExamSessionService examSessionService,
final ExamUpdateHandler examUpdateHandler, final ExamUpdateHandler examUpdateHandler) {
final ExamAdminService examAdminService) {
this.examDAO = examDAO; this.examDAO = examDAO;
this.configurationDAO = configurationDAO; this.configurationDAO = configurationDAO;
this.examConfigurationMapDAO = examConfigurationMapDAO; this.examConfigurationMapDAO = examConfigurationMapDAO;
this.examSessionService = examSessionService; this.examSessionService = examSessionService;
this.examUpdateHandler = examUpdateHandler; this.examUpdateHandler = examUpdateHandler;
this.examAdminService = examAdminService;
} }
// processing: // processing:
@ -129,11 +125,12 @@ public class ExamConfigUpdateServiceImpl implements ExamConfigUpdateService {
// generate the new Config Key and update the Config Key within the LMSSetup API for each exam (delete old Key and add new Key) // generate the new Config Key and update the Config Key within the LMSSetup API for each exam (delete old Key and add new Key)
for (final Exam exam : exams) { for (final Exam exam : exams) {
if (exam.getStatus() == ExamStatus.RUNNING || this.examAdminService.isRestricted(exam).getOr(false)) { if (exam.getStatus() == ExamStatus.RUNNING) {
this.examUpdateHandler this.examUpdateHandler
.getSEBRestrictionService() .getSEBRestrictionService()
.applySEBClientRestriction(exam) .applySEBClientRestriction(exam)
.flatMap(e -> this.examDAO.setSEBRestriction(e.id, true))
.onError(t -> log.error("Failed to update SEB Client restriction for Exam: {}", exam, t)); .onError(t -> log.error("Failed to update SEB Client restriction for Exam: {}", exam, t));
} }
} }
@ -201,15 +198,14 @@ public class ExamConfigUpdateServiceImpl implements ExamConfigUpdateService {
.getOrThrow(); .getOrThrow();
// update seb client restriction if the feature is activated for the exam // update seb client restriction if the feature is activated for the exam
if (this.examAdminService.isRestricted(exam).getOr(false)) { this.examUpdateHandler
this.examUpdateHandler .getSEBRestrictionService()
.getSEBRestrictionService() .applySEBClientRestriction(exam)
.applySEBClientRestriction(exam) .flatMap(e -> this.examDAO.setSEBRestriction(e.id, true))
.onError(t -> log.error( .onError(t -> log.error(
"Failed to update SEB Client restriction for Exam: {}", "Failed to update SEB Client restriction for Exam: {}",
exam, exam,
t)); t));
}
// flush the exam cache. If there was an error during flush, it is logged but this process goes on // flush the exam cache. If there was an error during flush, it is logged but this process goes on
// and the saved changes are not rolled back // and the saved changes are not rolled back

View file

@ -338,18 +338,29 @@ class ExamUpdateHandler {
} }
private boolean hasChanges(final Exam exam, final QuizData quizData) { private boolean hasChanges(final Exam exam, final QuizData quizData) {
if (!Objects.equals(exam.name, quizData.name) || if (!Utils.isEqualsWithEmptyCheck(exam.name, quizData.name) ||
!Objects.equals(exam.startTime, quizData.startTime) || !Objects.equals(exam.startTime, quizData.startTime) ||
!Objects.equals(exam.endTime, quizData.endTime) || !Objects.equals(exam.endTime, quizData.endTime) ||
!Objects.equals(exam.getDescription(), quizData.description) || !Utils.isEqualsWithEmptyCheck(exam.getDescription(), quizData.description) ||
!Objects.equals(exam.getStartURL(), quizData.startURL)) { !Utils.isEqualsWithEmptyCheck(exam.getStartURL(), quizData.startURL)) {
if (log.isDebugEnabled()) {
log.debug("Update difference from LMS. Exam:{}, QuizData: {}", exam, quizData);
}
return true; return true;
} }
if (quizData.additionalAttributes != null && !quizData.additionalAttributes.isEmpty()) { if (quizData.additionalAttributes != null && !quizData.additionalAttributes.isEmpty()) {
for (final Map.Entry<String, String> attr : quizData.additionalAttributes.entrySet()) { for (final Map.Entry<String, String> attr : quizData.additionalAttributes.entrySet()) {
if (!Objects.equals(exam.getAdditionalAttribute(attr.getKey()), attr.getValue())) { final String currentAttrValue = exam.getAdditionalAttribute(attr.getKey());
if (!Utils.isEqualsWithEmptyCheck(currentAttrValue, attr.getValue())) {
if (log.isDebugEnabled()) {
log.debug("Update difference from LMS: attribute{}, currentValue: {}, lmsValue: {}",
attr.getKey(),
currentAttrValue,
attr.getValue());
}
return true; return true;
} }
} }

View file

@ -475,7 +475,8 @@ public class ExamProctoringRoomServiceImpl implements ExamProctoringRoomService
final ExamProctoringService examProctoringService) { final ExamProctoringService examProctoringService) {
// get all connections of the room // get all connections of the room
final List<String> connectionTokens = this.getActiveCollectingRoomConnections(examId, roomName) final List<String> connectionTokens = this
.getActiveCollectingRoomConnections(examId, roomName)
.getOrThrow() .getOrThrow()
.stream() .stream()
.map(cc -> cc.connectionToken) .map(cc -> cc.connectionToken)
@ -501,6 +502,12 @@ public class ExamProctoringRoomServiceImpl implements ExamProctoringRoomService
connectionTokens, connectionTokens,
examProctoringService.getDefaultReconfigInstructionAttributes()); examProctoringService.getDefaultReconfigInstructionAttributes());
} }
// Send the rejoin to collecting room instruction to all involved clients
sendJoinCollectingRoomInstructions(
proctoringSettings,
connectionTokens,
examProctoringService);
} }
private void cleanupBreakOutRooms(final ClientConnectionRecord cc) { private void cleanupBreakOutRooms(final ClientConnectionRecord cc) {

View file

@ -8,6 +8,13 @@
package ch.ethz.seb.sebserver.gbl.util; package ch.ethz.seb.sebserver.gbl.util;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.Objects;
import org.junit.Test;
public class ReplTest { public class ReplTest {
// @Test // @Test
@ -48,4 +55,11 @@ public class ReplTest {
// assertTrue(new Boolean(false) == new Boolean(false)); // assertTrue(new Boolean(false) == new Boolean(false));
// } // }
@Test
public void testObjectEquals() {
assertTrue(Objects.equals("", ""));
assertTrue(Objects.equals(null, null));
assertFalse(Objects.equals("", null));
}
} }

View file

@ -243,4 +243,17 @@ public class UtilsTest {
.contains("ch.ethz.seb.sebserver.gbl.util.UtilsTest.testFormatStackTracePrint")); .contains("ch.ethz.seb.sebserver.gbl.util.UtilsTest.testFormatStackTracePrint"));
} }
@Test
public void testIsEqualsWithEmptyCheck() {
assertTrue(Utils.isEqualsWithEmptyCheck("aa", "aa"));
assertTrue(Utils.isEqualsWithEmptyCheck("", ""));
assertTrue(Utils.isEqualsWithEmptyCheck(null, null));
assertTrue(Utils.isEqualsWithEmptyCheck("", null));
assertTrue(Utils.isEqualsWithEmptyCheck(null, ""));
assertTrue(Utils.isEqualsWithEmptyCheck(" ", null));
assertTrue(Utils.isEqualsWithEmptyCheck(" ", " "));
assertFalse(Utils.isEqualsWithEmptyCheck(" ", "a"));
}
} }