SEBSERV-382

This commit is contained in:
anhefti 2023-02-08 13:15:17 +01:00
parent 80af47e14e
commit c26f8da944
7 changed files with 70 additions and 48 deletions

View file

@ -61,7 +61,7 @@ public class AllowedSEBVersion {
valid = false; valid = false;
} }
this.minor = num; this.minor = num;
if (split.length >= 3) { if (split.length > 3) {
try { try {
num = Integer.valueOf(split[3]); num = Integer.valueOf(split[3]);
} catch (final Exception e) { } catch (final Exception e) {

View file

@ -83,11 +83,6 @@ public class ProctoringSettingsPopup {
private final static LocTextKey SEB_PROCTORING_FORM_SECRET_JITSI = private final static LocTextKey SEB_PROCTORING_FORM_SECRET_JITSI =
new LocTextKey("sebserver.exam.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 = private final static LocTextKey SEB_PROCTORING_FORM_ACCOUNT_ID =
new LocTextKey("sebserver.exam.proctoring.form.accountId"); new LocTextKey("sebserver.exam.proctoring.form.accountId");
private final static LocTextKey SEB_PROCTORING_FORM_CLIENT_ID = private final static LocTextKey SEB_PROCTORING_FORM_CLIENT_ID =
@ -113,6 +108,8 @@ public class ProctoringSettingsPopup {
new LocTextKey("sebserver.exam.proctoring.form.resetConfirm"); new LocTextKey("sebserver.exam.proctoring.form.resetConfirm");
private final static LocTextKey RESET_ACTIVE_CON_KEY = private final static LocTextKey RESET_ACTIVE_CON_KEY =
new LocTextKey("sebserver.exam.proctoring.form.resetActive"); new LocTextKey("sebserver.exam.proctoring.form.resetActive");
private final static LocTextKey RESET_SUCCESS_KEY =
new LocTextKey("sebserver.exam.proctoring.form.resetOk");
Function<PageAction, PageAction> settingsFunction(final PageService pageService, final boolean modifyGrant) { Function<PageAction, PageAction> settingsFunction(final PageService pageService, final boolean modifyGrant) {
@ -144,6 +141,8 @@ public class ProctoringSettingsPopup {
} }
}); });
final EntityKey entityKey = pageContext.getEntityKey();
if (entityKey.entityType == EntityType.EXAM) {
final Button reset = widgetFactory.buttonLocalized(composite, RESET_TEXT_KEY); final Button reset = widgetFactory.buttonLocalized(composite, RESET_TEXT_KEY);
reset.setLayoutData(new RowData()); reset.setLayoutData(new RowData());
reset.addListener(SWT.Selection, event -> { reset.addListener(SWT.Selection, event -> {
@ -154,6 +153,7 @@ public class ProctoringSettingsPopup {
}); });
}); });
resetButtonHandler.set(reset); resetButtonHandler.set(reset);
}
}; };
final SEBProctoringPropertiesForm bindFormContext = new SEBProctoringPropertiesForm( final SEBProctoringPropertiesForm bindFormContext = new SEBProctoringPropertiesForm(
@ -208,16 +208,10 @@ public class ProctoringSettingsPopup {
.getBuilder(ResetProctoringSettings.class) .getBuilder(ResetProctoringSettings.class)
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId) .withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
.call() .call()
.onError(error -> { .onError(error -> handleResetError(pageContext, entityKey, error))
if (error.getMessage().contains("active connections") || .onSuccess(settings -> pageContext.publishInfo(RESET_SUCCESS_KEY))
(error.getCause() != null && .map(settings -> true)
error.getCause().getMessage().contains("active connections"))) { .getOr(false);
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);
} }
private boolean doSaveSettings( private boolean doSaveSettings(
@ -451,19 +445,6 @@ public class ProctoringSettingsPopup {
proctoringSettings.serverURL) proctoringSettings.serverURL)
.mandatory()) .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( .addField(FormBuilder.text(
ProctoringServiceSettings.ATTR_ACCOUNT_ID, ProctoringServiceSettings.ATTR_ACCOUNT_ID,
SEB_PROCTORING_FORM_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<ProctoringServiceSettings> formHandle; FormHandle<ProctoringServiceSettings> formHandle;
PageContext formContext; PageContext formContext;
} }
} }

View file

@ -63,6 +63,8 @@ public class ClientConnectionDetails implements MonitoringEntry {
new LocTextKey("sebserver.monitoring.connection.form.info"); new LocTextKey("sebserver.monitoring.connection.form.info");
private final static LocTextKey CONNECTION_STATUS_TEXT_KEY = private final static LocTextKey CONNECTION_STATUS_TEXT_KEY =
new LocTextKey("sebserver.monitoring.connection.form.status"); 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; private static final int NUMBER_OF_NONE_INDICATOR_ROWS = 3;
@ -130,12 +132,15 @@ public class ClientConnectionDetails implements MonitoringEntry {
CONNECTION_GROUP_TEXT_KEY, CONNECTION_GROUP_TEXT_KEY,
Constants.EMPTY_NOTE) Constants.EMPTY_NOTE)
.asMarkupLabel()) .asMarkupLabel())
.withDefaultSpanInput(3)
.addField(FormBuilder.text( .addField(FormBuilder.text(
ClientConnection.ATTR_INFO, ClientConnection.ATTR_INFO,
CONNECTION_INFO_TEXT_KEY, CONNECTION_INFO_TEXT_KEY,
Constants.EMPTY_NOTE) Constants.EMPTY_NOTE)
.asArea(50) .asArea(50)
.asColorBox()) .asColorBox())
.withDefaultSpanEmptyCell(2)
.withDefaultSpanInput(3) .withDefaultSpanInput(3)
.addField(FormBuilder.text( .addField(FormBuilder.text(
Domain.CLIENT_CONNECTION.ATTR_STATUS, Domain.CLIENT_CONNECTION.ATTR_STATUS,
@ -322,6 +327,8 @@ public class ClientConnectionDetails implements MonitoringEntry {
if (this.connectionData.clientConnection.clientVersionGranted != null && if (this.connectionData.clientConnection.clientVersionGranted != null &&
!this.connectionData.clientConnection.clientVersionGranted) { !this.connectionData.clientConnection.clientVersionGranted) {
form.setFieldColor(ClientConnection.ATTR_INFO, this.colorData.color2); form.setFieldColor(ClientConnection.ATTR_INFO, this.colorData.color2);
form.getFieldInput(ClientConnection.ATTR_INFO)
.setToolTipText(this.pageService.getI18nSupport().getText(WRONG_SEB_CLIENT_TOOLTIP));
} }
} }

View file

@ -195,8 +195,8 @@ public class ZoomProctoringService implements ExamProctoringService {
proctoringSettings.collectingRoomSize, proctoringSettings.collectingRoomSize,
proctoringSettings.enabledFeatures, proctoringSettings.enabledFeatures,
proctoringSettings.serviceInUse, proctoringSettings.serviceInUse,
proctoringSettings.appKey, null,
this.cryptor.encrypt(proctoringSettings.appSecret).getOrThrow(), null,
proctoringSettings.accountId, proctoringSettings.accountId,
proctoringSettings.clientId, proctoringSettings.clientId,
this.cryptor.encrypt(proctoringSettings.clientSecret).getOrThrow(), this.cryptor.encrypt(proctoringSettings.clientSecret).getOrThrow(),

View file

@ -55,6 +55,30 @@ public class ProctoringSettingsValidator
} }
if (value.serverType == ProctoringServerType.ZOOM) { 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)) { if (StringUtils.isBlank(value.sdkKey)) {
context.disableDefaultConstraintViolation(); context.disableDefaultConstraintViolation();
context context

View file

@ -500,7 +500,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
+ API.EXAM_ADMINISTRATION_PROCTORING_RESET_PATH_SEGMENT, + API.EXAM_ADMINISTRATION_PROCTORING_RESET_PATH_SEGMENT,
method = RequestMethod.POST, method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE) produces = MediaType.APPLICATION_JSON_VALUE)
public Exam resetProctoringServiceSettings( public Exam resetProctoringRooms(
@RequestParam( @RequestParam(
name = API.PARAM_INSTITUTION_ID, name = API.PARAM_INSTITUTION_ID,
required = true, required = true,
@ -520,7 +520,6 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
error.getMessage())); error.getMessage()));
return exam; return exam;
}) })
.flatMap(this.examAdminService::resetProctoringSettings)
.getOrThrow(); .getOrThrow();
} }

View file

@ -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=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.<br/>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.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.<br/>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.saveSettings=Save Settings
sebserver.exam.proctoring.form.resetSettings=Reset Settings sebserver.exam.proctoring.form.resetSettings=Reset Rooms
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.<br/>Please make sure there are no active SEB client connections for this exam, otherwise this reset will be denied.<br/><br/>Do you want to reset proctoring for this exam now? sebserver.exam.proctoring.form.resetConfirm=Reset will cleanup and remove all existing proctoring rooms for this exam.<br/>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.<br/>This action is only possible when there are no active SEB client connection within this exam. sebserver.exam.proctoring.form.resetActive=There are still active SEB client connection for this exam. Please disconnect or cancel them first.<br/>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=Jitsi Meet Server
sebserver.exam.proctoring.type.servertype.JITSI_MEET.tooltip=Use a Jitsi Meet server for proctoring 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=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.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=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.<br/>The version string has the following format: [OS.mayor.minor.patch(.minimal)], OS and mayor version are mandatory,<br/>"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.<br/>The version string has the following format: [OS.mayor.minor.patch(.AE)(.minimal)], OS and mayor version are mandatory,<br/>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.addAction=Add new allowed SEB version
sebserver.examconfig.props.label.sebAllowedVersions.deleteAction=Delete 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 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=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.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=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=Status
sebserver.finished.connection.form.status.tooltip=The current connection status sebserver.finished.connection.form.status.tooltip=The current connection status
sebserver.finished.connection.form.exam=Exam sebserver.finished.connection.form.exam=Exam