From 0f09ce47a9e299fd4160c873c48fb965276208cf Mon Sep 17 00:00:00 2001 From: Thomas Kurz Date: Mon, 25 Mar 2024 14:12:48 +0100 Subject: [PATCH] #mpa-227 changing lime survey id for running study is now forbidden --- .../lime/LimeSurveyObservation.java | 35 +++++++++++++++++- .../lime/LimeSurveyRequestService.java | 15 ++++++-- .../lime/LimeSurveyObservationTest.java | 37 +++++++++++++++++++ .../exception/BadRequestException.java | 5 +++ .../studymanager/service/StudyService.java | 2 +- 5 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 studymanager-observation/src/test/java/io/redlink/more/studymanager/component/observation/lime/LimeSurveyObservationTest.java diff --git a/studymanager-observation/src/main/java/io/redlink/more/studymanager/component/observation/lime/LimeSurveyObservation.java b/studymanager-observation/src/main/java/io/redlink/more/studymanager/component/observation/lime/LimeSurveyObservation.java index ac0ee493..8d672ea9 100644 --- a/studymanager-observation/src/main/java/io/redlink/more/studymanager/component/observation/lime/LimeSurveyObservation.java +++ b/studymanager-observation/src/main/java/io/redlink/more/studymanager/component/observation/lime/LimeSurveyObservation.java @@ -20,6 +20,7 @@ public class LimeSurveyObservation extends Observation { + public static final String LIME_SURVEY_ID = "limeSurveyId"; private final LimeSurveyRequestService limeSurveyRequestService; public LimeSurveyObservation(MoreObservationSDK sdk, C properties, LimeSurveyRequestService limeSurveyRequestService) throws ConfigurationValidationException { @@ -29,9 +30,9 @@ public LimeSurveyObservation(MoreObservationSDK sdk, C properties, LimeSurveyReq @Override public void activate(){ + String surveyId = checkAndGetSurveyId(); + Set participantIds = sdk.participantIds(MorePlatformSDK.ParticipantFilter.ALL); - String surveyId = properties.getString("limeSurveyId"); - //TODO disable keys fromm removed? participantIds.removeIf(id -> sdk.getPropertiesForParticipant(id).isPresent()); limeSurveyRequestService.activateParticipants(participantIds, surveyId) .forEach(data -> { @@ -45,6 +46,36 @@ public void activate(){ }); limeSurveyRequestService.setSurveyEndUrl(surveyId, sdk.getStudyId(), sdk.getObservationId()); limeSurveyRequestService.activateSurvey(surveyId); + sdk.setValue(LIME_SURVEY_ID, surveyId); + } + + protected String checkAndGetSurveyId() { + String newSurveyId = properties.getString(LIME_SURVEY_ID); + String activeSurveyId = sdk.getValue(LIME_SURVEY_ID, String.class).orElse(null); + + if(activeSurveyId != null && !activeSurveyId.equals(newSurveyId)) { + throw new RuntimeException(String.format( + "SurveyId on Observation %s must not be changed: %s -> %s", + sdk.getObservationId(), + activeSurveyId, + newSurveyId + )); + } else { + return newSurveyId; + } + } + + + + @Override + public void deactivate() { + // for downwards compatibility (already running studies) + String newSurveyId = properties.getString(LIME_SURVEY_ID); + String activeSurveyId = sdk.getValue(LIME_SURVEY_ID, String.class).orElse(null); + + if(activeSurveyId == null || activeSurveyId.equals(newSurveyId)) { + sdk.setValue(LIME_SURVEY_ID, newSurveyId); + } } public boolean writeDataPoints(String token, int surveyId, int savedId) { diff --git a/studymanager-observation/src/main/java/io/redlink/more/studymanager/component/observation/lime/LimeSurveyRequestService.java b/studymanager-observation/src/main/java/io/redlink/more/studymanager/component/observation/lime/LimeSurveyRequestService.java index 6417d6de..1a63b16f 100644 --- a/studymanager-observation/src/main/java/io/redlink/more/studymanager/component/observation/lime/LimeSurveyRequestService.java +++ b/studymanager-observation/src/main/java/io/redlink/more/studymanager/component/observation/lime/LimeSurveyRequestService.java @@ -138,15 +138,22 @@ private List createParticipants(Set participantIds, St ); LOGGER.info("sent {} participants to lime", participantIds.size()); - List data = mapper.readValue(client.send(request, HttpResponse.BodyHandlers.ofString()).body(), - LimeSurveyParticipantResponse.class) - .result(); + String rsp = client.send(request, HttpResponse.BodyHandlers.ofString()).body(); + + if(rsp.contains("Error: Invalid survey ID")) { + throw new RuntimeException("Invalid survey ID: " + surveyId); + } + + List data = mapper.readValue( + rsp, + LimeSurveyParticipantResponse.class + ).result(); releaseSessionKey(sessionKey); LOGGER.info("result: {}", data.stream().map(ParticipantData::toString).collect(Collectors.joining())); return data; - }catch(IOException | InterruptedException e){ + } catch( IOException | InterruptedException e){ LOGGER.error("Error creating participants for survey {}", surveyId); throw new RuntimeException(e); } diff --git a/studymanager-observation/src/test/java/io/redlink/more/studymanager/component/observation/lime/LimeSurveyObservationTest.java b/studymanager-observation/src/test/java/io/redlink/more/studymanager/component/observation/lime/LimeSurveyObservationTest.java new file mode 100644 index 00000000..ff206f6e --- /dev/null +++ b/studymanager-observation/src/test/java/io/redlink/more/studymanager/component/observation/lime/LimeSurveyObservationTest.java @@ -0,0 +1,37 @@ +package io.redlink.more.studymanager.component.observation.lime; + +import io.redlink.more.studymanager.core.properties.ObservationProperties; +import io.redlink.more.studymanager.core.sdk.MoreObservationSDK; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Optional; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class LimeSurveyObservationTest { + @Test + public void testLimeSurveyIdValidation() { + MoreObservationSDK sdk = mock(MoreObservationSDK.class); + ObservationProperties properties = mock(ObservationProperties.class); + + when(sdk.getValue(anyString(), any())) + .thenReturn(Optional.empty(), Optional.of("equals"), Optional.of("other")); + when(properties.getString(anyString())).thenReturn("valid", "equals", "different"); + + LimeSurveyObservation o = new LimeSurveyObservation(sdk, properties, null); + Assertions.assertEquals("valid", o.checkAndGetSurveyId()); + Assertions.assertEquals("equals", o.checkAndGetSurveyId()); + boolean expectedError = false; + try { + o.checkAndGetSurveyId(); + } catch (RuntimeException e) { + expectedError = true; + } + + Assertions.assertTrue(expectedError); + } +} diff --git a/studymanager/src/main/java/io/redlink/more/studymanager/exception/BadRequestException.java b/studymanager/src/main/java/io/redlink/more/studymanager/exception/BadRequestException.java index 0a951b02..2fce12e0 100644 --- a/studymanager/src/main/java/io/redlink/more/studymanager/exception/BadRequestException.java +++ b/studymanager/src/main/java/io/redlink/more/studymanager/exception/BadRequestException.java @@ -14,10 +14,15 @@ @ResponseStatus(code = HttpStatus.BAD_REQUEST) public class BadRequestException extends RuntimeException { + public BadRequestException(String cause) { super(cause); } + public BadRequestException(String cause, Throwable throwable) { + super(String.format("%s: %s", cause, throwable.getMessage()), throwable); + } + public BadRequestException(Throwable cause) { super(cause); } diff --git a/studymanager/src/main/java/io/redlink/more/studymanager/service/StudyService.java b/studymanager/src/main/java/io/redlink/more/studymanager/service/StudyService.java index 2bb003d0..81247031 100644 --- a/studymanager/src/main/java/io/redlink/more/studymanager/service/StudyService.java +++ b/studymanager/src/main/java/io/redlink/more/studymanager/service/StudyService.java @@ -127,7 +127,7 @@ public void setStatus(Long studyId, Study.Status status, User user) { //ROLLBACK studyRepository.setStateById(studyId, oldState); studyRepository.getById(studyId).ifPresent(this::alignWithStudyState); - throw new BadRequestException("Study cannot be initialized"); + throw new BadRequestException("Study cannot be initialized",e); } }); }