diff --git a/src/main/java/org/gridsuite/study/server/controller/StudyController.java b/src/main/java/org/gridsuite/study/server/controller/StudyController.java index 10a4aa839..240d9dc32 100644 --- a/src/main/java/org/gridsuite/study/server/controller/StudyController.java +++ b/src/main/java/org/gridsuite/study/server/controller/StudyController.java @@ -2492,7 +2492,6 @@ public ResponseEntity setPccMinParameters( @PathVariable("studyUuid") UUID studyUuid, @RequestBody(required = false) String pccMinParametersInfos, @RequestHeader(HEADER_USER_ID) String userId) { - studyService.setPccMinParameters(studyUuid, pccMinParametersInfos, userId); - return ResponseEntity.ok().build(); + return studyService.setPccMinParameters(studyUuid, pccMinParametersInfos, userId) ? ResponseEntity.noContent().build() : ResponseEntity.ok().build(); } } diff --git a/src/main/java/org/gridsuite/study/server/dto/UserProfileInfos.java b/src/main/java/org/gridsuite/study/server/dto/UserProfileInfos.java index 86a55e224..29832caca 100644 --- a/src/main/java/org/gridsuite/study/server/dto/UserProfileInfos.java +++ b/src/main/java/org/gridsuite/study/server/dto/UserProfileInfos.java @@ -32,6 +32,8 @@ public class UserProfileInfos { private UUID shortcircuitParameterId; + private UUID pccMinParameterId; + // note: this parameter is not managed by user-admin-server yet private UUID dynamicSecurityAnalysisParameterId; diff --git a/src/main/java/org/gridsuite/study/server/service/ConsumerService.java b/src/main/java/org/gridsuite/study/server/service/ConsumerService.java index f775df2ee..197b1ec85 100644 --- a/src/main/java/org/gridsuite/study/server/service/ConsumerService.java +++ b/src/main/java/org/gridsuite/study/server/service/ConsumerService.java @@ -297,7 +297,7 @@ private void insertStudy(UUID studyUuid, String userId, NetworkInfos networkInfo UUID voltageInitParametersUuid = createDefaultVoltageInitParameters(userId, userProfileInfos); UUID dynamicSecurityAnalysisParametersUuid = createDefaultDynamicSecurityAnalysisParameters(userId, userProfileInfos); UUID stateEstimationParametersUuid = createDefaultStateEstimationParameters(); - UUID pccMinParametersUuid = createDefaultPccMinParameters(); + UUID pccMinParametersUuid = createDefaultPccMinParameters(userId, userProfileInfos); UUID spreadsheetConfigCollectionUuid = createDefaultSpreadsheetConfigCollection(userId, userProfileInfos); UUID workspacesConfigUuid = createWorkspacesConfig(userProfileInfos); @@ -457,7 +457,18 @@ private UUID createDefaultStateEstimationParameters() { } } - private UUID createDefaultPccMinParameters() { + private UUID createDefaultPccMinParameters(String userId, UserProfileInfos userProfileInfos) { + if (userProfileInfos != null && userProfileInfos.getPccMinParameterId() != null) { + // try to access/duplicate the user profile pccmin parameters + try { + return pccMinService.duplicatePccMinParameters(userProfileInfos.getPccMinParameterId()); + } catch (Exception e) { + // TODO try to report a log in Root subreporter ? + LOGGER.error(String.format("Could not duplicate pccmin parameters with id '%s' from user/profile '%s/%s'. Using default parameters", + userProfileInfos.getPccMinParameterId(), userId, userProfileInfos.getName()), e); + } + } + // no profile, or no/bad pcc min parameters in profile => use default values try { return pccMinService.createDefaultPccMinParameters(); } catch (final Exception e) { diff --git a/src/main/java/org/gridsuite/study/server/service/StudyService.java b/src/main/java/org/gridsuite/study/server/service/StudyService.java index f7021968a..6e254dfb6 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -3476,23 +3476,43 @@ public String getPccMinParameters(UUID studyUuid) { } @Transactional - public void setPccMinParameters(UUID studyUuid, String parameters, String userId) { + public boolean setPccMinParameters(UUID studyUuid, String parameters, String userId) { StudyEntity studyEntity = getStudy(studyUuid); - createOrUpdatePccMinParameters(studyEntity, parameters); + boolean userProfileIssue = createOrUpdatePccMinParameters(studyEntity, parameters, userId); + invalidatePccMinStatusOnAllNodes(studyEntity.getId()); notificationService.emitStudyChanged(studyUuid, null, null, NotificationService.UPDATE_TYPE_PCC_MIN_STATUS); notificationService.emitElementUpdated(studyUuid, userId); notificationService.emitComputationParamsChanged(studyUuid, PCC_MIN); + return userProfileIssue; } - public void createOrUpdatePccMinParameters(StudyEntity studyEntity, String parameters) { + public boolean createOrUpdatePccMinParameters(StudyEntity studyEntity, String parameters, String userId) { UUID existingPccMinParametersUuid = studyEntity.getPccMinParametersUuid(); + boolean userProfileIssue = false; + + UserProfileInfos userProfileInfos = parameters == null ? userAdminService.getUserProfile(userId) : null; + if (parameters == null && userProfileInfos.getPccMinParameterId() != null) { + // reset case, with existing profile, having default pcc min params + try { + UUID pccMinParametersFromProfileUuid = pccMinService.duplicatePccMinParameters(userProfileInfos.getPccMinParameterId()); + studyEntity.setPccMinParametersUuid(pccMinParametersFromProfileUuid); + removePccMinParameters(existingPccMinParametersUuid); + return userProfileIssue; + } catch (Exception e) { + userProfileIssue = true; + LOGGER.error(String.format("Could not duplicate pcc min parameters with id '%s' from user/profile '%s/%s'. Using default parameters", + userProfileInfos.getPccMinParameterId(), userId, userProfileInfos.getName()), e); + // in case of duplication error (ex: wrong/dangling uuid in the profile), move on with default params below + } + } if (existingPccMinParametersUuid == null) { existingPccMinParametersUuid = pccMinService.createPccMinParameters(parameters); studyEntity.setPccMinParametersUuid(existingPccMinParametersUuid); } else { pccMinService.updatePccMinParameters(existingPccMinParametersUuid, parameters); } + return userProfileIssue; } @Transactional diff --git a/src/test/java/org/gridsuite/study/server/PccMinTest.java b/src/test/java/org/gridsuite/study/server/PccMinTest.java index 3a3a68a11..f34c396a3 100644 --- a/src/test/java/org/gridsuite/study/server/PccMinTest.java +++ b/src/test/java/org/gridsuite/study/server/PccMinTest.java @@ -27,6 +27,7 @@ import org.gridsuite.study.server.utils.ResultParameters; import org.gridsuite.study.server.utils.TestUtils; import org.gridsuite.study.server.utils.wiremock.ComputationServerStubs; +import org.gridsuite.study.server.utils.wiremock.UserAdminServerStubs; import org.gridsuite.study.server.utils.wiremock.WireMockStubs; import org.gridsuite.study.server.utils.elasticsearch.DisableElasticsearch; import org.gridsuite.study.server.utils.wiremock.WireMockUtilsCriteria; @@ -57,8 +58,8 @@ import org.springframework.web.client.HttpClientErrorException; import static org.gridsuite.study.server.StudyConstants.*; -import static org.gridsuite.study.server.notification.NotificationService.HEADER_UPDATE_TYPE; -import static org.gridsuite.study.server.notification.NotificationService.UPDATE_TYPE_COMPUTATION_PARAMETERS; +import static org.gridsuite.study.server.notification.NotificationService.*; +import static org.gridsuite.study.server.utils.TestUtils.USER_DEFAULT_PROFILE_JSON; import static org.junit.jupiter.api.Assertions.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @@ -70,7 +71,6 @@ class PccMinTest { private static final String PCC_MIN_URL_BASE = "/v1/studies/{studyUuid}/root-networks/{rootNetworkUuid}/nodes/{nodeUuid}/pcc-min/"; - private static final UUID CASE_LOADFLOW_UUID = UUID.fromString("11a91c11-2c2d-83bb-b45f-20b83e4ef00c"); private static final String NETWORK_UUID_STRING = "38400000-8cf0-11bd-b23e-10b96e4ef00d"; private static final String PCC_MIN_RESULT_UUID = "cf203721-6150-4203-8960-d61d815a9d16"; private static final String PCC_MIN_ERROR_RESULT_UUID = "25222222-9994-4e55-8ec7-07ea965d24eb"; @@ -78,6 +78,8 @@ class PccMinTest { private static final String PCC_MIN_STATUS_JSON = "{\"status\":\"COMPLETED\"}"; private static final String ELEMENT_UPDATE_DESTINATION = "element.update"; + private static final String CASE_UUID_STRING = "00000000-8cf0-11bd-b23e-10b96e4ef00d"; + private static final UUID CASE_UUID = UUID.fromString(CASE_UUID_STRING); private static final String VARIANT_ID = "variant_1"; private static final String VARIANT_ID_2 = "variant_2"; private static final long TIMEOUT = 1000; @@ -88,6 +90,24 @@ class PccMinTest { private static final String PCC_MIN_FAILED_DESTINATION = "pccmin.run.dlx"; private static final byte[] PCC_MIN_RESULTS_AS_ZIPPED_CSV = {0x00, 0x01}; + private static final String NO_PROFILE_USER_ID = "noProfileUser"; + private static final String NO_PARAMS_IN_PROFILE_USER_ID = "noParamInProfileUser"; + private static final String INVALID_PARAMS_IN_PROFILE_USER_ID = "invalidParamInProfileUser"; + private static final String USER_PROFILE_NO_PARAMS_JSON = "{\"id\":\"97bb1890-a90c-43c3-a004-e631246d42d6\",\"name\":\"Profile No params\"}"; + + private static final String PCC_MIN_PARAMETERS_UUID_STRING = "0c0f1efd-bd22-4a75-83d3-9e530245c7f4"; + private static final UUID PCC_MIN_PARAMETERS_UUID = UUID.fromString(PCC_MIN_PARAMETERS_UUID_STRING); + private static final String PCC_MIN_PROFILE_PARAMETERS_JSON = "{\"uuid\":\"7cce52fd-2aca-4d93-9b7b-6a2b4c0c2c11\",\"filters\":[{\"filterId\":\"b5fafd19-25f4-45b9-b5c8-3af51fdc9d1c\",\"filterName\":\"filterName\"}]}"; + + private static final String PROFILE_PCC_MIN_DUPLICATED_PARAMETERS_UUID_STRING = "a4ce25e1-59a7-401d-abb1-04425fe24587"; + private static final String PROFILE_PCC_MIN_INVALID_PARAMETERS_UUID_STRING = "f09f5282-8e34-48b5-b66e-7ef9f3f36c4f"; + private static final String VALID_PARAMS_IN_PROFILE_USER_ID = "validParamInProfileUser"; + private static final String PROFILE_PCC_MIN_VALID_PARAMETERS_UUID_STRING = "1cec4a7b-ab7e-4d78-9dd7-ce73c5ef11d9"; + + private static final String USER_PROFILE_VALID_PARAMS_JSON = "{\"id\":\"97bb1890-a90c-43c3-a004-e631246d42d6\",\"name\":\"Profile with valid pcc min params\",\"pccminParameterId\":\"" + PROFILE_PCC_MIN_VALID_PARAMETERS_UUID_STRING + "\",\"allParametersLinksValid\":true}"; + private static final String USER_PROFILE_INVALID_PARAMS_JSON = "{\"id\":\"97bb1890-a90c-43c3-a004-e631246d42d6\",\"name\":\"Profile with broken pcc min params\",\"pccminParameterId\":\"" + PROFILE_PCC_MIN_INVALID_PARAMETERS_UUID_STRING + "\",\"allParametersLinksValid\":false}"; + private static final String DUPLICATED_PARAMS_JSON = "\"" + PROFILE_PCC_MIN_DUPLICATED_PARAMETERS_UUID_STRING + "\""; + @Autowired private MockMvc mockMvc; @Autowired @@ -118,6 +138,7 @@ class PccMinTest { private WireMockServer wireMockServer; private WireMockStubs wireMockStubs; private ComputationServerStubs computationServerStubs; + private UserAdminServerStubs userAdminServerStubs; @BeforeEach void setup() { @@ -125,6 +146,7 @@ void setup() { wireMockServer.start(); wireMockStubs = new WireMockStubs(wireMockServer); computationServerStubs = new ComputationServerStubs(wireMockServer); + userAdminServerStubs = new UserAdminServerStubs(wireMockServer); configureFor("localhost", wireMockServer.port()); String baseUrl = wireMockServer.baseUrl(); @@ -154,7 +176,7 @@ private static final class StudyNodeIds { private StudyNodeIds createStudyAndNode(String variantId, String nodeName, UUID pccMinParametersUuid) throws Exception { StudyEntity studyEntity = TestUtils.createDummyStudy(UUID.fromString(NETWORK_UUID_STRING), - "netId", CASE_LOADFLOW_UUID, "", "", null, null, null, null, null, null, pccMinParametersUuid); + "netId", CASE_UUID, "", "", null, null, null, null, null, null, pccMinParametersUuid); studyRepository.save(studyEntity); networkModificationTreeService.createRoot(studyEntity); @@ -221,8 +243,8 @@ private void consumePccMinResult(StudyNodeIds ids, String resultUuid) throws Jso MessageHeaders headers = new MessageHeaders(Map.of("resultUuid", resultUuid, HEADER_RECEIVER, resultUuidJson)); consumerService.consumePccMinResult().accept(MessageBuilder.createMessage("", headers)); - checkPccMinMessagesReceived(ids.studyId, NotificationService.UPDATE_TYPE_PCC_MIN_STATUS); - checkPccMinMessagesReceived(ids.studyId, NotificationService.UPDATE_TYPE_PCC_MIN_STATUS); + checkPccMinMessagesReceived(ids.studyId, UPDATE_TYPE_PCC_MIN_STATUS); + checkPccMinMessagesReceived(ids.studyId, UPDATE_TYPE_PCC_MIN_STATUS); checkPccMinMessagesReceived(ids.studyId, NotificationService.UPDATE_TYPE_PCC_MIN_RESULT); wireMockServer.verify(postRequestedFor(urlPathMatching( @@ -270,7 +292,7 @@ void testStop() throws Exception { runPccMin(ids); wireMockServer.stubFor(put(urlPathMatching("/v1/results/" + PCC_MIN_RESULT_UUID + "/stop.*")) - .willReturn(ok())); + .willReturn(ok())); // stop pcc min mockMvc.perform(put(PCC_MIN_URL_BASE + "stop", ids.studyId, ids.rootNetworkUuid, ids.nodeId)) @@ -282,7 +304,7 @@ void testStop() throws Exception { .setHeader("resultUuid", PCC_MIN_RESULT_UUID) .build(); consumerService.consumePccMinStopped().accept(stoppedMessage); - checkPccMinMessagesReceived(ids.studyId, NotificationService.UPDATE_TYPE_PCC_MIN_STATUS); + checkPccMinMessagesReceived(ids.studyId, UPDATE_TYPE_PCC_MIN_STATUS); computationServerStubs.verifyComputationStop(PCC_MIN_RESULT_UUID, Map.of("receiver", WireMock.matching(".*"))); } @@ -303,7 +325,7 @@ void testFailure() throws Exception { .build(); consumerService.consumePccMinFailed().accept(failedMessage); - checkPccMinMessagesReceived(ids.studyId, NotificationService.UPDATE_TYPE_PCC_MIN_STATUS); + checkPccMinMessagesReceived(ids.studyId, UPDATE_TYPE_PCC_MIN_STATUS); checkPccMinMessagesReceived(ids.studyId, NotificationService.UPDATE_TYPE_PCC_MIN_FAILED); wireMockStubs.verifyPccMinFail(stubFail, NETWORK_UUID_STRING, VARIANT_ID_2); @@ -385,24 +407,24 @@ void testGetPccMinResults() throws Exception { wireMockServer.verify(0, WireMock.getRequestedFor(WireMock.urlMatching("/v1/pcc-min/results/.*"))); } - private void createOrUpdateParametersAndDoChecks(UUID studyNameUserIdUuid, String parameters, HttpStatusCode status) throws Exception { + private void createOrUpdateParametersAndDoChecks(UUID studyUuid, String parameters, String userId, HttpStatusCode status) throws Exception { mockMvc.perform( - post("/v1/studies/{studyUuid}/pcc-min/parameters", studyNameUserIdUuid) - .header("userId", "userId") + post("/v1/studies/{studyUuid}/pcc-min/parameters", studyUuid) + .header("userId", userId) .contentType(MediaType.ALL) .content(parameters)) .andExpect(status().is(status.value())); Message message = output.receive(TIMEOUT, STUDY_UPDATE_DESTINATION); - assertEquals(studyNameUserIdUuid, message.getHeaders().get(NotificationService.HEADER_STUDY_UUID)); - assertEquals(NotificationService.UPDATE_TYPE_PCC_MIN_STATUS, message.getHeaders().get(NotificationService.HEADER_UPDATE_TYPE)); + assertEquals(studyUuid, message.getHeaders().get(NotificationService.HEADER_STUDY_UUID)); + assertEquals(UPDATE_TYPE_PCC_MIN_STATUS, message.getHeaders().get(NotificationService.HEADER_UPDATE_TYPE)); message = output.receive(TIMEOUT, STUDY_UPDATE_DESTINATION); - assertEquals(studyNameUserIdUuid, message.getHeaders().get(NotificationService.HEADER_STUDY_UUID)); + assertEquals(studyUuid, message.getHeaders().get(NotificationService.HEADER_STUDY_UUID)); assertEquals(UPDATE_TYPE_COMPUTATION_PARAMETERS, message.getHeaders().get(NotificationService.HEADER_UPDATE_TYPE)); message = output.receive(TIMEOUT, ELEMENT_UPDATE_DESTINATION); - assertEquals(studyNameUserIdUuid, message.getHeaders().get(NotificationService.HEADER_ELEMENT_UUID)); + assertEquals(studyUuid, message.getHeaders().get(NotificationService.HEADER_ELEMENT_UUID)); } private StudyEntity insertDummyStudy(UUID networkUuid, UUID caseUuid, UUID pccMinParametersUuid) { @@ -454,7 +476,7 @@ void testSetPccMinParameters() throws Exception { .willReturn(ok())); UUID studyUuid = insertDummyStudy(UUID.randomUUID(), UUID.randomUUID(), PCCMIN_PARAMETERS_UUID).getId(); - createOrUpdateParametersAndDoChecks(studyUuid, parameterToUpdate, HttpStatus.OK); + createOrUpdateParametersAndDoChecks(studyUuid, parameterToUpdate, "userId", HttpStatus.OK); wireMockServer.verify(putRequestedFor(urlPathEqualTo("/v1/parameters/" + PCCMIN_PARAMETERS_UUID))); // Fail case @@ -570,4 +592,54 @@ void testExportPccMinResults() throws Exception { assertThrows(StudyException.class, () -> pccMinService.exportPccMinResultsAsCsv(null, "", null, null, Sort.unsorted(), null, null)); } + + private void testMessages(UUID studyNameUserIdUuid) { + Message message = output.receive(TIMEOUT, STUDY_UPDATE_DESTINATION); + assertEquals(studyNameUserIdUuid, message.getHeaders().get(NotificationService.HEADER_STUDY_UUID)); + assertEquals(NotificationService.UPDATE_TYPE_PCC_MIN_STATUS, message.getHeaders().get(NotificationService.HEADER_UPDATE_TYPE)); + message = output.receive(TIMEOUT, ELEMENT_UPDATE_DESTINATION); + assertEquals(studyNameUserIdUuid, message.getHeaders().get(NotificationService.HEADER_ELEMENT_UUID)); + message = output.receive(TIMEOUT, STUDY_UPDATE_DESTINATION); + assertEquals(UPDATE_TYPE_COMPUTATION_PARAMETERS, message.getHeaders().get(NotificationService.HEADER_UPDATE_TYPE)); + } + + private void updateParametersAndDoChecks(UUID studyNameUserIdUuid, String parameters, String userId, HttpStatusCode status, String returnedUserProfileJson, boolean shouldDuplicate, String duplicateFromUuid, boolean duplicateIsNotFound) throws Exception { + wireMockStubs.loadflowServer.stubPutLoadflowParameters(PccMinTest.PCC_MIN_PARAMETERS_UUID_STRING, parameters); + UUID duplicatedLoadflowParametersUuid = UUID.randomUUID(); + if (parameters == null || parameters.isEmpty()) { + wireMockStubs.userAdminServer.stubGetUserProfile(userId, returnedUserProfileJson); + } + if (shouldDuplicate) { + wireMockStubs.loadflowServer.stubDuplicateLoadflowParameters(duplicateFromUuid, objectMapper.writeValueAsString(duplicatedLoadflowParametersUuid), duplicateIsNotFound); + } + mockMvc.perform( + post("/v1/studies/{studyUuid}/pcc-min/parameters", studyNameUserIdUuid) + .header("userId", userId) + .contentType(MediaType.ALL) + .content(parameters == null ? "" : parameters)) + .andExpect(status().is(status.value())); + wireMockStubs.loadflowServer.verifyPutLoadflowParameters(PccMinTest.PCC_MIN_PARAMETERS_UUID_STRING, parameters); + if (parameters == null || parameters.isEmpty()) { + wireMockStubs.userAdminServer.verifyGetUserProfile(userId); + } + if (shouldDuplicate) { + wireMockStubs.loadflowServer.verifyDuplicateLoadflowParameters(duplicateFromUuid); + } + testMessages(studyNameUserIdUuid); + } + + @Test + void testResetPccMinParametersUserHasNoProfile() throws Exception { + StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, PCC_MIN_PARAMETERS_UUID); + UUID studyNameUserIdUuid = studyEntity.getId(); + updateParametersAndDoChecks(studyNameUserIdUuid, "", NO_PROFILE_USER_ID, HttpStatus.OK, USER_DEFAULT_PROFILE_JSON, false, null, false); + } + + @Test + void testResetPccMinParametersUserHasNoParamsInProfile() throws Exception { + StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, PCC_MIN_PARAMETERS_UUID); + UUID studyNameUserIdUuid = studyEntity.getId(); + updateParametersAndDoChecks(studyNameUserIdUuid, "", NO_PARAMS_IN_PROFILE_USER_ID, HttpStatus.OK, USER_PROFILE_NO_PARAMS_JSON, false, null, false); + } } +