diff --git a/src/main/java/de/imi/mopat/helper/controller/QuestionnaireService.java b/src/main/java/de/imi/mopat/helper/controller/QuestionnaireService.java index 359e03c8..41676257 100644 --- a/src/main/java/de/imi/mopat/helper/controller/QuestionnaireService.java +++ b/src/main/java/de/imi/mopat/helper/controller/QuestionnaireService.java @@ -196,13 +196,13 @@ public Optional getQuestionnaireDTOById(Long questionnaireId) public boolean editingQuestionnaireAllowed(QuestionnaireDTO questionnaireDTO) { Questionnaire questionnaire = questionnaireDao.getElementById(questionnaireDTO.getId()); - // Admins and moderators can edit if there are no encounters - if (authService.hasRoleOrAbove(UserRole.ROLE_MODERATOR)) { + // Admins can edit if there are no encounters + if (authService.hasRoleOrAbove(UserRole.ROLE_ADMIN)) { return questionnaire.isModifiable(); } - // Editors can edit if questionnaire is not part of any bundle that is enabled or if the bundle has executed encounters - if (authService.hasExactRole(UserRole.ROLE_EDITOR)) { + // Moderators and Editors can edit if questionnaire is not part of any bundle that is enabled or if the bundle has executed encounters + if (authService.hasExactRole(UserRole.ROLE_MODERATOR) || authService.hasExactRole(UserRole.ROLE_EDITOR)) { return questionnaire.isModifiable() && !isQuestionnairePartOfEnabledBundle(questionnaire); } @@ -228,11 +228,11 @@ public Pair canEditQuestionnaireWithReason(QuestionnaireDTO que boolean isModifiable = questionnaire.isModifiable(); boolean partOfEnabledBundle = isQuestionnairePartOfEnabledBundle(questionnaire); - if (authService.hasRoleOrAbove(UserRole.ROLE_MODERATOR) && !isModifiable) { + if (authService.hasRoleOrAbove(UserRole.ROLE_ADMIN) && !isModifiable) { return Pair.of(false, getLocalizedMessage("questionnaire.message.executedEncounters")); } - if (authService.hasExactRole(UserRole.ROLE_EDITOR)) { + if (authService.hasExactRole(UserRole.ROLE_MODERATOR) || authService.hasExactRole(UserRole.ROLE_EDITOR)) { if (!isModifiable && partOfEnabledBundle) { return Pair.of(false, getLocalizedMessage("questionnaire.message.executedEncountersAndEnabledBundle")); } diff --git a/src/test/java/de/imi/mopat/helper/controller/QuestionnaireServiceTest.java b/src/test/java/de/imi/mopat/helper/controller/QuestionnaireServiceTest.java index eb4f443d..99b80d03 100644 --- a/src/test/java/de/imi/mopat/helper/controller/QuestionnaireServiceTest.java +++ b/src/test/java/de/imi/mopat/helper/controller/QuestionnaireServiceTest.java @@ -291,7 +291,7 @@ public void testSaveOrUpdateQuestionnaire_CreateNew() { * Valid input: valid {@link QuestionnaireDTO} with ID, and admin can edit the questionnaire without executed surveys */ @Test - public void testSaveOrUpdateQuestionnaire_AdminModeratorCanEditQuestionnaireWithoutExecutedSurveys() { + public void testSaveOrUpdateQuestionnaire_AdminCanEditQuestionnaireWithoutExecutedSurveys() { // Arrange Questionnaire newValidQuestionnaire = createAndPersistQuestionnaire(); QuestionnaireDTO validQuestionnaireDTO = QuestionnaireDTOTest.getNewValidQuestionnaireDTO(); @@ -299,7 +299,7 @@ public void testSaveOrUpdateQuestionnaire_AdminModeratorCanEditQuestionnaireWith Long validUserId = Helper.generatePositiveNonZeroLong(); Questionnaire modifiableQuestionnaire = spy(QuestionnaireTest.getNewValidQuestionnaire()); - when(authService.hasRoleOrAbove(UserRole.ROLE_MODERATOR)).thenReturn(true); + when(authService.hasRoleOrAbove(UserRole.ROLE_ADMIN)).thenReturn(true); doReturn(true).when(modifiableQuestionnaire).isModifiable(); doReturn(Helper.generatePositiveNonZeroLong()).when(modifiableQuestionnaire).getId(); @@ -322,7 +322,7 @@ public void testSaveOrUpdateQuestionnaire_AdminModeratorCanEditQuestionnaireWith * Valid input: valid {@link QuestionnaireDTO} with ID, but admin can't edit the questionnaire with executed surveys */ @Test - public void testSaveOrUpdateQuestionnaire_AdminModeratorCantEditQuestionnaireWithExecutedSurvey() { + public void testSaveOrUpdateQuestionnaire_AdminCantEditQuestionnaireWithExecutedSurvey() { // Arrange Questionnaire existingQUestionnaire = createAndPersistQuestionnaire(); Question testQuestion = QuestionTest.getNewValidQuestion(existingQUestionnaire); @@ -343,7 +343,7 @@ public void testSaveOrUpdateQuestionnaire_AdminModeratorCantEditQuestionnaireWit Long userId = Helper.generatePositiveNonZeroLong(); Questionnaire newQuestionnaire = QuestionnaireTest.getNewValidQuestionnaire(); - when(authService.hasRoleOrAbove(UserRole.ROLE_MODERATOR)).thenReturn(true); + when(authService.hasRoleOrAbove(UserRole.ROLE_ADMIN)).thenReturn(true); when(questionnaireFactory.createQuestionnaire(any(), any(), any(), any())).thenReturn(newQuestionnaire); // Mock question duplication with empty maps @@ -368,6 +368,56 @@ public void testSaveOrUpdateQuestionnaire_AdminModeratorCantEditQuestionnaireWit questionnaireDao.remove(result); } + /** + * Test of {@link QuestionnaireService#saveOrUpdateQuestionnaire}
+ * Valid input: valid {@link QuestionnaireDTO} with ID, and moderator cannot edit the questionnaire if it has executed surveys + */ + @Test + public void testSaveOrUpdateQuestionnaire_ModeratorCannotEditWithExecutedSurveys() { + // Arrange + Questionnaire existingQUestionnaire = createAndPersistQuestionnaire(); + Question existingQuestion = QuestionTest.getNewValidQuestion(existingQUestionnaire); + questionDao.merge(existingQuestion); + SliderFreetextAnswer existingAnswer = SliderFreetextAnswerTest.getNewValidSliderFreetextAnswer(); + existingAnswer.setQuestion(existingQuestion); + answerDao.merge(existingAnswer); + Bundle existingBundle = BundleTest.getNewValidBundle(); + bundleDao.merge(existingBundle); + Encounter testEncounter = EncounterTest.getNewValidEncounter(existingBundle); + encounterDao.merge(testEncounter); + Response testResponse = new Response(existingAnswer, testEncounter); + responseDao.merge(testResponse); + questionnaireDao.merge(existingQUestionnaire); + + QuestionnaireDTO questionnaireDTO = QuestionnaireDTOTest.getNewValidQuestionnaireDTO(); + questionnaireDTO.setId(existingQUestionnaire.getId()); + Long userId = Helper.generatePositiveNonZeroLong(); + Questionnaire newQuestionnaire = QuestionnaireTest.getNewValidQuestionnaire(); + when(authService.hasExactRole(UserRole.ROLE_MODERATOR)).thenReturn(true); + when(questionnaireFactory.createQuestionnaire(any(), any(), any(), any())).thenReturn(newQuestionnaire); + + // Mock question duplication with empty maps + when(questionService.duplicateQuestionsToNewQuestionnaire(anySet(), any(Questionnaire.class))).thenReturn(newQuestionnaire); + when(questionService.getMappingForDuplicatedQuestions(any(Questionnaire.class), any(Questionnaire.class))).thenReturn(new MapHolder(Collections.emptyMap(), Collections.emptyMap())); + + // Act + Questionnaire result = questionnaireService.saveOrUpdateQuestionnaire( + questionnaireDTO, + MultipartFileUtils.getEmptyLogo(), + userId + ); + + // Assert + Assert.assertNotNull("The created questionnaire should not be null", result); + verify(questionService, atLeastOnce()).duplicateQuestionsToNewQuestionnaire(anySet(), any(Questionnaire.class)); // Ensure questions are copied, implying it's an update + + responseDao.remove(testResponse); + encounterDao.remove(testEncounter); + bundleDao.remove(existingBundle); + questionnaireDao.remove(existingQUestionnaire); + questionnaireDao.remove(result); + } + /** * Test of {@link QuestionnaireService#saveOrUpdateQuestionnaire}
* Valid input: valid {@link QuestionnaireDTO} with ID, and editor cannot edit the questionnaire if it has executed surveys @@ -418,6 +468,51 @@ public void testSaveOrUpdateQuestionnaire_EditorCannotEditWithExecutedSurveys() questionnaireDao.remove(result); } + /** + * Test of {@link QuestionnaireService#saveOrUpdateQuestionnaire}
+ * Valid input: valid {@link QuestionnaireDTO} with ID, and moderator cannot edit the questionnaire if it belongs to a bundle that is enabled + */ + @Test + public void testSaveOrUpdateQuestionnaire_ModeratorCannotEditIfPartOfEnabledBundle() throws Exception { + // Arrange + Questionnaire testQuestionnaire = createAndPersistQuestionnaire(); + QuestionnaireDTO validQuestionnaireDTO = QuestionnaireDTOTest.getNewValidQuestionnaireDTO(); + validQuestionnaireDTO.setId(testQuestionnaire.getId()); + Long validUserId = Helper.generatePositiveNonZeroLong(); + + Questionnaire existingQuestionnaire = spy(QuestionnaireTest.getNewValidQuestionnaire()); + Questionnaire copiedQuestionnaire = QuestionnaireTest.getNewValidQuestionnaire(); + + BundleQuestionnaire enabledBundleQuestionnaire = BundleQuestionnaireTest.getNewValidBundleQuestionnaire(); + enabledBundleQuestionnaire.setIsEnabled(true); + List bundleQuestionnaireList = List.of(enabledBundleQuestionnaire); + + when(bundleService.findByQuestionnaireId(any())).thenReturn(bundleQuestionnaireList); + when(authService.hasExactRole(UserRole.ROLE_MODERATOR)).thenReturn(true); + when(questionnaireFactory.createQuestionnaire(any(), any(), any(), any())).thenReturn(copiedQuestionnaire); + doReturn(true).when(existingQuestionnaire).isModifiable(); + doReturn(Helper.generatePositiveNonZeroLong()).when(existingQuestionnaire).getId(); + + // Mock question duplication with empty maps + when(questionService.duplicateQuestionsToNewQuestionnaire(anySet(), any(Questionnaire.class))).thenReturn(copiedQuestionnaire); + when(questionService.getMappingForDuplicatedQuestions(any(Questionnaire.class), any(Questionnaire.class))).thenReturn(new MapHolder(Collections.emptyMap(), Collections.emptyMap())); + + // Act + Questionnaire result = questionnaireService.saveOrUpdateQuestionnaire( + validQuestionnaireDTO, + MultipartFileUtils.getEmptyLogo(), + validUserId + ); + + // Assert + Assert.assertNotNull("The created questionnaire should not be null", result); + verify(questionService, times(1)).duplicateQuestionsToNewQuestionnaire(anySet(), eq(copiedQuestionnaire)); // Ensure questions are copied to the new questionnaire + + questionnaireDao.remove(testQuestionnaire); + questionnaireDao.remove(copiedQuestionnaire); + + } + /** * Test of {@link QuestionnaireService#saveOrUpdateQuestionnaire}
* Valid input: valid {@link QuestionnaireDTO} with ID, and editor cannot edit the questionnaire if it belongs to a bundle that is enabled @@ -463,6 +558,47 @@ public void testSaveOrUpdateQuestionnaire_EditorCannotEditIfPartOfEnabledBundle( } + /** + * Test of {@link QuestionnaireService#saveOrUpdateQuestionnaire}
+ * Valid input: valid {@link QuestionnaireDTO} with ID, and moderator can edit the questionnaire if it does not belong to a bundle that is enabled + */ + @Test + public void testSaveOrUpdateQuestionnaire_ModeratorCanEditIfNotPartOfEnabledBundle() { + // Arrange + Questionnaire testQuestionnaire = createAndPersistQuestionnaire(); + QuestionnaireDTO validQuestionnaireDTO = QuestionnaireDTOTest.getNewValidQuestionnaireDTO(); + validQuestionnaireDTO.setId(testQuestionnaire.getId()); + Long validUserId = Helper.generatePositiveNonZeroLong(); + + Questionnaire existingQuestionnaire = spy(QuestionnaireTest.getNewValidQuestionnaire()); + Questionnaire copiedQuestionnaire = QuestionnaireTest.getNewValidQuestionnaire(); + + // Create a BundleQuestionnaire with isEnabled set to false + BundleQuestionnaire newValidBundleQuestionnaire = BundleQuestionnaireTest.getNewValidBundleQuestionnaire(); + newValidBundleQuestionnaire.setIsEnabled(false); + List bundleQuestionnaireList = List.of(newValidBundleQuestionnaire); + + when(bundleService.findByQuestionnaireId(any())).thenReturn(bundleQuestionnaireList); + when(authService.hasExactRole(UserRole.ROLE_MODERATOR)).thenReturn(true); + when(questionnaireFactory.createQuestionnaire(any(), any(), any(), any())).thenReturn(copiedQuestionnaire); + doReturn(true).when(existingQuestionnaire).isModifiable(); + doReturn(1L).when(existingQuestionnaire).getId(); + + // Act + Questionnaire result = questionnaireService.saveOrUpdateQuestionnaire( + validQuestionnaireDTO, + MultipartFileUtils.getEmptyLogo(), + validUserId + ); + + // Assert + Assert.assertNotNull("The updated questionnaire should not be null", result); + verify(questionService, never()).duplicateQuestionsToNewQuestionnaire(anySet(), any(Questionnaire.class)); // Ensure no questions are copied, implying it's an update + + questionnaireDao.remove(testQuestionnaire); + questionnaireDao.remove(copiedQuestionnaire); + } + /** * Test of {@link QuestionnaireService#saveOrUpdateQuestionnaire}
* Valid input: valid {@link QuestionnaireDTO} with ID, and editor can edit the questionnaire if it does not belong to a bundle that is enabled