SEBSERV-139 implementing GUI
This commit is contained in:
parent
6eedcbb4a0
commit
548d4d132f
13 changed files with 261 additions and 17 deletions
|
@ -126,7 +126,6 @@ public final class API {
|
|||
public static final String EXAM_ADMINISTRATION_CHECK_RESTRICTION_PATH_SEGMENT = "/check-seb-restriction";
|
||||
public static final String EXAM_ADMINISTRATION_CHECK_IMPORTED_PATH_SEGMENT = "/check-imported";
|
||||
public static final String EXAM_ADMINISTRATION_SEB_RESTRICTION_CHAPTERS_PATH_SEGMENT = "/chapters";
|
||||
|
||||
public static final String EXAM_ADMINISTRATION_PROCTOR_PATH_SEGMENT = "/proctoring";
|
||||
|
||||
public static final String EXAM_INDICATOR_ENDPOINT = "/indicator";
|
||||
|
|
|
@ -18,8 +18,10 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.ValidProctoringSettings;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@ValidProctoringSettings
|
||||
public class ProctoringSettings implements Entity {
|
||||
|
||||
public enum ServerType {
|
||||
|
@ -42,7 +44,7 @@ public class ProctoringSettings implements Entity {
|
|||
public final ServerType serverType;
|
||||
|
||||
@JsonProperty(ATTR_SERVER_URL)
|
||||
@URL(message = "examProctoring:serverURL:invalidURL")
|
||||
@URL(message = "proctoringSettings:serverURL:invalidURL")
|
||||
public final String serverURL;
|
||||
|
||||
@JsonProperty(ATTR_APP_KEY)
|
||||
|
|
|
@ -33,6 +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.exam.Exam;
|
||||
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.QuizData;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult.ErrorType;
|
||||
|
@ -57,6 +58,7 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
|||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.CheckExamConsistency;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.CheckSEBRestriction;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExam;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetProctoringSettings;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.SaveExam;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.lmssetup.GetLmsSetup;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.lmssetup.TestLmsSetup;
|
||||
|
@ -119,6 +121,7 @@ public class ExamForm implements TemplateComposer {
|
|||
private final PageService pageService;
|
||||
private final ResourceService resourceService;
|
||||
private final ExamSEBRestrictionSettings examSEBRestrictionSettings;
|
||||
private final ExamProctoringSettings examProctoringSettings;
|
||||
private final WidgetFactory widgetFactory;
|
||||
private final RestService restService;
|
||||
private final ExamDeletePopup examDeletePopup;
|
||||
|
@ -128,6 +131,7 @@ public class ExamForm implements TemplateComposer {
|
|||
protected ExamForm(
|
||||
final PageService pageService,
|
||||
final ExamSEBRestrictionSettings examSEBRestrictionSettings,
|
||||
final ExamProctoringSettings examProctoringSettings,
|
||||
final ExamToConfigBindingForm examToConfigBindingForm,
|
||||
final DownloadService downloadService,
|
||||
final ExamDeletePopup examDeletePopup,
|
||||
|
@ -137,6 +141,7 @@ public class ExamForm implements TemplateComposer {
|
|||
this.pageService = pageService;
|
||||
this.resourceService = pageService.getResourceService();
|
||||
this.examSEBRestrictionSettings = examSEBRestrictionSettings;
|
||||
this.examProctoringSettings = examProctoringSettings;
|
||||
this.widgetFactory = pageService.getWidgetFactory();
|
||||
this.restService = this.resourceService.getRestService();
|
||||
this.examDeletePopup = examDeletePopup;
|
||||
|
@ -336,6 +341,13 @@ public class ExamForm implements TemplateComposer {
|
|||
? this.restService.getRestCall(ImportAsExam.class)
|
||||
: this.restService.getRestCall(SaveExam.class));
|
||||
|
||||
final boolean proctoringEnabled = this.restService
|
||||
.getBuilder(GetProctoringSettings.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||
.call()
|
||||
.map(ProctoringSettings::getEnableProctoring)
|
||||
.getOr(false);
|
||||
|
||||
final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(formContext
|
||||
.clearEntityKeys()
|
||||
.removeAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA));
|
||||
|
@ -384,6 +396,18 @@ public class ExamForm implements TemplateComposer {
|
|||
.publishIf(() -> sebRestrictionAvailable && readonly && modifyGrant && !importFromQuizData
|
||||
&& BooleanUtils.isTrue(isRestricted))
|
||||
|
||||
.newAction(ActionDefinition.EXAM_PROCTORING_ON)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(this.examProctoringSettings.settingsFunction(this.pageService))
|
||||
.noEventPropagation()
|
||||
.publishIf(() -> proctoringEnabled && readonly)
|
||||
|
||||
.newAction(ActionDefinition.EXAM_PROCTORING_OFF)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(this.examProctoringSettings.settingsFunction(this.pageService))
|
||||
.noEventPropagation()
|
||||
.publishIf(() -> !proctoringEnabled && readonly)
|
||||
|
||||
.newAction(ActionDefinition.EXAM_DELETE)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(this.examDeletePopup.deleteWizardFunction(pageContext))
|
||||
|
|
|
@ -16,12 +16,16 @@ import org.apache.commons.lang3.BooleanUtils;
|
|||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
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.ProctoringSettings.ServerType;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.form.Form;
|
||||
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
|
||||
import ch.ethz.seb.sebserver.gui.form.FormHandle;
|
||||
|
@ -30,12 +34,16 @@ import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
|||
import ch.ethz.seb.sebserver.gui.service.page.ModalInputDialogComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetProctoringSettings;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.SaveProctoringSettings;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class ExamProctoringSettings {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ExamProctoringSettings.class);
|
||||
|
@ -55,10 +63,6 @@ public class ExamProctoringSettings {
|
|||
private final static LocTextKey SEB_PROCTORING_FORM_SECRET =
|
||||
new LocTextKey("sebserver.exam.proctoring.form.secret");
|
||||
|
||||
public ExamProctoringSettings() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
Function<PageAction, PageAction> settingsFunction(final PageService pageService) {
|
||||
|
||||
return action -> {
|
||||
|
@ -75,7 +79,7 @@ public class ExamProctoringSettings {
|
|||
pageService,
|
||||
action.pageContext());
|
||||
|
||||
final Predicate<FormHandle<?>> doBind = formHandle -> doCreate(
|
||||
final Predicate<FormHandle<?>> doBind = formHandle -> doSaveSettings(
|
||||
pageService,
|
||||
pageContext,
|
||||
formHandle);
|
||||
|
@ -90,7 +94,7 @@ public class ExamProctoringSettings {
|
|||
};
|
||||
}
|
||||
|
||||
private boolean doCreate(
|
||||
private boolean doSaveSettings(
|
||||
final PageService pageService,
|
||||
final PageContext pageContext,
|
||||
final FormHandle<?> formHandle) {
|
||||
|
@ -105,6 +109,8 @@ public class ExamProctoringSettings {
|
|||
ProctoringSettings examProctoring = null;
|
||||
try {
|
||||
final Form form = formHandle.getForm();
|
||||
form.clearErrors();
|
||||
|
||||
final boolean enabled = BooleanUtils.toBoolean(
|
||||
form.getFieldValue(ProctoringSettings.ATTR_ENABLE_PROCTORING));
|
||||
final ServerType serverType = ServerType.valueOf(
|
||||
|
@ -126,7 +132,7 @@ public class ExamProctoringSettings {
|
|||
return false;
|
||||
}
|
||||
|
||||
return !pageService
|
||||
final boolean saveOk = !pageService
|
||||
.getRestService()
|
||||
.getBuilder(SaveProctoringSettings.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||
|
@ -134,6 +140,19 @@ public class ExamProctoringSettings {
|
|||
.call()
|
||||
.onError(formHandle::handleError)
|
||||
.hasError();
|
||||
|
||||
if (saveOk) {
|
||||
final PageAction action = pageService.pageActionBuilder(pageContext)
|
||||
.newAction(ActionDefinition.EXAM_VIEW_FROM_LIST)
|
||||
.create();
|
||||
|
||||
pageService.firePageEvent(
|
||||
new ActionEvent(action),
|
||||
action.pageContext());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private final class SEBProctoringPropertiesForm
|
||||
|
@ -196,9 +215,24 @@ public class ExamProctoringSettings {
|
|||
ProctoringSettings.ATTR_SERVER_TYPE,
|
||||
SEB_PROCTORING_FORM_TYPE,
|
||||
proctoringSettings.serverType.name(),
|
||||
this.pageService.getResourceService()::examProctoringTypeResources))
|
||||
resourceService::examProctoringTypeResources))
|
||||
|
||||
// TODO
|
||||
.addField(FormBuilder.text(
|
||||
ProctoringSettings.ATTR_SERVER_URL,
|
||||
SEB_PROCTORING_FORM_URL,
|
||||
proctoringSettings.serverURL))
|
||||
|
||||
.addField(FormBuilder.text(
|
||||
ProctoringSettings.ATTR_APP_KEY,
|
||||
SEB_PROCTORING_FORM_APPKEY,
|
||||
proctoringSettings.appKey))
|
||||
|
||||
.addField(FormBuilder.password(
|
||||
ProctoringSettings.ATTR_APP_SECRET,
|
||||
SEB_PROCTORING_FORM_SECRET,
|
||||
(proctoringSettings.appSecret != null)
|
||||
? String.valueOf(proctoringSettings.appSecret)
|
||||
: null))
|
||||
|
||||
.build();
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import ch.ethz.seb.sebserver.gbl.model.Domain;
|
|||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
||||
|
@ -45,8 +46,10 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
|||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExam;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetIndicators;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetProctoringSettings;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs.GetExtendedClientEventPage;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetClientConnectionData;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetProctorURLForClient;
|
||||
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.InstructionProcessor;
|
||||
|
@ -237,6 +240,13 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
final boolean proctoringEnabled = restService
|
||||
.getBuilder(GetProctoringSettings.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, parentEntityKey.modelId)
|
||||
.call()
|
||||
.map(ProctoringSettings::getEnableProctoring)
|
||||
.getOr(false);
|
||||
|
||||
actionBuilder
|
||||
.newAction(ActionDefinition.MONITOR_EXAM_BACK_TO_OVERVIEW)
|
||||
.withEntityKey(parentEntityKey)
|
||||
|
@ -256,15 +266,16 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
connectionData.clientConnection.status == ConnectionStatus.ACTIVE)
|
||||
|
||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_PROCTORING)
|
||||
.withExec(this::openProctorScreen)
|
||||
.withEntityKey(parentEntityKey)
|
||||
.withExec(action -> this.openProctorScreen(action, connectionToken))
|
||||
.noEventPropagation()
|
||||
.publish()
|
||||
.publishIf(() -> proctoringEnabled)
|
||||
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
private PageAction openProctorScreen(final PageAction action) {
|
||||
private PageAction openProctorScreen(final PageAction action, final String connectionToken) {
|
||||
//
|
||||
// final ProctorDialog dialog = new ProctorDialog(action.pageContext().getParent().getShell());
|
||||
// dialog.open(EVENT_LIST_TITLE_KEY,
|
||||
|
@ -274,6 +285,12 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
// urlLauncher.openURL(
|
||||
// "https://seb-jitsi.ethz.ch/TestRoomABC?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb250ZXh0Ijp7InVzZXIiOnsiYXZhdGFyIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9qb2huLWRvZSIsIm5hbWUiOiJEaXNwbGF5IE5hbWUiLCJlbWFpbCI6Im5hbWVAZXhhbXBsZS5jb20ifX0sImF1ZCI6InNlYi1qaXRzaSIsImlzcyI6InNlYi1qaXRzaSIsInN1YiI6Im1lZXQuaml0c2kiLCJyb29tIjoiKiJ9.SD9Zs78mMFqxS1tpalPTykYYaubIYsj_406WAOhcqxQ");
|
||||
|
||||
final String proctorURL = this.pageService.getRestService().getBuilder(GetProctorURLForClient.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, action.getEntityKey().modelId)
|
||||
.withURIVariable(API.EXAM_API_SEB_CONNECTION_TOKEN, connectionToken)
|
||||
.call()
|
||||
.getOrThrow();
|
||||
|
||||
final JavaScriptExecutor javaScriptExecutor = RWT.getClient().getService(JavaScriptExecutor.class);
|
||||
javaScriptExecutor.execute(
|
||||
"window.open("
|
||||
|
|
|
@ -297,6 +297,16 @@ public enum ActionDefinition {
|
|||
ImageIcon.LOCK,
|
||||
PageStateDefinitionImpl.EXAM_VIEW,
|
||||
ActionCategory.FORM),
|
||||
EXAM_PROCTORING_ON(
|
||||
new LocTextKey("sebserver.exam.proctoring.actions.open"),
|
||||
ImageIcon.VISIBILITY,
|
||||
PageStateDefinitionImpl.EXAM_VIEW,
|
||||
ActionCategory.FORM),
|
||||
EXAM_PROCTORING_OFF(
|
||||
new LocTextKey("sebserver.exam.proctoring.actions.open"),
|
||||
ImageIcon.VISIBILITY_OFF,
|
||||
PageStateDefinitionImpl.EXAM_VIEW,
|
||||
ActionCategory.FORM),
|
||||
|
||||
EXAM_CONFIGURATION_NEW(
|
||||
new LocTextKey("sebserver.exam.configuration.action.list.new"),
|
||||
|
|
|
@ -39,6 +39,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.OpenEdxSEBRestriction.PermissionComponent;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSEBRestriction.WhiteListPath;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ServerType;
|
||||
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.ConfigurationNode;
|
||||
|
@ -372,7 +373,7 @@ public class ResourceService {
|
|||
}
|
||||
|
||||
public List<Tuple<String>> examProctoringTypeResources() {
|
||||
return Arrays.stream(ExamType.values())
|
||||
return Arrays.stream(ServerType.values())
|
||||
.map(type -> new Tuple3<>(
|
||||
type.name(),
|
||||
this.i18nSupport.getText(EXAM_PROCTORING_TYPE_PREFIX + type.name()),
|
||||
|
|
|
@ -36,7 +36,7 @@ public class SaveProctoringSettings extends RestCall<Exam> {
|
|||
MediaType.APPLICATION_JSON_UTF8,
|
||||
API.EXAM_ADMINISTRATION_ENDPOINT
|
||||
+ API.MODEL_ID_VAR_PATH_SEGMENT
|
||||
+ API.EXAM_ADMINISTRATION_SEB_RESTRICTION_PATH_SEGMENT);
|
||||
+ API.EXAM_ADMINISTRATION_PROCTOR_PATH_SEGMENT);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2020 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.gui.service.remote.webservice.api.session;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class GetProctorURLForClient extends RestCall<String> {
|
||||
|
||||
public GetProctorURLForClient() {
|
||||
super(new TypeKey<>(
|
||||
CallType.GET_SINGLE,
|
||||
EntityType.EXAM_PROCTOR_DATA,
|
||||
new TypeReference<String>() {
|
||||
}),
|
||||
HttpMethod.GET,
|
||||
MediaType.APPLICATION_JSON_UTF8,
|
||||
API.EXAM_ADMINISTRATION_ENDPOINT
|
||||
+ API.MODEL_ID_VAR_PATH_SEGMENT
|
||||
+ API.EXAM_ADMINISTRATION_PROCTOR_PATH_SEGMENT
|
||||
+ API.EXAM_MONITORING_SEB_CONNECTION_TOKEN_PATH_SEGMENT);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2020 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.servicelayer.validation;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringSettings.ServerType;
|
||||
|
||||
public class ProctoringSettingsValidator implements ConstraintValidator<ValidProctoringSettings, ProctoringSettings> {
|
||||
|
||||
@Override
|
||||
public boolean isValid(final ProctoringSettings value, final ConstraintValidatorContext context) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value.enableProctoring) {
|
||||
if (value.serverType == ServerType.JITSI_MEET) {
|
||||
boolean passed = true;
|
||||
if (StringUtils.isBlank(value.serverURL)) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
context
|
||||
.buildConstraintViolationWithTemplate("proctoringSettings:serverURL:notNull")
|
||||
.addPropertyNode("serverURL").addConstraintViolation();
|
||||
passed = false;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
if (!InetAddress.getByName(new URI(value.serverURL).getHost()).isReachable(5000)) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
context
|
||||
.buildConstraintViolationWithTemplate("proctoringSettings:serverURL:serverNotAvailable")
|
||||
.addPropertyNode("serverURL").addConstraintViolation();
|
||||
passed = false;
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
context
|
||||
.buildConstraintViolationWithTemplate("proctoringSettings:serverURL:serverNotAvailable")
|
||||
.addPropertyNode("serverURL").addConstraintViolation();
|
||||
passed = false;
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(value.appKey)) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
context
|
||||
.buildConstraintViolationWithTemplate("proctoringSettings:appKey:notNull")
|
||||
.addPropertyNode("appKey").addConstraintViolation();
|
||||
passed = false;
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(value.appSecret)) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
context
|
||||
.buildConstraintViolationWithTemplate("proctoringSettings:appSecret:notNull")
|
||||
.addPropertyNode("appSecret").addConstraintViolation();
|
||||
passed = false;
|
||||
}
|
||||
|
||||
return passed;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2020 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.servicelayer.validation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
|
||||
@Target({ ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Constraint(validatedBy = ProctoringSettingsValidator.class)
|
||||
@Documented
|
||||
public @interface ValidProctoringSettings {
|
||||
|
||||
String message() default "{mandatoryWhenEnabled}";
|
||||
|
||||
Class<?>[] groups() default {};
|
||||
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
|
||||
}
|
|
@ -429,7 +429,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
|||
+ API.EXAM_ADMINISTRATION_PROCTOR_PATH_SEGMENT
|
||||
+ API.EXAM_MONITORING_SEB_CONNECTION_TOKEN_PATH_SEGMENT,
|
||||
method = RequestMethod.GET,
|
||||
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
produces = MediaType.TEXT_PLAIN_VALUE)
|
||||
public String getExamProctoringURL(
|
||||
@RequestParam(
|
||||
name = API.PARAM_INSTITUTION_ID,
|
||||
|
|
|
@ -90,6 +90,7 @@ sebserver.form.validation.fieldError.password.mismatch=The retyped password does
|
|||
sebserver.form.validation.fieldError.invalidURL=The input does not match the URL pattern.
|
||||
sebserver.form.validation.fieldError.exists=This name already exists. Please choose another one.
|
||||
sebserver.form.validation.fieldError.email=Invalid mail address
|
||||
sebserver.form.validation.fieldError.serverNotAvailable=No service seems to be available within the given URL
|
||||
sebserver.error.unexpected=Unexpected Error
|
||||
sebserver.page.message=Information
|
||||
sebserver.dialog.confirm.title=Confirmation
|
||||
|
@ -1396,6 +1397,7 @@ sebserver.monitoring.exam.connection.action.hide.disabled=Hide Canceled
|
|||
sebserver.monitoring.exam.connection.action.show.disabled=Show Canceled
|
||||
sebserver.monitoring.exam.connection.action.hide.undefined=Hide Undefined
|
||||
sebserver.monitoring.exam.connection.action.show.undefined=Show Undefined
|
||||
sebserver.monitoring.exam.connection.action.proctoring=Proctoring
|
||||
|
||||
sebserver.monitoring.exam.connection.eventlist.title=Events
|
||||
sebserver.monitoring.exam.connection.eventlist.title.tooltip=All events and logs sent by the SEB Client
|
||||
|
|
Loading…
Add table
Reference in a new issue