diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/SEBProctoringConnectionData.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/SEBProctoringConnection.java similarity index 94% rename from src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/SEBProctoringConnectionData.java rename to src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/SEBProctoringConnection.java index 1f6cd88a..f28cc761 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/SEBProctoringConnectionData.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/SEBProctoringConnection.java @@ -15,7 +15,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ProctoringServerType; @JsonIgnoreProperties(ignoreUnknown = true) -public class SEBProctoringConnectionData { +public class SEBProctoringConnection { public static final String ATTR_CONNECTION_TOKEN = "connectionToken"; public static final String ATTR_SERVER_HOST = "serverHost"; @@ -47,7 +47,7 @@ public class SEBProctoringConnectionData { public final String accessToken; @JsonCreator - public SEBProctoringConnectionData( + public SEBProctoringConnection( @JsonProperty(ProctoringSettings.ATTR_SERVER_TYPE) final ProctoringServerType proctoringServerType, @JsonProperty(ATTR_CONNECTION_TOKEN) final String connectionToken, @JsonProperty(ATTR_SERVER_HOST) final String serverHost, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringClientConnection.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringClientConnection.java index 0721d85f..8a927f1d 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringClientConnection.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringClientConnection.java @@ -32,7 +32,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.exam.Indicator; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings; -import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnectionData; +import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData; import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent; @@ -455,12 +455,12 @@ public class MonitoringClientConnection implements TemplateComposer { if (roomOptional.isPresent()) { final RemoteProctoringRoom room = roomOptional.get(); - final SEBProctoringConnectionData proctoringConnectionData = this.pageService + final SEBProctoringConnection proctoringConnectionData = this.pageService .getRestService() .getBuilder(GetProctorRoomConnectionData.class) .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(proctoringSettings.examId)) - .withQueryParam(SEBProctoringConnectionData.ATTR_ROOM_NAME, room.name) - .withQueryParam(SEBProctoringConnectionData.ATTR_SUBJECT, Utils.encodeFormURL_UTF_8(room.subject)) + .withQueryParam(SEBProctoringConnection.ATTR_ROOM_NAME, room.name) + .withQueryParam(SEBProctoringConnection.ATTR_SUBJECT, Utils.encodeFormURL_UTF_8(room.subject)) .call() .getOrThrow(); @@ -499,7 +499,7 @@ public class MonitoringClientConnection implements TemplateComposer { .getProctoringGUIService(); if (!proctoringGUIService.hasRoom(roomName)) { - final SEBProctoringConnectionData proctoringConnectionData = proctoringGUIService + final SEBProctoringConnection proctoringConnectionData = proctoringGUIService .registerNewSingleProcotringRoom( examId, roomName, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExam.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExam.java index 9d81d9d9..31384816 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExam.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExam.java @@ -44,7 +44,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.exam.Indicator; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings; -import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnectionData; +import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData; @@ -445,7 +445,7 @@ public class MonitoringRunningExam implements TemplateComposer { String activeAllRoomName = proctoringGUIService.getTownhallRoom(examId.modelId); if (activeAllRoomName == null) { - final SEBProctoringConnectionData proctoringConnectionData = proctoringGUIService + final SEBProctoringConnection proctoringConnectionData = proctoringGUIService .registerTownhallRoom( examId.modelId, this.pageService.getI18nSupport().getText(EXAM_ROOM_NAME)) @@ -642,12 +642,12 @@ public class MonitoringRunningExam implements TemplateComposer { final RemoteProctoringRoom room, final PageAction action) { - final SEBProctoringConnectionData proctoringConnectionData = this.pageService + final SEBProctoringConnection proctoringConnectionData = this.pageService .getRestService() .getBuilder(GetProctorRoomConnectionData.class) .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(proctoringSettings.examId)) - .withQueryParam(SEBProctoringConnectionData.ATTR_ROOM_NAME, room.name) - .withQueryParam(SEBProctoringConnectionData.ATTR_SUBJECT, Utils.encodeFormURL_UTF_8(room.subject)) + .withQueryParam(SEBProctoringConnection.ATTR_ROOM_NAME, room.name) + .withQueryParam(SEBProctoringConnection.ATTR_SUBJECT, Utils.encodeFormURL_UTF_8(room.subject)) .call() .getOrThrow(); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/ActivateTownhallRoom.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/ActivateTownhallRoom.java index 5e6852b8..93d8832b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/ActivateTownhallRoom.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/ActivateTownhallRoom.java @@ -17,20 +17,20 @@ import com.fasterxml.jackson.core.type.TypeReference; import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.EntityType; -import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnectionData; +import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; @Lazy @Component @GuiProfile -public class ActivateTownhallRoom extends RestCall { +public class ActivateTownhallRoom extends RestCall { public ActivateTownhallRoom() { super(new TypeKey<>( CallType.UNDEFINED, EntityType.EXAM_PROCTOR_DATA, - new TypeReference() { + new TypeReference() { }), HttpMethod.POST, MediaType.APPLICATION_FORM_URLENCODED, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/GetProctorRoomConnectionData.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/GetProctorRoomConnectionData.java index 960767b3..932d0f7b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/GetProctorRoomConnectionData.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/GetProctorRoomConnectionData.java @@ -17,20 +17,20 @@ import com.fasterxml.jackson.core.type.TypeReference; import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.EntityType; -import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnectionData; +import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; @Lazy @Component @GuiProfile -public class GetProctorRoomConnectionData extends RestCall { +public class GetProctorRoomConnectionData extends RestCall { public GetProctorRoomConnectionData() { super(new TypeKey<>( CallType.GET_SINGLE, EntityType.EXAM_PROCTOR_DATA, - new TypeReference() { + new TypeReference() { }), HttpMethod.GET, MediaType.APPLICATION_FORM_URLENCODED, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/SendJoinRemoteProctoringRoom.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/SendJoinRemoteProctoringRoom.java index 5e8fe9fc..50622ed6 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/SendJoinRemoteProctoringRoom.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/session/SendJoinRemoteProctoringRoom.java @@ -17,20 +17,20 @@ import com.fasterxml.jackson.core.type.TypeReference; import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.EntityType; -import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnectionData; +import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; @Lazy @Component @GuiProfile -public class SendJoinRemoteProctoringRoom extends RestCall { +public class SendJoinRemoteProctoringRoom extends RestCall { public SendJoinRemoteProctoringRoom() { super(new TypeKey<>( CallType.UNDEFINED, EntityType.EXAM_PROCTOR_DATA, - new TypeReference() { + new TypeReference() { }), HttpMethod.POST, MediaType.APPLICATION_FORM_URLENCODED, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ProctoringGUIService.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ProctoringGUIService.java index 0e449d2f..de5eb00b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ProctoringGUIService.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ProctoringGUIService.java @@ -27,7 +27,7 @@ import org.slf4j.LoggerFactory; import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.model.Domain; -import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnectionData; +import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.ActivateTownhallRoom; @@ -82,7 +82,7 @@ public class ProctoringGUIService { public static void setCurrentProctoringWindowData( final String examId, - final SEBProctoringConnectionData data) { + final SEBProctoringConnection data) { RWT.getUISession().getHttpSession().setAttribute( SESSION_ATTR_PROCTORING_DATA, @@ -103,7 +103,7 @@ public class ProctoringGUIService { .orElseGet(() -> null); } - public Result registerNewSingleProcotringRoom( + public Result registerNewSingleProcotringRoom( final String examId, final String roomName, final String subject, @@ -111,8 +111,8 @@ public class ProctoringGUIService { return this.restService.getBuilder(SendJoinRemoteProctoringRoom.class) .withURIVariable(API.PARAM_MODEL_ID, examId) - .withFormParam(SEBProctoringConnectionData.ATTR_ROOM_NAME, roomName) - .withFormParam(SEBProctoringConnectionData.ATTR_SUBJECT, subject) + .withFormParam(SEBProctoringConnection.ATTR_ROOM_NAME, roomName) + .withFormParam(SEBProctoringConnection.ATTR_SUBJECT, subject) .withFormParam(API.EXAM_API_SEB_CONNECTION_TOKEN, connectionToken) .call() .map(connection -> { @@ -122,13 +122,13 @@ public class ProctoringGUIService { }); } - public Result registerTownhallRoom( + public Result registerTownhallRoom( final String examId, final String subject) { return this.restService.getBuilder(ActivateTownhallRoom.class) .withURIVariable(API.PARAM_MODEL_ID, examId) - .withFormParam(SEBProctoringConnectionData.ATTR_SUBJECT, subject) + .withFormParam(SEBProctoringConnection.ATTR_SUBJECT, subject) .call() .map(connection -> { this.rooms.put( @@ -139,7 +139,7 @@ public class ProctoringGUIService { }); } - public Result registerNewProcotringRoom( + public Result registerNewProcotringRoom( final String examId, final String roomName, final String subject, @@ -147,8 +147,8 @@ public class ProctoringGUIService { return this.restService.getBuilder(SendJoinRemoteProctoringRoom.class) .withURIVariable(API.PARAM_MODEL_ID, examId) - .withFormParam(SEBProctoringConnectionData.ATTR_ROOM_NAME, roomName) - .withFormParam(SEBProctoringConnectionData.ATTR_SUBJECT, subject) + .withFormParam(SEBProctoringConnection.ATTR_ROOM_NAME, roomName) + .withFormParam(SEBProctoringConnection.ATTR_SUBJECT, subject) .withFormParam( API.EXAM_API_SEB_CONNECTION_TOKEN, StringUtils.join(connectionTokens, Constants.LIST_SEPARATOR_CHAR)) @@ -172,7 +172,7 @@ public class ProctoringGUIService { } this.restService.getBuilder(SendJoinRemoteProctoringRoom.class) .withURIVariable(API.PARAM_MODEL_ID, examId) - .withFormParam(SEBProctoringConnectionData.ATTR_ROOM_NAME, room) + .withFormParam(SEBProctoringConnection.ATTR_ROOM_NAME, room) .withFormParam( API.EXAM_API_SEB_CONNECTION_TOKEN, StringUtils.join(connectionTokens, Constants.LIST_SEPARATOR_CHAR)) @@ -288,11 +288,11 @@ public class ProctoringGUIService { public static class ProctoringWindowData { public final String examId; - public final SEBProctoringConnectionData connectionData; + public final SEBProctoringConnection connectionData; protected ProctoringWindowData( final String examId, - final SEBProctoringConnectionData connectionData) { + final SEBProctoringConnection connectionData) { this.examId = examId; this.connectionData = connectionData; } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/ExamProctoringService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/ExamProctoringService.java index b7f3df2d..965bc52a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/ExamProctoringService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/ExamProctoringService.java @@ -10,7 +10,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.session; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ProctoringServerType; -import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnectionData; +import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; import ch.ethz.seb.sebserver.gbl.util.Result; @@ -33,36 +33,28 @@ public interface ExamProctoringService { * @param roomName the name of the room * @param subject name of the room * @return SEBProctoringConnectionData that contains all connection data */ - Result createProctorPublicRoomConnection( + Result createProctorPublicRoomConnection( final ProctoringSettings proctoringSettings, final String roomName, final String subject); - Result getClientExamCollectingRoomConnectionData( - final ProctoringSettings proctoringSettings, - final String connectionToken); - - Result getClientExamCollectingRoomConnectionData( + Result getClientExamCollectingRoomConnection( final ProctoringSettings proctoringSettings, final ClientConnection connection); - Result getClientExamCollectingRoomConnectionData( + Result getClientExamCollectingRoomConnection( final ProctoringSettings proctoringSettings, final String connectionToken, final String roomName, final String subject); - Result getClientRoomConnectionData( - final ProctoringSettings proctoringSettings, - final String connectionToken); - - Result getClientRoomConnectionData( + Result getClientRoomConnection( final ProctoringSettings examProctoring, final String connectionToken, final String roomName, final String subject); - Result createProctoringConnectionData( + Result createProctoringConnection( final ProctoringServerType proctoringServerType, final String connectionToken, final String url, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamJITSIProctoringService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamJITSIProctoringService.java index e01da641..63b21282 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamJITSIProctoringService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamJITSIProctoringService.java @@ -25,7 +25,7 @@ import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ProctoringServerType; -import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnectionData; +import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; @@ -77,13 +77,13 @@ public class ExamJITSIProctoringService implements ExamProctoringService { } @Override - public Result createProctorPublicRoomConnection( + public Result createProctorPublicRoomConnection( final ProctoringSettings proctoringSettings, final String roomName, final String subject) { return Result.tryCatch(() -> { - return createProctoringConnectionData( + return createProctoringConnection( proctoringSettings.serverType, null, proctoringSettings.serverURL, @@ -100,19 +100,7 @@ public class ExamJITSIProctoringService implements ExamProctoringService { } @Override - public Result getClientExamCollectingRoomConnectionData( - final ProctoringSettings proctoringSettings, - final String connectionToken) { - - return this.examSessionService - .getConnectionData(connectionToken) - .flatMap(connection -> getClientExamCollectingRoomConnectionData( - proctoringSettings, - connection.clientConnection)); - } - - @Override - public Result getClientExamCollectingRoomConnectionData( + public Result getClientExamCollectingRoomConnection( final ProctoringSettings proctoringSettings, final ClientConnection connection) { @@ -122,7 +110,7 @@ public class ExamJITSIProctoringService implements ExamProctoringService { .getRoomName(connection.getRemoteProctoringRoomId()) .getOrThrow(); - return createProctoringConnectionData( + return createProctoringConnection( proctoringSettings.serverType, null, proctoringSettings.serverURL, @@ -139,7 +127,7 @@ public class ExamJITSIProctoringService implements ExamProctoringService { } @Override - public Result getClientExamCollectingRoomConnectionData( + public Result getClientExamCollectingRoomConnection( final ProctoringSettings proctoringSettings, final String connectionToken, final String roomName, @@ -150,7 +138,7 @@ public class ExamJITSIProctoringService implements ExamProctoringService { .getConnectionData(connectionToken) .getOrThrow(); - return createProctoringConnectionData( + return createProctoringConnection( proctoringSettings.serverType, null, proctoringSettings.serverURL, @@ -167,29 +155,7 @@ public class ExamJITSIProctoringService implements ExamProctoringService { } @Override - public Result getClientRoomConnectionData( - final ProctoringSettings proctoringSettings, - final String connectionToken) { - - return Result.tryCatch(() -> this.examSessionService - .getConnectionData(connectionToken) - .getOrThrow() - - ).flatMap(clientConnection -> { - final Encoder urlEncoder = Base64.getUrlEncoder().withoutPadding(); - final String roomName = urlEncoder.encodeToString( - Utils.toByteArray(clientConnection.clientConnection.connectionToken)); - - return getClientRoomConnectionData( - proctoringSettings, - connectionToken, - roomName, - clientConnection.clientConnection.userSessionId); - }); - } - - @Override - public Result getClientRoomConnectionData( + public Result getClientRoomConnection( final ProctoringSettings proctoringSettings, final String connectionToken, final String roomName, @@ -202,7 +168,7 @@ public class ExamJITSIProctoringService implements ExamProctoringService { .getConnectionData(connectionToken) .getOrThrow(); - return createProctoringConnectionData( + return createProctoringConnection( proctoringSettings.serverType, connectionToken, proctoringSettings.serverURL, @@ -220,7 +186,7 @@ public class ExamJITSIProctoringService implements ExamProctoringService { } @Override - public Result createProctoringConnectionData( + public Result createProctoringConnection( final ProctoringServerType proctoringServerType, final String connectionToken, final String url, @@ -250,7 +216,7 @@ public class ExamJITSIProctoringService implements ExamProctoringService { host, moderator); - return new SEBProctoringConnectionData( + return new SEBProctoringConnection( proctoringServerType, connectionToken, host, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamProctoringRoomServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamProctoringRoomServiceImpl.java index 3ee5c152..3c90f48f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamProctoringRoomServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamProctoringRoomServiceImpl.java @@ -20,7 +20,7 @@ import org.springframework.stereotype.Service; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ProctoringServerType; -import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnectionData; +import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction; import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction.InstructionType; @@ -196,9 +196,9 @@ public class ExamProctoringRoomServiceImpl implements ExamProctoringRoomService .getExamProctoring(examId) .getOrThrow(); - final SEBProctoringConnectionData proctoringData = + final SEBProctoringConnection proctoringData = this.examAdminService.getExamProctoringService(proctoringSettings.serverType) - .flatMap(s -> s.getClientExamCollectingRoomConnectionData( + .flatMap(s -> s.getClientExamCollectingRoomConnection( proctoringSettings, connectionToken, roomName, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamProctoringController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamProctoringController.java index a963b71a..5e9e2381 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamProctoringController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamProctoringController.java @@ -9,6 +9,8 @@ package ch.ethz.seb.sebserver.webservice.weblayer.api; import java.util.Arrays; +import java.util.Base64; +import java.util.Base64.Encoder; import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -31,13 +33,14 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType; import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings; -import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnectionData; +import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction; import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction.InstructionType; import ch.ethz.seb.sebserver.gbl.model.session.RemoteProctoringRoom; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Result; +import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService; import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService; @@ -108,14 +111,14 @@ public class ExamProctoringController { method = RequestMethod.GET, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) - public SEBProctoringConnectionData getProctorRoomData( + public SEBProctoringConnection getProctorRoomData( @RequestParam( name = API.PARAM_INSTITUTION_ID, required = true, defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId, @PathVariable(name = API.PARAM_MODEL_ID) final Long examId, - @RequestParam(name = SEBProctoringConnectionData.ATTR_ROOM_NAME, required = true) final String roomName, - @RequestParam(name = SEBProctoringConnectionData.ATTR_SUBJECT, required = false) final String subject) { + @RequestParam(name = SEBProctoringConnection.ATTR_ROOM_NAME, required = true) final String roomName, + @RequestParam(name = SEBProctoringConnection.ATTR_SUBJECT, required = false) final String subject) { checkAccess(institutionId, examId); @@ -217,27 +220,12 @@ public class ExamProctoringController { checkAccess(institutionId, examId); - final ProctoringSettings settings = this.examSessionService + final ProctoringSettings proctoringSettings = this.examSessionService .getRunningExam(examId) .flatMap(this.examAdminService::getExamProctoring) .getOrThrow(); - final ExamProctoringService examProctoringService = this.examAdminService - .getExamProctoringService(settings.serverType) - .getOrThrow(); - - Arrays.asList(StringUtils.split(connectionTokens, Constants.LIST_SEPARATOR)) - .stream() - .forEach(connectionToken -> { - examProctoringService - .getClientExamCollectingRoomConnectionData( - settings, - connectionToken) - .flatMap(data -> this.sendJoinInstruction(examId, connectionToken, data)) - .onError(error -> log.error("Failed to send rejoin for: {} cause: {}", - connectionToken, - error.getMessage())); - }); + sendJoinInstructions(connectionTokens, proctoringSettings); } @RequestMapping( @@ -245,17 +233,17 @@ public class ExamProctoringController { + API.EXAM_PROCTORING_JOIN_ROOM_PATH_SEGMENT, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) - public SEBProctoringConnectionData sendJoinProctoringRoomToClients( + public SEBProctoringConnection sendJoinProctoringRoomToClients( @RequestParam( name = API.PARAM_INSTITUTION_ID, required = true, defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId, @PathVariable(name = API.PARAM_MODEL_ID) final Long examId, @RequestParam( - name = SEBProctoringConnectionData.ATTR_ROOM_NAME, + name = SEBProctoringConnection.ATTR_ROOM_NAME, required = true) final String roomName, @RequestParam( - name = SEBProctoringConnectionData.ATTR_SUBJECT, + name = SEBProctoringConnection.ATTR_SUBJECT, required = false) final String subject, @RequestParam( name = API.EXAM_API_SEB_CONNECTION_TOKEN, @@ -273,39 +261,30 @@ public class ExamProctoringController { .getOrThrow(); if (StringUtils.isNotBlank(connectionTokens)) { - final boolean single = connectionTokens.contains(Constants.LIST_SEPARATOR); - (single - ? Arrays.asList(StringUtils.split(connectionTokens, Constants.LIST_SEPARATOR)) - : Arrays.asList(connectionTokens)) - .stream() - .forEach(connectionToken -> { - final SEBProctoringConnectionData data = (single) - ? examProctoringService - .getClientRoomConnectionData(settings, connectionToken) - .onError(error -> log.error( - "Failed to get client room connection data for {} cause: {}", - connectionToken, - error.getMessage())) - .get() - : examProctoringService - .getClientRoomConnectionData( - settings, - connectionToken, - roomName, - (StringUtils.isNotBlank(subject)) ? subject : roomName) - .onError(error -> log.error( - "Failed to get client room connection data for {} cause: {}", - connectionToken, - error.getMessage())) - .get(); - if (data != null) { - sendJoinInstruction(examId, connectionToken, data) - .onError(error -> log.error( - "Failed to send proctoring leave instruction to client: {} cause: {}", - connectionToken, - error.getMessage())); - } - }); + + Arrays.asList(connectionTokens.split(Constants.LIST_SEPARATOR)) + .stream() + .forEach(connectionToken -> { + final SEBProctoringConnection proctoringConnection = + examProctoringService + .getClientRoomConnection( + settings, + connectionToken, + verifyRoomName(roomName, connectionToken), + (StringUtils.isNotBlank(subject)) ? subject : roomName) + .onError(error -> log.error( + "Failed to get client room connection data for {} cause: {}", + connectionToken, + error.getMessage())) + .get(); + if (proctoringConnection != null) { + sendJoinInstruction(settings.examId, connectionToken, proctoringConnection) + .onError(error -> log.error( + "Failed to send proctoring leave instruction to client: {} cause: {}", + connectionToken, + error.getMessage())); + } + }); } return examProctoringService.createProctorPublicRoomConnection( @@ -315,6 +294,16 @@ public class ExamProctoringController { .getOrThrow(); } + private String verifyRoomName(final String requestedRoomName, final String connectionToken) { + if (StringUtils.isNotBlank(requestedRoomName)) { + return requestedRoomName; + } + + final Encoder urlEncoder = Base64.getUrlEncoder().withoutPadding(); + return urlEncoder.encodeToString( + Utils.toByteArray(connectionToken)); + } + @RequestMapping( path = API.MODEL_ID_VAR_PATH_SEGMENT + API.EXAM_PROCTORING_TOWNHALL_ROOM_DATA, @@ -338,14 +327,14 @@ public class ExamProctoringController { + API.EXAM_PROCTORING_ACTIVATE_TOWNHALL_ROOM, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) - public SEBProctoringConnectionData activateTownhall( + public SEBProctoringConnection activateTownhall( @RequestParam( name = API.PARAM_INSTITUTION_ID, required = true, defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId, @PathVariable(name = API.PARAM_MODEL_ID) final Long examId, @RequestParam( - name = SEBProctoringConnectionData.ATTR_SUBJECT, + name = SEBProctoringConnection.ATTR_SUBJECT, required = false) final String subject) { checkAccess(institutionId, examId); @@ -371,8 +360,8 @@ public class ExamProctoringController { .getOrThrow() .stream() .forEach(cc -> { - final SEBProctoringConnectionData data = examProctoringService - .getClientRoomConnectionData( + final SEBProctoringConnection data = examProctoringService + .getClientRoomConnection( settings, cc.clientConnection.connectionToken, townhallRoom.name, @@ -431,7 +420,7 @@ public class ExamProctoringController { .stream() .forEach(cc -> { examProctoringService - .getClientExamCollectingRoomConnectionData( + .getClientExamCollectingRoomConnection( settings, cc.clientConnection) .flatMap(data -> this.sendJoinInstruction( @@ -455,64 +444,16 @@ public class ExamProctoringController { return; } - if (StringUtils.isNotBlank(connectionTokens)) { - // we have defined connection tokens to send instructions to + final boolean definedClients = StringUtils.isNotBlank(connectionTokens); + final boolean inTownhall = this.examProcotringRoomService.getTownhallRoomData(examId).hasValue(); + final boolean roomSpecified = StringUtils.isNotBlank(roomName); - final boolean single = connectionTokens.contains(Constants.LIST_SEPARATOR); - (single - ? Arrays.asList(StringUtils.split(connectionTokens, Constants.LIST_SEPARATOR)) - : Arrays.asList(connectionTokens)) - .stream() - .forEach(connectionToken -> { - this.sebInstructionService.registerInstruction( - examId, - InstructionType.SEB_RECONFIGURE_SETTINGS, - attributes, - connectionToken, - true) - .onError(error -> log.error( - "Failed to register reconfiguring instruction for connection: {}", - connectionToken, - error)); - - }); - } else if (this.examProcotringRoomService.getTownhallRoomData(examId).hasValue()) { - // we are in the town hall so all active connections are involved - - this.examSessionService.getAllActiveConnectionData(examId) - .getOrThrow() - .stream() - .forEach(connection -> { - this.sebInstructionService.registerInstruction( - examId, - InstructionType.SEB_RECONFIGURE_SETTINGS, - attributes, - connection.clientConnection.connectionToken, - true) - .onError(error -> log.error( - "Failed to register reconfiguring instruction for connection: {}", - connection.clientConnection.connectionToken, - error)); - }); - } else if (StringUtils.isNotBlank(roomName)) { - // we have a room name so all connection of this room are involved - - this.examProcotringRoomService.getRoomConnections(examId, roomName) - .getOrThrow() - .stream() - .filter(ExamSessionService.ACTIVE_CONNECTION_FILTER) - .forEach(connection -> { - this.sebInstructionService.registerInstruction( - examId, - InstructionType.SEB_RECONFIGURE_SETTINGS, - attributes, - connection.connectionToken, - true) - .onError(error -> log.error( - "Failed to register reconfiguring instruction for connection: {}", - connection.connectionToken, - error)); - }); + if (definedClients) { + sendBroadcastInstructionsToClients(examId, connectionTokens, attributes); + } else if (inTownhall) { + sendBroadcastInstructionToClientsInExam(examId, attributes); + } else if (roomSpecified) { + sendBroadcastInstructionToClientsInRoom(examId, roomName, attributes); } else { throw new RuntimeException("API attribute validation error: missing " + Domain.REMOTE_PROCTORING_ROOM.ATTR_ID + " and/or" + @@ -520,12 +461,111 @@ public class ExamProctoringController { } } + private void sendBroadcastInstructionsToClients(final Long examId, final String connectionTokens, + final Map attributes) { + final boolean single = connectionTokens.contains(Constants.LIST_SEPARATOR); + (single + ? Arrays.asList(StringUtils.split(connectionTokens, Constants.LIST_SEPARATOR)) + : Arrays.asList(connectionTokens)) + .stream() + .forEach(connectionToken -> { + this.sebInstructionService.registerInstruction( + examId, + InstructionType.SEB_RECONFIGURE_SETTINGS, + attributes, + connectionToken, + true) + .onError(error -> log.error( + "Failed to register reconfiguring instruction for connection: {}", + connectionToken, + error)); + + }); + } + + private void sendBroadcastInstructionToClientsInExam(final Long examId, final Map attributes) { + this.examSessionService + .getAllActiveConnectionData(examId) + .getOrThrow() + .stream() + .forEach(connection -> { + this.sebInstructionService.registerInstruction( + examId, + InstructionType.SEB_RECONFIGURE_SETTINGS, + attributes, + connection.clientConnection.connectionToken, + true) + .onError(error -> log.error( + "Failed to register reconfiguring instruction for connection: {}", + connection.clientConnection.connectionToken, + error)); + }); + } + + private void sendBroadcastInstructionToClientsInRoom( + final Long examId, + final String roomName, + final Map attributes) { + + this.examProcotringRoomService + .getRoomConnections(examId, roomName) + .getOrThrow() + .stream() + .filter(ExamSessionService.ACTIVE_CONNECTION_FILTER) + .forEach(connection -> { + this.sebInstructionService.registerInstruction( + examId, + InstructionType.SEB_RECONFIGURE_SETTINGS, + attributes, + connection.connectionToken, + true) + .onError(error -> log.error( + "Failed to register reconfiguring instruction for connection: {}", + connection.connectionToken, + error)); + }); + } + + private void sendJoinInstructions( + final String connectionTokens, + final ProctoringSettings proctoringSettings) { + + final ExamProctoringService examProctoringService = this.examAdminService + .getExamProctoringService(proctoringSettings.serverType) + .getOrThrow(); + + Arrays.asList(StringUtils.split(connectionTokens, Constants.LIST_SEPARATOR)) + .stream() + .forEach(connectionToken -> { + sendJoinInstructionToClient(proctoringSettings, examProctoringService, connectionToken); + }); + } + + private void sendJoinInstructionToClient( + final ProctoringSettings proctoringSettings, + final ExamProctoringService examProctoringService, + final String connectionToken) { + + this.examSessionService + .getConnectionData(connectionToken) + .flatMap(connection -> examProctoringService.getClientExamCollectingRoomConnection( + proctoringSettings, + connection.clientConnection)) + .flatMap(data -> this.sendJoinInstruction( + proctoringSettings.examId, + connectionToken, data)) + .onError(error -> log.error("Failed to send rejoin for: {} cause: {}", + connectionToken, + error.getMessage())); + } + private Result sendJoinInstruction( final Long examId, final String connectionToken, - final SEBProctoringConnectionData data) { + final SEBProctoringConnection data) { final Map attributes = new HashMap<>(); + attributes.put( ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_PROCTORING.SERVICE_TYPE, ProctoringSettings.ProctoringServerType.JITSI_MEET.name()); @@ -541,6 +581,7 @@ public class ExamProctoringController { attributes.put( ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_PROCTORING.JITSI_TOKEN, data.accessToken); + return this.sebInstructionService.registerInstruction( examId, InstructionType.SEB_PROCTORING, diff --git a/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamJITSIProctoringServiceTest.java b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamJITSIProctoringServiceTest.java index e24cd7dd..4b138e37 100644 --- a/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamJITSIProctoringServiceTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamJITSIProctoringServiceTest.java @@ -18,7 +18,7 @@ import org.junit.Test; import org.mockito.Mockito; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ProctoringServerType; -import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnectionData; +import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.util.Cryptor; public class ExamJITSIProctoringServiceTest { @@ -63,7 +63,7 @@ public class ExamJITSIProctoringServiceTest { Mockito.when(cryptorMock.decrypt(Mockito.any())).thenReturn("fbvgeghergrgrthrehreg123"); final ExamJITSIProctoringService examJITSIProctoringService = new ExamJITSIProctoringService(null, null, null, cryptorMock); - final SEBProctoringConnectionData data = examJITSIProctoringService.createProctoringConnectionData( + final SEBProctoringConnection data = examJITSIProctoringService.createProctoringConnection( ProctoringServerType.JITSI_MEET, "connectionToken", "https://seb-jitsi.example.ch",