proctoring refactoring and tests

This commit is contained in:
anhefti 2021-02-17 16:52:28 +01:00
parent 1796ff4a7a
commit 2f2a318f9d
26 changed files with 311 additions and 240 deletions

View file

@ -12,10 +12,10 @@ import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ProctoringServerType; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class SEBProctoringConnection { public class ProctoringRoomConnection {
public static final String ATTR_CONNECTION_TOKEN = "connectionToken"; public static final String ATTR_CONNECTION_TOKEN = "connectionToken";
public static final String ATTR_SERVER_HOST = "serverHost"; public static final String ATTR_SERVER_HOST = "serverHost";
@ -25,7 +25,7 @@ public class SEBProctoringConnection {
public static final String ATTR_ACCESS_TOKEN = "accessToken"; public static final String ATTR_ACCESS_TOKEN = "accessToken";
public static final String ATTR_CONNECTION_URL = "connectionURL"; public static final String ATTR_CONNECTION_URL = "connectionURL";
@JsonProperty(ProctoringSettings.ATTR_SERVER_TYPE) @JsonProperty(ProctoringServiceSettings.ATTR_SERVER_TYPE)
public final ProctoringServerType proctoringServerType; public final ProctoringServerType proctoringServerType;
@JsonProperty(ATTR_CONNECTION_TOKEN) @JsonProperty(ATTR_CONNECTION_TOKEN)
@ -47,8 +47,8 @@ public class SEBProctoringConnection {
public final String accessToken; public final String accessToken;
@JsonCreator @JsonCreator
public SEBProctoringConnection( public ProctoringRoomConnection(
@JsonProperty(ProctoringSettings.ATTR_SERVER_TYPE) final ProctoringServerType proctoringServerType, @JsonProperty(ProctoringServiceSettings.ATTR_SERVER_TYPE) final ProctoringServerType proctoringServerType,
@JsonProperty(ATTR_CONNECTION_TOKEN) final String connectionToken, @JsonProperty(ATTR_CONNECTION_TOKEN) final String connectionToken,
@JsonProperty(ATTR_SERVER_HOST) final String serverHost, @JsonProperty(ATTR_SERVER_HOST) final String serverHost,
@JsonProperty(ATTR_SERVER_URL) final String serverURL, @JsonProperty(ATTR_SERVER_URL) final String serverURL,

View file

@ -22,7 +22,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.validation.ValidProctoringS
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
@ValidProctoringSettings @ValidProctoringSettings
public class ProctoringSettings implements Entity { public class ProctoringServiceSettings implements Entity {
public enum ProctoringServerType { public enum ProctoringServerType {
JITSI_MEET JITSI_MEET
@ -59,7 +59,7 @@ public class ProctoringSettings implements Entity {
public final Integer collectingRoomSize; public final Integer collectingRoomSize;
@JsonCreator @JsonCreator
public ProctoringSettings( public ProctoringServiceSettings(
@JsonProperty(Domain.EXAM.ATTR_ID) final Long examId, @JsonProperty(Domain.EXAM.ATTR_ID) final Long examId,
@JsonProperty(ATTR_ENABLE_PROCTORING) final Boolean enableProctoring, @JsonProperty(ATTR_ENABLE_PROCTORING) final Boolean enableProctoring,
@JsonProperty(ATTR_SERVER_TYPE) final ProctoringServerType serverType, @JsonProperty(ATTR_SERVER_TYPE) final ProctoringServerType serverType,
@ -137,7 +137,7 @@ public class ProctoringSettings implements Entity {
return false; return false;
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
final ProctoringSettings other = (ProctoringSettings) obj; final ProctoringServiceSettings other = (ProctoringServiceSettings) obj;
if (this.examId == null) { if (this.examId == null) {
if (other.examId != null) if (other.examId != null)
return false; return false;

View file

@ -33,7 +33,7 @@ import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; 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;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus; import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; 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.LmsSetup;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.Features; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.Features;
@ -350,7 +350,7 @@ public class ExamForm implements TemplateComposer {
.getBuilder(GetProctoringSettings.class) .getBuilder(GetProctoringSettings.class)
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
.call() .call()
.map(ProctoringSettings::getEnableProctoring) .map(ProctoringServiceSettings::getEnableProctoring)
.getOr(false); .getOr(false);
final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(formContext final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(formContext

View file

@ -22,8 +22,8 @@ import org.springframework.stereotype.Component;
import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ProctoringServerType; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition; import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
@ -121,24 +121,24 @@ public class ExamProctoringSettings {
} }
final EntityKey entityKey = pageContext.getEntityKey(); final EntityKey entityKey = pageContext.getEntityKey();
ProctoringSettings examProctoring = null; ProctoringServiceSettings examProctoring = null;
try { try {
final Form form = formHandle.getForm(); final Form form = formHandle.getForm();
form.clearErrors(); form.clearErrors();
final boolean enabled = BooleanUtils.toBoolean( final boolean enabled = BooleanUtils.toBoolean(
form.getFieldValue(ProctoringSettings.ATTR_ENABLE_PROCTORING)); form.getFieldValue(ProctoringServiceSettings.ATTR_ENABLE_PROCTORING));
final ProctoringServerType serverType = ProctoringServerType.valueOf( final ProctoringServerType serverType = ProctoringServerType.valueOf(
form.getFieldValue(ProctoringSettings.ATTR_SERVER_TYPE)); form.getFieldValue(ProctoringServiceSettings.ATTR_SERVER_TYPE));
examProctoring = new ProctoringSettings( examProctoring = new ProctoringServiceSettings(
Long.parseLong(entityKey.modelId), Long.parseLong(entityKey.modelId),
enabled, enabled,
serverType, serverType,
form.getFieldValue(ProctoringSettings.ATTR_SERVER_URL), form.getFieldValue(ProctoringServiceSettings.ATTR_SERVER_URL),
Integer.parseInt(form.getFieldValue(ProctoringSettings.ATTR_COLLECTING_ROOM_SIZE)), Integer.parseInt(form.getFieldValue(ProctoringServiceSettings.ATTR_COLLECTING_ROOM_SIZE)),
form.getFieldValue(ProctoringSettings.ATTR_APP_KEY), form.getFieldValue(ProctoringServiceSettings.ATTR_APP_KEY),
form.getFieldValue(ProctoringSettings.ATTR_APP_SECRET)); form.getFieldValue(ProctoringServiceSettings.ATTR_APP_SECRET));
} catch (final Exception e) { } catch (final Exception e) {
log.error("Unexpected error while trying to get settings from form: ", e); log.error("Unexpected error while trying to get settings from form: ", e);
@ -198,7 +198,7 @@ public class ExamProctoringSettings {
.getWidgetFactory() .getWidgetFactory()
.createPopupScrollComposite(parent); .createPopupScrollComposite(parent);
final ProctoringSettings proctoringSettings = restService final ProctoringServiceSettings proctoringSettings = restService
.getBuilder(GetProctoringSettings.class) .getBuilder(GetProctoringSettings.class)
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
.call() .call()
@ -208,7 +208,7 @@ public class ExamProctoringSettings {
.copyOf(content) .copyOf(content)
.clearEntityKeys(); .clearEntityKeys();
final FormHandle<ProctoringSettings> formHandle = this.pageService.formBuilder( final FormHandle<ProctoringServiceSettings> formHandle = this.pageService.formBuilder(
formContext) formContext)
.withDefaultSpanInput(5) .withDefaultSpanInput(5)
.withEmptyCellSeparation(true) .withEmptyCellSeparation(true)
@ -224,24 +224,24 @@ public class ExamProctoringSettings {
.readonly(true)) .readonly(true))
.addField(FormBuilder.checkbox( .addField(FormBuilder.checkbox(
ProctoringSettings.ATTR_ENABLE_PROCTORING, ProctoringServiceSettings.ATTR_ENABLE_PROCTORING,
SEB_PROCTORING_FORM_ENABLE, SEB_PROCTORING_FORM_ENABLE,
String.valueOf(proctoringSettings.enableProctoring))) String.valueOf(proctoringSettings.enableProctoring)))
.addField(FormBuilder.singleSelection( .addField(FormBuilder.singleSelection(
ProctoringSettings.ATTR_SERVER_TYPE, ProctoringServiceSettings.ATTR_SERVER_TYPE,
SEB_PROCTORING_FORM_TYPE, SEB_PROCTORING_FORM_TYPE,
proctoringSettings.serverType.name(), proctoringSettings.serverType.name(),
resourceService::examProctoringTypeResources)) resourceService::examProctoringTypeResources))
.addField(FormBuilder.text( .addField(FormBuilder.text(
ProctoringSettings.ATTR_SERVER_URL, ProctoringServiceSettings.ATTR_SERVER_URL,
SEB_PROCTORING_FORM_URL, SEB_PROCTORING_FORM_URL,
proctoringSettings.serverURL)) proctoringSettings.serverURL))
.withDefaultSpanInput(1) .withDefaultSpanInput(1)
.addField(FormBuilder.text( .addField(FormBuilder.text(
ProctoringSettings.ATTR_COLLECTING_ROOM_SIZE, ProctoringServiceSettings.ATTR_COLLECTING_ROOM_SIZE,
SEB_PROCTORING_FORM_ROOM_SIZE, SEB_PROCTORING_FORM_ROOM_SIZE,
String.valueOf(proctoringSettings.getCollectingRoomSize())) String.valueOf(proctoringSettings.getCollectingRoomSize()))
.asNumber(numString -> Long.parseLong(numString))) .asNumber(numString -> Long.parseLong(numString)))
@ -249,13 +249,13 @@ public class ExamProctoringSettings {
.withDefaultSpanEmptyCell(4) .withDefaultSpanEmptyCell(4)
.addField(FormBuilder.text( .addField(FormBuilder.text(
ProctoringSettings.ATTR_APP_KEY, ProctoringServiceSettings.ATTR_APP_KEY,
SEB_PROCTORING_FORM_APPKEY, SEB_PROCTORING_FORM_APPKEY,
proctoringSettings.appKey)) proctoringSettings.appKey))
.withEmptyCellSeparation(false) .withEmptyCellSeparation(false)
.addField(FormBuilder.password( .addField(FormBuilder.password(
ProctoringSettings.ATTR_APP_SECRET, ProctoringServiceSettings.ATTR_APP_SECRET,
SEB_PROCTORING_FORM_SECRET, SEB_PROCTORING_FORM_SECRET,
(proctoringSettings.appSecret != null) (proctoringSettings.appSecret != null)
? String.valueOf(proctoringSettings.appSecret) ? String.valueOf(proctoringSettings.appSecret)

View file

@ -31,8 +31,8 @@ import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; 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;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; 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.ProctoringServiceSettings;
import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringRoomConnection;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus; 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.ClientConnectionData;
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent; import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
@ -64,7 +64,7 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.ConfirmPe
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetClientConnectionData; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetClientConnectionData;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetPendingClientNotifications; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetPendingClientNotifications;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetProcotringRooms; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetProcotringRooms;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetProctorRoomConnectionData; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetProctorRoomConnection;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser; import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
import ch.ethz.seb.sebserver.gui.service.session.ClientConnectionDetails; import ch.ethz.seb.sebserver.gui.service.session.ClientConnectionDetails;
import ch.ethz.seb.sebserver.gui.service.session.InstructionProcessor; import ch.ethz.seb.sebserver.gui.service.session.InstructionProcessor;
@ -374,7 +374,7 @@ public class MonitoringClientConnection implements TemplateComposer {
connectionData.clientConnection.status == ConnectionStatus.ACTIVE); connectionData.clientConnection.status == ConnectionStatus.ACTIVE);
if (connectionData.clientConnection.status == ConnectionStatus.ACTIVE) { if (connectionData.clientConnection.status == ConnectionStatus.ACTIVE) {
final ProctoringSettings procotringSettings = restService final ProctoringServiceSettings procotringSettings = restService
.getBuilder(GetProctoringSettings.class) .getBuilder(GetProctoringSettings.class)
.withURIVariable(API.PARAM_MODEL_ID, parentEntityKey.modelId) .withURIVariable(API.PARAM_MODEL_ID, parentEntityKey.modelId)
.call() .call()
@ -438,7 +438,7 @@ public class MonitoringClientConnection implements TemplateComposer {
final String examId = action.getEntityKey().modelId; final String examId = action.getEntityKey().modelId;
final ProctoringSettings proctoringSettings = this.pageService.getRestService() final ProctoringServiceSettings proctoringSettings = this.pageService.getRestService()
.getBuilder(GetProctoringSettings.class) .getBuilder(GetProctoringSettings.class)
.withURIVariable(API.PARAM_MODEL_ID, examId) .withURIVariable(API.PARAM_MODEL_ID, examId)
.call() .call()
@ -455,12 +455,12 @@ public class MonitoringClientConnection implements TemplateComposer {
if (roomOptional.isPresent()) { if (roomOptional.isPresent()) {
final RemoteProctoringRoom room = roomOptional.get(); final RemoteProctoringRoom room = roomOptional.get();
final SEBProctoringConnection proctoringConnectionData = this.pageService final ProctoringRoomConnection proctoringConnectionData = this.pageService
.getRestService() .getRestService()
.getBuilder(GetProctorRoomConnectionData.class) .getBuilder(GetProctorRoomConnection.class)
.withURIVariable(API.PARAM_MODEL_ID, String.valueOf(proctoringSettings.examId)) .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(proctoringSettings.examId))
.withQueryParam(SEBProctoringConnection.ATTR_ROOM_NAME, room.name) .withQueryParam(ProctoringRoomConnection.ATTR_ROOM_NAME, room.name)
.withQueryParam(SEBProctoringConnection.ATTR_SUBJECT, Utils.encodeFormURL_UTF_8(room.subject)) .withQueryParam(ProctoringRoomConnection.ATTR_SUBJECT, Utils.encodeFormURL_UTF_8(room.subject))
.call() .call()
.getOrThrow(); .getOrThrow();
@ -499,7 +499,7 @@ public class MonitoringClientConnection implements TemplateComposer {
.getProctoringGUIService(); .getProctoringGUIService();
if (!proctoringGUIService.hasRoom(roomName)) { if (!proctoringGUIService.hasRoom(roomName)) {
final SEBProctoringConnection proctoringConnectionData = proctoringGUIService final ProctoringRoomConnection proctoringConnectionData = proctoringGUIService
.registerNewSingleProcotringRoom( .registerNewSingleProcotringRoom(
examId, examId,
roomName, roomName,

View file

@ -43,8 +43,8 @@ import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; 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;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; 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.ProctoringServiceSettings;
import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringRoomConnection;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; 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.ClientConnection.ConnectionStatus;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
@ -76,7 +76,7 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetIndicator
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetProctoringSettings; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetProctoringSettings;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetClientConnectionDataList; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetClientConnectionDataList;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetProcotringRooms; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetProcotringRooms;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetProctorRoomConnectionData; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetProctorRoomConnection;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetTownhallRoom; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetTownhallRoom;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser; import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
import ch.ethz.seb.sebserver.gui.service.session.ClientConnectionTable; import ch.ethz.seb.sebserver.gui.service.session.ClientConnectionTable;
@ -349,7 +349,7 @@ public class MonitoringRunningExam implements TemplateComposer {
} }
final ProctoringSettings proctoringSettings = restService final ProctoringServiceSettings proctoringSettings = restService
.getBuilder(GetProctoringSettings.class) .getBuilder(GetProctoringSettings.class)
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
.call() .call()
@ -445,7 +445,7 @@ public class MonitoringRunningExam implements TemplateComposer {
String activeAllRoomName = proctoringGUIService.getTownhallRoom(examId.modelId); String activeAllRoomName = proctoringGUIService.getTownhallRoom(examId.modelId);
if (activeAllRoomName == null) { if (activeAllRoomName == null) {
final SEBProctoringConnection proctoringConnectionData = proctoringGUIService final ProctoringRoomConnection proctoringConnectionData = proctoringGUIService
.registerTownhallRoom( .registerTownhallRoom(
examId.modelId, examId.modelId,
this.pageService.getI18nSupport().getText(EXAM_ROOM_NAME)) this.pageService.getI18nSupport().getText(EXAM_ROOM_NAME))
@ -528,7 +528,7 @@ public class MonitoringRunningExam implements TemplateComposer {
final PageContext pageContext, final PageContext pageContext,
final Map<String, Pair<RemoteProctoringRoom, TreeItem>> rooms, final Map<String, Pair<RemoteProctoringRoom, TreeItem>> rooms,
final PageActionBuilder actionBuilder, final PageActionBuilder actionBuilder,
final ProctoringSettings proctoringSettings) { final ProctoringServiceSettings proctoringSettings) {
updateTownhallButton(entityKey, pageContext); updateTownhallButton(entityKey, pageContext);
final I18nSupport i18nSupport = this.pageService.getI18nSupport(); final I18nSupport i18nSupport = this.pageService.getI18nSupport();
@ -638,16 +638,16 @@ public class MonitoringRunningExam implements TemplateComposer {
} }
private PageAction showExamProctoringRoom( private PageAction showExamProctoringRoom(
final ProctoringSettings proctoringSettings, final ProctoringServiceSettings proctoringSettings,
final RemoteProctoringRoom room, final RemoteProctoringRoom room,
final PageAction action) { final PageAction action) {
final SEBProctoringConnection proctoringConnectionData = this.pageService final ProctoringRoomConnection proctoringConnectionData = this.pageService
.getRestService() .getRestService()
.getBuilder(GetProctorRoomConnectionData.class) .getBuilder(GetProctorRoomConnection.class)
.withURIVariable(API.PARAM_MODEL_ID, String.valueOf(proctoringSettings.examId)) .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(proctoringSettings.examId))
.withQueryParam(SEBProctoringConnection.ATTR_ROOM_NAME, room.name) .withQueryParam(ProctoringRoomConnection.ATTR_ROOM_NAME, room.name)
.withQueryParam(SEBProctoringConnection.ATTR_SUBJECT, Utils.encodeFormURL_UTF_8(room.subject)) .withQueryParam(ProctoringRoomConnection.ATTR_SUBJECT, Utils.encodeFormURL_UTF_8(room.subject))
.call() .call()
.getOrThrow(); .getOrThrow();

View file

@ -40,7 +40,7 @@ import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSEBRestriction.PermissionComponent; import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSEBRestriction.PermissionComponent;
import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSEBRestriction.WhiteListPath; import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSEBRestriction.WhiteListPath;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ProctoringServerType; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType; import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;

View file

@ -8,7 +8,7 @@
package ch.ethz.seb.sebserver.gui.service.page; package ch.ethz.seb.sebserver.gui.service.page;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ProctoringServerType; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
public interface RemoteProctoringView extends TemplateComposer { public interface RemoteProctoringView extends TemplateComposer {

View file

@ -25,7 +25,7 @@ import org.springframework.stereotype.Component;
import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ProctoringServerType; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction; import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.GuiServiceInfo; import ch.ethz.seb.sebserver.gui.GuiServiceInfo;

View file

@ -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.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy @Lazy
@Component @Component
@GuiProfile @GuiProfile
public class GetProctoringSettings extends RestCall<ProctoringSettings> { public class GetProctoringSettings extends RestCall<ProctoringServiceSettings> {
public GetProctoringSettings() { public GetProctoringSettings() {
super(new TypeKey<>( super(new TypeKey<>(
CallType.GET_SINGLE, CallType.GET_SINGLE,
EntityType.EXAM_PROCTOR_DATA, EntityType.EXAM_PROCTOR_DATA,
new TypeReference<ProctoringSettings>() { new TypeReference<ProctoringServiceSettings>() {
}), }),
HttpMethod.GET, HttpMethod.GET,
MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON,

View file

@ -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.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringRoomConnection;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy @Lazy
@Component @Component
@GuiProfile @GuiProfile
public class ActivateTownhallRoom extends RestCall<SEBProctoringConnection> { public class ActivateTownhallRoom extends RestCall<ProctoringRoomConnection> {
public ActivateTownhallRoom() { public ActivateTownhallRoom() {
super(new TypeKey<>( super(new TypeKey<>(
CallType.UNDEFINED, CallType.UNDEFINED,
EntityType.EXAM_PROCTOR_DATA, EntityType.EXAM_PROCTOR_DATA,
new TypeReference<SEBProctoringConnection>() { new TypeReference<ProctoringRoomConnection>() {
}), }),
HttpMethod.POST, HttpMethod.POST,
MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_FORM_URLENCODED,

View file

@ -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.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringRoomConnection;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy @Lazy
@Component @Component
@GuiProfile @GuiProfile
public class GetProctorRoomConnectionData extends RestCall<SEBProctoringConnection> { public class GetProctorRoomConnection extends RestCall<ProctoringRoomConnection> {
public GetProctorRoomConnectionData() { public GetProctorRoomConnection() {
super(new TypeKey<>( super(new TypeKey<>(
CallType.GET_SINGLE, CallType.GET_SINGLE,
EntityType.EXAM_PROCTOR_DATA, EntityType.EXAM_PROCTOR_DATA,
new TypeReference<SEBProctoringConnection>() { new TypeReference<ProctoringRoomConnection>() {
}), }),
HttpMethod.GET, HttpMethod.GET,
MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_FORM_URLENCODED,

View file

@ -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.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringRoomConnection;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
@Lazy @Lazy
@Component @Component
@GuiProfile @GuiProfile
public class SendJoinRemoteProctoringRoom extends RestCall<SEBProctoringConnection> { public class SendJoinRemoteProctoringRoom extends RestCall<ProctoringRoomConnection> {
public SendJoinRemoteProctoringRoom() { public SendJoinRemoteProctoringRoom() {
super(new TypeKey<>( super(new TypeKey<>(
CallType.UNDEFINED, CallType.UNDEFINED,
EntityType.EXAM_PROCTOR_DATA, EntityType.EXAM_PROCTOR_DATA,
new TypeReference<SEBProctoringConnection>() { new TypeReference<ProctoringRoomConnection>() {
}), }),
HttpMethod.POST, HttpMethod.POST,
MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_FORM_URLENCODED,

View file

@ -27,7 +27,7 @@ import org.slf4j.LoggerFactory;
import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringRoomConnection;
import ch.ethz.seb.sebserver.gbl.util.Result; 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.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.ActivateTownhallRoom; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.ActivateTownhallRoom;
@ -82,7 +82,7 @@ public class ProctoringGUIService {
public static void setCurrentProctoringWindowData( public static void setCurrentProctoringWindowData(
final String examId, final String examId,
final SEBProctoringConnection data) { final ProctoringRoomConnection data) {
RWT.getUISession().getHttpSession().setAttribute( RWT.getUISession().getHttpSession().setAttribute(
SESSION_ATTR_PROCTORING_DATA, SESSION_ATTR_PROCTORING_DATA,
@ -103,7 +103,7 @@ public class ProctoringGUIService {
.orElseGet(() -> null); .orElseGet(() -> null);
} }
public Result<SEBProctoringConnection> registerNewSingleProcotringRoom( public Result<ProctoringRoomConnection> registerNewSingleProcotringRoom(
final String examId, final String examId,
final String roomName, final String roomName,
final String subject, final String subject,
@ -111,8 +111,8 @@ public class ProctoringGUIService {
return this.restService.getBuilder(SendJoinRemoteProctoringRoom.class) return this.restService.getBuilder(SendJoinRemoteProctoringRoom.class)
.withURIVariable(API.PARAM_MODEL_ID, examId) .withURIVariable(API.PARAM_MODEL_ID, examId)
.withFormParam(SEBProctoringConnection.ATTR_ROOM_NAME, roomName) .withFormParam(ProctoringRoomConnection.ATTR_ROOM_NAME, roomName)
.withFormParam(SEBProctoringConnection.ATTR_SUBJECT, subject) .withFormParam(ProctoringRoomConnection.ATTR_SUBJECT, subject)
.withFormParam(API.EXAM_API_SEB_CONNECTION_TOKEN, connectionToken) .withFormParam(API.EXAM_API_SEB_CONNECTION_TOKEN, connectionToken)
.call() .call()
.map(connection -> { .map(connection -> {
@ -122,13 +122,13 @@ public class ProctoringGUIService {
}); });
} }
public Result<SEBProctoringConnection> registerTownhallRoom( public Result<ProctoringRoomConnection> registerTownhallRoom(
final String examId, final String examId,
final String subject) { final String subject) {
return this.restService.getBuilder(ActivateTownhallRoom.class) return this.restService.getBuilder(ActivateTownhallRoom.class)
.withURIVariable(API.PARAM_MODEL_ID, examId) .withURIVariable(API.PARAM_MODEL_ID, examId)
.withFormParam(SEBProctoringConnection.ATTR_SUBJECT, subject) .withFormParam(ProctoringRoomConnection.ATTR_SUBJECT, subject)
.call() .call()
.map(connection -> { .map(connection -> {
this.rooms.put( this.rooms.put(
@ -139,7 +139,7 @@ public class ProctoringGUIService {
}); });
} }
public Result<SEBProctoringConnection> registerNewProcotringRoom( public Result<ProctoringRoomConnection> registerNewProcotringRoom(
final String examId, final String examId,
final String roomName, final String roomName,
final String subject, final String subject,
@ -147,8 +147,8 @@ public class ProctoringGUIService {
return this.restService.getBuilder(SendJoinRemoteProctoringRoom.class) return this.restService.getBuilder(SendJoinRemoteProctoringRoom.class)
.withURIVariable(API.PARAM_MODEL_ID, examId) .withURIVariable(API.PARAM_MODEL_ID, examId)
.withFormParam(SEBProctoringConnection.ATTR_ROOM_NAME, roomName) .withFormParam(ProctoringRoomConnection.ATTR_ROOM_NAME, roomName)
.withFormParam(SEBProctoringConnection.ATTR_SUBJECT, subject) .withFormParam(ProctoringRoomConnection.ATTR_SUBJECT, subject)
.withFormParam( .withFormParam(
API.EXAM_API_SEB_CONNECTION_TOKEN, API.EXAM_API_SEB_CONNECTION_TOKEN,
StringUtils.join(connectionTokens, Constants.LIST_SEPARATOR_CHAR)) StringUtils.join(connectionTokens, Constants.LIST_SEPARATOR_CHAR))
@ -172,7 +172,7 @@ public class ProctoringGUIService {
} }
this.restService.getBuilder(SendJoinRemoteProctoringRoom.class) this.restService.getBuilder(SendJoinRemoteProctoringRoom.class)
.withURIVariable(API.PARAM_MODEL_ID, examId) .withURIVariable(API.PARAM_MODEL_ID, examId)
.withFormParam(SEBProctoringConnection.ATTR_ROOM_NAME, room) .withFormParam(ProctoringRoomConnection.ATTR_ROOM_NAME, room)
.withFormParam( .withFormParam(
API.EXAM_API_SEB_CONNECTION_TOKEN, API.EXAM_API_SEB_CONNECTION_TOKEN,
StringUtils.join(connectionTokens, Constants.LIST_SEPARATOR_CHAR)) StringUtils.join(connectionTokens, Constants.LIST_SEPARATOR_CHAR))
@ -288,11 +288,11 @@ public class ProctoringGUIService {
public static class ProctoringWindowData { public static class ProctoringWindowData {
public final String examId; public final String examId;
public final SEBProctoringConnection connectionData; public final ProctoringRoomConnection connectionData;
protected ProctoringWindowData( protected ProctoringWindowData(
final String examId, final String examId,
final SEBProctoringConnection connectionData) { final ProctoringRoomConnection connectionData) {
this.examId = examId; this.examId = examId;
this.connectionData = connectionData; this.connectionData = connectionData;
} }

View file

@ -9,8 +9,8 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.exam; package ch.ethz.seb.sebserver.webservice.servicelayer.exam;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam; 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.ProctoringServiceSettings;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ProctoringServerType; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamProctoringService; import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamProctoringService;
@ -41,46 +41,48 @@ public interface ExamAdminService {
* @return Result refer to the restriction flag or to an error when happened */ * @return Result refer to the restriction flag or to an error when happened */
Result<Boolean> isRestricted(Exam exam); Result<Boolean> isRestricted(Exam exam);
/** Get ExamProctoring data for a certain exam to an error when happened. /** Get the proctoring service settings for a certain exam to an error when happened.
* *
* @param examId the exam instance * @param examId the exam instance
* @return Result refer to ExamProctoring data for the exam. */ * @return Result refer to proctoring service settings for the exam. */
default Result<ProctoringSettings> getExamProctoringSettings(final Exam exam) { default Result<ProctoringServiceSettings> getProctoringServiceSettings(final Exam exam) {
if (exam == null || exam.id == null) { if (exam == null || exam.id == null) {
return Result.ofRuntimeError("Invalid Exam model"); return Result.ofRuntimeError("Invalid Exam model");
} }
return getExamProctoringSettings(exam.id); return getProctoringServiceSettings(exam.id);
} }
/** Get ExamProctoring data for a certain exam to an error when happened. /** Get proctoring service settings for a certain exam to an error when happened.
* *
* @param examId the exam identifier * @param examId the exam identifier
* @return Result refer to ExamProctoring data for the exam. */ * @return Result refer to proctoring service settings for the exam. */
Result<ProctoringSettings> getExamProctoringSettings(Long examId); Result<ProctoringServiceSettings> getProctoringServiceSettings(Long examId);
/** Save the given ExamProctoring data for an existing Exam. /** Save the given proctoring service settings for an existing Exam.
* *
* @param examId the exam identifier * @param examId the exam identifier
* @param examProctoring The ExamProctoring data to save for the exam * @param examProctoring The proctoring service settings to save for the exam
* @return Result refer to saved ExamProctoring data or to an error when happened. */ * @return Result refer to saved proctoring service settings or to an error when happened. */
Result<ProctoringSettings> saveExamProctoringSettings(Long examId, ProctoringSettings examProctoring); Result<ProctoringServiceSettings> saveProctoringServiceSettings(
Long examId,
ProctoringServiceSettings examProctoring);
/** This indicates if proctoring is set and enabled for a certain exam. /** This indicates if proctoring is set and enabled for a certain exam.
* *
* @param examId the exam instance * @param examId the exam instance
* @return Result refer to proctoring is enabled flag or to an error when happened. */ * @return Result refer to proctoring is enabled flag or to an error when happened. */
default Result<Boolean> isExamProctoringEnabled(final Exam exam) { default Result<Boolean> isProctoringEnabled(final Exam exam) {
if (exam == null || exam.id == null) { if (exam == null || exam.id == null) {
return Result.ofRuntimeError("Invalid Exam model"); return Result.ofRuntimeError("Invalid Exam model");
} }
return isExamProctoringEnabled(exam.id); return isProctoringEnabled(exam.id);
} }
/** This indicates if proctoring is set and enabled for a certain exam. /** This indicates if proctoring is set and enabled for a certain exam.
* *
* @param examId the exam identifier * @param examId the exam identifier
* @return Result refer to proctoring is enabled flag or to an error when happened. */ * @return Result refer to proctoring is enabled flag or to an error when happened. */
Result<Boolean> isExamProctoringEnabled(final Long examId); Result<Boolean> isProctoringEnabled(final Long examId);
/** Get the exam proctoring service implementation of specified type. /** Get the exam proctoring service implementation of specified type.
* *
@ -92,18 +94,25 @@ public interface ExamAdminService {
* *
* @param settings the ProctoringSettings that defines the ProctoringServerType * @param settings the ProctoringSettings that defines the ProctoringServerType
* @return ExamProctoringService instance */ * @return ExamProctoringService instance */
default Result<ExamProctoringService> getExamProctoringService(final ProctoringSettings settings) { default Result<ExamProctoringService> getExamProctoringService(final ProctoringServiceSettings settings) {
return Result.tryCatch(() -> getExamProctoringService(settings.serverType).getOrThrow()); return Result.tryCatch(() -> getExamProctoringService(settings.serverType).getOrThrow());
} }
/** Get the exam proctoring service implementation for specified exam.
*
* @param exam the exam instance
* @return ExamProctoringService instance */
default Result<ExamProctoringService> getExamProctoringService(final Exam exam) { default Result<ExamProctoringService> getExamProctoringService(final Exam exam) {
return Result.tryCatch(() -> getExamProctoringService(exam.id).getOrThrow()); return Result.tryCatch(() -> getExamProctoringService(exam.id).getOrThrow());
} }
/** Get the exam proctoring service implementation for specified exam.
*
* @param examId the exam identifier
* @return ExamProctoringService instance */
default Result<ExamProctoringService> getExamProctoringService(final Long examId) { default Result<ExamProctoringService> getExamProctoringService(final Long examId) {
return getExamProctoringSettings(examId) return getProctoringServiceSettings(examId)
.flatMap(this::getExamProctoringService); .flatMap(this::getExamProctoringService);
} }
} }

View file

@ -31,8 +31,8 @@ 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.Indicator;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSEBRestriction; import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSEBRestriction;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ProctoringServerType; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; 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.LmsSetup;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
@ -186,64 +186,64 @@ public class ExamAdminServiceImpl implements ExamAdminService {
} }
@Override @Override
public Result<ProctoringSettings> getExamProctoringSettings(final Long examId) { public Result<ProctoringServiceSettings> getProctoringServiceSettings(final Long examId) {
return this.additionalAttributesDAO.getAdditionalAttributes(EntityType.EXAM, examId) return this.additionalAttributesDAO.getAdditionalAttributes(EntityType.EXAM, examId)
.map(attrs -> attrs.stream() .map(attrs -> attrs.stream()
.collect(Collectors.toMap( .collect(Collectors.toMap(
attr -> attr.getName(), attr -> attr.getName(),
Function.identity()))) Function.identity())))
.map(mapping -> { .map(mapping -> {
return new ProctoringSettings( return new ProctoringServiceSettings(
examId, examId,
getEnabled(mapping), getEnabled(mapping),
getServerType(mapping), getServerType(mapping),
getString(mapping, ProctoringSettings.ATTR_SERVER_URL), getString(mapping, ProctoringServiceSettings.ATTR_SERVER_URL),
getCollectingRoomSize(mapping), getCollectingRoomSize(mapping),
getString(mapping, ProctoringSettings.ATTR_APP_KEY), getString(mapping, ProctoringServiceSettings.ATTR_APP_KEY),
getString(mapping, ProctoringSettings.ATTR_APP_SECRET)); getString(mapping, ProctoringServiceSettings.ATTR_APP_SECRET));
}); });
} }
@Override @Override
@Transactional @Transactional
public Result<ProctoringSettings> saveExamProctoringSettings(final Long examId, public Result<ProctoringServiceSettings> saveProctoringServiceSettings(final Long examId,
final ProctoringSettings examProctoring) { final ProctoringServiceSettings examProctoring) {
return Result.tryCatch(() -> { return Result.tryCatch(() -> {
this.additionalAttributesDAO.saveAdditionalAttribute( this.additionalAttributesDAO.saveAdditionalAttribute(
EntityType.EXAM, EntityType.EXAM,
examId, examId,
ProctoringSettings.ATTR_ENABLE_PROCTORING, ProctoringServiceSettings.ATTR_ENABLE_PROCTORING,
String.valueOf(examProctoring.enableProctoring)); String.valueOf(examProctoring.enableProctoring));
this.additionalAttributesDAO.saveAdditionalAttribute( this.additionalAttributesDAO.saveAdditionalAttribute(
EntityType.EXAM, EntityType.EXAM,
examId, examId,
ProctoringSettings.ATTR_SERVER_TYPE, ProctoringServiceSettings.ATTR_SERVER_TYPE,
examProctoring.serverType.name()); examProctoring.serverType.name());
this.additionalAttributesDAO.saveAdditionalAttribute( this.additionalAttributesDAO.saveAdditionalAttribute(
EntityType.EXAM, EntityType.EXAM,
examId, examId,
ProctoringSettings.ATTR_SERVER_URL, ProctoringServiceSettings.ATTR_SERVER_URL,
examProctoring.serverURL); examProctoring.serverURL);
this.additionalAttributesDAO.saveAdditionalAttribute( this.additionalAttributesDAO.saveAdditionalAttribute(
EntityType.EXAM, EntityType.EXAM,
examId, examId,
ProctoringSettings.ATTR_COLLECTING_ROOM_SIZE, ProctoringServiceSettings.ATTR_COLLECTING_ROOM_SIZE,
String.valueOf(examProctoring.collectingRoomSize)); String.valueOf(examProctoring.collectingRoomSize));
this.additionalAttributesDAO.saveAdditionalAttribute( this.additionalAttributesDAO.saveAdditionalAttribute(
EntityType.EXAM, EntityType.EXAM,
examId, examId,
ProctoringSettings.ATTR_APP_KEY, ProctoringServiceSettings.ATTR_APP_KEY,
examProctoring.appKey); examProctoring.appKey);
this.additionalAttributesDAO.saveAdditionalAttribute( this.additionalAttributesDAO.saveAdditionalAttribute(
EntityType.EXAM, EntityType.EXAM,
examId, examId,
ProctoringSettings.ATTR_APP_SECRET, ProctoringServiceSettings.ATTR_APP_SECRET,
this.cryptor.encrypt(examProctoring.appSecret).toString()); this.cryptor.encrypt(examProctoring.appSecret).toString());
return examProctoring; return examProctoring;
@ -251,11 +251,11 @@ public class ExamAdminServiceImpl implements ExamAdminService {
} }
@Override @Override
public Result<Boolean> isExamProctoringEnabled(final Long examId) { public Result<Boolean> isProctoringEnabled(final Long examId) {
final Result<Boolean> result = this.additionalAttributesDAO.getAdditionalAttribute( final Result<Boolean> result = this.additionalAttributesDAO.getAdditionalAttribute(
EntityType.EXAM, EntityType.EXAM,
examId, examId,
ProctoringSettings.ATTR_ENABLE_PROCTORING) ProctoringServiceSettings.ATTR_ENABLE_PROCTORING)
.map(rec -> BooleanUtils.toBoolean(rec.getValue())); .map(rec -> BooleanUtils.toBoolean(rec.getValue()));
if (result.hasError()) { if (result.hasError()) {
return Result.of(false); return Result.of(false);
@ -270,16 +270,16 @@ public class ExamAdminServiceImpl implements ExamAdminService {
} }
private Boolean getEnabled(final Map<String, AdditionalAttributeRecord> mapping) { private Boolean getEnabled(final Map<String, AdditionalAttributeRecord> mapping) {
if (mapping.containsKey(ProctoringSettings.ATTR_ENABLE_PROCTORING)) { if (mapping.containsKey(ProctoringServiceSettings.ATTR_ENABLE_PROCTORING)) {
return BooleanUtils.toBoolean(mapping.get(ProctoringSettings.ATTR_ENABLE_PROCTORING).getValue()); return BooleanUtils.toBoolean(mapping.get(ProctoringServiceSettings.ATTR_ENABLE_PROCTORING).getValue());
} else { } else {
return false; return false;
} }
} }
private ProctoringServerType getServerType(final Map<String, AdditionalAttributeRecord> mapping) { private ProctoringServerType getServerType(final Map<String, AdditionalAttributeRecord> mapping) {
if (mapping.containsKey(ProctoringSettings.ATTR_SERVER_TYPE)) { if (mapping.containsKey(ProctoringServiceSettings.ATTR_SERVER_TYPE)) {
return ProctoringServerType.valueOf(mapping.get(ProctoringSettings.ATTR_SERVER_TYPE).getValue()); return ProctoringServerType.valueOf(mapping.get(ProctoringServiceSettings.ATTR_SERVER_TYPE).getValue());
} else { } else {
return ProctoringServerType.JITSI_MEET; return ProctoringServerType.JITSI_MEET;
} }
@ -294,8 +294,8 @@ public class ExamAdminServiceImpl implements ExamAdminService {
} }
private Integer getCollectingRoomSize(final Map<String, AdditionalAttributeRecord> mapping) { private Integer getCollectingRoomSize(final Map<String, AdditionalAttributeRecord> mapping) {
if (mapping.containsKey(ProctoringSettings.ATTR_COLLECTING_ROOM_SIZE)) { if (mapping.containsKey(ProctoringServiceSettings.ATTR_COLLECTING_ROOM_SIZE)) {
return Integer.valueOf(mapping.get(ProctoringSettings.ATTR_COLLECTING_ROOM_SIZE).getValue()); return Integer.valueOf(mapping.get(ProctoringServiceSettings.ATTR_COLLECTING_ROOM_SIZE).getValue());
} else { } else {
return 20; return 20;
} }

View file

@ -8,17 +8,14 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.session; package ch.ethz.seb.sebserver.webservice.servicelayer.session;
import java.util.Base64;
import java.util.Base64.Encoder;
import java.util.Collection; import java.util.Collection;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringRoomConnection;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ProctoringServerType; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Utils;
public interface ExamProctoringService { public interface ExamProctoringService {
@ -31,21 +28,50 @@ public interface ExamProctoringService {
* *
* @param examProctoring the settings to test * @param examProctoring the settings to test
* @return Result refer to true if the settings are correct and the proctoring server can be accessed. */ * @return Result refer to true if the settings are correct and the proctoring server can be accessed. */
Result<Boolean> testExamProctoring(final ProctoringSettings examProctoring); Result<Boolean> testExamProctoring(final ProctoringServiceSettings examProctoring);
Result<SEBProctoringConnection> getProctorRoomConnection( /** Gets the room connection data for a certain room for the proctor.
ProctoringSettings proctoringSettings, *
* @param proctoringSettings the proctoring service settings
* @param roomName the name of the room
* @param subject the subject of the room
* @return Result refer to the room connection data for the proctor to connect to specified room or to an error when
* happened */
Result<ProctoringRoomConnection> getProctorRoomConnection(
ProctoringServiceSettings proctoringSettings,
String roomName, String roomName,
String subject); String subject);
Result<SEBProctoringConnection> sendJoinRoomToClients( /** This instructs all sepcified SEB clients to join a defined room by creating a individual room access token
ProctoringSettings proctoringSettings, * and join instruction for each client and put this instruction to the clients instruction queue.
*
* @param proctoringSettings The proctoring service settings
* @param clientConnectionTokens A collection of SEB connection tokens. Only active SEB clients will get the
* instructions
* @param roomName The name of the room to join
* @param subject the subject of the room to join
* @return Result refer to the room connection data for the proctor to join to room too or to an error when
* happened */
Result<ProctoringRoomConnection> sendJoinRoomToClients(
ProctoringServiceSettings proctoringSettings,
Collection<String> clientConnectionTokens, Collection<String> clientConnectionTokens,
String roomName, String roomName,
String subject); String subject);
/** Sends instructions to join or rejoin the individual assigned collecting rooms of each involved SEB client.
* Creates an individual join instruction for each involved client and put that to the clients instruction queue.
*
* INFO:
* A collecting room is assigned to each SEB client connection while connecting to the SEB server and
* each SEB client that has successfully connected to the SEB Server and is participating in an exam
* with proctoring enabled, is assigned to a collecting room.
*
* @param proctoringSettings he proctoring service settings
* @param clientConnectionTokens A collection of SEB connection tokens. Only active SEB clients will get the
* instructions
* @return Empty Result that refers to an error when happened */
Result<Void> sendJoinCollectingRoomToClients( Result<Void> sendJoinCollectingRoomToClients(
ProctoringSettings proctoringSettings, ProctoringServiceSettings proctoringSettings,
Collection<String> clientConnectionTokens); Collection<String> clientConnectionTokens);
default String verifyRoomName(final String requestedRoomName, final String connectionToken) { default String verifyRoomName(final String requestedRoomName, final String connectionToken) {
@ -53,49 +79,7 @@ public interface ExamProctoringService {
return requestedRoomName; return requestedRoomName;
} }
final Encoder urlEncoder = Base64.getUrlEncoder().withoutPadding(); throw new RuntimeException("Test Why: " + connectionToken);
return urlEncoder.encodeToString(
Utils.toByteArray(connectionToken));
} }
// /** Used to get the proctor's room connection data.
// *
// * @param proctoringSettings the proctoring settings
// * @param roomName the name of the room
// * @param subject name of the room
// * @return SEBProctoringConnectionData that contains all connection data */
// Result<SEBProctoringConnection> createProctorPublicRoomConnection(
// final ProctoringSettings proctoringSettings,
// final String roomName,
// final String subject);
//
// Result<SEBProctoringConnection> getClientExamCollectingRoomConnection(
// final ProctoringSettings proctoringSettings,
// final ClientConnection connection);
//
// Result<SEBProctoringConnection> getClientExamCollectingRoomConnection(
// final ProctoringSettings proctoringSettings,
// final String connectionToken,
// final String roomName,
// final String subject);
//
// Result<SEBProctoringConnection> getClientRoomConnection(
// final ProctoringSettings examProctoring,
// final String connectionToken,
// final String roomName,
// final String subject);
//
// Result<SEBProctoringConnection> createProctoringConnection(
// final ProctoringServerType proctoringServerType,
// final String connectionToken,
// final String url,
// final String appKey,
// final CharSequence appSecret,
// final String clientName,
// final String clientKey,
// final String roomName,
// final String subject,
// final Long expTime,
// final boolean moderator);
} }

View file

@ -29,9 +29,9 @@ import org.springframework.web.util.UriComponentsBuilder;
import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam; 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.ProctoringServiceSettings;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ProctoringServerType; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringRoomConnection;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction; 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.ClientInstruction.InstructionType;
@ -84,14 +84,14 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
} }
@Override @Override
public Result<Boolean> testExamProctoring(final ProctoringSettings examProctoring) { public Result<Boolean> testExamProctoring(final ProctoringServiceSettings examProctoring) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return null;
} }
@Override @Override
public Result<SEBProctoringConnection> getProctorRoomConnection( public Result<ProctoringRoomConnection> getProctorRoomConnection(
final ProctoringSettings proctoringSettings, final ProctoringServiceSettings proctoringSettings,
final String roomName, final String roomName,
final String subject) { final String subject) {
@ -102,8 +102,8 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
} }
@Override @Override
public Result<SEBProctoringConnection> sendJoinRoomToClients( public Result<ProctoringRoomConnection> sendJoinRoomToClients(
final ProctoringSettings proctoringSettings, final ProctoringServiceSettings proctoringSettings,
final Collection<String> clientConnectionTokens, final Collection<String> clientConnectionTokens,
final String roomName, final String roomName,
final String subject) { final String subject) {
@ -112,7 +112,7 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
clientConnectionTokens clientConnectionTokens
.stream() .stream()
.forEach(connectionToken -> { .forEach(connectionToken -> {
final SEBProctoringConnection proctoringConnection = final ProctoringRoomConnection proctoringConnection =
getClientRoomConnection( getClientRoomConnection(
proctoringSettings, proctoringSettings,
connectionToken, connectionToken,
@ -141,7 +141,7 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
@Override @Override
public Result<Void> sendJoinCollectingRoomToClients( public Result<Void> sendJoinCollectingRoomToClients(
final ProctoringSettings proctoringSettings, final ProctoringServiceSettings proctoringSettings,
final Collection<String> clientConnectionTokens) { final Collection<String> clientConnectionTokens) {
return Result.tryCatch(() -> { return Result.tryCatch(() -> {
@ -155,7 +155,7 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
.getRoomName(clientConnection.clientConnection.getRemoteProctoringRoomId()) .getRoomName(clientConnection.clientConnection.getRemoteProctoringRoomId())
.getOrThrow(); .getOrThrow();
final SEBProctoringConnection proctoringConnection = getClientExamCollectingRoomConnection( final ProctoringRoomConnection proctoringConnection = getClientExamCollectingRoomConnection(
proctoringSettings, proctoringSettings,
clientConnection.clientConnection.connectionToken, clientConnection.clientConnection.connectionToken,
roomName, roomName,
@ -173,13 +173,13 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
private void sendJoinInstruction( private void sendJoinInstruction(
final Long examId, final Long examId,
final String connectionToken, final String connectionToken,
final SEBProctoringConnection proctoringConnection) { final ProctoringRoomConnection proctoringConnection) {
final Map<String, String> attributes = new HashMap<>(); final Map<String, String> attributes = new HashMap<>();
attributes.put( attributes.put(
ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_PROCTORING.SERVICE_TYPE, ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_PROCTORING.SERVICE_TYPE,
ProctoringSettings.ProctoringServerType.JITSI_MEET.name()); ProctoringServiceSettings.ProctoringServerType.JITSI_MEET.name());
attributes.put( attributes.put(
ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_PROCTORING.METHOD, ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_PROCTORING.METHOD,
ClientInstruction.ProctoringInstructionMethod.JOIN.name()); ClientInstruction.ProctoringInstructionMethod.JOIN.name());
@ -207,8 +207,8 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
.onError(error -> log.error("Failed to send join instruction: {}", connectionToken, error)); .onError(error -> log.error("Failed to send join instruction: {}", connectionToken, error));
} }
private Result<SEBProctoringConnection> createProctorPublicRoomConnection( private Result<ProctoringRoomConnection> createProctorPublicRoomConnection(
final ProctoringSettings proctoringSettings, final ProctoringServiceSettings proctoringSettings,
final String roomName, final String roomName,
final String subject) { final String subject) {
@ -229,8 +229,8 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
}); });
} }
private Result<SEBProctoringConnection> getClientExamCollectingRoomConnection( private Result<ProctoringRoomConnection> getClientExamCollectingRoomConnection(
final ProctoringSettings proctoringSettings, final ProctoringServiceSettings proctoringSettings,
final String connectionToken, final String connectionToken,
final String roomName, final String roomName,
final String subject) { final String subject) {
@ -256,8 +256,8 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
}); });
} }
private Result<SEBProctoringConnection> getClientRoomConnection( private Result<ProctoringRoomConnection> getClientRoomConnection(
final ProctoringSettings proctoringSettings, final ProctoringServiceSettings proctoringSettings,
final String connectionToken, final String connectionToken,
final String roomName, final String roomName,
final String subject) { final String subject) {
@ -286,7 +286,7 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
} }
protected Result<SEBProctoringConnection> createProctoringConnection( protected Result<ProctoringRoomConnection> createProctoringConnection(
final ProctoringServerType proctoringServerType, final ProctoringServerType proctoringServerType,
final String connectionToken, final String connectionToken,
final String url, final String url,
@ -316,7 +316,7 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
host, host,
moderator); moderator);
return new SEBProctoringConnection( return new ProctoringRoomConnection(
proctoringServerType, proctoringServerType,
connectionToken, connectionToken,
host, host,
@ -385,7 +385,7 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
return jwtPayload; return jwtPayload;
} }
private long forExam(final ProctoringSettings examProctoring) { private long forExam(final ProctoringServiceSettings examProctoring) {
if (examProctoring.examId == null) { if (examProctoring.examId == null) {
throw new IllegalStateException("Missing exam identifier from ExamProctoring data"); throw new IllegalStateException("Missing exam identifier from ExamProctoring data");
} }

View file

@ -17,7 +17,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
import ch.ethz.seb.sebserver.gbl.model.session.RemoteProctoringRoom; import ch.ethz.seb.sebserver.gbl.model.session.RemoteProctoringRoom;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
@ -71,11 +71,13 @@ public class ExamProctoringRoomServiceImpl implements ExamProctoringRoomService
@Override @Override
public void updateProctoringCollectingRooms() { public void updateProctoringCollectingRooms() {
try { try {
// Applying to collecting room
this.clientConnectionDAO.getAllConnectionIdsForRoomUpdateActive() this.clientConnectionDAO.getAllConnectionIdsForRoomUpdateActive()
.getOrThrow() .getOrThrow()
.stream() .stream()
.forEach(this::assignToCollectingRoom); .forEach(this::assignToCollectingRoom);
// Dispose form collecting room
this.clientConnectionDAO.getAllConnectionIdsForRoomUpdateInactive() this.clientConnectionDAO.getAllConnectionIdsForRoomUpdateInactive()
.getOrThrow() .getOrThrow()
.stream() .stream()
@ -156,8 +158,8 @@ public class ExamProctoringRoomServiceImpl implements ExamProctoringRoomService
private RemoteProctoringRoom getProctoringRoom(final Long examId, final String connectionToken) { private RemoteProctoringRoom getProctoringRoom(final Long examId, final String connectionToken) {
try { try {
final ProctoringSettings proctoringSettings = this.examAdminService final ProctoringServiceSettings proctoringSettings = this.examAdminService
.getExamProctoringSettings(examId) .getProctoringServiceSettings(examId)
.getOrThrow(); .getOrThrow();
return this.remoteProctoringRoomDAO.reservePlaceInCollectingRoom( return this.remoteProctoringRoomDAO.reservePlaceInCollectingRoom(
examId, examId,
@ -181,7 +183,7 @@ public class ExamProctoringRoomServiceImpl implements ExamProctoringRoomService
final String subject) { final String subject) {
return this.examAdminService return this.examAdminService
.getExamProctoringSettings(examId) .getProctoringServiceSettings(examId)
.flatMap(proctoringSettings -> this.examAdminService .flatMap(proctoringSettings -> this.examAdminService
.getExamProctoringService(proctoringSettings.serverType) .getExamProctoringService(proctoringSettings.serverType)
.getOrThrow() .getOrThrow()

View file

@ -16,7 +16,7 @@ import java.util.stream.Collectors;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ProctoringServerType; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamProctoringService; import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamProctoringService;

View file

@ -307,7 +307,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
} }
final Boolean proctoringEnabled = this.examAdminService final Boolean proctoringEnabled = this.examAdminService
.isExamProctoringEnabled(clientConnection.examId) .isProctoringEnabled(clientConnection.examId)
.getOr(false); .getOr(false);
final Long currentExamId = (examId != null) ? examId : clientConnection.examId; final Long currentExamId = (examId != null) ? examId : clientConnection.examId;
final String currentVdiConnectionId = (clientId != null) final String currentVdiConnectionId = (clientId != null)
@ -714,7 +714,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
private ClientConnection saveInState(final ClientConnection clientConnection, final ConnectionStatus status) { private ClientConnection saveInState(final ClientConnection clientConnection, final ConnectionStatus status) {
final Boolean proctoringEnabled = this.examAdminService final Boolean proctoringEnabled = this.examAdminService
.isExamProctoringEnabled(clientConnection.examId) .isProctoringEnabled(clientConnection.examId)
.getOr(false); .getOr(false);
return this.clientConnectionDAO.save(new ClientConnection( return this.clientConnectionDAO.save(new ClientConnection(

View file

@ -13,13 +13,13 @@ import javax.validation.ConstraintValidatorContext;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ProctoringServerType; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
public class ProctoringSettingsValidator implements ConstraintValidator<ValidProctoringSettings, ProctoringSettings> { public class ProctoringSettingsValidator implements ConstraintValidator<ValidProctoringSettings, ProctoringServiceSettings> {
@Override @Override
public boolean isValid(final ProctoringSettings value, final ConstraintValidatorContext context) { public boolean isValid(final ProctoringServiceSettings value, final ConstraintValidatorContext context) {
if (value == null) { if (value == null) {
return false; return false;
} }

View file

@ -50,7 +50,7 @@ import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.model.PageSortOrder; import ch.ethz.seb.sebserver.gbl.model.PageSortOrder;
import ch.ethz.seb.sebserver.gbl.model.exam.Chapters; import ch.ethz.seb.sebserver.gbl.model.exam.Chapters;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam; 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.ProctoringServiceSettings;
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
import ch.ethz.seb.sebserver.gbl.model.exam.SEBRestriction; import ch.ethz.seb.sebserver.gbl.model.exam.SEBRestriction;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
@ -386,7 +386,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
+ API.EXAM_ADMINISTRATION_PROCTORING_PATH_SEGMENT, + API.EXAM_ADMINISTRATION_PROCTORING_PATH_SEGMENT,
method = RequestMethod.GET, method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE) produces = MediaType.APPLICATION_JSON_VALUE)
public ProctoringSettings getExamProctoring( public ProctoringServiceSettings getProctoringServiceSettings(
@RequestParam( @RequestParam(
name = API.PARAM_INSTITUTION_ID, name = API.PARAM_INSTITUTION_ID,
required = true, required = true,
@ -396,7 +396,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
checkReadPrivilege(institutionId); checkReadPrivilege(institutionId);
return this.entityDAO.byPK(modelId) return this.entityDAO.byPK(modelId)
.flatMap(this.authorization::checkRead) .flatMap(this.authorization::checkRead)
.flatMap(this.examAdminService::getExamProctoringSettings) .flatMap(this.examAdminService::getProctoringServiceSettings)
.getOrThrow(); .getOrThrow();
} }
@ -405,19 +405,19 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
+ API.EXAM_ADMINISTRATION_PROCTORING_PATH_SEGMENT, + API.EXAM_ADMINISTRATION_PROCTORING_PATH_SEGMENT,
method = RequestMethod.POST, method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE) produces = MediaType.APPLICATION_JSON_VALUE)
public Exam saveExamProctoring( public Exam saveProctoringServiceSettings(
@RequestParam( @RequestParam(
name = API.PARAM_INSTITUTION_ID, name = API.PARAM_INSTITUTION_ID,
required = true, required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId, defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@PathVariable(API.PARAM_MODEL_ID) final Long examId, @PathVariable(API.PARAM_MODEL_ID) final Long examId,
@Valid @RequestBody final ProctoringSettings examProctoring) { @Valid @RequestBody final ProctoringServiceSettings examProctoring) {
checkModifyPrivilege(institutionId); checkModifyPrivilege(institutionId);
return this.entityDAO.byPK(examId) return this.entityDAO.byPK(examId)
.flatMap(this.authorization::checkModify) .flatMap(this.authorization::checkModify)
.map(exam -> { .map(exam -> {
this.examAdminService.saveExamProctoringSettings(examId, examProctoring); this.examAdminService.saveProctoringServiceSettings(examId, examProctoring);
return exam; return exam;
}) })
.flatMap(this.userActivityLogDAO::logModify) .flatMap(this.userActivityLogDAO::logModify)

View file

@ -30,8 +30,8 @@ import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType; import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
import ch.ethz.seb.sebserver.gbl.model.Domain; 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.ProctoringServiceSettings;
import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringRoomConnection;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; 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;
import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction.InstructionType; import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction.InstructionType;
@ -90,7 +90,7 @@ public class ExamProctoringController {
method = RequestMethod.GET, method = RequestMethod.GET,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE) produces = MediaType.APPLICATION_JSON_VALUE)
public Collection<RemoteProctoringRoom> getProcotringCollectingRoomsOfExam( public Collection<RemoteProctoringRoom> getCollectingRoomsOfExam(
@RequestParam( @RequestParam(
name = API.PARAM_INSTITUTION_ID, name = API.PARAM_INSTITUTION_ID,
required = true, required = true,
@ -108,14 +108,14 @@ public class ExamProctoringController {
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE) produces = MediaType.APPLICATION_JSON_VALUE)
public SEBProctoringConnection getProctorRoomConnection( public ProctoringRoomConnection getProctorRoomConnection(
@RequestParam( @RequestParam(
name = API.PARAM_INSTITUTION_ID, name = API.PARAM_INSTITUTION_ID,
required = true, required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId, defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@PathVariable(name = API.PARAM_MODEL_ID) final Long examId, @PathVariable(name = API.PARAM_MODEL_ID) final Long examId,
@RequestParam(name = SEBProctoringConnection.ATTR_ROOM_NAME, required = true) final String roomName, @RequestParam(name = ProctoringRoomConnection.ATTR_ROOM_NAME, required = true) final String roomName,
@RequestParam(name = SEBProctoringConnection.ATTR_SUBJECT, required = false) final String subject) { @RequestParam(name = ProctoringRoomConnection.ATTR_SUBJECT, required = false) final String subject) {
checkAccess(institutionId, examId); checkAccess(institutionId, examId);
@ -123,7 +123,7 @@ public class ExamProctoringController {
.flatMap(this.authorization::checkRead) .flatMap(this.authorization::checkRead)
.flatMap(this.examAdminService::getExamProctoringService) .flatMap(this.examAdminService::getExamProctoringService)
.flatMap(service -> service.getProctorRoomConnection( .flatMap(service -> service.getProctorRoomConnection(
this.examAdminService.getExamProctoringSettings(examId).getOrThrow(), this.examAdminService.getProctoringServiceSettings(examId).getOrThrow(),
roomName, roomName,
StringUtils.isNoneBlank(subject) ? subject : roomName)) StringUtils.isNoneBlank(subject) ? subject : roomName))
.getOrThrow(); .getOrThrow();
@ -135,7 +135,7 @@ public class ExamProctoringController {
method = RequestMethod.GET, method = RequestMethod.GET,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE) produces = MediaType.APPLICATION_JSON_VALUE)
public Collection<ClientConnection> getProctorRoomConnectionData( public Collection<ClientConnection> getAllClientConnectionsInRoom(
@RequestParam( @RequestParam(
name = API.PARAM_INSTITUTION_ID, name = API.PARAM_INSTITUTION_ID,
required = true, required = true,
@ -147,7 +147,8 @@ public class ExamProctoringController {
checkAccess(institutionId, examId); checkAccess(institutionId, examId);
return this.examProcotringRoomService.getRoomConnections(examId, roomName) return this.examProcotringRoomService
.getRoomConnections(examId, roomName)
.getOrThrow(); .getOrThrow();
} }
@ -215,9 +216,9 @@ public class ExamProctoringController {
checkAccess(institutionId, examId); checkAccess(institutionId, examId);
final ProctoringSettings proctoringSettings = this.examSessionService final ProctoringServiceSettings proctoringSettings = this.examSessionService
.getRunningExam(examId) .getRunningExam(examId)
.flatMap(this.examAdminService::getExamProctoringSettings) .flatMap(this.examAdminService::getProctoringServiceSettings)
.getOrThrow(); .getOrThrow();
this.examAdminService this.examAdminService
@ -235,17 +236,17 @@ public class ExamProctoringController {
+ API.EXAM_PROCTORING_JOIN_ROOM_PATH_SEGMENT, + API.EXAM_PROCTORING_JOIN_ROOM_PATH_SEGMENT,
method = RequestMethod.POST, method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE) produces = MediaType.APPLICATION_JSON_VALUE)
public SEBProctoringConnection sendJoinProctoringRoomToClients( public ProctoringRoomConnection sendJoinProctoringRoomToClients(
@RequestParam( @RequestParam(
name = API.PARAM_INSTITUTION_ID, name = API.PARAM_INSTITUTION_ID,
required = true, required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId, defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@PathVariable(name = API.PARAM_MODEL_ID) final Long examId, @PathVariable(name = API.PARAM_MODEL_ID) final Long examId,
@RequestParam( @RequestParam(
name = SEBProctoringConnection.ATTR_ROOM_NAME, name = ProctoringRoomConnection.ATTR_ROOM_NAME,
required = true) final String roomName, required = true) final String roomName,
@RequestParam( @RequestParam(
name = SEBProctoringConnection.ATTR_SUBJECT, name = ProctoringRoomConnection.ATTR_SUBJECT,
required = false) final String subject, required = false) final String subject,
@RequestParam( @RequestParam(
name = API.EXAM_API_SEB_CONNECTION_TOKEN, name = API.EXAM_API_SEB_CONNECTION_TOKEN,
@ -253,9 +254,9 @@ public class ExamProctoringController {
checkAccess(institutionId, examId); checkAccess(institutionId, examId);
final ProctoringSettings settings = this.examSessionService final ProctoringServiceSettings settings = this.examSessionService
.getRunningExam(examId) .getRunningExam(examId)
.flatMap(this.examAdminService::getExamProctoringSettings) .flatMap(this.examAdminService::getProctoringServiceSettings)
.getOrThrow(); .getOrThrow();
return this.examAdminService return this.examAdminService
@ -275,7 +276,7 @@ public class ExamProctoringController {
+ API.EXAM_PROCTORING_TOWNHALL_ROOM_DATA, + API.EXAM_PROCTORING_TOWNHALL_ROOM_DATA,
method = RequestMethod.GET, method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE) produces = MediaType.APPLICATION_JSON_VALUE)
public RemoteProctoringRoom getTownhallRoomData( public RemoteProctoringRoom getTownhallRoom(
@RequestParam( @RequestParam(
name = API.PARAM_INSTITUTION_ID, name = API.PARAM_INSTITUTION_ID,
required = true, required = true,
@ -293,21 +294,21 @@ public class ExamProctoringController {
+ API.EXAM_PROCTORING_ACTIVATE_TOWNHALL_ROOM, + API.EXAM_PROCTORING_ACTIVATE_TOWNHALL_ROOM,
method = RequestMethod.POST, method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE) produces = MediaType.APPLICATION_JSON_VALUE)
public SEBProctoringConnection activateTownhall( public ProctoringRoomConnection activateTownhall(
@RequestParam( @RequestParam(
name = API.PARAM_INSTITUTION_ID, name = API.PARAM_INSTITUTION_ID,
required = true, required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId, defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@PathVariable(name = API.PARAM_MODEL_ID) final Long examId, @PathVariable(name = API.PARAM_MODEL_ID) final Long examId,
@RequestParam( @RequestParam(
name = SEBProctoringConnection.ATTR_SUBJECT, name = ProctoringRoomConnection.ATTR_SUBJECT,
required = false) final String subject) { required = false) final String subject) {
checkAccess(institutionId, examId); checkAccess(institutionId, examId);
final ProctoringSettings settings = this.examSessionService final ProctoringServiceSettings settings = this.examSessionService
.getRunningExam(examId) .getRunningExam(examId)
.flatMap(this.examAdminService::getExamProctoringSettings) .flatMap(this.examAdminService::getProctoringServiceSettings)
.getOrThrow(); .getOrThrow();
// First create and get the town-hall room for specified exam // First create and get the town-hall room for specified exam
@ -345,9 +346,9 @@ public class ExamProctoringController {
checkAccess(institutionId, examId); checkAccess(institutionId, examId);
final ProctoringSettings settings = this.examSessionService final ProctoringServiceSettings settings = this.examSessionService
.getRunningExam(examId) .getRunningExam(examId)
.flatMap(this.examAdminService::getExamProctoringSettings) .flatMap(this.examAdminService::getProctoringServiceSettings)
.getOrThrow(); .getOrThrow();
final ExamProctoringService examProctoringService = this.examAdminService final ExamProctoringService examProctoringService = this.examAdminService

View file

@ -0,0 +1,75 @@
/*
* 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.integration.api.admin;
import static org.junit.Assert.*;
import java.util.Collection;
import org.junit.Test;
import org.junit.jupiter.api.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.jdbc.Sql;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO;
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.ExamSessionService;
@Sql(scripts = { "classpath:schema-test.sql", "classpath:data-test.sql", "classpath:data-test-additional.sql" })
public class ExamProctoringRoomServiceTest extends AdministrationAPIIntegrationTester {
private static final String CONNECTION_TOKEN_1 = "connection_token1";
private static final String CONNECTION_TOKEN_2 = "connection_token2";
@Autowired
private ExamProctoringRoomService examProctoringRoomService;
@Autowired
private ExamSessionService examSessionService;
@Autowired
private ExamAdminService examAdminService;
@Autowired
private ClientConnectionDAO clientConnectionDAO;
@Test
@Order(1)
public void test01_checkExamRunning() {
final Result<Collection<Exam>> runningExamsForInstitution =
this.examSessionService.getRunningExamsForInstitution(1L);
assertFalse(runningExamsForInstitution.hasError());
final Collection<Exam> collection = runningExamsForInstitution.get();
assertFalse(collection.isEmpty());
final Exam exam = collection.iterator().next();
assertEquals("Demo Quiz 6 (MOCKUP)", exam.name);
assertEquals("2", String.valueOf(exam.id));
}
@Test
@Order(2)
public void test02_setProctoringServiceSettings() {
this.examAdminService.saveProctoringServiceSettings(
2L,
new ProctoringServiceSettings(
2L, true, ProctoringServerType.JITSI_MEET, "http://jitsi.ch", 1,
"app-key", "app.secret"));
assertTrue(this.examAdminService.isProctoringEnabled(2L).get());
}
// @Test
// @Order(3)
// public void test03_addClientConnection() {
// clientConnectionDAO.createNew(new ClientConnection(null, 1L, 2L, ConnectionStatus.CONNECTION_REQUESTED, CONNECTION_TOKEN_1))
// }
}

View file

@ -17,8 +17,8 @@ import java.security.NoSuchAlgorithmException;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ProctoringServerType; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
import ch.ethz.seb.sebserver.gbl.model.exam.SEBProctoringConnection; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringRoomConnection;
import ch.ethz.seb.sebserver.gbl.util.Cryptor; import ch.ethz.seb.sebserver.gbl.util.Cryptor;
public class ExamJITSIProctoringServiceTest { public class ExamJITSIProctoringServiceTest {
@ -63,7 +63,7 @@ public class ExamJITSIProctoringServiceTest {
Mockito.when(cryptorMock.decrypt(Mockito.any())).thenReturn("fbvgeghergrgrthrehreg123"); Mockito.when(cryptorMock.decrypt(Mockito.any())).thenReturn("fbvgeghergrgrthrehreg123");
final ExamJITSIProctoringService examJITSIProctoringService = final ExamJITSIProctoringService examJITSIProctoringService =
new ExamJITSIProctoringService(null, null, null, null, cryptorMock); new ExamJITSIProctoringService(null, null, null, null, cryptorMock);
final SEBProctoringConnection data = examJITSIProctoringService.createProctoringConnection( final ProctoringRoomConnection data = examJITSIProctoringService.createProctoringConnection(
ProctoringServerType.JITSI_MEET, ProctoringServerType.JITSI_MEET,
"connectionToken", "connectionToken",
"https://seb-jitsi.example.ch", "https://seb-jitsi.example.ch",