Skip to content

Commit 9cd3eb6

Browse files
freddidierRTEClementBouvierN
authored andcommitted
Refacto : Extract ack an read logic in a new backend service
Signed-off-by: freddidierRTE <[email protected]>
1 parent 4db679b commit 9cd3eb6

File tree

6 files changed

+177
-76
lines changed

6 files changed

+177
-76
lines changed

services/cards-publication/src/main/java/org/opfab/cards/publication/configuration/Services.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.opfab.cards.publication.services.CardDeletionService;
2020
import org.opfab.cards.publication.services.CardNotificationService;
2121
import org.opfab.cards.publication.services.CardProcessingService;
22+
import org.opfab.cards.publication.services.CardReadAndAckService;
2223
import org.opfab.cards.publication.services.CardTranslationService;
2324
import org.opfab.cards.publication.services.CardValidationService;
2425
import org.opfab.cards.publication.services.ExternalAppService;
@@ -38,6 +39,8 @@ public class Services {
3839

3940
private final CardTranslationService cardTranslationService;
4041

42+
private final CardReadAndAckService cardReadAndAckService;
43+
4144
private final UserActionLogService userActionLogService;
4245

4346
private final CardValidationService cardValidationService;
@@ -65,7 +68,8 @@ public class Services {
6568
this.cardTranslationService = new CardTranslationService(i18nRepository.get());
6669
}
6770
this.userActionLogService = userActionLogService;
68-
CardNotificationService cardNotificationService = new CardNotificationService(eventBus, objectMapper, customScreenDataFields);
71+
CardNotificationService cardNotificationService = new CardNotificationService(eventBus, objectMapper,
72+
customScreenDataFields);
6973
cardValidationService = new CardValidationService(cardRepository,
7074
new ProcessRepositoryImpl(businessconfigUrl, eventBus));
7175
cardDeletionService = new CardDeletionService(cardNotificationService, cardRepository, externalAppService,
@@ -76,6 +80,7 @@ public class Services {
7680
checkPerimeterForCardSending,
7781
authorizeToSendCardWithInvalidProcessState, cardSendingLimitCardCount, cardSendingLimitPeriod,
7882
activateCardSendingLimiter);
83+
cardReadAndAckService = new CardReadAndAckService(cardNotificationService, cardRepository);
7984

8085
}
8186

@@ -91,6 +96,10 @@ public CardProcessingService getCardProcessingService() {
9196
return cardProcessingService;
9297
}
9398

99+
public CardReadAndAckService getCardReadAndAckService() {
100+
return cardReadAndAckService;
101+
}
102+
94103
public CardTranslationService getCardTranslationService() {
95104
return cardTranslationService;
96105
}

services/cards-publication/src/main/java/org/opfab/cards/publication/controllers/CardController.java

+8-5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.opfab.cards.publication.repositories.UserBasedOperationResult;
2020
import org.opfab.cards.publication.services.CardDeletionService;
2121
import org.opfab.cards.publication.services.CardProcessingService;
22+
import org.opfab.cards.publication.services.CardReadAndAckService;
2223
import org.opfab.cards.publication.services.CardTranslationService;
2324
import org.opfab.springtools.configuration.oauth.OpFabJwtAuthenticationToken;
2425
import org.opfab.users.model.CurrentUserWithPerimeters;
@@ -44,6 +45,7 @@ public class CardController {
4445
private CardDeletionService cardDeletionService;
4546
private CardProcessingService cardProcessingService;
4647
private CardTranslationService cardTranslationService;
48+
private CardReadAndAckService cardReadAndAckService;
4749
private UserActionLogService userActionLogService;
4850

4951
private @Value("${operatorfabric.userActionLogActivated:true}") boolean userActionLogActivated;
@@ -54,6 +56,7 @@ public class CardController {
5456
cardTranslationService = services.getCardTranslationService();
5557
userActionLogService = services.getUserActionLogService();
5658
cardProcessingService = services.getCardProcessingService();
59+
cardReadAndAckService = services.getCardReadAndAckService();
5760

5861
}
5962

@@ -174,7 +177,7 @@ public Void postUserAcknowledgement(Principal principal,
174177
OpFabJwtAuthenticationToken jwtPrincipal = (OpFabJwtAuthenticationToken) principal;
175178
CurrentUserWithPerimeters user = (CurrentUserWithPerimeters) jwtPrincipal.getPrincipal();
176179

177-
UserBasedOperationResult result = cardProcessingService.processUserAcknowledgement(cardUid, user, entitiesAcks);
180+
UserBasedOperationResult result = cardReadAndAckService.processUserAcknowledgement(cardUid, user, entitiesAcks);
178181

179182
if (!result.isCardFound())
180183
response.setStatus(404);
@@ -202,7 +205,7 @@ public Void postUserCardRead(Principal principal,
202205
OpFabJwtAuthenticationToken jwtPrincipal = (OpFabJwtAuthenticationToken) principal;
203206
CurrentUserWithPerimeters user = (CurrentUserWithPerimeters) jwtPrincipal.getPrincipal();
204207

205-
UserBasedOperationResult result = cardProcessingService.processUserRead(cardUid, user.getUserData().getLogin());
208+
UserBasedOperationResult result = cardReadAndAckService.processUserRead(cardUid, user.getUserData().getLogin());
206209
if (!result.isCardFound())
207210
response.setStatus(404);
208211
else {
@@ -228,7 +231,7 @@ public Void deleteUserAcknowledgement(Principal principal, @PathVariable("cardUi
228231
HttpServletResponse response) {
229232
OpFabJwtAuthenticationToken jwtPrincipal = (OpFabJwtAuthenticationToken) principal;
230233
CurrentUserWithPerimeters user = (CurrentUserWithPerimeters) jwtPrincipal.getPrincipal();
231-
UserBasedOperationResult result = cardProcessingService.deleteUserAcknowledgement(cardUid, user, entitiesAcks);
234+
UserBasedOperationResult result = cardReadAndAckService.deleteUserAcknowledgement(cardUid, user, entitiesAcks);
232235
if (!result.isCardFound())
233236
response.setStatus(404);
234237
else {
@@ -253,7 +256,7 @@ public Void deleteUserRead(Principal principal, @PathVariable("cardUid") String
253256
HttpServletResponse response) {
254257
OpFabJwtAuthenticationToken jwtPrincipal = (OpFabJwtAuthenticationToken) principal;
255258
CurrentUserWithPerimeters user = (CurrentUserWithPerimeters) jwtPrincipal.getPrincipal();
256-
UserBasedOperationResult result = cardProcessingService.deleteUserRead(cardUid, user.getUserData().getLogin());
259+
UserBasedOperationResult result = cardReadAndAckService.deleteUserRead(cardUid, user.getUserData().getLogin());
257260
if (!result.isCardFound())
258261
response.setStatus(404);
259262
else {
@@ -303,7 +306,7 @@ public TranslatedField translateCardField(HttpServletRequest request, HttpServle
303306
public Void postResetReadAndAcks(Principal principal,
304307
@PathVariable("cardUid") String cardUid, HttpServletResponse response) {
305308

306-
UserBasedOperationResult result = cardProcessingService.resetReadAndAcks(cardUid);
309+
UserBasedOperationResult result = cardReadAndAckService.resetReadAndAcks(cardUid);
307310
if (!result.isCardFound())
308311
response.setStatus(404);
309312
else {

services/cards-publication/src/main/java/org/opfab/cards/publication/services/CardProcessingService.java

-59
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import org.opfab.cards.publication.model.*;
1313
import org.opfab.cards.publication.ratelimiter.CardSendingLimiter;
1414
import org.opfab.cards.publication.repositories.CardRepository;
15-
import org.opfab.cards.publication.repositories.UserBasedOperationResult;
1615
import org.opfab.springtools.error.model.ApiError;
1716
import org.opfab.springtools.error.model.ApiErrorException;
1817
import org.opfab.users.model.CurrentUserWithPerimeters;
@@ -270,64 +269,6 @@ private String buildPublisherErrorMessage(Card card, String login) {
270269
return errorMessagePrefix + ", the card cannot be sent";
271270
}
272271

273-
public UserBasedOperationResult processUserAcknowledgement(String cardUid, CurrentUserWithPerimeters user,
274-
List<String> entitiesAcks) {
275-
if (cardPermissionControlService.isCurrentUserReadOnly(user) && entitiesAcks != null && !entitiesAcks.isEmpty())
276-
throw new ApiErrorException(
277-
new ApiError(HttpStatus.FORBIDDEN, "Acknowledgement impossible : User has READONLY opfab role"));
278-
279-
if (!user.getUserData().getEntities().containsAll(entitiesAcks))
280-
throw new ApiErrorException(
281-
new ApiError(HttpStatus.FORBIDDEN,
282-
"Acknowledgement impossible : User is not member of all the entities given in the request"));
283-
284-
cardRepository.findByUid(cardUid).ifPresent(selectedCard -> cardNotificationService
285-
.pushAckOfCardInEventBus(cardUid, selectedCard.id, entitiesAcks, CardOperationTypeEnum.ACK));
286-
287-
log.info("Set ack on card with uid {} for user {} and entities {}", cardUid, user.getUserData().getLogin(),
288-
entitiesAcks);
289-
return cardRepository.addUserAck(user.getUserData(), cardUid, entitiesAcks);
290-
}
291-
292-
public UserBasedOperationResult processUserRead(String cardUid, String userName) {
293-
log.info("Set read on card with uid {} for user {} ", cardUid, userName);
294-
return cardRepository.addUserRead(userName, cardUid);
295-
}
296-
297-
public UserBasedOperationResult deleteUserRead(String cardUid, String userName) {
298-
log.info("Delete read on card with uid {} for user {} ", cardUid, userName);
299-
return cardRepository.deleteUserRead(userName, cardUid);
300-
}
301-
302-
public UserBasedOperationResult deleteUserAcknowledgement(String cardUid, CurrentUserWithPerimeters user,
303-
List<String> entitiesAcks) {
304-
log.info("Delete ack on card with uid {} for user {} and entities {} ", cardUid, user.getUserData().getLogin(),
305-
entitiesAcks);
306-
307-
if (!user.getUserData().getEntities().containsAll(entitiesAcks))
308-
throw new ApiErrorException(
309-
310-
new ApiError(HttpStatus.FORBIDDEN,
311-
"Cancel acknowledgement impossible : User is not member of all the entities given in the request"));
312-
313-
cardRepository.findByUid(cardUid).ifPresent(selectedCard -> cardNotificationService
314-
.pushAckOfCardInEventBus(cardUid, selectedCard.id, entitiesAcks, CardOperationTypeEnum.UNACK));
315-
316-
return cardRepository.deleteUserAck(user.getUserData().getLogin(), cardUid, entitiesAcks);
317-
318-
}
319-
320-
public UserBasedOperationResult resetReadAndAcks(String cardUid) {
321-
log.info("Delete ack and reads on card with uid {} ", cardUid);
322-
UserBasedOperationResult acksResult = cardRepository.deleteAcksAndReads(cardUid);
323-
if (acksResult.isCardFound()) {
324-
cardRepository.findByUid(cardUid)
325-
.ifPresent(card -> cardNotificationService.notifyOneCard(card, CardOperationTypeEnum.UPDATE));
326-
}
327-
328-
return acksResult;
329-
}
330-
331272
public void resetRateLimiter() {
332273
this.cardSendingLimiter.reset();
333274
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
2+
/* Copyright (c) 2018-2025, RTE (http://www.rte-france.com)
3+
* See AUTHORS.txt
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
7+
* SPDX-License-Identifier: MPL-2.0
8+
* This file is part of the OperatorFabric project.
9+
*/
10+
11+
package org.opfab.cards.publication.services;
12+
13+
import org.opfab.cards.publication.model.*;
14+
import org.opfab.cards.publication.repositories.CardRepository;
15+
import org.opfab.cards.publication.repositories.UserBasedOperationResult;
16+
import org.opfab.springtools.error.model.ApiError;
17+
import org.opfab.springtools.error.model.ApiErrorException;
18+
import org.opfab.users.model.CurrentUserWithPerimeters;
19+
import org.springframework.http.HttpStatus;
20+
import java.util.List;
21+
22+
public class CardReadAndAckService {
23+
24+
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CardReadAndAckService.class);
25+
26+
private CardNotificationService cardNotificationService;
27+
private CardRepository cardRepository;
28+
private CardPermissionControlService cardPermissionControlService;
29+
30+
public CardReadAndAckService(
31+
CardNotificationService cardNotificationService,
32+
CardRepository cardRepository) {
33+
this.cardNotificationService = cardNotificationService;
34+
this.cardRepository = cardRepository;
35+
this.cardPermissionControlService = new CardPermissionControlService();
36+
37+
}
38+
39+
public UserBasedOperationResult processUserAcknowledgement(String cardUid, CurrentUserWithPerimeters user,
40+
List<String> entitiesAcks) {
41+
if (cardPermissionControlService.isCurrentUserReadOnly(user) && entitiesAcks != null && !entitiesAcks.isEmpty())
42+
throw new ApiErrorException(
43+
new ApiError(HttpStatus.FORBIDDEN, "Acknowledgement impossible : User has READONLY opfab role"));
44+
45+
if (!user.getUserData().getEntities().containsAll(entitiesAcks))
46+
throw new ApiErrorException(
47+
new ApiError(HttpStatus.FORBIDDEN,
48+
"Acknowledgement impossible : User is not member of all the entities given in the request"));
49+
50+
cardRepository.findByUid(cardUid).ifPresent(selectedCard -> cardNotificationService
51+
.pushAckOfCardInEventBus(cardUid, selectedCard.id, entitiesAcks, CardOperationTypeEnum.ACK));
52+
53+
log.info("Set ack on card with uid {} for user {} and entities {}", cardUid, user.getUserData().getLogin(),
54+
entitiesAcks);
55+
return cardRepository.addUserAck(user.getUserData(), cardUid, entitiesAcks);
56+
}
57+
58+
public UserBasedOperationResult processUserRead(String cardUid, String userName) {
59+
log.info("Set read on card with uid {} for user {} ", cardUid, userName);
60+
return cardRepository.addUserRead(userName, cardUid);
61+
}
62+
63+
public UserBasedOperationResult deleteUserRead(String cardUid, String userName) {
64+
log.info("Delete read on card with uid {} for user {} ", cardUid, userName);
65+
return cardRepository.deleteUserRead(userName, cardUid);
66+
}
67+
68+
public UserBasedOperationResult deleteUserAcknowledgement(String cardUid, CurrentUserWithPerimeters user,
69+
List<String> entitiesAcks) {
70+
log.info("Delete ack on card with uid {} for user {} and entities {} ", cardUid, user.getUserData().getLogin(),
71+
entitiesAcks);
72+
73+
if (!user.getUserData().getEntities().containsAll(entitiesAcks))
74+
throw new ApiErrorException(
75+
76+
new ApiError(HttpStatus.FORBIDDEN,
77+
"Cancel acknowledgement impossible : User is not member of all the entities given in the request"));
78+
79+
cardRepository.findByUid(cardUid).ifPresent(selectedCard -> cardNotificationService
80+
.pushAckOfCardInEventBus(cardUid, selectedCard.id, entitiesAcks, CardOperationTypeEnum.UNACK));
81+
82+
return cardRepository.deleteUserAck(user.getUserData().getLogin(), cardUid, entitiesAcks);
83+
84+
}
85+
86+
public UserBasedOperationResult resetReadAndAcks(String cardUid) {
87+
log.info("Delete ack and reads on card with uid {} ", cardUid);
88+
UserBasedOperationResult acksResult = cardRepository.deleteAcksAndReads(cardUid);
89+
if (acksResult.isCardFound()) {
90+
cardRepository.findByUid(cardUid)
91+
.ifPresent(card -> cardNotificationService.notifyOneCard(card, CardOperationTypeEnum.UPDATE));
92+
}
93+
94+
return acksResult;
95+
}
96+
97+
}

services/cards-publication/src/test/java/org/opfab/cards/publication/services/CardProcessServiceShould.java

+5-11
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class CardProcessServiceShould {
8080
private ExternalAppService externalAppService;
8181

8282
private CardProcessingService cardProcessingService;
83+
private CardReadAndAckService cardReadAndAckService;
8384
private CardTranslationService cardTranslationService;
8485
private EventBusSpy eventBusSpy;
8586
private CardNotificationService cardNotificationService;
@@ -110,6 +111,7 @@ public void init() {
110111
cardRepositoryMock, externalAppService,
111112
cardTranslationService, cardValidationService, true, true,
112113
false, 1000, 3600, true);
114+
cardReadAndAckService = new CardReadAndAckService(cardNotificationService, cardRepositoryMock);
113115
user = TestHelpers.getCurrentUser();
114116
currentUserWithPerimeters = TestHelpers.getCurrentUserWithPerimeter(user);
115117
cardRepositoryMock.clear();
@@ -883,24 +885,16 @@ void GIVEN_a_user_with_the_write_right_in_perimeter_for_state1_WHEN_sending_card
883885
Assertions.assertThat(TestHelpers.checkCardCount(cardRepositoryMock, 1)).isTrue();
884886
}
885887

886-
@Test
887-
void GIVEN_a_card_WHEN_reset_reads_and_acks_THEN_card_event_UPDATE_is_sent_to_eventBus() {
888-
Card card = TestHelpers.generateOneCard();
889-
cardProcessingService.processCard(card);
890-
cardProcessingService.resetReadAndAcks(card.uid);
891-
Assertions.assertThat(eventBusSpy.getMessagesSent().get(1)[1]).contains("{\"type\":\"UPDATE\"");
892-
}
893-
894888
@Test
895889
void GIVEN_an_existing_card_WHEN_update_card_CONTAINS_KEEP_EXISTING_ACKS_AND_READS_THEN_acks_and_reads_are_kept() {
896890
Card card = TestHelpers.generateOneCard("entity2");
897891
cardProcessingService.processUserCard(card, currentUserWithPerimeters, token);
898-
cardProcessingService.processUserRead(card.uid,
892+
cardReadAndAckService.processUserRead(card.uid,
899893
currentUserWithPerimeters.getUserData().getLogin());
900-
cardProcessingService.processUserRead(card.uid, "user2");
894+
cardReadAndAckService.processUserRead(card.uid, "user2");
901895

902896
List<String> entitiesAcks = List.of("entity2");
903-
cardProcessingService.processUserAcknowledgement(card.uid, currentUserWithPerimeters,
897+
cardReadAndAckService.processUserAcknowledgement(card.uid, currentUserWithPerimeters,
904898
entitiesAcks);
905899
Assertions.assertThat(TestHelpers.checkCardCount(cardRepositoryMock, 1)).isTrue();
906900

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
2+
/* Copyright (c) 2018-2025, RTE (http://www.rte-france.com)
3+
* See AUTHORS.txt
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
7+
* SPDX-License-Identifier: MPL-2.0
8+
* This file is part of the OperatorFabric project.
9+
*/
10+
11+
package org.opfab.cards.publication.services;
12+
13+
import org.assertj.core.api.Assertions;
14+
import org.junit.jupiter.api.*;
15+
import org.junit.jupiter.api.extension.ExtendWith;
16+
import org.opfab.cards.publication.application.UnitTestApplication;
17+
import org.opfab.cards.publication.mocks.CardRepositoryMock;
18+
import org.opfab.cards.publication.model.Card;
19+
import org.opfab.test.EventBusSpy;
20+
import org.springframework.beans.factory.annotation.Autowired;
21+
import org.springframework.boot.test.context.SpringBootTest;
22+
import org.springframework.test.context.junit.jupiter.SpringExtension;
23+
import com.fasterxml.jackson.databind.ObjectMapper;
24+
25+
@ExtendWith(SpringExtension.class)
26+
@SpringBootTest(classes = { UnitTestApplication.class })
27+
class CardReadAndAckServiceShould {
28+
29+
@Autowired
30+
private ObjectMapper objectMapper;
31+
32+
private CardReadAndAckService cardReadAndAckService;
33+
private EventBusSpy eventBusSpy;
34+
private CardNotificationService cardNotificationService;
35+
36+
@Autowired
37+
private CardRepositoryMock cardRepositoryMock;
38+
39+
@BeforeEach
40+
void init() {
41+
eventBusSpy = new EventBusSpy();
42+
cardNotificationService = new CardNotificationService(eventBusSpy, objectMapper, null);
43+
cardReadAndAckService = new CardReadAndAckService(
44+
cardNotificationService,
45+
cardRepositoryMock);
46+
cardRepositoryMock.clear();
47+
eventBusSpy.clearMessageSent();
48+
}
49+
50+
@Test
51+
void GIVEN_a_card_WHEN_reset_reads_and_acks_THEN_card_event_UPDATE_is_sent_to_eventBus() {
52+
Card card = TestHelpers.generateOneCard();
53+
cardRepositoryMock.saveCard(card);
54+
cardReadAndAckService.resetReadAndAcks(card.uid);
55+
Assertions.assertThat(eventBusSpy.getMessagesSent().get(0)[1]).contains("{\"type\":\"UPDATE\"");
56+
}
57+
}

0 commit comments

Comments
 (0)