SEBSERV-57 fixed

This commit is contained in:
anhefti 2022-05-24 16:05:32 +02:00
parent 605a6fcea7
commit b7717ed2de
5 changed files with 67 additions and 51 deletions

View file

@ -240,6 +240,7 @@ public final class Indicator implements Entity {
}
}
@JsonIgnoreProperties(ignoreUnknown = true)
public static final class Threshold implements Comparable<Threshold> {
@JsonProperty(THRESHOLD.ATTR_VALUE)

View file

@ -131,7 +131,7 @@ public final class ThresholdList extends Composite {
private void removeInvalidListEntries() {
this.thresholds
.stream()
.filter(entry -> entry.getValue() == null || StringUtils.isBlank(entry.getColor()))
.filter(entry -> entry.getValue() == null && StringUtils.isBlank(entry.getColor()))
.collect(Collectors.toList())
.forEach(this::removeThreshold);
}

View file

@ -8,9 +8,18 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.exam;
import org.apache.commons.lang3.BooleanUtils;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.validation.FieldError;
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.Threshold;
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamProctoringService;
@ -88,4 +97,39 @@ public interface ExamAdminService {
* @return ExamProctoringService instance */
Result<ExamProctoringService> getExamProctoringService(final Long examId);
/** Used to check threshold consistency for a given list of thresholds.
* Checks if all values are present (none null value)
* Checks if there are duplicates
*
* If a check fails, the methods throws a APIMessageException with a FieldError to notify the caller
*
* @param thresholds List of Threshold */
public static void checkThresholdConsistency(final List<Threshold> thresholds) {
if (thresholds != null) {
final List<Threshold> emptyThresholds = thresholds.stream()
.filter(t -> t.getValue() == null || t.getColor() == null)
.collect(Collectors.toList());
if (!emptyThresholds.isEmpty()) {
throw new APIMessageException(APIMessage.fieldValidationError(
new FieldError(
Domain.EXAM.TYPE_NAME,
Domain.EXAM.ATTR_SUPPORTER,
"indicator:thresholds:thresholdEmpty")));
}
final Set<Double> values = thresholds.stream()
.map(t -> t.getValue())
.collect(Collectors.toSet());
if (values.size() != thresholds.size()) {
throw new APIMessageException(APIMessage.fieldValidationError(
new FieldError(
Domain.EXAM.TYPE_NAME,
Domain.EXAM.ATTR_SUPPORTER,
"indicator:thresholds:thresholdDuplicate")));
}
}
}
}

View file

@ -49,6 +49,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionServic
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamTemplateDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService;
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ProctoringAdminService;
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
@ -191,6 +192,10 @@ public class ExamTemplateController extends EntityController<ExamTemplate, ExamT
null,
postMap.getLong(IndicatorTemplate.ATTR_EXAM_TEMPLATE_ID),
postMap))
.map(indicator -> {
ExamAdminService.checkThresholdConsistency(indicator.thresholds);
return indicator;
})
.flatMap(this.examTemplateDAO::createNewIndicatorTemplate)
.flatMap(this.userActivityLogDAO::logCreate)
.getOrThrow();
@ -212,6 +217,10 @@ public class ExamTemplateController extends EntityController<ExamTemplate, ExamT
this.checkModifyPrivilege(institutionId);
return this.beanValidationService
.validateBean(modifyData)
.map(indicator -> {
ExamAdminService.checkThresholdConsistency(indicator.thresholds);
return indicator;
})
.flatMap(this.examTemplateDAO::saveIndicatorTemplate)
.flatMap(this.userActivityLogDAO::logModify)
.getOrThrow();

View file

@ -8,25 +8,17 @@
package ch.ethz.seb.sebserver.webservice.weblayer.api;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.mybatis.dynamic.sql.SqlTable;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.Threshold;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Pair;
import ch.ethz.seb.sebserver.gbl.util.Result;
@ -37,6 +29,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionServic
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.IndicatorDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
@ -95,22 +88,20 @@ public class IndicatorController extends EntityController<Indicator, Indicator>
@Override
protected Result<Indicator> validForCreate(final Indicator entity) {
final Result<Indicator> validForCreate = super.validForCreate(entity);
if (validForCreate.hasError()) {
return validForCreate;
}
return checkThresholdConsistency(entity);
return super.validForCreate(entity)
.map(indicator -> {
ExamAdminService.checkThresholdConsistency(indicator.thresholds);
return indicator;
});
}
@Override
protected Result<Indicator> validForSave(final Indicator entity) {
final Result<Indicator> validForSave = super.validForSave(entity);
if (validForSave.hasError()) {
return validForSave;
}
return checkThresholdConsistency(entity);
return super.validForSave(entity)
.map(indicator -> {
ExamAdminService.checkThresholdConsistency(indicator.thresholds);
return indicator;
});
}
@Override
@ -156,33 +147,4 @@ public class IndicatorController extends EntityController<Indicator, Indicator>
}
private Result<Indicator> checkThresholdConsistency(final Indicator entity) {
if (entity != null) {
final List<Threshold> emptyThresholds = entity.thresholds.stream()
.filter(t -> t.getValue() == null)
.collect(Collectors.toList());
if (!emptyThresholds.isEmpty()) {
throw new APIMessageException(APIMessage.fieldValidationError(
new FieldError(
Domain.EXAM.TYPE_NAME,
Domain.EXAM.ATTR_SUPPORTER,
"indicator:thresholds:thresholdEmpty")));
}
final Set<Double> values = entity.thresholds.stream()
.map(t -> t.getValue())
.collect(Collectors.toSet());
if (values.size() != entity.thresholds.size()) {
throw new APIMessageException(APIMessage.fieldValidationError(
new FieldError(
Domain.EXAM.TYPE_NAME,
Domain.EXAM.ATTR_SUPPORTER,
"indicator:thresholds:thresholdDuplicate")));
}
}
return Result.of(entity);
}
}