From c26f8da944017eb0716340fe4029d9e82c3358a8 Mon Sep 17 00:00:00 2001 From: anhefti Date: Wed, 8 Feb 2023 13:15:17 +0100 Subject: [PATCH] SEBSERV-382 --- .../gbl/model/exam/AllowedSEBVersion.java | 2 +- .../content/exam/ProctoringSettingsPopup.java | 68 ++++++++----------- .../session/ClientConnectionDetails.java | 7 ++ .../proctoring/ZoomProctoringService.java | 4 +- .../ProctoringSettingsValidator.java | 24 +++++++ .../api/ExamAdministrationController.java | 3 +- src/main/resources/messages.properties | 10 +-- 7 files changed, 70 insertions(+), 48 deletions(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/AllowedSEBVersion.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/AllowedSEBVersion.java index 3e640ce1..2b2cd8f6 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/AllowedSEBVersion.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/AllowedSEBVersion.java @@ -61,7 +61,7 @@ public class AllowedSEBVersion { valid = false; } this.minor = num; - if (split.length >= 3) { + if (split.length > 3) { try { num = Integer.valueOf(split[3]); } catch (final Exception e) { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ProctoringSettingsPopup.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ProctoringSettingsPopup.java index 36b92781..9b947755 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ProctoringSettingsPopup.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ProctoringSettingsPopup.java @@ -83,11 +83,6 @@ public class ProctoringSettingsPopup { private final static LocTextKey SEB_PROCTORING_FORM_SECRET_JITSI = new LocTextKey("sebserver.exam.proctoring.form.secret.jitsi"); - private final static LocTextKey SEB_PROCTORING_FORM_APPKEY_ZOOM = - new LocTextKey("sebserver.exam.proctoring.form.appkey.zoom"); - private final static LocTextKey SEB_PROCTORING_FORM_SECRET_ZOOM = - new LocTextKey("sebserver.exam.proctoring.form.secret.zoom"); - private final static LocTextKey SEB_PROCTORING_FORM_ACCOUNT_ID = new LocTextKey("sebserver.exam.proctoring.form.accountId"); private final static LocTextKey SEB_PROCTORING_FORM_CLIENT_ID = @@ -113,6 +108,8 @@ public class ProctoringSettingsPopup { new LocTextKey("sebserver.exam.proctoring.form.resetConfirm"); private final static LocTextKey RESET_ACTIVE_CON_KEY = new LocTextKey("sebserver.exam.proctoring.form.resetActive"); + private final static LocTextKey RESET_SUCCESS_KEY = + new LocTextKey("sebserver.exam.proctoring.form.resetOk"); Function settingsFunction(final PageService pageService, final boolean modifyGrant) { @@ -144,16 +141,19 @@ public class ProctoringSettingsPopup { } }); - final Button reset = widgetFactory.buttonLocalized(composite, RESET_TEXT_KEY); - reset.setLayoutData(new RowData()); - reset.addListener(SWT.Selection, event -> { - pageContext.applyConfirmDialog(RESET_CONFIRM_KEY, apply -> { - if (apply && doResetSettings(pageService, pageContext)) { - dialog.close(); - } + final EntityKey entityKey = pageContext.getEntityKey(); + if (entityKey.entityType == EntityType.EXAM) { + final Button reset = widgetFactory.buttonLocalized(composite, RESET_TEXT_KEY); + reset.setLayoutData(new RowData()); + reset.addListener(SWT.Selection, event -> { + pageContext.applyConfirmDialog(RESET_CONFIRM_KEY, apply -> { + if (apply && doResetSettings(pageService, pageContext)) { + dialog.close(); + } + }); }); - }); - resetButtonHandler.set(reset); + resetButtonHandler.set(reset); + } }; final SEBProctoringPropertiesForm bindFormContext = new SEBProctoringPropertiesForm( @@ -208,16 +208,10 @@ public class ProctoringSettingsPopup { .getBuilder(ResetProctoringSettings.class) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .call() - .onError(error -> { - if (error.getMessage().contains("active connections") || - (error.getCause() != null && - error.getCause().getMessage().contains("active connections"))) { - pageContext.publishInfo(RESET_ACTIVE_CON_KEY); - } else { - log.error("Failed to rest proctoring settings for exam: {}", entityKey, error); - pageContext.notifyUnexpectedError(error); - } - }).map(settings -> true).getOr(false); + .onError(error -> handleResetError(pageContext, entityKey, error)) + .onSuccess(settings -> pageContext.publishInfo(RESET_SUCCESS_KEY)) + .map(settings -> true) + .getOr(false); } private boolean doSaveSettings( @@ -451,19 +445,6 @@ public class ProctoringSettingsPopup { proctoringSettings.serverURL) .mandatory()) - .addField(FormBuilder.text( - ProctoringServiceSettings.ATTR_APP_KEY, - SEB_PROCTORING_FORM_APPKEY_ZOOM, - proctoringSettings.appKey)) - .withEmptyCellSeparation(false) - - .addField(FormBuilder.password( - ProctoringServiceSettings.ATTR_APP_SECRET, - SEB_PROCTORING_FORM_SECRET_ZOOM, - (proctoringSettings.appSecret != null) - ? String.valueOf(proctoringSettings.appSecret) - : null)) - .addField(FormBuilder.text( ProctoringServiceSettings.ATTR_ACCOUNT_ID, SEB_PROCTORING_FORM_ACCOUNT_ID, @@ -559,11 +540,20 @@ public class ProctoringSettingsPopup { } } - private static final class FormHandleAnchor { + private void handleResetError(final PageContext pageContext, final EntityKey entityKey, final Exception error) { + if (error.getMessage().contains("active connections") || + (error.getCause() != null && + error.getCause().getMessage().contains("active connections"))) { + pageContext.publishInfo(RESET_ACTIVE_CON_KEY); + } else { + log.error("Failed to rest proctoring settings for exam: {}", entityKey, error); + pageContext.notifyUnexpectedError(error); + } + } + private static final class FormHandleAnchor { FormHandle formHandle; PageContext formContext; - } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ClientConnectionDetails.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ClientConnectionDetails.java index 1caeaad9..5e314356 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ClientConnectionDetails.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ClientConnectionDetails.java @@ -63,6 +63,8 @@ public class ClientConnectionDetails implements MonitoringEntry { new LocTextKey("sebserver.monitoring.connection.form.info"); private final static LocTextKey CONNECTION_STATUS_TEXT_KEY = new LocTextKey("sebserver.monitoring.connection.form.status"); + private final static LocTextKey WRONG_SEB_CLIENT_TOOLTIP = + new LocTextKey("sebserver.finished.connection.form.info.wrong.client.tooltip"); private static final int NUMBER_OF_NONE_INDICATOR_ROWS = 3; @@ -130,12 +132,15 @@ public class ClientConnectionDetails implements MonitoringEntry { CONNECTION_GROUP_TEXT_KEY, Constants.EMPTY_NOTE) .asMarkupLabel()) + .withDefaultSpanInput(3) + .addField(FormBuilder.text( ClientConnection.ATTR_INFO, CONNECTION_INFO_TEXT_KEY, Constants.EMPTY_NOTE) .asArea(50) .asColorBox()) + .withDefaultSpanEmptyCell(2) .withDefaultSpanInput(3) .addField(FormBuilder.text( Domain.CLIENT_CONNECTION.ATTR_STATUS, @@ -322,6 +327,8 @@ public class ClientConnectionDetails implements MonitoringEntry { if (this.connectionData.clientConnection.clientVersionGranted != null && !this.connectionData.clientConnection.clientVersionGranted) { form.setFieldColor(ClientConnection.ATTR_INFO, this.colorData.color2); + form.getFieldInput(ClientConnection.ATTR_INFO) + .setToolTipText(this.pageService.getI18nSupport().getText(WRONG_SEB_CLIENT_TOOLTIP)); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ZoomProctoringService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ZoomProctoringService.java index b88ecfdf..7f4f204b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ZoomProctoringService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ZoomProctoringService.java @@ -195,8 +195,8 @@ public class ZoomProctoringService implements ExamProctoringService { proctoringSettings.collectingRoomSize, proctoringSettings.enabledFeatures, proctoringSettings.serviceInUse, - proctoringSettings.appKey, - this.cryptor.encrypt(proctoringSettings.appSecret).getOrThrow(), + null, + null, proctoringSettings.accountId, proctoringSettings.clientId, this.cryptor.encrypt(proctoringSettings.clientSecret).getOrThrow(), diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/validation/ProctoringSettingsValidator.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/validation/ProctoringSettingsValidator.java index 27d76459..d47056f6 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/validation/ProctoringSettingsValidator.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/validation/ProctoringSettingsValidator.java @@ -55,6 +55,30 @@ public class ProctoringSettingsValidator } if (value.serverType == ProctoringServerType.ZOOM) { + if (StringUtils.isBlank(value.accountId)) { + context.disableDefaultConstraintViolation(); + context + .buildConstraintViolationWithTemplate("proctoringSettings:accountId:notNull") + .addPropertyNode("accountId").addConstraintViolation(); + passed = false; + } + + if (StringUtils.isBlank(value.clientId)) { + context.disableDefaultConstraintViolation(); + context + .buildConstraintViolationWithTemplate("proctoringSettings:clientId:notNull") + .addPropertyNode("clientId").addConstraintViolation(); + passed = false; + } + + if (StringUtils.isBlank(value.clientSecret)) { + context.disableDefaultConstraintViolation(); + context + .buildConstraintViolationWithTemplate("proctoringSettings:clientSecret:notNull") + .addPropertyNode("clientSecret").addConstraintViolation(); + passed = false; + } + if (StringUtils.isBlank(value.sdkKey)) { context.disableDefaultConstraintViolation(); context diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java index c871b17d..9b3df645 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAdministrationController.java @@ -500,7 +500,7 @@ public class ExamAdministrationController extends EntityController { + API.EXAM_ADMINISTRATION_PROCTORING_RESET_PATH_SEGMENT, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - public Exam resetProctoringServiceSettings( + public Exam resetProctoringRooms( @RequestParam( name = API.PARAM_INSTITUTION_ID, required = true, @@ -520,7 +520,6 @@ public class ExamAdministrationController extends EntityController { error.getMessage())); return exam; }) - .flatMap(this.examAdminService::resetProctoringSettings) .getOrThrow(); } diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 73c2c998..5a821bc5 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -833,9 +833,10 @@ sebserver.exam.proctoring.form.features.RESET_BROADCAST_ON_LAVE=Reset broadcast sebserver.exam.proctoring.form.useZoomAppClient=Use Zoom App-Client sebserver.exam.proctoring.form.useZoomAppClient.tooltip=If this is set SEB Server opens a start link for the meeting instead of a new popup-window with the Zoom Web Client.
A Zoom App Client must already be installed on the proctor's device or can be installed by following the instructions shown in the browser window. sebserver.exam.proctoring.form.saveSettings=Save Settings -sebserver.exam.proctoring.form.resetSettings=Reset Settings -sebserver.exam.proctoring.form.resetConfirm=Reset will first cleanup and remove all existing proctoring rooms for this exam and then reset to default or template settings.
Please make sure there are no active SEB client connections for this exam, otherwise this reset will be denied.

Do you want to reset proctoring for this exam now? +sebserver.exam.proctoring.form.resetSettings=Reset Rooms +sebserver.exam.proctoring.form.resetConfirm=Reset will cleanup and remove all existing proctoring rooms for this exam.
So you are able to switch to another proctoring service or just for cleanup and testing purposes. sebserver.exam.proctoring.form.resetActive=There are still active SEB client connection for this exam. Please disconnect or cancel them first.
This action is only possible when there are no active SEB client connection within this exam. +sebserver.exam.proctoring.form.resetOk=Successfully deleted all existing proctoring rooms for this exam. sebserver.exam.proctoring.type.servertype.JITSI_MEET=Jitsi Meet Server sebserver.exam.proctoring.type.servertype.JITSI_MEET.tooltip=Use a Jitsi Meet server for proctoring @@ -1840,7 +1841,7 @@ sebserver.examconfig.props.label.terminateProcesses.tooltip=SEB will attempt to sebserver.examconfig.props.label.prohibitedProcesses.ignoreInAAC=Ignore in AAC sebserver.examconfig.props.label.prohibitedProcesses.ignoreInAAC.tooltip=When using the AAC kiosk mode (which prevents network and screen access for other processes), ignore this prohibited process sebserver.examconfig.props.label.sebAllowedVersions=Allowed SEB Versions -sebserver.examconfig.props.label.sebAllowedVersions.tooltip=List of text inputs which represent either a specific or a minimal SEB version which is allowed to access the (exam) session using current settings.
The version string has the following format: [OS.mayor.minor.patch(.minimal)], OS and mayor version are mandatory,
"minimal" indicates if version shall be interpreted as minimal version this and all above are valid. +sebserver.examconfig.props.label.sebAllowedVersions.tooltip=List of text inputs which represent either a specific or a minimal SEB version which is allowed to access the (exam) session using current settings.
The version string has the following format: [OS.mayor.minor.patch(.AE)(.minimal)], OS and mayor version are mandatory,
OS is either "Win", "Mac" or "iOS", "minimal" indicates if version shall be interpreted as minimal version this and all above are valid. AE indicates a Alliance Edition version. sebserver.examconfig.props.label.sebAllowedVersions.addAction=Add new allowed SEB version sebserver.examconfig.props.label.sebAllowedVersions.deleteAction=Delete allowed SEB version sebserver.examconfig.props.validation.SEBVersionValidator=At least one SEB Version has wrong format @@ -2275,7 +2276,8 @@ sebserver.finished.exam.connection.title=SEB Client Connection sebserver.finished.connection.form.id=User Name or Session sebserver.finished.connection.form.id.tooltip=The user session identifier or username sent by the SEB client after LMS login sebserver.finished.connection.form.info=Connection Info -sebserver.finished.connection.form.info.tooltip=Format: IP Address,SEB Version, OSName +sebserver.finished.connection.form.info.tooltip=SEB Version, OSName and IP Address +sebserver.finished.connection.form.info.wrong.client.tooltip:This SEB client version is not allowed due to the allowed SEB client setting of the exam configuration for this exam. sebserver.finished.connection.form.status=Status sebserver.finished.connection.form.status.tooltip=The current connection status sebserver.finished.connection.form.exam=Exam