From ce95b457e605d9c139cd63d8a2b1bf0090f2c5c7 Mon Sep 17 00:00:00 2001 From: "antonio.torre" Date: Tue, 2 Jul 2024 17:53:33 +0200 Subject: [PATCH] P4ADEV-668 operators list retrieve --- openapi/p4pa-auth.openapi.yaml | 14 +-- .../auth/repository/OperatorsRepository.java | 1 + .../payhub/auth/service/user/UserService.java | 3 + .../auth/service/user/UserServiceImpl.java | 17 ++- .../user/retrieve/OperatorDTOMapper.java | 26 ++++ .../OrganizationOperatorRetrieverService.java | 44 +++++++ .../auth/service/user/UserServiceTest.java | 26 +++- .../user/retrieve/OperatorDTOMapperTest.java | 57 +++++++++ ...anizationOperatorRetrieverServiceTest.java | 111 ++++++++++++++++++ 9 files changed, 286 insertions(+), 13 deletions(-) create mode 100644 src/main/java/it/gov/pagopa/payhub/auth/service/user/retrieve/OperatorDTOMapper.java create mode 100644 src/main/java/it/gov/pagopa/payhub/auth/service/user/retrieve/OrganizationOperatorRetrieverService.java create mode 100644 src/test/java/it/gov/pagopa/payhub/auth/service/user/retrieve/OperatorDTOMapperTest.java create mode 100644 src/test/java/it/gov/pagopa/payhub/auth/service/user/retrieve/OrganizationOperatorRetrieverServiceTest.java diff --git a/openapi/p4pa-auth.openapi.yaml b/openapi/p4pa-auth.openapi.yaml index 302beaa9..b057285e 100644 --- a/openapi/p4pa-auth.openapi.yaml +++ b/openapi/p4pa-auth.openapi.yaml @@ -244,7 +244,7 @@ components: content: type: array items: - $ref: '#/components/schemas/Operator' + $ref: '#/components/schemas/OperatorDTO' description: "The list of organization operators" pageNo: type: integer @@ -262,7 +262,7 @@ components: type: integer format: int32 description: "Number of total pages" - Operator: + OperatorDTO: type: object required: - userId @@ -273,15 +273,13 @@ components: - organizationIpaCode properties: userId: - type: integer - format: int32 + type: string mappedExternalUserId: type: string userCode: type: string operatorId: - type: integer - format: int32 + type: string roles: type: array items: @@ -290,9 +288,9 @@ components: type: string fiscalCode: type: string - name: + firstName: type: string - familyName: + lastName: type: string email: type: string diff --git a/src/main/java/it/gov/pagopa/payhub/auth/repository/OperatorsRepository.java b/src/main/java/it/gov/pagopa/payhub/auth/repository/OperatorsRepository.java index 48e76784..07c05044 100644 --- a/src/main/java/it/gov/pagopa/payhub/auth/repository/OperatorsRepository.java +++ b/src/main/java/it/gov/pagopa/payhub/auth/repository/OperatorsRepository.java @@ -7,4 +7,5 @@ public interface OperatorsRepository extends OperatorsRepositoryExt, MongoRepository { List findAllByUserId(String userId); + List findAllByOrganizationIpaCode(String organizationIpaCode); } diff --git a/src/main/java/it/gov/pagopa/payhub/auth/service/user/UserService.java b/src/main/java/it/gov/pagopa/payhub/auth/service/user/UserService.java index 1441af29..77b54539 100644 --- a/src/main/java/it/gov/pagopa/payhub/auth/service/user/UserService.java +++ b/src/main/java/it/gov/pagopa/payhub/auth/service/user/UserService.java @@ -2,12 +2,15 @@ import it.gov.pagopa.payhub.auth.model.Operator; import it.gov.pagopa.payhub.auth.model.User; +import it.gov.pagopa.payhub.model.generated.OperatorDTO; import it.gov.pagopa.payhub.model.generated.UserInfo; +import java.util.List; import java.util.Set; public interface UserService { User registerUser(String externalUserId, String fiscalCode, String iamIssuer, String firstName, String lastName, String email); Operator registerOperator(String userId, String organizationIpaCode, Set roles); UserInfo getUserInfo(String accessToken); + List retrieveOrganizationOperators(String organizationIpaCode); } diff --git a/src/main/java/it/gov/pagopa/payhub/auth/service/user/UserServiceImpl.java b/src/main/java/it/gov/pagopa/payhub/auth/service/user/UserServiceImpl.java index b61cbd78..6c9f2cdf 100644 --- a/src/main/java/it/gov/pagopa/payhub/auth/service/user/UserServiceImpl.java +++ b/src/main/java/it/gov/pagopa/payhub/auth/service/user/UserServiceImpl.java @@ -7,26 +7,31 @@ import it.gov.pagopa.payhub.auth.service.TokenStoreService; import it.gov.pagopa.payhub.auth.service.user.registration.OperatorRegistrationService; import it.gov.pagopa.payhub.auth.service.user.registration.UserRegistrationService; +import it.gov.pagopa.payhub.auth.service.user.retrieve.OrganizationOperatorRetrieverService; +import it.gov.pagopa.payhub.model.generated.OperatorDTO; import it.gov.pagopa.payhub.model.generated.UserInfo; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.List; import java.util.Set; @Service @Slf4j -public class UserServiceImpl implements UserService{ +public class UserServiceImpl implements UserService { private final TokenStoreService tokenStoreService; private final UserRegistrationService userRegistrationService; private final OperatorRegistrationService operatorRegistrationService; private final IamUserInfoDTO2UserInfoMapper userInfoMapper; + private final OrganizationOperatorRetrieverService organizationOperatorRetrieverService; - public UserServiceImpl(TokenStoreService tokenStoreService, UserRegistrationService userRegistrationService, OperatorRegistrationService operatorRegistrationService, IamUserInfoDTO2UserInfoMapper userInfoMapper) { + public UserServiceImpl(TokenStoreService tokenStoreService, UserRegistrationService userRegistrationService, OperatorRegistrationService operatorRegistrationService, IamUserInfoDTO2UserInfoMapper userInfoMapper, OrganizationOperatorRetrieverService organizationOperatorRetrieverService) { this.tokenStoreService = tokenStoreService; this.userRegistrationService = userRegistrationService; this.operatorRegistrationService = operatorRegistrationService; this.userInfoMapper = userInfoMapper; + this.organizationOperatorRetrieverService = organizationOperatorRetrieverService; } @Override @@ -43,10 +48,16 @@ public Operator registerOperator(String userId, String organizationIpaCode, Set< public UserInfo getUserInfo(String accessToken) { log.info("Retrieving user info"); IamUserInfoDTO userInfo = tokenStoreService.load(accessToken); - if(userInfo==null){ + if (userInfo == null) { throw new InvalidAccessTokenException("AccessToken not found"); } else { return userInfoMapper.apply(userInfo); } } + + @Override + public List retrieveOrganizationOperators(String organizationIpaCode) { + log.info("Retrieving organization {} operators", organizationIpaCode); + return organizationOperatorRetrieverService.retrieveOrganizationOperators(organizationIpaCode); + } } diff --git a/src/main/java/it/gov/pagopa/payhub/auth/service/user/retrieve/OperatorDTOMapper.java b/src/main/java/it/gov/pagopa/payhub/auth/service/user/retrieve/OperatorDTOMapper.java new file mode 100644 index 00000000..02b24a4d --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/auth/service/user/retrieve/OperatorDTOMapper.java @@ -0,0 +1,26 @@ +package it.gov.pagopa.payhub.auth.service.user.retrieve; + +import it.gov.pagopa.payhub.auth.model.Operator; +import it.gov.pagopa.payhub.auth.model.User; +import it.gov.pagopa.payhub.model.generated.OperatorDTO; + +import java.util.ArrayList; +import java.util.function.BiFunction; + +public class OperatorDTOMapper implements BiFunction { + @Override + public OperatorDTO apply(User user, Operator operator) { + return OperatorDTO.builder() + .userId(user.getUserId()) + .mappedExternalUserId(user.getMappedExternalUserId()) + .userCode(user.getUserCode()) + .operatorId(operator.getOperatorId()) + .roles(new ArrayList<>(operator.getRoles())) + .organizationIpaCode(operator.getOrganizationIpaCode()) + .fiscalCode(user.getFiscalCode()) + .firstName(user.getFirstName()) + .lastName(user.getLastName()) + .email(user.getEmail()) + .build(); + } +} diff --git a/src/main/java/it/gov/pagopa/payhub/auth/service/user/retrieve/OrganizationOperatorRetrieverService.java b/src/main/java/it/gov/pagopa/payhub/auth/service/user/retrieve/OrganizationOperatorRetrieverService.java new file mode 100644 index 00000000..10d1ba92 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/auth/service/user/retrieve/OrganizationOperatorRetrieverService.java @@ -0,0 +1,44 @@ +package it.gov.pagopa.payhub.auth.service.user.retrieve; + +import it.gov.pagopa.payhub.auth.model.Operator; +import it.gov.pagopa.payhub.auth.model.User; +import it.gov.pagopa.payhub.auth.repository.OperatorsRepository; +import it.gov.pagopa.payhub.auth.repository.UsersRepository; +import it.gov.pagopa.payhub.model.generated.OperatorDTO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +@Service +@Slf4j +public class OrganizationOperatorRetrieverService { + + private final OperatorsRepository operatorsRepository; + private final UsersRepository usersRepository; + private final OperatorDTOMapper operatorDTOMapper; + + public OrganizationOperatorRetrieverService(OperatorsRepository operatorsRepository, UsersRepository usersRepository, OperatorDTOMapper operatorDTOMapper) { + this.operatorsRepository = operatorsRepository; + this.usersRepository = usersRepository; + this.operatorDTOMapper = operatorDTOMapper; + } + + public List retrieveOrganizationOperators(String organizationIpaCode) { + List operators = operatorsRepository.findAllByOrganizationIpaCode(organizationIpaCode); + return operators.stream() + .map(op -> { + Optional user = usersRepository.findById(op.getUserId()); + if(user.isEmpty()){ + log.warn("Found an operator without a user: {}", op); + return null; + } else { + return operatorDTOMapper.apply(user.get(), op); + } + }) + .filter(Objects::nonNull) + .toList(); + } +} diff --git a/src/test/java/it/gov/pagopa/payhub/auth/service/user/UserServiceTest.java b/src/test/java/it/gov/pagopa/payhub/auth/service/user/UserServiceTest.java index 67426b65..054756a7 100644 --- a/src/test/java/it/gov/pagopa/payhub/auth/service/user/UserServiceTest.java +++ b/src/test/java/it/gov/pagopa/payhub/auth/service/user/UserServiceTest.java @@ -7,6 +7,8 @@ import it.gov.pagopa.payhub.auth.service.TokenStoreService; import it.gov.pagopa.payhub.auth.service.user.registration.OperatorRegistrationService; import it.gov.pagopa.payhub.auth.service.user.registration.UserRegistrationService; +import it.gov.pagopa.payhub.auth.service.user.retrieve.OrganizationOperatorRetrieverService; +import it.gov.pagopa.payhub.model.generated.OperatorDTO; import it.gov.pagopa.payhub.model.generated.UserInfo; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; @@ -17,6 +19,8 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; +import java.util.Collections; +import java.util.List; import java.util.Set; @ExtendWith(MockitoExtension.class) @@ -30,12 +34,14 @@ class UserServiceTest { private OperatorRegistrationService operatorRegistrationServiceMock; @Mock private IamUserInfoDTO2UserInfoMapper userInfoMapperMock; + @Mock + private OrganizationOperatorRetrieverService organizationOperatorRetrieverServiceMock; private UserService service; @BeforeEach void init() { - service = new UserServiceImpl(tokenStoreServiceMock, userRegistrationServiceMock, operatorRegistrationServiceMock, userInfoMapperMock); + service = new UserServiceImpl(tokenStoreServiceMock, userRegistrationServiceMock, operatorRegistrationServiceMock, userInfoMapperMock, organizationOperatorRetrieverServiceMock); } @AfterEach @@ -44,7 +50,8 @@ void verifyNotMoreInteractions() { tokenStoreServiceMock, userRegistrationServiceMock, operatorRegistrationServiceMock, - userInfoMapperMock); + userInfoMapperMock, + organizationOperatorRetrieverServiceMock); } @Test @@ -113,4 +120,19 @@ void whenRegisterOperatorThenReturnStoredOperator() { // Then Assertions.assertSame(storedOperator, result); } + + @Test + void whenRetrieveOrganizationOperatorsThenReturnOperatorList(){ + // Given + String organizationIpaCode = "IPACODE"; + + List expectedOperators = Collections.emptyList(); + Mockito.when(organizationOperatorRetrieverServiceMock.retrieveOrganizationOperators(organizationIpaCode)).thenReturn(expectedOperators); + + // When + List result = service.retrieveOrganizationOperators(organizationIpaCode); + + // Then + Assertions.assertSame(expectedOperators, result); + } } diff --git a/src/test/java/it/gov/pagopa/payhub/auth/service/user/retrieve/OperatorDTOMapperTest.java b/src/test/java/it/gov/pagopa/payhub/auth/service/user/retrieve/OperatorDTOMapperTest.java new file mode 100644 index 00000000..705d97ca --- /dev/null +++ b/src/test/java/it/gov/pagopa/payhub/auth/service/user/retrieve/OperatorDTOMapperTest.java @@ -0,0 +1,57 @@ +package it.gov.pagopa.payhub.auth.service.user.retrieve; + +import it.gov.pagopa.payhub.auth.model.Operator; +import it.gov.pagopa.payhub.auth.model.User; +import it.gov.pagopa.payhub.model.generated.OperatorDTO; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Set; + +class OperatorDTOMapperTest { + + private final OperatorDTOMapper mapper = new OperatorDTOMapper(); + + @Test + void test(){ + // Given + User user = User.builder() + .userId("USERID") + .iamIssuer("IAMISSUER") + .mappedExternalUserId("MAPPEDEXTERNALUSERID") + .userCode("USERCODE") + .fiscalCode("FISCALCODE") + .firstName("FIRSTNAME") + .lastName("LASTNAME") + .email("EMAIL") + .build(); + + Operator operator = Operator.builder() + .operatorId("OPERATORID") + .userId("USERID") + .roles(Set.of("ROLES")) + .organizationIpaCode("ORGANIZATIONIPACODE") + .build(); + + // When + OperatorDTO result = mapper.apply(user, operator); + + // Then + Assertions.assertEquals( + OperatorDTO.builder() + .userId("USERID") + .mappedExternalUserId("MAPPEDEXTERNALUSERID") + .userCode("USERCODE") + .operatorId("OPERATORID") + .roles(List.of("ROLES")) + .organizationIpaCode("ORGANIZATIONIPACODE") + .fiscalCode("FISCALCODE") + .firstName("FIRSTNAME") + .lastName("LASTNAME") + .email("EMAIL") + .build(), + result + ); + } +} diff --git a/src/test/java/it/gov/pagopa/payhub/auth/service/user/retrieve/OrganizationOperatorRetrieverServiceTest.java b/src/test/java/it/gov/pagopa/payhub/auth/service/user/retrieve/OrganizationOperatorRetrieverServiceTest.java new file mode 100644 index 00000000..87840fff --- /dev/null +++ b/src/test/java/it/gov/pagopa/payhub/auth/service/user/retrieve/OrganizationOperatorRetrieverServiceTest.java @@ -0,0 +1,111 @@ +package it.gov.pagopa.payhub.auth.service.user.retrieve; + +import it.gov.pagopa.payhub.auth.model.Operator; +import it.gov.pagopa.payhub.auth.model.User; +import it.gov.pagopa.payhub.auth.repository.OperatorsRepository; +import it.gov.pagopa.payhub.auth.repository.UsersRepository; +import it.gov.pagopa.payhub.model.generated.OperatorDTO; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +@ExtendWith(MockitoExtension.class) +class OrganizationOperatorRetrieverServiceTest { + + @Mock + private OperatorsRepository operatorsRepositoryMock; + @Mock + private UsersRepository usersRepositoryMock; + @Mock + private OperatorDTOMapper operatorDTOMapperMock; + + private OrganizationOperatorRetrieverService service; + + @BeforeEach + void init() { + service = new OrganizationOperatorRetrieverService(operatorsRepositoryMock, usersRepositoryMock, operatorDTOMapperMock); + } + + @AfterEach + void verifyNotMoreInteractions() { + Mockito.verifyNoMoreInteractions( + operatorsRepositoryMock, + usersRepositoryMock, + operatorDTOMapperMock); + } + + @Test + void givenNoOperatorsWhenRetrieveOrganizationOperatorsThenEmptyList() { + // Given + String organizationIpaCode = "IPACODE"; + + Mockito.when(operatorsRepositoryMock.findAllByOrganizationIpaCode(organizationIpaCode)).thenReturn(Collections.emptyList()); + + // When + List result = service.retrieveOrganizationOperators(organizationIpaCode); + + // Then + Assertions.assertEquals(Collections.emptyList(), result); + } + + @Test + void givenNoUsersWhenRetrieveOrganizationOperatorsThenEmptyList() { + // Given + String organizationIpaCode = "IPACODE"; + + Mockito.when(operatorsRepositoryMock.findAllByOrganizationIpaCode(organizationIpaCode)).thenReturn(List.of(Operator.builder().userId("USERID").build())); + Mockito.when(usersRepositoryMock.findById("USERID")).thenReturn(Optional.empty()); + + // When + List result = service.retrieveOrganizationOperators(organizationIpaCode); + + // Then + Assertions.assertEquals(Collections.emptyList(), result); + } + + @Test + void givenOperatorsAndUsersWhenRetrieveOrganizationOperatorsThenEmptyList() { + // Given + String organizationIpaCode = "IPACODE"; + + Operator op1 = Operator.builder().userId("USERID1").build(); + Operator op2 = Operator.builder().userId("USERID2").build(); + Operator op3 = Operator.builder().userId("USERID3").build(); + Operator op4 = Operator.builder().userId("USERID4").build(); + Mockito.when(operatorsRepositoryMock.findAllByOrganizationIpaCode(organizationIpaCode)).thenReturn(List.of( + op1, + op2, + op3, + op4 + )); + + User us1 = User.builder().userId("USERID1").build(); + User us3 = User.builder().userId("USERID3").build(); + Mockito.when(usersRepositoryMock.findById("USERID1")).thenReturn(Optional.of(us1)); + Mockito.when(usersRepositoryMock.findById("USERID2")).thenReturn(Optional.empty()); + Mockito.when(usersRepositoryMock.findById("USERID3")).thenReturn(Optional.of(us3)); + Mockito.when(usersRepositoryMock.findById("USERID4")).thenReturn(Optional.empty()); + + OperatorDTO expectedOpDto1 = new OperatorDTO(); + OperatorDTO expectedOpDto3 = new OperatorDTO(); + Mockito.when(operatorDTOMapperMock.apply(us1, op1)).thenReturn(expectedOpDto1); + Mockito.when(operatorDTOMapperMock.apply(us3, op3)).thenReturn(expectedOpDto1); + + // When + List result = service.retrieveOrganizationOperators(organizationIpaCode); + + // Then + Assertions.assertEquals( + List.of(expectedOpDto1, expectedOpDto3), + result); + } +}