SEBSERV-270 fixed and service test and validation improvements
This commit is contained in:
parent
f0166afd6a
commit
1d6bd86b57
7 changed files with 48 additions and 38 deletions
|
@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.gbl.model.exam;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.hibernate.validator.constraints.URL;
|
import org.hibernate.validator.constraints.URL;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
@ -110,9 +111,9 @@ public class ProctoringServiceSettings implements Entity {
|
||||||
this.collectingRoomSize = (collectingRoomSize != null) ? collectingRoomSize : 20;
|
this.collectingRoomSize = (collectingRoomSize != null) ? collectingRoomSize : 20;
|
||||||
this.enabledFeatures = enabledFeatures != null ? enabledFeatures : EnumSet.allOf(ProctoringFeature.class);
|
this.enabledFeatures = enabledFeatures != null ? enabledFeatures : EnumSet.allOf(ProctoringFeature.class);
|
||||||
this.serviceInUse = serviceInUse;
|
this.serviceInUse = serviceInUse;
|
||||||
this.appKey = appKey;
|
this.appKey = StringUtils.trim(appKey);
|
||||||
this.appSecret = appSecret;
|
this.appSecret = appSecret;
|
||||||
this.sdkKey = sdkKey;
|
this.sdkKey = StringUtils.trim(sdkKey);
|
||||||
this.sdkSecret = sdkSecret;
|
this.sdkSecret = sdkSecret;
|
||||||
this.useZoomAppClientForCollectingRoom = BooleanUtils.toBoolean(useZoomAppClientForCollectingRoom);
|
this.useZoomAppClientForCollectingRoom = BooleanUtils.toBoolean(useZoomAppClientForCollectingRoom);
|
||||||
}
|
}
|
||||||
|
|
|
@ -265,12 +265,14 @@ public class ExamProctoringSettings {
|
||||||
.addField(FormBuilder.text(
|
.addField(FormBuilder.text(
|
||||||
ProctoringServiceSettings.ATTR_SERVER_URL,
|
ProctoringServiceSettings.ATTR_SERVER_URL,
|
||||||
SEB_PROCTORING_FORM_URL,
|
SEB_PROCTORING_FORM_URL,
|
||||||
proctoringSettings.serverURL))
|
proctoringSettings.serverURL)
|
||||||
|
.mandatory())
|
||||||
|
|
||||||
.addField(FormBuilder.text(
|
.addField(FormBuilder.text(
|
||||||
ProctoringServiceSettings.ATTR_APP_KEY,
|
ProctoringServiceSettings.ATTR_APP_KEY,
|
||||||
SEB_PROCTORING_FORM_APPKEY,
|
SEB_PROCTORING_FORM_APPKEY,
|
||||||
proctoringSettings.appKey))
|
proctoringSettings.appKey)
|
||||||
|
.mandatory())
|
||||||
.withEmptyCellSeparation(false)
|
.withEmptyCellSeparation(false)
|
||||||
|
|
||||||
.addField(FormBuilder.password(
|
.addField(FormBuilder.password(
|
||||||
|
@ -278,7 +280,8 @@ public class ExamProctoringSettings {
|
||||||
SEB_PROCTORING_FORM_SECRET,
|
SEB_PROCTORING_FORM_SECRET,
|
||||||
(proctoringSettings.appSecret != null)
|
(proctoringSettings.appSecret != null)
|
||||||
? String.valueOf(proctoringSettings.appSecret)
|
? String.valueOf(proctoringSettings.appSecret)
|
||||||
: null))
|
: null)
|
||||||
|
.mandatory())
|
||||||
|
|
||||||
.addField(FormBuilder.text(
|
.addField(FormBuilder.text(
|
||||||
ProctoringServiceSettings.ATTR_SDK_KEY,
|
ProctoringServiceSettings.ATTR_SDK_KEY,
|
||||||
|
|
|
@ -141,25 +141,40 @@ public class JitsiProctoringService implements ExamProctoringService {
|
||||||
"proctoringSettings:serverURL:invalidURL");
|
"proctoringSettings:serverURL:invalidURL");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(proctoringSettings.appKey)) {
|
||||||
|
throw new APIMessageException(Arrays.asList(
|
||||||
|
APIMessage.fieldValidationError(ProctoringServiceSettings.ATTR_APP_KEY,
|
||||||
|
"proctoringSettings:appKey:notNull"),
|
||||||
|
APIMessage.ErrorMessage.EXTERNAL_SERVICE_BINDING_ERROR.of()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(proctoringSettings.appSecret)) {
|
||||||
|
throw new APIMessageException(Arrays.asList(
|
||||||
|
APIMessage.fieldValidationError(ProctoringServiceSettings.ATTR_APP_SECRET,
|
||||||
|
"proctoringSettings:appSecret:notNull"),
|
||||||
|
APIMessage.ErrorMessage.EXTERNAL_SERVICE_BINDING_ERROR.of()));
|
||||||
|
}
|
||||||
|
|
||||||
final ClientHttpRequestFactory clientHttpRequestFactory = this.clientHttpRequestFactoryService
|
final ClientHttpRequestFactory clientHttpRequestFactory = this.clientHttpRequestFactoryService
|
||||||
.getClientHttpRequestFactory()
|
.getClientHttpRequestFactory()
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
final String testURL = proctoringSettings.serverURL + "/external_api.js";
|
||||||
final RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);
|
final RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);
|
||||||
final ResponseEntity<String> result =
|
final ResponseEntity<String> result =
|
||||||
restTemplate.getForEntity(proctoringSettings.serverURL, String.class);
|
restTemplate.getForEntity(testURL, String.class);
|
||||||
if (result.getStatusCode() != HttpStatus.OK) {
|
if (result.getStatusCode() != HttpStatus.OK) {
|
||||||
throw new APIMessageException(Arrays.asList(
|
throw new APIMessageException(Arrays.asList(
|
||||||
APIMessage.fieldValidationError(ProctoringServiceSettings.ATTR_SERVER_URL,
|
APIMessage.fieldValidationError(ProctoringServiceSettings.ATTR_SERVER_URL,
|
||||||
"proctoringSettings:serverURL:url.invalid"),
|
"proctoringSettings:serverURL:url.noservice"),
|
||||||
APIMessage.ErrorMessage.EXTERNAL_SERVICE_BINDING_ERROR.of()));
|
APIMessage.ErrorMessage.EXTERNAL_SERVICE_BINDING_ERROR.of()));
|
||||||
}
|
}
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
log.error("Failed to access proctoring service: {}", e.getMessage());
|
log.error("Failed to access proctoring service: {}", e.getMessage());
|
||||||
throw new APIMessageException(Arrays.asList(
|
throw new APIMessageException(Arrays.asList(
|
||||||
APIMessage.fieldValidationError(ProctoringServiceSettings.ATTR_SERVER_URL,
|
APIMessage.fieldValidationError(ProctoringServiceSettings.ATTR_SERVER_URL,
|
||||||
"proctoringSettings:serverURL:url.invalid"),
|
"proctoringSettings:serverURL:url.noservice"),
|
||||||
APIMessage.ErrorMessage.EXTERNAL_SERVICE_BINDING_ERROR.of(e)));
|
APIMessage.ErrorMessage.EXTERNAL_SERVICE_BINDING_ERROR.of(e)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,6 +172,20 @@ public class ZoomProctoringService implements ExamProctoringService {
|
||||||
"proctoringSettings:serverURL:invalidURL");
|
"proctoringSettings:serverURL:invalidURL");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(proctoringSettings.appKey)) {
|
||||||
|
throw new APIMessageException(Arrays.asList(
|
||||||
|
APIMessage.fieldValidationError(ProctoringServiceSettings.ATTR_APP_KEY,
|
||||||
|
"proctoringSettings:appKey:notNull"),
|
||||||
|
APIMessage.ErrorMessage.EXTERNAL_SERVICE_BINDING_ERROR.of()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(proctoringSettings.appSecret)) {
|
||||||
|
throw new APIMessageException(Arrays.asList(
|
||||||
|
APIMessage.fieldValidationError(ProctoringServiceSettings.ATTR_APP_SECRET,
|
||||||
|
"proctoringSettings:appSecret:notNull"),
|
||||||
|
APIMessage.ErrorMessage.EXTERNAL_SERVICE_BINDING_ERROR.of()));
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
final ClientCredentials credentials = new ClientCredentials(
|
final ClientCredentials credentials = new ClientCredentials(
|
||||||
|
@ -192,10 +206,10 @@ public class ZoomProctoringService implements ExamProctoringService {
|
||||||
APIMessage.ErrorMessage.EXTERNAL_SERVICE_BINDING_ERROR.of()));
|
APIMessage.ErrorMessage.EXTERNAL_SERVICE_BINDING_ERROR.of()));
|
||||||
}
|
}
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
log.error("Failed to access Zoom service at: {}", proctoringSettings.serverURL, e);
|
log.error("Failed to access Zoom service at: {}", proctoringSettings.serverURL, e.getMessage());
|
||||||
throw new APIMessageException(Arrays.asList(
|
throw new APIMessageException(Arrays.asList(
|
||||||
APIMessage.fieldValidationError(ProctoringServiceSettings.ATTR_SERVER_URL,
|
APIMessage.fieldValidationError(ProctoringServiceSettings.ATTR_SERVER_URL,
|
||||||
"proctoringSettings:serverURL:url.invalid"),
|
"proctoringSettings:serverURL:url.noservice"),
|
||||||
APIMessage.ErrorMessage.EXTERNAL_SERVICE_BINDING_ERROR.of()));
|
APIMessage.ErrorMessage.EXTERNAL_SERVICE_BINDING_ERROR.of()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,8 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
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.model.exam.ProctoringServiceSettings.ProctoringServerType;
|
||||||
|
|
||||||
public class ProctoringSettingsValidator implements ConstraintValidator<ValidProctoringSettings, ProctoringServiceSettings> {
|
public class ProctoringSettingsValidator
|
||||||
|
implements ConstraintValidator<ValidProctoringSettings, ProctoringServiceSettings> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValid(final ProctoringServiceSettings value, final ConstraintValidatorContext context) {
|
public boolean isValid(final ProctoringServiceSettings value, final ConstraintValidatorContext context) {
|
||||||
|
@ -25,33 +26,8 @@ public class ProctoringSettingsValidator implements ConstraintValidator<ValidPro
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.enableProctoring) {
|
if (value.enableProctoring) {
|
||||||
if (value.serverType == ProctoringServerType.JITSI_MEET) {
|
if (value.serverType == ProctoringServerType.JITSI_MEET || value.serverType == ProctoringServerType.ZOOM) {
|
||||||
boolean passed = true;
|
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)) {
|
if (StringUtils.isBlank(value.appKey)) {
|
||||||
context.disableDefaultConstraintViolation();
|
context.disableDefaultConstraintViolation();
|
||||||
context
|
context
|
||||||
|
|
|
@ -379,7 +379,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
||||||
return this.entityDAO.byPK(examId)
|
return this.entityDAO.byPK(examId)
|
||||||
.flatMap(this.authorization::checkModify)
|
.flatMap(this.authorization::checkModify)
|
||||||
.map(exam -> {
|
.map(exam -> {
|
||||||
if (proctoringServiceSettings.enableProctoring) {
|
if (StringUtils.isNotBlank(proctoringServiceSettings.serverURL)) {
|
||||||
this.examAdminService.getExamProctoringService(proctoringServiceSettings.serverType)
|
this.examAdminService.getExamProctoringService(proctoringServiceSettings.serverType)
|
||||||
.flatMap(service -> service.testExamProctoring(proctoringServiceSettings))
|
.flatMap(service -> service.testExamProctoring(proctoringServiceSettings))
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
|
|
@ -95,6 +95,7 @@ sebserver.form.validation.fieldError.exists=This name already exists. Please cho
|
||||||
sebserver.form.validation.fieldError.email=Invalid mail address
|
sebserver.form.validation.fieldError.email=Invalid mail address
|
||||||
sebserver.form.validation.fieldError.serverNotAvailable=No service seems to be available within the given URL
|
sebserver.form.validation.fieldError.serverNotAvailable=No service seems to be available within the given URL
|
||||||
sebserver.form.validation.fieldError.url.invalid=Invalid URL. The given URL cannot be reached.
|
sebserver.form.validation.fieldError.url.invalid=Invalid URL. The given URL cannot be reached.
|
||||||
|
sebserver.form.validation.fieldError.url.noservice=The expected service is not available within the given URL and API access.
|
||||||
sebserver.form.validation.fieldError.thresholdDuplicate=There are duplicate threshold values.
|
sebserver.form.validation.fieldError.thresholdDuplicate=There are duplicate threshold values.
|
||||||
sebserver.form.validation.fieldError.thresholdEmpty=There are empty threshold entries.
|
sebserver.form.validation.fieldError.thresholdEmpty=There are empty threshold entries.
|
||||||
sebserver.error.unexpected=Unexpected Error
|
sebserver.error.unexpected=Unexpected Error
|
||||||
|
|
Loading…
Reference in a new issue