diff --git a/apps/pom.xml b/apps/pom.xml index f6a81700..ca693ae0 100644 --- a/apps/pom.xml +++ b/apps/pom.xml @@ -13,14 +13,14 @@ pom - 0.4.1 + 0.3.2 it.pagopa.selfcare onboarding-sdk-azure-storage - ${onboarding-sdk.version} + 0.3.2 it.pagopa.selfcare diff --git a/apps/user-group-ms/app/pom.xml b/apps/user-group-ms/app/pom.xml deleted file mode 100644 index 269786c5..00000000 --- a/apps/user-group-ms/app/pom.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - user-group-ms - it.pagopa.selfcare - 1.0.0-SNAPSHOT - - 4.0.0 - - user-group-ms-app - - - - it.pagopa.selfcare - user-group-ms-web - - - it.pagopa.selfcare - user-group-ms-connector-dao - runtime - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - false - ${project.parent.artifactId}-${project.parent.version}-FATJAR - ../target - - - org.projectlombok - lombok - - - - - - - - diff --git a/apps/user-group-ms/connector-api/pom.xml b/apps/user-group-ms/connector-api/pom.xml deleted file mode 100644 index 50b303e9..00000000 --- a/apps/user-group-ms/connector-api/pom.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - user-group-ms - it.pagopa.selfcare - 1.0.0-SNAPSHOT - - 4.0.0 - - user-group-ms-connector-api - - - - org.springframework.data - spring-data-commons - - - - - - - org.apache.maven.plugins - maven-jar-plugin - - true - - - - - test-jar - - - - - - - - diff --git a/apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/api/UserGroupConnector.java b/apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/api/UserGroupConnector.java deleted file mode 100644 index 9a57401f..00000000 --- a/apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/api/UserGroupConnector.java +++ /dev/null @@ -1,29 +0,0 @@ -package it.pagopa.selfcare.user_group.connector.api; - -import it.pagopa.selfcare.user_group.connector.model.UserGroupFilter; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; - -import java.util.Optional; - -public interface UserGroupConnector { - UserGroupOperations insert(UserGroupOperations entity); - - UserGroupOperations save(UserGroupOperations entity); - - void insertMember(String id, String memberId); - - void deleteMember(String id, String memberId); - - void deleteMembers(String memberId, String institutionId, String productId); - - Optional findById(String id); - - Page findAll(UserGroupFilter filter, Pageable pageable); - - void activateById(String id); - - void deleteById(String id); - - void suspendById(String id); -} diff --git a/apps/user-group-ms/connector/dao/pom.xml b/apps/user-group-ms/connector/dao/pom.xml deleted file mode 100644 index 8991f8ca..00000000 --- a/apps/user-group-ms/connector/dao/pom.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - user-group-ms-connector - it.pagopa.selfcare - 1.0.0-SNAPSHOT - - 4.0.0 - - user-group-ms-connector-dao - - - - org.springframework.boot - spring-boot-starter-data-mongodb - - - de.flapdoodle.embed - de.flapdoodle.embed.mongo - test - - - - diff --git a/apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/UserGroupConnectorImpl.java b/apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/UserGroupConnectorImpl.java deleted file mode 100644 index 89f1149b..00000000 --- a/apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/UserGroupConnectorImpl.java +++ /dev/null @@ -1,219 +0,0 @@ -package it.pagopa.selfcare.user_group.connector.dao; - -import com.mongodb.client.result.UpdateResult; -import it.pagopa.selfcare.user_group.connector.api.UserGroupConnector; -import it.pagopa.selfcare.user_group.connector.api.UserGroupOperations; -import it.pagopa.selfcare.user_group.connector.dao.model.CriteriaBuilder; -import it.pagopa.selfcare.user_group.connector.dao.model.UserGroupEntity; -import it.pagopa.selfcare.user_group.connector.exception.ResourceAlreadyExistsException; -import it.pagopa.selfcare.user_group.connector.exception.ResourceNotFoundException; -import it.pagopa.selfcare.user_group.connector.exception.ResourceUpdateException; -import it.pagopa.selfcare.user_group.connector.model.UserGroupFilter; -import it.pagopa.selfcare.user_group.connector.model.UserGroupStatus; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.dao.DuplicateKeyException; -import org.springframework.data.domain.AuditorAware; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.query.Criteria; -import org.springframework.data.mongodb.core.query.Query; -import org.springframework.data.mongodb.core.query.Update; -import org.springframework.data.support.PageableExecutionUtils; -import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; - -import javax.validation.ValidationException; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.function.Function; - -@Service -@Slf4j -public class UserGroupConnectorImpl implements UserGroupConnector { - - private final UserGroupRepository repository; - private final MongoTemplate mongoTemplate; - private final AuditorAware auditorAware; - private static final String COULD_NOT_UPDATE_MESSAGE = "Couldn't update resource"; - - - @Autowired - public UserGroupConnectorImpl(UserGroupRepository repository, MongoTemplate mongoTemplate, AuditorAware auditorAware) { - this.repository = repository; - this.mongoTemplate = mongoTemplate; - this.auditorAware = auditorAware; - } - - @Override - public UserGroupOperations insert(UserGroupOperations entity) { - log.trace("insert start"); - log.debug("insert entity = {}", entity); - UserGroupEntity insert; - try { - insert = repository.insert(new UserGroupEntity(entity)); - } catch (DuplicateKeyException e) { - throw new ResourceAlreadyExistsException("Failed _id or unique index constraint.", e); - } - - log.trace("insert end"); - return insert; - } - - @Override - public UserGroupOperations save(UserGroupOperations entity) { - log.trace("save start"); - log.debug("save entity = {}", entity); - UserGroupEntity result; - try { - result = repository.save(new UserGroupEntity(entity)); - } catch (DuplicateKeyException e) { - throw new ResourceAlreadyExistsException("Failed _id or unique index constraint.", e); - } - log.debug("save result = {}", result); - log.trace("save end"); - return result; - } - - @Override - public void insertMember(String id, String memberId) { - log.trace("insertMember start"); - log.debug("insertMember id = {}, memberId = {}", id, memberId); - - UpdateResult updateResult = mongoTemplate.updateFirst( - Query.query(Criteria.where(UserGroupEntity.Fields.id).is(id) - .and(UserGroupEntity.Fields.status).is(UserGroupStatus.ACTIVE)), - new Update().push(UserGroupEntity.Fields.members, memberId) - .set(UserGroupEntity.Fields.modifiedBy, auditorAware.getCurrentAuditor().orElse(null)) - .currentDate(UserGroupEntity.Fields.modifiedAt), - UserGroupEntity.class); - if (updateResult.getModifiedCount() == 0) { - throw new ResourceUpdateException(COULD_NOT_UPDATE_MESSAGE); - } - log.trace("insertMember end"); - - } - - @Override - public void deleteMember(String id, String memberId) { - log.trace("deleteMember start"); - log.debug("deleteMember id = {}, memberId = {}", id, memberId); - - UpdateResult updateResult = mongoTemplate.updateFirst( - Query.query(Criteria.where(UserGroupEntity.Fields.id).is(id) - .and(UserGroupEntity.Fields.status).is(UserGroupStatus.ACTIVE)), - new Update().pull(UserGroupEntity.Fields.members, memberId) - .set(UserGroupEntity.Fields.modifiedBy, auditorAware.getCurrentAuditor().orElse(null)) - .currentTimestamp(UserGroupEntity.Fields.modifiedAt), - UserGroupEntity.class); - if (updateResult.getModifiedCount() == 0) { - throw new ResourceUpdateException(COULD_NOT_UPDATE_MESSAGE); - } - log.trace("deleteMember end"); - } - - public void deleteMembers(String memberId, String institutionId, String productId) { - log.trace("deleteMembers start"); - log.debug("deleteMembers id = {}, institutionId = {}, productId= {}", memberId, institutionId, productId); - - UpdateResult updateResult = mongoTemplate.updateMulti( - Query.query(Criteria.where(UserGroupEntity.Fields.members).is(memberId) - .and(UserGroupEntity.Fields.institutionId).is(institutionId) - .and(UserGroupEntity.Fields.productId).is(productId)), - new Update().pull(UserGroupEntity.Fields.members, memberId) - .set(UserGroupEntity.Fields.modifiedBy, auditorAware.getCurrentAuditor().orElse(null)) - .currentTimestamp(UserGroupEntity.Fields.modifiedAt), - UserGroupEntity.class); - if (updateResult.getModifiedCount() == 0) { - log.warn("No user to delete from UserGroup"); - } - log.trace("deleteMembers end"); - } - - @Override - public Optional findById(String id) { - log.trace("findById start"); - log.debug("findById id = {} ", id); - Optional result = repository.findById(id).map(Function.identity()); - log.debug("findById result = {}", result); - log.trace("findById end"); - - return result; - } - - @Override - public Page findAll(UserGroupFilter filter, Pageable pageable) { - log.trace("findAll start"); - log.debug("findAll institutionId= {} , productId = {}, userId = {}, pageable = {}", filter.getInstitutionId(), filter.getProductId(), filter.getUserId(), pageable); - if (pageable.getSort().isSorted() && !StringUtils.hasText(filter.getProductId()) && !StringUtils.hasText(filter.getInstitutionId())) { - throw new ValidationException("Sorting not allowed without productId or institutionId"); - } - if (filter.getStatus().size() == 1 && !StringUtils.hasText(filter.getUserId()) && !StringUtils.hasText(filter.getProductId()) && !StringUtils.hasText(filter.getInstitutionId())) { - throw new ValidationException("At least one of productId, institutionId and userId must be provided with status filter"); - } - Query query = new Query(constructCriteria(filter)); - long count = this.mongoTemplate.count(query, UserGroupEntity.class); - List userGroupOperations = new ArrayList<>(mongoTemplate.find(query.with(pageable), UserGroupEntity.class)); - final Page result = PageableExecutionUtils.getPage(userGroupOperations, pageable, () -> count); - log.debug("findAll result = {}", result); - log.trace("findAll end"); - return result; - } - - - @Override - public void activateById(String id) { - log.trace("activateById start"); - log.debug("activateById id = {} ", id); - updateUserById(id, UserGroupStatus.ACTIVE); - log.trace("activateById end"); - - } - - - @Override - public void deleteById(String id) { - log.trace("deleteById start"); - log.debug("deleteById id = {} ", id); - updateUserById(id, UserGroupStatus.DELETED); - log.trace("deleteById end"); - } - - @Override - public void suspendById(String id) { - log.trace("suspendById start"); - log.debug("suspendById id = {} ", id); - updateUserById(id, UserGroupStatus.SUSPENDED); - log.trace("suspendById end"); - - } - - private void updateUserById(String id, UserGroupStatus status) { - log.trace("updateUserById start"); - log.debug("updateUserById id = {}, status = {}", id, status); - UpdateResult updateResult = mongoTemplate.updateFirst( - Query.query(Criteria.where(UserGroupEntity.Fields.id).is(id)), - Update.update(UserGroupEntity.Fields.status, status) - .set(UserGroupEntity.Fields.modifiedBy, auditorAware.getCurrentAuditor().orElse(null)) - .currentTimestamp(UserGroupEntity.Fields.modifiedAt), - UserGroupEntity.class); - if (updateResult.getMatchedCount() == 0) { - throw new ResourceNotFoundException(); - } - log.trace("updateUserById end"); - - } - - private Criteria constructCriteria(UserGroupFilter filter) { - return CriteriaBuilder.builder() - .isIfNotNull(UserGroupEntity.Fields.institutionId, filter.getInstitutionId()) - .isIfNotNull(UserGroupEntity.Fields.productId, filter.getProductId()) - .isIfNotNull(UserGroupEntity.Fields.members, filter.getUserId()) - .inIfNotEmpty(UserGroupEntity.Fields.status, filter.getStatus()) - .build(); - - } - -} diff --git a/apps/user-group-ms/connector/dao/src/main/resources/config/dao-config.properties b/apps/user-group-ms/connector/dao/src/main/resources/config/dao-config.properties deleted file mode 100644 index 1d25e708..00000000 --- a/apps/user-group-ms/connector/dao/src/main/resources/config/dao-config.properties +++ /dev/null @@ -1,2 +0,0 @@ -spring.data.mongodb.uri=${MONGODB_CONNECTION_URI:mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass&directConnection=true&ssl=false}&appname=${MONGODB_APPNAME:selcUserGroup} -spring.data.mongodb.database=${MONGODB_NAME:selcUserGroup} \ No newline at end of file diff --git a/apps/user-group-ms/connector/dao/src/test/java/it/pagopa/selfcare/user_group/connector/dao/UserGroupConnectorImplTest.java b/apps/user-group-ms/connector/dao/src/test/java/it/pagopa/selfcare/user_group/connector/dao/UserGroupConnectorImplTest.java deleted file mode 100644 index b2c01ef2..00000000 --- a/apps/user-group-ms/connector/dao/src/test/java/it/pagopa/selfcare/user_group/connector/dao/UserGroupConnectorImplTest.java +++ /dev/null @@ -1,894 +0,0 @@ -package it.pagopa.selfcare.user_group.connector.dao; - -import com.mongodb.client.result.DeleteResult; -import com.mongodb.client.result.UpdateResult; -import it.pagopa.selfcare.commons.base.security.SelfCareUser; -import it.pagopa.selfcare.user_group.connector.api.UserGroupOperations; -import it.pagopa.selfcare.user_group.connector.dao.auditing.SpringSecurityAuditorAware; -import it.pagopa.selfcare.user_group.connector.dao.model.UserGroupEntity; -import it.pagopa.selfcare.user_group.connector.exception.ResourceAlreadyExistsException; -import it.pagopa.selfcare.user_group.connector.exception.ResourceNotFoundException; -import it.pagopa.selfcare.user_group.connector.exception.ResourceUpdateException; -import it.pagopa.selfcare.user_group.connector.model.UserGroupFilter; -import it.pagopa.selfcare.user_group.connector.model.UserGroupStatus; -import org.bson.BsonValue; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.function.Executable; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; -import org.springframework.dao.DuplicateKeyException; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.query.Query; -import org.springframework.data.mongodb.core.query.Update; -import org.springframework.security.authentication.TestingAuthenticationToken; -import org.springframework.security.test.context.TestSecurityContextHolder; - -import javax.validation.ValidationException; -import java.time.Instant; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; - -import static it.pagopa.selfcare.commons.utils.TestUtils.mockInstance; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; - -class UserGroupConnectorImplTest { - - private final static String LOGGED_USER_ID = "id"; - - private final UserGroupRepository repositoryMock; - - @AfterEach - void clear() { - repositoryMock.deleteAll(); - Mockito.reset(repositoryMock, mongoTemplateMock); - } - - private final MongoTemplate mongoTemplateMock; - - private final UserGroupConnectorImpl groupConnector; - - private final SelfCareUser selfCareUser; - - public UserGroupConnectorImplTest() { - selfCareUser = SelfCareUser.builder(LOGGED_USER_ID).build(); - TestingAuthenticationToken authenticationToken = new TestingAuthenticationToken(selfCareUser, null); - TestSecurityContextHolder.setAuthentication(authenticationToken); - repositoryMock = Mockito.mock(UserGroupRepository.class); - mongoTemplateMock = Mockito.mock(MongoTemplate.class); - groupConnector = new UserGroupConnectorImpl(repositoryMock, mongoTemplateMock, new SpringSecurityAuditorAware()); - } - - @Test - void insert_duplicateKey() { - UserGroupEntity entity = mockInstance(new UserGroupEntity()); - Mockito.doThrow(DuplicateKeyException.class) - .when(repositoryMock) - .insert(any(UserGroupEntity.class)); - //when - Executable executable = () -> groupConnector.insert(entity); - //then - ResourceAlreadyExistsException e = assertThrows(ResourceAlreadyExistsException.class, executable); - assertEquals("Failed _id or unique index constraint.", e.getMessage()); - verify(repositoryMock, times(1)) - .insert(entity); - verifyNoMoreInteractions(repositoryMock); - } - - @Test - void insert() { - //given - UserGroupEntity entity = mockInstance(new UserGroupEntity()); - when(repositoryMock.insert(any(UserGroupEntity.class))) - .thenReturn(entity); - //when - UserGroupOperations saved = groupConnector.insert(entity); - //then - Assertions.assertEquals(entity, saved); - verify(repositoryMock, times(1)) - .insert(entity); - verifyNoMoreInteractions(repositoryMock); - } - - @Test - void findById() { - // given - String id = "id"; - Optional entity = Optional.of(mockInstance(new UserGroupEntity())); - when(repositoryMock.findById(any())) - .thenReturn(entity); - // when - Optional found = groupConnector.findById(id); - // then - Assertions.assertEquals(entity, found); - verify(repositoryMock, times(1)) - .findById(id); - verifyNoMoreInteractions(repositoryMock); - } - - @Test - void findAll_fullyValued() { - //given - String institutionId = "institutionId"; - String productId = "productId"; - String userId = UUID.randomUUID().toString(); - List allowedStatus = List.of(UserGroupStatus.ACTIVE); - Pageable pageable = PageRequest.of(1, 3, Sort.by("name")); - UserGroupFilter groupFilter = new UserGroupFilter(institutionId, productId, userId, allowedStatus); - - List entities = List.of(mockInstance(new UserGroupEntity())); - - final long countResult = pageable.isPaged() - ? (long) pageable.getPageSize() * pageable.getPageNumber() + entities.size() - : entities.size(); - when(mongoTemplateMock.count(any(Query.class), eq(UserGroupEntity.class))) - .thenReturn(countResult); - when(mongoTemplateMock.find(any(Query.class), eq(UserGroupEntity.class))) - .thenReturn(entities); - //when - Page page = groupConnector.findAll(groupFilter, pageable); - //then - assertEquals(pageable, page.getPageable()); - assertEquals(pageable.getSort(), page.getSort()); - assertEquals(entities.size(), page.getContent().size()); - assertEquals(countResult, page.getTotalElements()); - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - verify(mongoTemplateMock, times(1)) - .count(queryCaptor.capture(), eq(UserGroupEntity.class)); - Query queryCount = queryCaptor.getValue(); - verify(mongoTemplateMock, times(1)) - .find(queryCaptor.capture(), eq(UserGroupEntity.class)); - Query query = queryCaptor.getValue(); - assertEquals(queryCount, query); - assertEquals(pageable.getSort().isSorted(), query.isSorted()); - assertEquals(pageable.isPaged() ? pageable.getPageSize() : 0, query.getLimit()); - assertTrue(query.toString().contains(institutionId)); - assertTrue(query.toString().contains(userId)); - assertTrue(query.toString().contains(productId)); - verifyNoMoreInteractions(mongoTemplateMock); - } - - @Test - void findAll_fullyNull() { - //given - Pageable pageable = Pageable.unpaged(); - UserGroupFilter groupFilter = new UserGroupFilter(); - List entities = List.of(mockInstance(new UserGroupEntity())); - final long countResult = pageable.isPaged() - ? (long) pageable.getPageSize() * pageable.getPageNumber() + entities.size() - : entities.size(); - when(mongoTemplateMock.count(any(Query.class), eq(UserGroupEntity.class))) - .thenReturn(countResult); - when(mongoTemplateMock.find(any(Query.class), eq(UserGroupEntity.class))) - .thenReturn(entities); - //when - Page page = groupConnector.findAll(groupFilter, pageable); - //then - assertEquals(pageable, page.getPageable()); - assertEquals(pageable.getSort(), page.getSort()); - assertEquals(entities.size(), page.getContent().size()); - assertEquals(countResult, page.getTotalElements()); - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - verify(mongoTemplateMock, times(1)) - .count(queryCaptor.capture(), eq(UserGroupEntity.class)); - Query queryCount = queryCaptor.getValue(); - verify(mongoTemplateMock, times(1)) - .find(queryCaptor.capture(), any()); - Query query = queryCaptor.getValue(); - assertEquals(queryCount, query); - assertEquals(pageable.getSort().isSorted(), query.isSorted()); - assertEquals(pageable.isPaged() ? pageable.getPageSize() : 0, query.getLimit()); - assertTrue(query.getFieldsObject().isEmpty()); - verifyNoMoreInteractions(mongoTemplateMock); - } - - @Test - void findAll_differentFilterCombination1() { - //given - String productId = "productId"; - List allowedStatus = List.of(UserGroupStatus.ACTIVE); - Pageable pageable = PageRequest.of(1, 3, Sort.by("name")); - UserGroupFilter groupFilter = new UserGroupFilter(null, productId, "", allowedStatus); - List entities = List.of(mockInstance(new UserGroupEntity())); - final long countResult = pageable.isPaged() - ? (long) pageable.getPageSize() * pageable.getPageNumber() + entities.size() - : entities.size(); - when(mongoTemplateMock.count(any(Query.class), eq(UserGroupEntity.class))) - .thenReturn(countResult); - when(mongoTemplateMock.find(any(Query.class), eq(UserGroupEntity.class))) - .thenReturn(entities); - //when - Page page = groupConnector.findAll(groupFilter, pageable); - //then - assertEquals(pageable, page.getPageable()); - assertEquals(pageable.getSort(), page.getSort()); - assertEquals(entities.size(), page.getContent().size()); - assertEquals(countResult, page.getTotalElements()); - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - verify(mongoTemplateMock, times(1)) - .count(queryCaptor.capture(), eq(UserGroupEntity.class)); - Query queryCount = queryCaptor.getValue(); - verify(mongoTemplateMock, times(1)) - .find(queryCaptor.capture(), any()); - Query query = queryCaptor.getValue(); - assertEquals(queryCount, query); - assertEquals(pageable.getSort().isSorted(), query.isSorted()); - assertEquals(pageable.isPaged() ? pageable.getPageSize() : 0, query.getLimit()); - assertTrue(query.toString().contains(productId)); - verifyNoMoreInteractions(mongoTemplateMock); - } - - @Test - void findAll_differentFilterCombination2() { - //given - String institutionId = "institutionId"; - UserGroupStatus allowedStatus = UserGroupStatus.ACTIVE; - Pageable pageable = PageRequest.of(1, 3, Sort.by("name")); - UserGroupFilter groupFilter = new UserGroupFilter(institutionId, null, "", List.of(allowedStatus)); - List entities = List.of(mockInstance(new UserGroupEntity())); - final long countResult = pageable.isPaged() - ? (long) pageable.getPageSize() * pageable.getPageNumber() + entities.size() - : entities.size(); - when(mongoTemplateMock.count(any(Query.class), eq(UserGroupEntity.class))) - .thenReturn(countResult); - when(mongoTemplateMock.find(any(Query.class), eq(UserGroupEntity.class))) - .thenReturn(entities); - //when - Page page = groupConnector.findAll(groupFilter, pageable); - //then - assertEquals(pageable, page.getPageable()); - assertEquals(pageable.getSort(), page.getSort()); - assertEquals(entities.size(), page.getContent().size()); - assertEquals(countResult, page.getTotalElements()); - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - verify(mongoTemplateMock, times(1)) - .count(queryCaptor.capture(), eq(UserGroupEntity.class)); - Query queryCount = queryCaptor.getValue(); - verify(mongoTemplateMock, times(1)) - .find(queryCaptor.capture(), any()); - Query query = queryCaptor.getValue(); - assertEquals(queryCount, query); - assertEquals(pageable.getSort().isSorted(), query.isSorted()); - assertEquals(pageable.isPaged() ? pageable.getPageSize() : 0, query.getLimit()); - assertTrue(query.toString().contains(institutionId)); - assertTrue(query.toString().contains(allowedStatus.name())); - verifyNoMoreInteractions(mongoTemplateMock); - } - - @Test - void findAll_sortNotAllowedException() { - //given - Pageable pageable = PageRequest.of(0, 3, Sort.by("name")); - UserGroupFilter groupFilter = new UserGroupFilter(); - //when - Executable executable = () -> groupConnector.findAll(groupFilter, pageable); - //then - ValidationException e = assertThrows(ValidationException.class, executable); - assertEquals("Sorting not allowed without productId or institutionId", e.getMessage()); - verifyNoInteractions(mongoTemplateMock); - } - - @Test - void findAll_filterNotAllowedException() { - //given - Pageable pageable = Pageable.unpaged(); - UserGroupStatus allowedStatus = UserGroupStatus.ACTIVE; - UserGroupFilter groupFilter = new UserGroupFilter(null, null, "", List.of(allowedStatus)); - //when - Executable executable = () -> groupConnector.findAll(groupFilter, pageable); - //then - ValidationException e = assertThrows(ValidationException.class, executable); - assertEquals("At least one of productId, institutionId and userId must be provided with status filter", e.getMessage()); - verifyNoInteractions(mongoTemplateMock); - } - - @Test - void deleteById() { - String groupId = "groupId"; - UpdateResult result = mockInstance(new UpdateResult() { - @Override - public boolean wasAcknowledged() { - return false; - } - - @Override - public long getMatchedCount() { - return 1; - } - - @Override - public long getModifiedCount() { - return 1; - } - - @Override - public BsonValue getUpsertedId() { - return null; - } - }); - when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), (Class) any())) - .thenReturn(result); - //when - Executable executable = () -> groupConnector.deleteById(groupId); - //then - assertDoesNotThrow(executable); - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - ArgumentCaptor updateCaptor = ArgumentCaptor.forClass(Update.class); - verify(mongoTemplateMock, times(1)) - .updateFirst(queryCaptor.capture(), updateCaptor.capture(), (Class) any()); - Query query = queryCaptor.getValue(); - Update update = updateCaptor.getValue(); - Map set = (Map) update.getUpdateObject().get("$set"); - Map currentDate = (Map) update.getUpdateObject().get("$currentDate"); - assertEquals(groupId, query.getQueryObject().get(UserGroupEntity.Fields.id)); - assertEquals(UserGroupStatus.DELETED, set.get("status")); - assertEquals(selfCareUser.getId(), set.get("modifiedBy")); - assertTrue(currentDate.containsKey("modifiedAt")); - verifyNoMoreInteractions(mongoTemplateMock); - - } - - @Test - void deleteById_resourceNotFound() { - //given - String groupId = "groupId"; - UpdateResult result = mockInstance(new UpdateResult() { - @Override - public boolean wasAcknowledged() { - return false; - } - - @Override - public long getMatchedCount() { - return 0; - } - - @Override - public long getModifiedCount() { - return 1; - } - - @Override - public BsonValue getUpsertedId() { - return null; - } - }); - when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), (Class) any())) - .thenReturn(result); - //when - Executable executable = () -> groupConnector.deleteById(groupId); - //then - assertThrows(ResourceNotFoundException.class, executable); - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - ArgumentCaptor updateCaptor = ArgumentCaptor.forClass(Update.class); - verify(mongoTemplateMock, times(1)) - .updateFirst(queryCaptor.capture(), updateCaptor.capture(), (Class) any()); - Query query = queryCaptor.getValue(); - Update update = updateCaptor.getValue(); - Map set = (Map) update.getUpdateObject().get("$set"); - Map currentDate = (Map) update.getUpdateObject().get("$currentDate"); - assertEquals(groupId, query.getQueryObject().get(UserGroupEntity.Fields.id)); - assertEquals(UserGroupStatus.DELETED, set.get("status")); - assertEquals(selfCareUser.getId(), set.get("modifiedBy")); - assertTrue(currentDate.containsKey("modifiedAt")); - verifyNoMoreInteractions(mongoTemplateMock); - } - - @Test - void suspendById() { - //given - String groupId = "groupId"; - UpdateResult result = mockInstance(new UpdateResult() { - @Override - public boolean wasAcknowledged() { - return false; - } - - @Override - public long getMatchedCount() { - return 1; - } - - @Override - public long getModifiedCount() { - return 1; - } - - @Override - public BsonValue getUpsertedId() { - return null; - } - }); - when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), (Class) any())) - .thenReturn(result); - //when - Executable executable = () -> groupConnector.suspendById(groupId); - //then - assertDoesNotThrow(executable); - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - ArgumentCaptor updateCaptor = ArgumentCaptor.forClass(Update.class); - verify(mongoTemplateMock, times(1)) - .updateFirst(queryCaptor.capture(), updateCaptor.capture(), (Class) any()); - Query query = queryCaptor.getValue(); - Update update = updateCaptor.getValue(); - Map set = (Map) update.getUpdateObject().get("$set"); - Map currentDate = (Map) update.getUpdateObject().get("$currentDate"); - assertEquals(groupId, query.getQueryObject().get(UserGroupEntity.Fields.id)); - assertEquals(UserGroupStatus.SUSPENDED, set.get("status")); - assertEquals(selfCareUser.getId(), set.get("modifiedBy")); - assertTrue(currentDate.containsKey("modifiedAt")); - verifyNoMoreInteractions(mongoTemplateMock); - - - } - - @Test - void suspendById_resourceNotFound() { - //given - String groupId = "groupId"; - UpdateResult result = mockInstance(new UpdateResult() { - @Override - public boolean wasAcknowledged() { - return false; - } - - @Override - public long getMatchedCount() { - return 0; - } - - @Override - public long getModifiedCount() { - return 1; - } - - @Override - public BsonValue getUpsertedId() { - return null; - } - }); - when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), (Class) any())) - .thenReturn(result); - //when - Executable executable = () -> groupConnector.suspendById(groupId); - //then - assertThrows(ResourceNotFoundException.class, executable); - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - ArgumentCaptor updateCaptor = ArgumentCaptor.forClass(Update.class); - verify(mongoTemplateMock, times(1)) - .updateFirst(queryCaptor.capture(), updateCaptor.capture(), (Class) any()); - Query query = queryCaptor.getValue(); - Update update = updateCaptor.getValue(); - Map set = (Map) update.getUpdateObject().get("$set"); - Map currentDate = (Map) update.getUpdateObject().get("$currentDate"); - assertEquals(groupId, query.getQueryObject().get(UserGroupEntity.Fields.id)); - assertEquals(UserGroupStatus.SUSPENDED, set.get("status")); - assertEquals(selfCareUser.getId(), set.get("modifiedBy")); - assertTrue(currentDate.containsKey("modifiedAt")); - verifyNoMoreInteractions(mongoTemplateMock); - - } - - @Test - void activateById() { - //given - String groupId = "groupId"; - UpdateResult result = mockInstance(new UpdateResult() { - @Override - public boolean wasAcknowledged() { - return false; - } - - @Override - public long getMatchedCount() { - return 1; - } - - @Override - public long getModifiedCount() { - return 1; - } - - @Override - public BsonValue getUpsertedId() { - return null; - } - }); - when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), (Class) any())) - .thenReturn(result); - //when - Executable executable = () -> groupConnector.activateById(groupId); - //then - assertDoesNotThrow(executable); - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - ArgumentCaptor updateCaptor = ArgumentCaptor.forClass(Update.class); - verify(mongoTemplateMock, times(1)) - .updateFirst(queryCaptor.capture(), updateCaptor.capture(), (Class) any()); - Query query = queryCaptor.getValue(); - Update update = updateCaptor.getValue(); - Map set = (Map) update.getUpdateObject().get("$set"); - Map currentDate = (Map) update.getUpdateObject().get("$currentDate"); - assertEquals(groupId, query.getQueryObject().get(UserGroupEntity.Fields.id)); - assertEquals(UserGroupStatus.ACTIVE, set.get("status")); - assertEquals(selfCareUser.getId(), set.get("modifiedBy")); - assertTrue(currentDate.containsKey("modifiedAt")); - verifyNoMoreInteractions(mongoTemplateMock); - - - } - - @Test - void activateById_resourceNotFound() { - //given - String groupId = "groupId"; - UpdateResult result = mockInstance(new UpdateResult() { - @Override - public boolean wasAcknowledged() { - return false; - } - - @Override - public long getMatchedCount() { - return 0; - } - - @Override - public long getModifiedCount() { - return 1; - } - - @Override - public BsonValue getUpsertedId() { - return null; - } - }); - when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), (Class) any())) - .thenReturn(result); - //when - Executable executable = () -> groupConnector.activateById(groupId); - //then - assertThrows(ResourceNotFoundException.class, executable); - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - ArgumentCaptor updateCaptor = ArgumentCaptor.forClass(Update.class); - verify(mongoTemplateMock, times(1)) - .updateFirst(queryCaptor.capture(), updateCaptor.capture(), (Class) any()); - Query query = queryCaptor.getValue(); - Update update = updateCaptor.getValue(); - Map set = (Map) update.getUpdateObject().get("$set"); - Map currentDate = (Map) update.getUpdateObject().get("$currentDate"); - assertEquals(groupId, query.getQueryObject().get(UserGroupEntity.Fields.id)); - assertEquals(UserGroupStatus.ACTIVE, set.get("status")); - assertEquals(selfCareUser.getId(), set.get("modifiedBy")); - assertTrue(currentDate.containsKey("modifiedAt")); - verifyNoMoreInteractions(mongoTemplateMock); - } - - @Test - void insertMember_updateError() { - //given - String groupId = "groupId"; - String memberId = UUID.randomUUID().toString(); - UpdateResult result = mockInstance(new UpdateResult() { - @Override - public boolean wasAcknowledged() { - return false; - } - - @Override - public long getMatchedCount() { - return 1; - } - - @Override - public long getModifiedCount() { - return 0; - } - - @Override - public BsonValue getUpsertedId() { - return null; - } - }); - when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), (Class) any())) - .thenReturn(result); - //when - Executable executable = () -> groupConnector.insertMember(groupId, memberId); - //then - ResourceUpdateException resourceUpdateException = assertThrows(ResourceUpdateException.class, executable); - assertEquals("Couldn't update resource", resourceUpdateException.getMessage()); - - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - ArgumentCaptor updateCaptor = ArgumentCaptor.forClass(Update.class); - verify(mongoTemplateMock, times(1)) - .updateFirst(queryCaptor.capture(), updateCaptor.capture(), (Class) any()); - Query query = queryCaptor.getValue(); - Update update = updateCaptor.getValue(); - Map set = (Map) update.getUpdateObject().get("$set"); - Map currentDate = (Map) update.getUpdateObject().get("$currentDate"); - assertEquals(groupId, query.getQueryObject().get(UserGroupEntity.Fields.id)); - assertEquals(UserGroupStatus.ACTIVE, query.getQueryObject().get("status", UserGroupStatus.class)); - assertEquals(selfCareUser.getId(), set.get("modifiedBy")); - assertTrue(currentDate.containsKey("modifiedAt")); - verifyNoMoreInteractions(mongoTemplateMock); - } - - @Test - void insertMember() { - //given - String groupId = "groupId"; - String memberId = UUID.randomUUID().toString(); - - UpdateResult result = mockInstance(new UpdateResult() { - @Override - public boolean wasAcknowledged() { - return false; - } - - @Override - public long getMatchedCount() { - return 1; - } - - @Override - public long getModifiedCount() { - return 1; - } - - @Override - public BsonValue getUpsertedId() { - return null; - } - }); - when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), (Class) any())) - .thenReturn(result); - //when - Executable executable = () -> groupConnector.insertMember(groupId, memberId); - //then - assertDoesNotThrow(executable); - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - ArgumentCaptor updateCaptor = ArgumentCaptor.forClass(Update.class); - verify(mongoTemplateMock, times(1)) - .updateFirst(queryCaptor.capture(), updateCaptor.capture(), (Class) any()); - Query query = queryCaptor.getValue(); - Update update = updateCaptor.getValue(); - Map set = (Map) update.getUpdateObject().get("$set"); - Map currentDate = (Map) update.getUpdateObject().get("$currentDate"); - assertEquals(groupId, query.getQueryObject().get(UserGroupEntity.Fields.id)); - assertEquals(UserGroupStatus.ACTIVE, query.getQueryObject().get("status", UserGroupStatus.class)); - assertEquals(selfCareUser.getId(), set.get("modifiedBy")); - assertTrue(currentDate.containsKey("modifiedAt")); - verifyNoMoreInteractions(mongoTemplateMock); - } - - @Test - void deleteMember_updateError() { - //given - String groupId = "groupId"; - String memberId = UUID.randomUUID().toString(); - UpdateResult result = mockInstance(new UpdateResult() { - @Override - public boolean wasAcknowledged() { - return false; - } - - @Override - public long getMatchedCount() { - return 1; - } - - @Override - public long getModifiedCount() { - return 0; - } - - @Override - public BsonValue getUpsertedId() { - return null; - } - }); - when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), (Class) any())) - .thenReturn(result); - //when - Executable executable = () -> groupConnector.deleteMember(groupId, memberId); - //then - ResourceUpdateException resourceUpdateException = assertThrows(ResourceUpdateException.class, executable); - assertEquals("Couldn't update resource", resourceUpdateException.getMessage()); - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - ArgumentCaptor updateCaptor = ArgumentCaptor.forClass(Update.class); - verify(mongoTemplateMock, times(1)) - .updateFirst(queryCaptor.capture(), updateCaptor.capture(), (Class) any()); - Query query = queryCaptor.getValue(); - Update update = updateCaptor.getValue(); - Map set = (Map) update.getUpdateObject().get("$set"); - Map currentDate = (Map) update.getUpdateObject().get("$currentDate"); - assertEquals(groupId, query.getQueryObject().get(UserGroupEntity.Fields.id)); - assertEquals(UserGroupStatus.ACTIVE, query.getQueryObject().get("status", UserGroupStatus.class)); - assertEquals(selfCareUser.getId(), set.get("modifiedBy")); - assertTrue(currentDate.containsKey("modifiedAt")); - verifyNoMoreInteractions(mongoTemplateMock); - } - - @Test - void deleteMember() { - //given - String groupId = "groupId"; - String memberId = UUID.randomUUID().toString(); - - UpdateResult result = mockInstance(new UpdateResult() { - @Override - public boolean wasAcknowledged() { - return false; - } - - @Override - public long getMatchedCount() { - return 1; - } - - @Override - public long getModifiedCount() { - return 1; - } - - @Override - public BsonValue getUpsertedId() { - return null; - } - }); - when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), (Class) any())) - .thenReturn(result); - //when - Executable executable = () -> groupConnector.deleteMember(groupId, memberId); - //then - assertDoesNotThrow(executable); - verify(mongoTemplateMock, times(1)) - .updateFirst(any(Query.class), any(Update.class), (Class) any()); - verifyNoMoreInteractions(mongoTemplateMock); - } - - @Test - void deleteMembers_updateError() { - //given - String memberId = UUID.randomUUID().toString(); - String institutionId = "institutionId"; - String productId = "productId"; - UpdateResult result = mockInstance(new UpdateResult() { - @Override - public boolean wasAcknowledged() { - return false; - } - - @Override - public long getMatchedCount() { - return 1; - } - - @Override - public long getModifiedCount() { - return 0; - } - - @Override - public BsonValue getUpsertedId() { - return null; - } - }); - when(mongoTemplateMock.updateMulti(any(Query.class), any(Update.class), (Class) any())) - .thenReturn(result); - //when - Executable executable = () -> groupConnector.deleteMembers(memberId, institutionId, productId); - //then - Assertions.assertDoesNotThrow(executable); - - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - ArgumentCaptor updateCaptor = ArgumentCaptor.forClass(Update.class); - verify(mongoTemplateMock, times(1)) - .updateMulti(queryCaptor.capture(), updateCaptor.capture(), (Class) any()); - Query query = queryCaptor.getValue(); - Update update = updateCaptor.getValue(); - Map set = (Map) update.getUpdateObject().get("$set"); - Map currentDate = (Map) update.getUpdateObject().get("$currentDate"); - assertEquals(memberId, query.getQueryObject().get(UserGroupEntity.Fields.members)); - assertEquals(institutionId, query.getQueryObject().get(UserGroupEntity.Fields.institutionId)); - assertEquals(productId, query.getQueryObject().get(UserGroupEntity.Fields.productId)); - assertEquals(selfCareUser.getId(), set.get("modifiedBy")); - assertTrue(currentDate.containsKey("modifiedAt")); - verifyNoMoreInteractions(mongoTemplateMock); - } - - @Test - void deleteMembers() { - //given - String memberId = UUID.randomUUID().toString(); - String institutionId = "institutionId"; - String productId = "productId"; - UpdateResult result = mockInstance(new UpdateResult() { - @Override - public boolean wasAcknowledged() { - return false; - } - - @Override - public long getMatchedCount() { - return 1; - } - - @Override - public long getModifiedCount() { - return 1; - } - - @Override - public BsonValue getUpsertedId() { - return null; - } - }); - when(mongoTemplateMock.updateMulti(any(Query.class), any(Update.class), (Class) any())) - .thenReturn(result); - //when - Executable executable = () -> groupConnector.deleteMembers(memberId, institutionId, productId); - //then - assertDoesNotThrow(executable); - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - ArgumentCaptor updateCaptor = ArgumentCaptor.forClass(Update.class); - verify(mongoTemplateMock, times(1)) - .updateMulti(queryCaptor.capture(), updateCaptor.capture(), (Class) any()); - Query query = queryCaptor.getValue(); - Update update = updateCaptor.getValue(); - Map set = (Map) update.getUpdateObject().get("$set"); - Map currentDate = (Map) update.getUpdateObject().get("$currentDate"); - assertEquals(memberId, query.getQueryObject().get(UserGroupEntity.Fields.members)); - assertEquals(institutionId, query.getQueryObject().get(UserGroupEntity.Fields.institutionId)); - assertEquals(productId, query.getQueryObject().get(UserGroupEntity.Fields.productId)); - assertEquals(selfCareUser.getId(), set.get("modifiedBy")); - assertTrue(currentDate.containsKey("modifiedAt")); - verifyNoMoreInteractions(mongoTemplateMock); - } - - @Test - void save() { - //given - UserGroupEntity entity = mockInstance(new UserGroupEntity()); - when(repositoryMock.save(any())) - .thenReturn(entity); - //when - UserGroupOperations saved = groupConnector.save(entity); - //then - assertEquals(entity, saved); - ArgumentCaptor entityCaptor = ArgumentCaptor.forClass(UserGroupEntity.class); - verify(repositoryMock, times(1)) - .save(entityCaptor.capture()); - UserGroupEntity capturedEntity = entityCaptor.getValue(); - assertEquals(entity, capturedEntity); - verifyNoMoreInteractions(repositoryMock); - } - - @Test - void save_duplicateKey() { - //givenn - UserGroupEntity entity = mockInstance(new UserGroupEntity()); - Mockito.doThrow(DuplicateKeyException.class) - .when(repositoryMock) - .save(any(UserGroupEntity.class)); - //when - Executable executable = () -> groupConnector.save(entity); - //then - ResourceAlreadyExistsException e = assertThrows(ResourceAlreadyExistsException.class, executable); - assertEquals("Failed _id or unique index constraint.", e.getMessage()); - verify(repositoryMock, times(1)) - .save(entity); - verifyNoMoreInteractions(repositoryMock); - } - - -} \ No newline at end of file diff --git a/apps/user-group-ms/connector/dao/src/test/java/it/pagopa/selfcare/user_group/connector/dao/UserGroupRepositoryTest.java b/apps/user-group-ms/connector/dao/src/test/java/it/pagopa/selfcare/user_group/connector/dao/UserGroupRepositoryTest.java deleted file mode 100644 index 30fde6da..00000000 --- a/apps/user-group-ms/connector/dao/src/test/java/it/pagopa/selfcare/user_group/connector/dao/UserGroupRepositoryTest.java +++ /dev/null @@ -1,372 +0,0 @@ -package it.pagopa.selfcare.user_group.connector.dao; - -import com.mongodb.client.result.UpdateResult; -import it.pagopa.selfcare.commons.base.security.SelfCareUser; -import it.pagopa.selfcare.commons.utils.TestUtils; -import it.pagopa.selfcare.user_group.connector.dao.config.DaoTestConfig; -import it.pagopa.selfcare.user_group.connector.dao.model.UserGroupEntity; -import it.pagopa.selfcare.user_group.connector.model.UserGroupFilter; -import it.pagopa.selfcare.user_group.connector.model.UserGroupStatus; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; -import org.springframework.data.domain.AuditorAware; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.query.Criteria; -import org.springframework.data.mongodb.core.query.Query; -import org.springframework.data.mongodb.core.query.Update; -import org.springframework.security.authentication.TestingAuthenticationToken; -import org.springframework.security.test.context.TestSecurityContextHolder; -import org.springframework.test.context.ContextConfiguration; - -import javax.validation.ValidationException; -import java.time.Instant; -import java.util.*; - -import static org.junit.jupiter.api.Assertions.*; - -@DataMongoTest -@EnableAutoConfiguration -@ContextConfiguration(classes = {UserGroupEntity.class, UserGroupRepository.class, DaoTestConfig.class}) -class UserGroupRepositoryTest { - - @Autowired - private UserGroupRepository repository; - - @Autowired - private MongoTemplate mongoTemplate; - - @Autowired - private AuditorAware auditorAware; - - @AfterEach - void clear() { - repository.deleteAll(); - } - - - @Test - void create() { - //given - Instant now = Instant.now().minusSeconds(1); - SelfCareUser selfCareUser = SelfCareUser.builder("id") - .email("test@example.com") - .name("name") - .surname("surname") - .build(); - TestingAuthenticationToken authenticationToken = new TestingAuthenticationToken(selfCareUser, null); - TestSecurityContextHolder.setAuthentication(authenticationToken); - UserGroupEntity group = TestUtils.mockInstance(new UserGroupEntity(), "setId", - "setCreatedAt", - "setCreateBy", - "setModifiedAt", - "setModifiedBy"); - //when - UserGroupEntity savedGroup = repository.insert(group); - //then - assertTrue(now.isBefore(savedGroup.getCreatedAt())); - assertEquals(selfCareUser.getId(), savedGroup.getCreatedBy()); - assertNull(savedGroup.getModifiedBy()); - assertNotNull(savedGroup, "id cannot be null after entity creation"); - } - - - @Test - void delete() { - //given - Instant now = Instant.now().minusSeconds(1); - SelfCareUser selfCareUser = SelfCareUser.builder("id") - .email("test@example.com") - .name("name") - .surname("surname") - .build(); - TestingAuthenticationToken authenticationToken = new TestingAuthenticationToken(selfCareUser, null); - TestSecurityContextHolder.setAuthentication(authenticationToken); - UserGroupEntity group = TestUtils.mockInstance(new UserGroupEntity(), "setId", - "setCreatedAt", - "setCreateBy", - "setModifiedAt", - "setModifiedBy"); - UserGroupEntity savedGroup = repository.insert(group); - Optional found = repository.findById(savedGroup.getId()); - //when - mongoTemplate.remove(Query.query(Criteria.where("_id").is(savedGroup.getId())), UserGroupEntity.class); - //then - Optional deleted = repository.findById(savedGroup.getId()); - assertEquals(Optional.empty(), deleted); - - } - - @Test - void update() { - //given - Instant now = Instant.now().minusSeconds(1); - SelfCareUser selfCareUser = SelfCareUser.builder("id") - .email("test@example.com") - .name("name") - .surname("surname") - .build(); - TestingAuthenticationToken authenticationToken = new TestingAuthenticationToken(selfCareUser, null); - TestSecurityContextHolder.setAuthentication(authenticationToken); - UserGroupEntity group = TestUtils.mockInstance(new UserGroupEntity(), "setId", - "setCreatedAt", - "setCreateBy", - "setModifiedAt", - "setModifiedBy"); - UserGroupEntity savedGroup = repository.insert(group); - - Optional groupMod = repository.findById(savedGroup.getId()); - groupMod.get().setId(savedGroup.getId()); - groupMod.get().setStatus(UserGroupStatus.SUSPENDED); - //when - UserGroupEntity modifiedGroup = repository.save(groupMod.get()); - //then - assertNull(savedGroup.getModifiedBy()); - assertEquals(selfCareUser.getId(), modifiedGroup.getModifiedBy()); - assertTrue(modifiedGroup.getModifiedAt().isAfter(savedGroup.getCreatedAt())); - assertEquals(UserGroupStatus.ACTIVE, savedGroup.getStatus()); - assertEquals(UserGroupStatus.SUSPENDED, modifiedGroup.getStatus()); - } - - @Test - void addMember() { - //given - Instant now = Instant.now().minusSeconds(1); - SelfCareUser selfCareUser = SelfCareUser.builder("id") - .email("test@example.com") - .name("name") - .surname("surname") - .build(); - TestingAuthenticationToken authenticationToken = new TestingAuthenticationToken(selfCareUser, null); - TestSecurityContextHolder.setAuthentication(authenticationToken); - UserGroupEntity group = TestUtils.mockInstance(new UserGroupEntity(), "setId", - "setCreatedAt", - "setCreateBy", - "setModifiedAt", - "setModifiedBy"); - UserGroupEntity savedGroup = repository.insert(group); - UUID memberUID = UUID.randomUUID(); - //when - UpdateResult updateResult1 = mongoTemplate.updateFirst( - Query.query(Criteria.where("_id").is(savedGroup.getId())), - new Update().push("members", memberUID.toString()), - UserGroupEntity.class); - UpdateResult updateResult2 = mongoTemplate.updateFirst( - Query.query(Criteria.where("_id").is(savedGroup.getId())), - new Update().push("members", UUID.randomUUID()), - UserGroupEntity.class); - UpdateResult updateResult3 = mongoTemplate.updateFirst( - Query.query(Criteria.where("_id").is(savedGroup.getId())), - new Update().push("members", memberUID.toString()), - UserGroupEntity.class); - //then - Optional groupMod = repository.findById(savedGroup.getId()); - assertEquals(selfCareUser.getId(), savedGroup.getCreatedBy()); - assertEquals(1, updateResult1.getMatchedCount()); - assertEquals(1, updateResult2.getMatchedCount()); - assertEquals(1, updateResult3.getMatchedCount()); - assertEquals(2, groupMod.get().getMembers().size()); - } - - @Test - void suspend() { - Instant now = Instant.now().minusSeconds(1); - SelfCareUser selfCareUser = SelfCareUser.builder("id") - .email("test@example.com") - .name("name") - .surname("surname") - .build(); - TestingAuthenticationToken authenticationToken = new TestingAuthenticationToken(selfCareUser, null); - TestSecurityContextHolder.setAuthentication(authenticationToken); - UserGroupEntity group = TestUtils.mockInstance(new UserGroupEntity(), "setId", - "setCreatedAt", - "setCreateBy", - "setModifiedAt", - "setModifiedBy"); - UserGroupEntity savedGroup = repository.insert(group); - UUID memberUID = UUID.randomUUID(); - //when - UpdateResult updateResult = mongoTemplate.updateFirst( - Query.query(Criteria.where(UserGroupEntity.Fields.id).is(savedGroup.getId())), - Update.update(UserGroupEntity.Fields.status, UserGroupStatus.SUSPENDED) - .set("modifiedBy", auditorAware.getCurrentAuditor().get()) - .set("modifiedAt", now), - UserGroupEntity.class); - //then - Optional groupMod = repository.findById(savedGroup.getId()); - assertEquals(selfCareUser.getId(), groupMod.get().getModifiedBy()); - assertEquals(selfCareUser.getId(), savedGroup.getCreatedBy()); - } - - @Test - void findAll() { - //given - Instant now = Instant.now().minusSeconds(1); - SelfCareUser selfCareUser = SelfCareUser.builder("id") - .email("test@example.com") - .name("name") - .surname("surname") - .build(); - TestingAuthenticationToken authenticationToken = new TestingAuthenticationToken(selfCareUser, null); - TestSecurityContextHolder.setAuthentication(authenticationToken); - UserGroupEntity group1 = TestUtils.mockInstance(new UserGroupEntity(), "setId", - "setCreatedAt", - "setCreateBy", - "setModifiedAt", - "setModifiedBy"); - String institutionId = "institutionId"; - String productId = "productId"; - String userId = "userId"; - group1.setProductId(productId); - group1.setName("alfa"); - group1.setMembers(Set.of("userId", "userId2")); - group1.setInstitutionId(institutionId); - UserGroupEntity savedGroup = repository.insert(group1); - UserGroupEntity group2 = TestUtils.mockInstance(new UserGroupEntity(), "setId", - "setCreatedAt", - "setCreateBy", - "setModifiedAt", - "setModifiedBy"); - group2.setProductId(productId); - group2.setName("beta"); - group2.setInstitutionId(institutionId); - group2.setMembers(Set.of("userId")); - UserGroupEntity savedGroup1 = repository.insert(group2); - - Pageable pageable = PageRequest.of(0, 3); - UserGroupFilter filter = new UserGroupFilter(institutionId, productId, userId, Collections.emptyList()); - - Query query = new Query(); - if (pageable.getSort().isSorted() && filter.getProductId().isEmpty() && filter.getInstitutionId().isEmpty()) { - throw new ValidationException(); - } - query.addCriteria(Criteria.where(UserGroupEntity.Fields.institutionId).is(institutionId)); - query.addCriteria(Criteria.where(UserGroupEntity.Fields.productId).is(productId)); - query.addCriteria(Criteria.where(UserGroupEntity.Fields.members).is(userId)); - //when - List foundGroups = mongoTemplate.find(query.with(pageable), UserGroupEntity.class); - //then - assertEquals(2, foundGroups.size()); - } - - @Test - void findAll_allowedState() { - //given - Instant now = Instant.now().minusSeconds(1); - String institutionId = "institutionId"; - String productId = "productId"; - String userId = "userId"; - List allowedStatus = List.of(UserGroupStatus.ACTIVE); - SelfCareUser selfCareUser = SelfCareUser.builder("id") - .email("test@example.com") - .name("name") - .surname("surname") - .build(); - TestingAuthenticationToken authenticationToken = new TestingAuthenticationToken(selfCareUser, null); - TestSecurityContextHolder.setAuthentication(authenticationToken); - UserGroupEntity group1 = TestUtils.mockInstance(new UserGroupEntity(), "setId", - "setCreatedAt", - "setCreateBy", - "setModifiedAt", - "setModifiedBy"); - group1.setProductId(productId); - group1.setName("alfa"); - group1.setMembers(Set.of("userId", "userId2")); - group1.setInstitutionId(institutionId); - group1.setStatus(UserGroupStatus.SUSPENDED); - UserGroupEntity savedGroup = repository.insert(group1); - UserGroupEntity group2 = TestUtils.mockInstance(new UserGroupEntity(), "setId", - "setCreatedAt", - "setCreateBy", - "setModifiedAt", - "setModifiedBy"); - group2.setProductId(productId); - group2.setName("beta"); - group2.setInstitutionId(institutionId); - group2.setMembers(Set.of("userId")); - UserGroupEntity savedGroup1 = repository.insert(group2); - UserGroupFilter filter = new UserGroupFilter(institutionId, productId, userId, allowedStatus); - Pageable pageable = PageRequest.of(0, 3); - Query query = new Query(); - if (pageable.getSort().isSorted() && filter.getProductId().isEmpty() && filter.getInstitutionId().isEmpty()) { - throw new ValidationException(); - } - query.addCriteria(Criteria.where(UserGroupEntity.Fields.institutionId).is(institutionId)); - query.addCriteria(Criteria.where(UserGroupEntity.Fields.productId).is(productId)); - query.addCriteria(Criteria.where(UserGroupEntity.Fields.members).is(userId)); - query.addCriteria(Criteria.where(UserGroupEntity.Fields.status).in(allowedStatus)); - //when - List foundGroups = mongoTemplate.find(query.with(pageable), UserGroupEntity.class); - //then - assertEquals(1, foundGroups.size()); - } - - @Test - void deleteMembers() { - //given - Instant now = Instant.now().minusSeconds(1); - SelfCareUser selfCareUser = SelfCareUser.builder("id") - .email("test@example.com") - .name("name") - .surname("surname") - .build(); - TestingAuthenticationToken authenticationToken = new TestingAuthenticationToken(selfCareUser, null); - TestSecurityContextHolder.setAuthentication(authenticationToken); - UserGroupEntity group1 = TestUtils.mockInstance(new UserGroupEntity(), "setId", - "setCreatedAt", - "setCreateBy", - "setModifiedAt", - "setModifiedBy"); - String productId = "productId"; - String institutionId = "institutionId"; - group1.setProductId(productId); - group1.setName("alfa"); - group1.setMembers(Set.of("userId", "userId2")); - group1.setInstitutionId(institutionId); - UserGroupEntity savedGroup = repository.insert(group1); - UserGroupEntity group2 = TestUtils.mockInstance(new UserGroupEntity(), "setId", - "setCreatedAt", - "setCreateBy", - "setModifiedAt", - "setModifiedBy"); - group2.setProductId(productId); - group2.setName("beta"); - group2.setInstitutionId(institutionId); - group2.setMembers(Set.of("userId")); - UserGroupEntity savedGroup1 = repository.insert(group2); - Pageable pageable = PageRequest.of(0, 3); - UserGroupFilter filter = new UserGroupFilter(); - String userId = "userId"; - filter.setInstitutionId(institutionId); - filter.setProductId(productId); - Query query = new Query(); - if (pageable.getSort().isSorted() && filter.getProductId().isEmpty() && filter.getInstitutionId().isEmpty()) { - throw new ValidationException(); - } - - //when - UpdateResult updateResult = mongoTemplate.updateMulti( - Query.query(Criteria.where(UserGroupEntity.Fields.members).is("userId2") - .and(UserGroupEntity.Fields.institutionId).is(institutionId) - .and(UserGroupEntity.Fields.productId).is(productId)), - new Update().pull("members", "userId2") - .set("modifiedBy", auditorAware.getCurrentAuditor().get()) - .set("modifiedAt", now), - UserGroupEntity.class); - - //then - query.addCriteria(Criteria.where(UserGroupEntity.Fields.institutionId).is(institutionId)); - query.addCriteria(Criteria.where(UserGroupEntity.Fields.productId).is(productId)); - List foundGroups = mongoTemplate.find(query.with(pageable), UserGroupEntity.class); - - assertEquals(1, foundGroups.get(1).getMembers().size()); - assertEquals(1, foundGroups.get(0).getMembers().size()); - assertEquals(1, updateResult.getModifiedCount()); - } - - -} \ No newline at end of file diff --git a/apps/user-group-ms/connector/dao/src/test/java/it/pagopa/selfcare/user_group/connector/dao/config/DaoTestConfig.java b/apps/user-group-ms/connector/dao/src/test/java/it/pagopa/selfcare/user_group/connector/dao/config/DaoTestConfig.java deleted file mode 100644 index eaceb49a..00000000 --- a/apps/user-group-ms/connector/dao/src/test/java/it/pagopa/selfcare/user_group/connector/dao/config/DaoTestConfig.java +++ /dev/null @@ -1,9 +0,0 @@ -package it.pagopa.selfcare.user_group.connector.dao.config; - -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.context.annotation.Import; - -@TestConfiguration -@Import(DaoConfig.class) -public class DaoTestConfig { -} \ No newline at end of file diff --git a/apps/user-group-ms/connector/pom.xml b/apps/user-group-ms/connector/pom.xml deleted file mode 100644 index be850795..00000000 --- a/apps/user-group-ms/connector/pom.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - user-group-ms - it.pagopa.selfcare - 1.0.0-SNAPSHOT - - 4.0.0 - user-group-ms-connector - pom - - dao - - - - - it.pagopa.selfcare - user-group-ms-connector-api - - - diff --git a/apps/user-group-ms/core/pom.xml b/apps/user-group-ms/core/pom.xml deleted file mode 100644 index 10d41b6e..00000000 --- a/apps/user-group-ms/core/pom.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - user-group-ms - it.pagopa.selfcare - 1.0.0-SNAPSHOT - - 4.0.0 - - user-group-ms-core - - - - it.pagopa.selfcare - user-group-ms-connector-api - - - it.pagopa.selfcare - user-group-ms-connector-api - test-jar - test - - - - diff --git a/apps/user-group-ms/core/src/main/java/it/pagopa/selfcare/user_group/core/UserGroupServiceImpl.java b/apps/user-group-ms/core/src/main/java/it/pagopa/selfcare/user_group/core/UserGroupServiceImpl.java deleted file mode 100644 index 46cfa08c..00000000 --- a/apps/user-group-ms/core/src/main/java/it/pagopa/selfcare/user_group/core/UserGroupServiceImpl.java +++ /dev/null @@ -1,191 +0,0 @@ -package it.pagopa.selfcare.user_group.core; - -import it.pagopa.selfcare.commons.base.security.SelfCareUser; -import it.pagopa.selfcare.user_group.connector.api.UserGroupConnector; -import it.pagopa.selfcare.user_group.connector.api.UserGroupOperations; -import it.pagopa.selfcare.user_group.connector.exception.ResourceAlreadyExistsException; -import it.pagopa.selfcare.user_group.connector.exception.ResourceNotFoundException; -import it.pagopa.selfcare.user_group.connector.exception.ResourceUpdateException; -import it.pagopa.selfcare.user_group.connector.model.UserGroupFilter; -import it.pagopa.selfcare.user_group.connector.model.UserGroupStatus; -import lombok.extern.slf4j.Slf4j; -import org.owasp.encoder.Encode; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Service; -import org.springframework.util.Assert; - -import javax.validation.ValidationException; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; - -@Slf4j -@Service -class UserGroupServiceImpl implements UserGroupService { - - private final UserGroupConnector groupConnector; - private static final String USER_GROUP_ID_REQUIRED_MESSAGE = "A user group id is required"; - private static final String TRYING_TO_MODIFY_SUSPENDED_GROUP = "Trying to modify suspended group"; - private static final String MEMBER_ID_REQUIRED = "A member id is required"; - private static final String GROUP_NAME_ALREADY_EXISTS = "A group with the same name already exists in ACTIVE or SUSPENDED state"; - private final List allowedSortingParams; - - @Autowired - UserGroupServiceImpl(UserGroupConnector groupConnector, - @Value("${user-group.allowed.sorting.parameters}") String[] allowedSortingParams) { - this.groupConnector = groupConnector; - this.allowedSortingParams = Arrays.asList(allowedSortingParams); - } - - @Override - public UserGroupOperations createGroup(UserGroupOperations group) { - log.trace("createGroup start"); - log.debug("createGroup group = {}", group); - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - Assert.state(authentication != null, "Authentication is required"); - Assert.state(authentication.getPrincipal() instanceof SelfCareUser, "Not SelfCareUser principal"); - Assert.notNull(group, "A group is required"); - - checkNameUniqueness(group.getId(), group.getName(), group.getProductId(), group.getInstitutionId()); - UserGroupOperations insert = groupConnector.insert(group); - log.debug("insert = {}", insert); - log.trace("createGroup end"); - return insert; - } - - private void checkNameUniqueness(String currentGroupId, String groupName, String productId, String institutionId) { - UserGroupFilter filter = new UserGroupFilter(); - filter.setProductId(productId); - filter.setInstitutionId(institutionId); - filter.setStatus(Arrays.asList(UserGroupStatus.ACTIVE, UserGroupStatus.SUSPENDED)); - - Page existingGroups = groupConnector.findAll(filter, Pageable.unpaged()); - boolean isDuplicate = existingGroups.stream() - .anyMatch(g -> g.getName().equals(groupName) && !g.getId().equals(currentGroupId)); - - if (isDuplicate) { - log.warn("Attempted to create/update group with duplicate name: {}", groupName); - throw new ResourceAlreadyExistsException(GROUP_NAME_ALREADY_EXISTS); - } - } - - @Override - public void addMember(String id, UUID memberId) { - log.trace("addMember start"); - log.debug("addMember id = {}, memberId ={}", Encode.forJava(id), memberId); - Assert.hasText(id, USER_GROUP_ID_REQUIRED_MESSAGE); - Assert.notNull(memberId, MEMBER_ID_REQUIRED); - UserGroupOperations foundGroup = groupConnector.findById(id).orElseThrow(ResourceNotFoundException::new); - if (UserGroupStatus.SUSPENDED.equals(foundGroup.getStatus())) { - throw new ResourceUpdateException(TRYING_TO_MODIFY_SUSPENDED_GROUP); - } - groupConnector.insertMember(id, memberId.toString()); - log.trace("addMember end"); - } - - @Override - public void deleteMember(String groupId, String memberId) { - log.trace("deleteMember start"); - log.debug("deleteMember groupId = {}, memberId = {}", Encode.forJava(groupId), Encode.forJava(memberId)); - Assert.hasText(groupId, USER_GROUP_ID_REQUIRED_MESSAGE); - Assert.hasText(memberId, MEMBER_ID_REQUIRED); - UserGroupOperations foundGroup = groupConnector.findById(groupId).orElseThrow(ResourceNotFoundException::new); - if (UserGroupStatus.SUSPENDED.equals(foundGroup.getStatus())) { - throw new ResourceUpdateException(TRYING_TO_MODIFY_SUSPENDED_GROUP); - } - groupConnector.deleteMember(groupId, memberId); - log.trace("deleteMember end"); - } - - @Override - public void deleteMembers(String memberId, String institutionId, String productId) { - log.trace("deleteMembers start"); - log.debug("deleteMembers memberId = {}, institutionId = {}, productId= {}", Encode.forJava(memberId), Encode.forJava(institutionId), Encode.forJava(productId)); - Assert.hasText(memberId, MEMBER_ID_REQUIRED); - Assert.hasText(institutionId, "A institution id is required"); - Assert.hasText(productId, "A product id is required"); - groupConnector.deleteMembers(memberId, institutionId, productId); - log.trace("deleteMembers end"); - } - - @Override - public UserGroupOperations getUserGroup(String id) { - log.trace("getUserGroup start"); - log.debug("getUserGroup id = {}", id); - Assert.hasText(id, USER_GROUP_ID_REQUIRED_MESSAGE); - UserGroupOperations foundGroup = groupConnector.findById(id).orElseThrow(ResourceNotFoundException::new); - log.debug("getUserGroup result = {}", foundGroup); - log.trace("getUserGroup end"); - - return foundGroup; - } - - - @Override - public Page getUserGroups(UserGroupFilter filter, Pageable pageable) { - log.trace("getUserGroups start"); - log.debug("getUserGroups filter = {}, pageable = {}", filter, pageable); - boolean match = pageable.getSort().stream().allMatch(order -> allowedSortingParams.contains(order.getProperty())); - if (!match) { - throw new ValidationException("Given sort parameters aren't valid"); - } - Page result = groupConnector.findAll(filter, pageable); - log.debug("getUserGroups result = {}", result); - log.trace("getUserGroups end"); - return result; - } - - - @Override - public void deleteGroup(String id) { - log.trace("deleteGroup start"); - log.debug("deleteGroup id = {}", Encode.forJava(id)); - Assert.hasText(id, USER_GROUP_ID_REQUIRED_MESSAGE); - groupConnector.deleteById(id); - log.trace("deleteProduct end"); - } - - @Override - public void suspendGroup(String id) { - log.trace("suspendGroup start"); - log.debug("suspendGroup id = {}", Encode.forJava(id)); - Assert.hasText(id, USER_GROUP_ID_REQUIRED_MESSAGE); - groupConnector.suspendById(id); - log.trace("suspendGroup end"); - } - - @Override - public void activateGroup(String id) { - log.trace("activateGroup start"); - log.debug("activateGroup id = {}", Encode.forJava(id)); - Assert.hasText(id, USER_GROUP_ID_REQUIRED_MESSAGE); - groupConnector.activateById(id); - log.trace("activateGroup end"); - } - - @Override - public UserGroupOperations updateGroup(String id, UserGroupOperations group) { - log.trace("updateGroup start"); - log.debug("updateGroup id = {}, group = {}", Encode.forJava(id), group); - Assert.hasText(id, USER_GROUP_ID_REQUIRED_MESSAGE); - Assert.notNull(group, "A user group is required"); - UserGroupOperations foundGroup = groupConnector.findById(id).orElseThrow(ResourceNotFoundException::new); - if (UserGroupStatus.SUSPENDED.equals(foundGroup.getStatus())) { - throw new ResourceUpdateException(TRYING_TO_MODIFY_SUSPENDED_GROUP); - } - checkNameUniqueness(id, group.getName(), foundGroup.getProductId(), foundGroup.getInstitutionId()); - - foundGroup.setMembers(group.getMembers()); - foundGroup.setName(group.getName()); - foundGroup.setDescription(group.getDescription()); - UserGroupOperations updatedGroup = groupConnector.save(foundGroup); - log.debug("updateGroup updatedGroup = {}", updatedGroup); - log.trace("updateGroup end"); - return updatedGroup; - } -} diff --git a/apps/user-group-ms/core/src/main/java/it/pagopa/selfcare/user_group/core/config/CoreConfig.java b/apps/user-group-ms/core/src/main/java/it/pagopa/selfcare/user_group/core/config/CoreConfig.java deleted file mode 100644 index 95dd8a4e..00000000 --- a/apps/user-group-ms/core/src/main/java/it/pagopa/selfcare/user_group/core/config/CoreConfig.java +++ /dev/null @@ -1,10 +0,0 @@ -package it.pagopa.selfcare.user_group.core.config; - -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; - -@Configuration -@PropertySource("classpath:config/core-config.properties") -class CoreConfig { - -} diff --git a/apps/user-group-ms/core/src/main/resources/config/core-config.properties b/apps/user-group-ms/core/src/main/resources/config/core-config.properties deleted file mode 100644 index 439b256a..00000000 --- a/apps/user-group-ms/core/src/main/resources/config/core-config.properties +++ /dev/null @@ -1 +0,0 @@ -user-group.allowed.sorting.parameters=${ALLOWED_SORTING_PARAMETERS:name} \ No newline at end of file diff --git a/apps/user-group-ms/core/src/test/java/it/pagopa/selfcare/user_group/core/UserGroupServiceImplTest.java b/apps/user-group-ms/core/src/test/java/it/pagopa/selfcare/user_group/core/UserGroupServiceImplTest.java deleted file mode 100644 index 56624b30..00000000 --- a/apps/user-group-ms/core/src/test/java/it/pagopa/selfcare/user_group/core/UserGroupServiceImplTest.java +++ /dev/null @@ -1,700 +0,0 @@ -package it.pagopa.selfcare.user_group.core; - -import it.pagopa.selfcare.commons.base.security.SelfCareUser; -import it.pagopa.selfcare.commons.utils.TestUtils; -import it.pagopa.selfcare.user_group.connector.DummyGroup; -import it.pagopa.selfcare.user_group.connector.api.UserGroupConnector; -import it.pagopa.selfcare.user_group.connector.api.UserGroupOperations; -import it.pagopa.selfcare.user_group.connector.exception.ResourceAlreadyExistsException; -import it.pagopa.selfcare.user_group.connector.exception.ResourceNotFoundException; -import it.pagopa.selfcare.user_group.connector.exception.ResourceUpdateException; -import it.pagopa.selfcare.user_group.connector.model.UserGroupFilter; -import it.pagopa.selfcare.user_group.connector.model.UserGroupStatus; -import it.pagopa.selfcare.user_group.core.config.CoreTestConfig; -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.junit.jupiter.api.function.Executable; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mockito; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.security.authentication.TestingAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.test.context.TestSecurityContextHolder; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -import javax.validation.ValidationException; -import java.util.*; -import static java.util.UUID.randomUUID; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; -import static org.springframework.data.support.PageableExecutionUtils.getPage; - -@ExtendWith(SpringExtension.class) -@ContextConfiguration(classes = {UserGroupServiceImpl.class, CoreTestConfig.class}) -@TestPropertySource(properties = { - "ALLOWED_SORTING_PARAMETERS=name" -}) -class UserGroupServiceImplTest { - - @BeforeEach - void beforeEach() { - TestSecurityContextHolder.clearContext(); - } - - @MockBean - private UserGroupConnector groupConnectorMock; - - @Autowired - private UserGroupServiceImpl groupService; - - @Captor - private ArgumentCaptor filter; - - @Test - void createGroup_nullAuth() { - //given - UserGroupOperations input = null; - //when - Executable executable = () -> groupService.createGroup(input); - //then - IllegalStateException e = assertThrows(IllegalStateException.class, executable); - assertEquals("Authentication is required", e.getMessage()); - verifyNoInteractions(groupConnectorMock); - } - - @Test - void createGroup_nullPrincipal() { - //given - UserGroupOperations input = null; - Authentication authentication = new TestingAuthenticationToken(null, null); - TestSecurityContextHolder.setAuthentication(authentication); - //when - Executable executable = () -> groupService.createGroup(input); - //then - IllegalStateException illegalStateException = Assertions.assertThrows(IllegalStateException.class, executable); - Assertions.assertEquals("Not SelfCareUser principal", illegalStateException.getMessage()); - verifyNoInteractions(groupConnectorMock); - } - - @Test - void createGroup_nullGroup() { - //given - SelfCareUser selfCareUser = SelfCareUser.builder("id") - .email("test@example.com") - .name("name") - .surname("surname") - .build(); - TestingAuthenticationToken authenticationToken = new TestingAuthenticationToken(selfCareUser, null); - TestSecurityContextHolder.setAuthentication(authenticationToken); - UserGroupOperations input = null; - //when - Executable executable = () -> groupService.createGroup(input); - //then - IllegalArgumentException illegalArgumentException = Assertions.assertThrows(IllegalArgumentException.class, executable); - Assertions.assertEquals("A group is required", illegalArgumentException.getMessage()); - verifyNoInteractions(groupConnectorMock); - } - - @Test - void createGroup_ok() { - //given - SelfCareUser selfCareUser = SelfCareUser.builder("userId") - .email("test@example.com") - .name("name") - .surname("surname") - .build(); - TestingAuthenticationToken authenticationToken = new TestingAuthenticationToken(selfCareUser, null); - TestSecurityContextHolder.setAuthentication(authenticationToken); - UserGroupOperations input = TestUtils.mockInstance(new DummyGroup(), "setId", "setCreateAt", "setModifiedAt"); - Page existingGroups = getPage(Collections.emptyList(), Pageable.unpaged(), () -> 0L); - when(groupConnectorMock.findAll(any(), any())) - .thenReturn(existingGroups); - when(groupConnectorMock.insert(any(UserGroupOperations.class))) - .thenAnswer(invocation -> invocation.getArgument(0, UserGroupOperations.class)); - //when - UserGroupOperations output = groupService.createGroup(input); - //then - assertNotNull(output); - - verify(groupConnectorMock, times(1)) - .insert(any(UserGroupOperations.class)); - verify(groupConnectorMock, times(1)) - .findAll(filter.capture(), any()); - verifyNoMoreInteractions(groupConnectorMock); - } - - @Test - void createGroup_conflict() { - //given - SelfCareUser selfCareUser = SelfCareUser.builder("userId") - .email("test@example.com") - .name("name") - .surname("surname") - .build(); - TestingAuthenticationToken authenticationToken = new TestingAuthenticationToken(selfCareUser, null); - TestSecurityContextHolder.setAuthentication(authenticationToken); - UserGroupOperations input = TestUtils.mockInstance(new DummyGroup(), "setId", "setCreateAt", "setModifiedAt"); - input.setName("existingGroupName"); - - UserGroupOperations existingGroup = TestUtils.mockInstance(new DummyGroup(), "setCreateAt", "setModifiedAt"); - existingGroup.setName("existingGroupName"); - Page existingGroups = getPage(Collections.singletonList(existingGroup), Pageable.unpaged(), () -> 1L); - - when(groupConnectorMock.findAll(any(), any())) - .thenReturn(existingGroups); - - //when - Executable executable = () -> groupService.createGroup(input); - - //then - assertThrows(ResourceAlreadyExistsException.class, executable); - - verify(groupConnectorMock, times(1)) - .findAll(filter.capture(), any()); - verifyNoMoreInteractions(groupConnectorMock); - } - - @Test - void deleteGroup() { - //given - String id = "id"; - //when - groupService.deleteGroup(id); - //then - verify(groupConnectorMock, times(1)) - .deleteById(id); - verifyNoMoreInteractions(groupConnectorMock); - } - - - @Test - void deleteGroup_nullId() { - //given - String id = null; - //when - Executable executable = () -> groupService.deleteGroup(id); - //then - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, executable); - assertEquals("A user group id is required", e.getMessage()); - verifyNoInteractions(groupConnectorMock); - } - - @Test - void suspendGroup() { - //given - String id = "id"; - //when - groupService.suspendGroup(id); - //then - verify(groupConnectorMock, times(1)) - .suspendById(id); - verifyNoMoreInteractions(groupConnectorMock); - } - - - @Test - void suspendGroup_nullId() { - //given - String id = null; - //when - Executable executable = () -> groupService.suspendGroup(id); - //then - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, executable); - assertEquals("A user group id is required", e.getMessage()); - verifyNoInteractions(groupConnectorMock); - } - - @Test - void activateGroup() { - //given - String id = "id"; - //when - groupService.activateGroup(id); - //then - verify(groupConnectorMock, times(1)) - .activateById(id); - verifyNoMoreInteractions(groupConnectorMock); - } - - @Test - void activateGroup_nullId() { - //given - String id = null; - //when - Executable executable = () -> groupService.activateGroup(id); - //then - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, executable); - assertEquals("A user group id is required", e.getMessage()); - verifyNoInteractions(groupConnectorMock); - } - - @Test - void updateGroup_nullId() { - //given - String id = null; - UserGroupOperations input = new DummyGroup(); - //when - Executable executable = () -> groupService.updateGroup(id, input); - //then - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, executable); - assertEquals("A user group id is required", e.getMessage()); - verifyNoInteractions(groupConnectorMock); - } - - @Test - void updateGroup_nullGroup() { - //given - String id = "id"; - UserGroupOperations input = null; - //when - Executable executable = () -> groupService.updateGroup(id, input); - //then - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, executable); - assertEquals("A user group is required", e.getMessage()); - verifyNoInteractions(groupConnectorMock); - } - - @Test - void updateGroup_foundGroupSuspended() { - //given - String id = "id"; - UserGroupOperations group = TestUtils.mockInstance(new DummyGroup()); - group.setStatus(UserGroupStatus.SUSPENDED); - when(groupConnectorMock.findById(Mockito.anyString())) - .thenReturn(Optional.of(group)); - //when - Executable executable = () -> groupService.updateGroup(id, group); - //then - ResourceUpdateException e = assertThrows(ResourceUpdateException.class, executable); - assertEquals("Trying to modify suspended group", e.getMessage()); - verify(groupConnectorMock, times(1)) - .findById(id); - verifyNoMoreInteractions(groupConnectorMock); - } - - @Test - void updateGroup_notExists() { - //given - String id = "id"; - UserGroupOperations input = new DummyGroup(); - //when - Executable executable = () -> groupService.updateGroup(id, input); - //then - assertThrows(ResourceNotFoundException.class, executable); - verify(groupConnectorMock, times(1)) - .findById(id); - verifyNoMoreInteractions(groupConnectorMock); - } - - @Test - void updateGroup_exists_ok() { - //given - String id = "id"; - UserGroupOperations group = TestUtils.mockInstance(new DummyGroup(), "setId"); - UserGroupOperations foundGroup = TestUtils.mockInstance(new DummyGroup()); - Page existingGroups = getPage(Collections.emptyList(), Pageable.unpaged(), () -> 0L); - - when(groupConnectorMock.findAll(any(), any())) - .thenReturn(existingGroups); - when(groupConnectorMock.findById(Mockito.anyString())) - .thenReturn(Optional.of(foundGroup)); - when(groupConnectorMock.save(any())) - .thenAnswer(invocationOnMock -> invocationOnMock.getArgument(0, UserGroupOperations.class)); - //when - UserGroupOperations saved = groupService.updateGroup(id, group); - //then - assertEquals(saved.getDescription(), group.getDescription()); - assertEquals(saved.getMembers(), group.getMembers()); - assertEquals(saved.getName(), group.getName()); - verify(groupConnectorMock, times(1)) - .findById(id); - verify(groupConnectorMock, times(1)) - .findAll(any(), any()); - verify(groupConnectorMock, times(1)) - .save(any()); - verifyNoMoreInteractions(groupConnectorMock); - } - - @Test - void updateGroup_exists_notChangingName() { - //given - String id = "id"; - UserGroupOperations group = TestUtils.mockInstance(new DummyGroup(), "setId"); - group.setName("existingGroupName"); - - UserGroupOperations foundGroup = TestUtils.mockInstance(new DummyGroup()); - foundGroup.setId(id); - foundGroup.setName("existingGroupName"); - foundGroup.setStatus(UserGroupStatus.ACTIVE); - - // existing group find the same group without changing the name - Page existingGroups = getPage(Collections.singletonList(foundGroup), Pageable.unpaged(), () -> 1L); - - when(groupConnectorMock.findAll(any(), any())) - .thenReturn(existingGroups); - when(groupConnectorMock.findById(Mockito.anyString())) - .thenReturn(Optional.of(foundGroup)); - when(groupConnectorMock.save(any())) - .thenAnswer(invocationOnMock -> invocationOnMock.getArgument(0, UserGroupOperations.class)); - - //when - UserGroupOperations saved = groupService.updateGroup(id, group); - //then - assertEquals(saved.getDescription(), group.getDescription()); - assertEquals(saved.getMembers(), group.getMembers()); - assertEquals(saved.getName(), group.getName()); - - verify(groupConnectorMock, times(1)) - .findById(id); - verify(groupConnectorMock, times(1)) - .findAll(any(), any()); - verify(groupConnectorMock, times(1)) - .save(any()); - verifyNoMoreInteractions(groupConnectorMock); - } - - @Test - void updateGroup_exists_conflict() { - //given - String id = "id"; - UserGroupOperations group = TestUtils.mockInstance(new DummyGroup(), "setId"); - group.setName("existingGroupName"); - UserGroupOperations foundGroup = TestUtils.mockInstance(new DummyGroup()); - foundGroup.setStatus(UserGroupStatus.ACTIVE); - - UserGroupOperations existingGroup = TestUtils.mockInstance(new DummyGroup(), "setId"); - existingGroup.setName("existingGroupName"); - existingGroup.setId("differentId"); - Page existingGroups = getPage(Collections.singletonList(existingGroup), Pageable.unpaged(), () -> 1L); - - when(groupConnectorMock.findAll(any(), any())) - .thenReturn(existingGroups); - when(groupConnectorMock.findById(Mockito.anyString())) - .thenReturn(Optional.of(foundGroup)); - when(groupConnectorMock.save(any())) - .thenAnswer(invocationOnMock -> invocationOnMock.getArgument(0, UserGroupOperations.class)); - - //when - Executable executable = () -> groupService.updateGroup(id, group); - - //then - assertThrows(ResourceAlreadyExistsException.class, executable); - - verify(groupConnectorMock, times(1)) - .findById(id); - verify(groupConnectorMock, times(1)) - .findAll(any(), any()); - verifyNoMoreInteractions(groupConnectorMock); - } - - @Test - void addMember_nullId() { - //given - String id = null; - UUID memberId = randomUUID(); - //when - Executable executable = () -> groupService.addMember(id, memberId); - //then - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, executable); - assertEquals("A user group id is required", e.getMessage()); - verifyNoInteractions(groupConnectorMock); - } - - @Test - void addMember_nullMemberId() { - //given - String id = "id"; - UUID memberId = null; - //when - Executable executable = () -> groupService.addMember(id, memberId); - //then - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, executable); - assertEquals("A member id is required", e.getMessage()); - verifyNoInteractions(groupConnectorMock); - } - - @Test - void addMember_doesNotExist() { - //given - String id = "id"; - UUID memberId = randomUUID(); - //when - Executable executable = () -> groupService.addMember(id, memberId); - //then - assertThrows(ResourceNotFoundException.class, executable); - verify(groupConnectorMock, times(1)) - .findById(id); - verifyNoMoreInteractions(groupConnectorMock); - - } - - @Test - void addMember_groupSuspended() { - //given - String id = "id"; - UUID memberId = randomUUID(); - UserGroupOperations group = TestUtils.mockInstance(new DummyGroup()); - group.setStatus(UserGroupStatus.SUSPENDED); - when(groupConnectorMock.findById(Mockito.anyString())) - .thenReturn(Optional.of(group)); - //when - Executable executable = () -> groupService.addMember(id, memberId); - //then - ResourceUpdateException e = assertThrows(ResourceUpdateException.class, executable); - assertEquals("Trying to modify suspended group", e.getMessage()); - verify(groupConnectorMock, times(1)) - .findById(id); - verifyNoMoreInteractions(groupConnectorMock); - } - - @Test - void addMember() { - //given - String id = "id"; - UUID memberUUID = randomUUID(); - UserGroupOperations group = TestUtils.mockInstance(new DummyGroup()); - when(groupConnectorMock.findById(Mockito.anyString())) - .thenReturn(Optional.of(group)); - //when - groupService.addMember(id, memberUUID); - //then - verify(groupConnectorMock, times(1)) - .findById(id); - verify(groupConnectorMock, times(1)) - .insertMember(Mockito.anyString(), Mockito.anyString()); - verifyNoMoreInteractions(groupConnectorMock); - } - - @Test - void deleteMember_nullId() { - //given - String id = null; - String memberId = randomUUID().toString(); - //when - Executable executable = () -> groupService.deleteMember(id, memberId); - //then - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, executable); - assertEquals("A user group id is required", e.getMessage()); - verifyNoInteractions(groupConnectorMock); - } - - @Test - void deleteMember_nullMemberId() { - //given - String id = "id"; - String memberId = null; - //when - Executable executable = () -> groupService.deleteMember(id, memberId); - //then - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, executable); - assertEquals("A member id is required", e.getMessage()); - verifyNoInteractions(groupConnectorMock); - } - - @Test - void deleteMember_doesNotExist() { - //given - String id = "id"; - String memberId = randomUUID().toString(); - //when - Executable executable = () -> groupService.deleteMember(id, memberId); - //then - assertThrows(ResourceNotFoundException.class, executable); - verify(groupConnectorMock, times(1)) - .findById(id); - verifyNoMoreInteractions(groupConnectorMock); - - } - - @Test - void deleteMember_groupSuspended() { - //given - String id = "id"; - String memberId = randomUUID().toString(); - UserGroupOperations group = TestUtils.mockInstance(new DummyGroup()); - group.setStatus(UserGroupStatus.SUSPENDED); - when(groupConnectorMock.findById(Mockito.anyString())) - .thenReturn(Optional.of(group)); - //when - Executable executable = () -> groupService.deleteMember(id, memberId); - //then - ResourceUpdateException e = assertThrows(ResourceUpdateException.class, executable); - assertEquals("Trying to modify suspended group", e.getMessage()); - verify(groupConnectorMock, times(1)) - .findById(id); - verifyNoMoreInteractions(groupConnectorMock); - } - - @Test - void deleteMember() { - //given - String id = "id"; - String memberId = randomUUID().toString(); - - UserGroupOperations group = TestUtils.mockInstance(new DummyGroup()); - when(groupConnectorMock.findById(Mockito.anyString())) - .thenReturn(Optional.of(group)); - //when - Executable executable = () -> groupService.deleteMember(id, memberId); - //then - assertDoesNotThrow(executable); - verify(groupConnectorMock, times(1)) - .findById(id); - verify(groupConnectorMock, times(1)) - .deleteMember(Mockito.anyString(), Mockito.anyString()); - verifyNoMoreInteractions(groupConnectorMock); - } - - @Test - void deleteMembers_nullMemberId() { - //given - String memberId = null; - String institutionId = "institutionId"; - String productId = "productId"; - //when - Executable executable = () -> groupService.deleteMembers(memberId, institutionId, productId); - //then - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, executable); - assertEquals("A member id is required", e.getMessage()); - verifyNoInteractions(groupConnectorMock); - } - - @Test - void deleteMembers_nullInstitutionId() { - //given - String memberId = "memberid"; - String institutionId = null; - String productId = "productId"; - //when - Executable executable = () -> groupService.deleteMembers(memberId, institutionId, productId); - //then - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, executable); - assertEquals("A institution id is required", e.getMessage()); - verifyNoInteractions(groupConnectorMock); - } - - @Test - void deleteMembers_nullProductId() { - //given - String memberId = "memberId"; - String institutionId = "institutionId"; - String productId = null; - //when - Executable executable = () -> groupService.deleteMembers(memberId, institutionId, productId); - //then - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, executable); - assertEquals("A product id is required", e.getMessage()); - verifyNoInteractions(groupConnectorMock); - } - - @Test - void deleteMembers() { - //given - String memberId = "memberId"; - String institutionId = "institutionId"; - String productId = "productId"; - //when - Executable executable = () -> groupService.deleteMembers(memberId, institutionId, productId); - //then - assertDoesNotThrow(executable); - verify(groupConnectorMock, times(1)) - .deleteMembers(memberId, institutionId, productId); - verifyNoMoreInteractions(groupConnectorMock); - } - - - @Test - void getGroup() { - //given - String groupId = "groupId"; - when(groupConnectorMock.findById(Mockito.anyString())) - .thenAnswer(invocation -> Optional.of(new DummyGroup())); - //when - UserGroupOperations group = groupService.getUserGroup(groupId); - //then - assertNotNull(group); - verify(groupConnectorMock, times(1)) - .findById(groupId); - verifyNoMoreInteractions(groupConnectorMock); - } - - @Test - void getGroup_null() { - //given - String groupId = "groupId"; - //when - Executable executable = () -> groupService.getUserGroup(groupId); - //then - assertThrows(ResourceNotFoundException.class, executable); - verify(groupConnectorMock, times(1)) - .findById(groupId); - verifyNoMoreInteractions(groupConnectorMock); - } - - @Test - void getGroup_nullId() { - //given - String groupId = null; - //when - Executable executable = () -> groupService.getUserGroup(groupId); - //then - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, executable); - assertEquals("A user group id is required", e.getMessage()); - verifyNoInteractions(groupConnectorMock); - } - - @Test - void getUserGroups() { - //given - String institutionId = "institutionId"; - String productId = "productId"; - String userId = randomUUID().toString(); - List allowedStatus = List.of(UserGroupStatus.ACTIVE); - UserGroupFilter filterMock = new UserGroupFilter(institutionId, productId, userId, allowedStatus); - Pageable pageable = PageRequest.of(0, 3, Sort.by("name")); - when(groupConnectorMock.findAll(any(), any())) - .thenReturn(getPage(List.of(new DummyGroup()), pageable, () -> pageable.isPaged() - ? (long) pageable.getPageSize() * pageable.getPageNumber() + 1 - : 1)); - //when - Page page = groupService.getUserGroups(filterMock, pageable); - //then - assertEquals(1, page.getContent().size()); - verify(groupConnectorMock, times(1)) - .findAll(filter.capture(), any()); - UserGroupFilter capturedFilter = filter.getValue(); - assertEquals(capturedFilter.getInstitutionId(), filterMock.getInstitutionId()); - assertEquals(capturedFilter.getProductId(), filterMock.getProductId()); - assertEquals(capturedFilter.getUserId(), filterMock.getUserId()); - assertEquals(capturedFilter.getStatus(), filterMock.getStatus()); - verifyNoMoreInteractions(groupConnectorMock); - } - - @Test - void getUserGroups_invalidSortParams() { - //given - Pageable pageable = PageRequest.of(0, 3, Sort.by("description")); - when(groupConnectorMock.findAll(any(), any())) - .thenReturn(getPage(Collections.singletonList(new DummyGroup()), pageable, () -> pageable.isPaged() - ? (long) pageable.getPageSize() * pageable.getPageNumber() + 1 - : 1)); - //when - Executable executable = () -> groupService.getUserGroups(null, pageable); - //then - ValidationException e = assertThrows(ValidationException.class, executable); - assertEquals("Given sort parameters aren't valid", e.getMessage()); - verifyNoInteractions(groupConnectorMock); - } - -} \ No newline at end of file diff --git a/apps/user-group-ms/pom.xml b/apps/user-group-ms/pom.xml index b6345be3..760a8cfb 100644 --- a/apps/user-group-ms/pom.xml +++ b/apps/user-group-ms/pom.xml @@ -1,8 +1,9 @@ - - + + 4.0.0 - + it.pagopa.selfcare selc-starter-parent @@ -12,7 +13,7 @@ user-group-ms - pom + jar 1.0.0-SNAPSHOT user-group-ms Microservice to manage Self Care User Group @@ -21,66 +22,27 @@ 2.5.1 https://sonarcloud.io/ true + 17 + 17 + UTF-8 + - it.pagopa.selfcare - user-group-ms-connector-api - 1.0.0-SNAPSHOT - - - - it.pagopa.selfcare - user-group-ms-connector-api - 1.0.0-SNAPSHOT - test-jar - - - - it.pagopa.selfcare - user-group-ms-core - 1.0.0-SNAPSHOT - - - - it.pagopa.selfcare - user-group-ms-web - 1.0.0-SNAPSHOT + io.cucumber + cucumber-bom + 7.20.1 + pom + import - - it.pagopa.selfcare - selc-commons-base - ${selc-commons.version} + org.junit + junit-bom + 5.10.1 + pom + import - - - it.pagopa.selfcare - selc-commons-base - ${selc-commons.version} - test-jar - - - - it.pagopa.selfcare - selc-commons-web - ${selc-commons.version} - - - - it.pagopa.selfcare - selc-commons-web - ${selc-commons.version} - test-jar - - - - it.pagopa.selfcare - user-group-ms-connector-dao - 1.0.0-SNAPSHOT - - @@ -88,6 +50,24 @@ it.pagopa.selfcare selc-commons-base + 2.5.4 + + + it.pagopa.selfcare + selc-commons-base + 2.5.4 + test-jar + + + it.pagopa.selfcare + selc-commons-web + 2.5.4 + + + it.pagopa.selfcare + selc-commons-web + 2.5.4 + test-jar @@ -97,25 +77,88 @@ - it.pagopa.selfcare - selc-commons-base - test-jar + org.springframework.data + spring-data-commons + + + io.springfox + springfox-boot-starter + + + io.cucumber + cucumber-java + 7.20.1 test - - - - core - web - app - connector-api - connector - + + io.rest-assured + rest-assured + 5.3.0 + test + + + io.rest-assured + rest-assured-common + 5.3.0 + + + io.rest-assured + json-path + 5.3.0 + + + io.rest-assured + xml-path + 5.3.0 + + + org.junit.platform + junit-platform-suite + 1.10.1 + test + + + io.cucumber + cucumber-junit-platform-engine + 7.20.1 + test + + + org.junit.jupiter + junit-jupiter + test + + + io.cucumber + cucumber-spring + 7.19.0 + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + 2.14.0 + + + de.flapdoodle.embed + de.flapdoodle.embed.mongo + 4.18.1 + test + + + org.springframework + spring-webmvc + 5.3.24 + test + + - @@ -160,8 +203,35 @@ + + org.springframework.boot + spring-boot-maven-plugin + + false + ${project.parent.artifactId}-${project.parent.version}-FATJAR + + + org.projectlombok + lombok + + + + + + org.apache.maven.plugins + maven-jar-plugin + + true + + + + + test-jar + + + + - @@ -172,4 +242,4 @@ - + \ No newline at end of file diff --git a/apps/user-group-ms/app/src/main/docs/openapi.json b/apps/user-group-ms/src/main/docs/openapi.json similarity index 99% rename from apps/user-group-ms/app/src/main/docs/openapi.json rename to apps/user-group-ms/src/main/docs/openapi.json index c9875eb7..17fdef00 100644 --- a/apps/user-group-ms/app/src/main/docs/openapi.json +++ b/apps/user-group-ms/src/main/docs/openapi.json @@ -1,7 +1,7 @@ { "openapi" : "3.0.3", "info" : { - "title" : "user-group-ms", + "title" : "selc-starter-parent", "description" : "The services described in this section deal with the management of UserGroup entity, providing the necessary methods for its creation, consultation and activation.", "version" : "1.0.0-SNAPSHOT" }, diff --git a/apps/user-group-ms/app/src/main/java/it/pagopa/selfcare/user_group/SelfCareUserGroupApplication.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/SelfCareUserGroupApplication.java similarity index 100% rename from apps/user-group-ms/app/src/main/java/it/pagopa/selfcare/user_group/SelfCareUserGroupApplication.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/SelfCareUserGroupApplication.java diff --git a/apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/api/UserGroupOperations.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/api/UserGroupOperations.java similarity index 87% rename from apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/api/UserGroupOperations.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/api/UserGroupOperations.java index 48b47821..cc7956b8 100644 --- a/apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/api/UserGroupOperations.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/api/UserGroupOperations.java @@ -1,6 +1,7 @@ -package it.pagopa.selfcare.user_group.connector.api; +package it.pagopa.selfcare.user_group.api; -import it.pagopa.selfcare.user_group.connector.model.UserGroupStatus; + +import it.pagopa.selfcare.user_group.model.UserGroupStatus; import java.time.Instant; import java.util.Set; diff --git a/apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/auditing/SpringSecurityAuditorAware.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/auditing/SpringSecurityAuditorAware.java similarity index 93% rename from apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/auditing/SpringSecurityAuditorAware.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/auditing/SpringSecurityAuditorAware.java index 726d4248..deb0ac62 100644 --- a/apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/auditing/SpringSecurityAuditorAware.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/auditing/SpringSecurityAuditorAware.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.connector.dao.auditing; +package it.pagopa.selfcare.user_group.auditing; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.AuditorAware; diff --git a/apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/config/DaoConfig.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/config/CoreConfig.java similarity index 67% rename from apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/config/DaoConfig.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/config/CoreConfig.java index bf61e6f8..f02e02ea 100644 --- a/apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/config/DaoConfig.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/config/CoreConfig.java @@ -1,6 +1,6 @@ -package it.pagopa.selfcare.user_group.connector.dao.config; +package it.pagopa.selfcare.user_group.config; -import it.pagopa.selfcare.user_group.connector.dao.auditing.SpringSecurityAuditorAware; +import it.pagopa.selfcare.user_group.auditing.SpringSecurityAuditorAware; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; @@ -9,12 +9,10 @@ @Configuration @EnableMongoAuditing(modifyOnCreate = false) -@PropertySource("classpath:config/dao-config.properties") -class DaoConfig { - +@PropertySource("classpath:config/core-config.properties") +public class CoreConfig { @Bean public AuditorAware myAuditorProvider() { return new SpringSecurityAuditorAware(); } - } diff --git a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/config/SwaggerConfig.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/config/SwaggerConfig.java similarity index 95% rename from apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/config/SwaggerConfig.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/config/SwaggerConfig.java index 24bf6715..ca3d3b81 100644 --- a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/config/SwaggerConfig.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/config/SwaggerConfig.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.web.config; +package it.pagopa.selfcare.user_group.config; import com.fasterxml.classmate.TypeResolver; import it.pagopa.selfcare.commons.web.model.Problem; @@ -29,20 +29,20 @@ */ @Configuration @Import(BaseSwaggerConfig.class) -class SwaggerConfig { +public class SwaggerConfig { private static final String AUTH_SCHEMA_NAME = "bearerAuth"; @Configuration @Profile("swaggerIT") @PropertySource("classpath:/swagger/swagger_it.properties") - public static class itConfig { + public static class ItConfig { } @Configuration @Profile("swaggerEN") @PropertySource("classpath:/swagger/swagger_en.properties") - public static class enConfig { + public static class EnConfig { } private final Environment environment; @@ -61,7 +61,7 @@ public Docket swaggerSpringPlugin(@Autowired TypeResolver typeResolver) { .description(environment.getProperty("swagger.description", "Api and Models")) .version(environment.getProperty("swagger.version", environment.getProperty("spring.application.version"))) .build()) - .select().apis(RequestHandlerSelectors.basePackage("it.pagopa.selfcare.user_group.web.controller")).build() + .select().apis(RequestHandlerSelectors.basePackage("it.pagopa.selfcare.user_group.controller")).build() .tags(new Tag("UserGroup", environment.getProperty("swagger.user-group.api.description"))) .directModelSubstitute(LocalTime.class, String.class) .ignoredParameterTypes(Pageable.class) diff --git a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/config/UserGroupSecurityConfig.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/config/UserGroupSecurityConfig.java similarity index 89% rename from apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/config/UserGroupSecurityConfig.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/config/UserGroupSecurityConfig.java index a6e76d05..128cbe96 100644 --- a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/config/UserGroupSecurityConfig.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/config/UserGroupSecurityConfig.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.web.config; +package it.pagopa.selfcare.user_group.config; import it.pagopa.selfcare.commons.web.config.SecurityConfig; import lombok.extern.slf4j.Slf4j; diff --git a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/config/WebConfig.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/config/WebConfig.java similarity index 75% rename from apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/config/WebConfig.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/config/WebConfig.java index 0b81dc86..ebdb3a28 100644 --- a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/config/WebConfig.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/config/WebConfig.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.web.config; +package it.pagopa.selfcare.user_group.config; import it.pagopa.selfcare.commons.web.config.BaseWebConfig; import org.springframework.context.annotation.Configuration; @@ -6,5 +6,5 @@ @Configuration @Import(BaseWebConfig.class) -class WebConfig { +public class WebConfig { } diff --git a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/controller/UserGroupV1Controller.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/controller/UserGroupV1Controller.java similarity index 93% rename from apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/controller/UserGroupV1Controller.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/controller/UserGroupV1Controller.java index d21c5cc5..75e033b8 100644 --- a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/controller/UserGroupV1Controller.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/controller/UserGroupV1Controller.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.web.controller; +package it.pagopa.selfcare.user_group.controller; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -10,14 +10,10 @@ import it.pagopa.selfcare.commons.web.model.Page; import it.pagopa.selfcare.commons.web.model.Problem; import it.pagopa.selfcare.commons.web.model.mapper.PageMapper; -import it.pagopa.selfcare.user_group.connector.api.UserGroupOperations; -import it.pagopa.selfcare.user_group.connector.model.UserGroupFilter; -import it.pagopa.selfcare.user_group.connector.model.UserGroupStatus; -import it.pagopa.selfcare.user_group.core.UserGroupService; -import it.pagopa.selfcare.user_group.web.model.CreateUserGroupDto; -import it.pagopa.selfcare.user_group.web.model.UpdateUserGroupDto; -import it.pagopa.selfcare.user_group.web.model.UserGroupResource; -import it.pagopa.selfcare.user_group.web.model.mapper.UserGroupMapper; +import it.pagopa.selfcare.user_group.api.UserGroupOperations; +import it.pagopa.selfcare.user_group.model.*; +import it.pagopa.selfcare.user_group.model.mapper.UserGroupMapper; +import it.pagopa.selfcare.user_group.service.UserGroupService; import lombok.extern.slf4j.Slf4j; import org.owasp.encoder.Encode; import org.springframework.beans.factory.annotation.Autowired; @@ -57,7 +53,7 @@ public UserGroupV1Controller(UserGroupService groupService, }) public UserGroupResource createGroup(@RequestBody @Valid - CreateUserGroupDto group) { + CreateUserGroupDto group) { log.trace("createGroup start"); log.debug("createGroup group = {}", group); UserGroupOperations groupOperations = groupService.createGroup(userGroupMapper.fromDto(group)); @@ -122,7 +118,7 @@ public UserGroupResource updateUserGroup(@ApiParam("${swagger.user-group.model.i String id, @RequestBody @Valid - UpdateUserGroupDto groupDto) { + UpdateUserGroupDto groupDto) { log.trace("updateUserGroup start"); log.debug("updateUserGroup id = {}", Encode.forJava(id)); UserGroupOperations updatedGroup = groupService.updateGroup(id, userGroupMapper.toUserGroupOperations(groupDto)); diff --git a/apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/UserGroupRepository.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/dao/UserGroupRepository.java similarity index 55% rename from apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/UserGroupRepository.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/dao/UserGroupRepository.java index 75742161..e7a4396d 100644 --- a/apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/UserGroupRepository.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/dao/UserGroupRepository.java @@ -1,6 +1,6 @@ -package it.pagopa.selfcare.user_group.connector.dao; +package it.pagopa.selfcare.user_group.dao; -import it.pagopa.selfcare.user_group.connector.dao.model.UserGroupEntity; +import it.pagopa.selfcare.user_group.model.UserGroupEntity; import org.springframework.data.mongodb.repository.MongoRepository; public interface UserGroupRepository extends MongoRepository { diff --git a/apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/exception/ResourceAlreadyExistsException.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/exception/ResourceAlreadyExistsException.java similarity index 81% rename from apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/exception/ResourceAlreadyExistsException.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/exception/ResourceAlreadyExistsException.java index 89623f06..efcb5405 100644 --- a/apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/exception/ResourceAlreadyExistsException.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/exception/ResourceAlreadyExistsException.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.connector.exception; +package it.pagopa.selfcare.user_group.exception; public class ResourceAlreadyExistsException extends RuntimeException { diff --git a/apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/exception/ResourceNotFoundException.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/exception/ResourceNotFoundException.java similarity index 53% rename from apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/exception/ResourceNotFoundException.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/exception/ResourceNotFoundException.java index f3351e83..05b6906e 100644 --- a/apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/exception/ResourceNotFoundException.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/exception/ResourceNotFoundException.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.connector.exception; +package it.pagopa.selfcare.user_group.exception; public class ResourceNotFoundException extends RuntimeException { } diff --git a/apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/exception/ResourceUpdateException.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/exception/ResourceUpdateException.java similarity index 70% rename from apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/exception/ResourceUpdateException.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/exception/ResourceUpdateException.java index 1fbab29f..89bb5569 100644 --- a/apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/exception/ResourceUpdateException.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/exception/ResourceUpdateException.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.connector.exception; +package it.pagopa.selfcare.user_group.exception; public class ResourceUpdateException extends RuntimeException { public ResourceUpdateException(String msg) { diff --git a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/handler/UserGroupExceptionHandler.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/handler/UserGroupExceptionHandler.java similarity index 77% rename from apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/handler/UserGroupExceptionHandler.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/handler/UserGroupExceptionHandler.java index 23ca627b..f2d78377 100644 --- a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/handler/UserGroupExceptionHandler.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/handler/UserGroupExceptionHandler.java @@ -1,11 +1,11 @@ -package it.pagopa.selfcare.user_group.web.handler; +package it.pagopa.selfcare.user_group.handler; import it.pagopa.selfcare.commons.web.model.Problem; import it.pagopa.selfcare.commons.web.model.mapper.ProblemMapper; -import it.pagopa.selfcare.user_group.connector.exception.ResourceAlreadyExistsException; -import it.pagopa.selfcare.user_group.connector.exception.ResourceNotFoundException; -import it.pagopa.selfcare.user_group.connector.exception.ResourceUpdateException; -import it.pagopa.selfcare.user_group.web.controller.UserGroupV1Controller; +import it.pagopa.selfcare.user_group.controller.UserGroupV1Controller; +import it.pagopa.selfcare.user_group.exception.ResourceAlreadyExistsException; +import it.pagopa.selfcare.user_group.exception.ResourceNotFoundException; +import it.pagopa.selfcare.user_group.exception.ResourceUpdateException; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; diff --git a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/CreateUserGroupDto.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/CreateUserGroupDto.java similarity index 91% rename from apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/CreateUserGroupDto.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/CreateUserGroupDto.java index 265f720d..1661e1f3 100644 --- a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/CreateUserGroupDto.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/CreateUserGroupDto.java @@ -1,8 +1,7 @@ -package it.pagopa.selfcare.user_group.web.model; +package it.pagopa.selfcare.user_group.model; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.annotations.ApiModelProperty; -import it.pagopa.selfcare.user_group.connector.model.UserGroupStatus; import lombok.Data; import javax.validation.constraints.NotBlank; diff --git a/apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/model/CriteriaBuilder.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/CriteriaBuilder.java similarity index 95% rename from apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/model/CriteriaBuilder.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/CriteriaBuilder.java index 81db9ee5..75e8166e 100644 --- a/apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/model/CriteriaBuilder.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/CriteriaBuilder.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.connector.dao.model; +package it.pagopa.selfcare.user_group.model; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.lang.NonNull; diff --git a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/GroupDto.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/GroupDto.java similarity index 71% rename from apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/GroupDto.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/GroupDto.java index 9c047c18..0a62e52e 100644 --- a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/GroupDto.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/GroupDto.java @@ -1,7 +1,6 @@ -package it.pagopa.selfcare.user_group.web.model; +package it.pagopa.selfcare.user_group.model; -import it.pagopa.selfcare.user_group.connector.api.UserGroupOperations; -import it.pagopa.selfcare.user_group.connector.model.UserGroupStatus; +import it.pagopa.selfcare.user_group.api.UserGroupOperations; import lombok.Data; import java.time.Instant; diff --git a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/MemberUUID.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/MemberUUID.java similarity index 88% rename from apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/MemberUUID.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/MemberUUID.java index c2229031..793163f9 100644 --- a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/MemberUUID.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/MemberUUID.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.web.model; +package it.pagopa.selfcare.user_group.model; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.annotations.ApiModelProperty; diff --git a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/UpdateUserGroupDto.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/UpdateUserGroupDto.java similarity index 94% rename from apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/UpdateUserGroupDto.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/UpdateUserGroupDto.java index b6932fd2..ac0d5c7f 100644 --- a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/UpdateUserGroupDto.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/UpdateUserGroupDto.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.web.model; +package it.pagopa.selfcare.user_group.model; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.annotations.ApiModelProperty; diff --git a/apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/model/UserGroupEntity.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/UserGroupEntity.java similarity index 80% rename from apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/model/UserGroupEntity.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/UserGroupEntity.java index 327b2114..1b9328b0 100644 --- a/apps/user-group-ms/connector/dao/src/main/java/it/pagopa/selfcare/user_group/connector/dao/model/UserGroupEntity.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/UserGroupEntity.java @@ -1,11 +1,7 @@ -package it.pagopa.selfcare.user_group.connector.dao.model; +package it.pagopa.selfcare.user_group.model; - -import it.pagopa.selfcare.user_group.connector.api.UserGroupOperations; -import it.pagopa.selfcare.user_group.connector.model.UserGroupStatus; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; +import it.pagopa.selfcare.user_group.api.UserGroupOperations; +import lombok.*; import lombok.experimental.FieldNameConstants; import org.springframework.data.annotation.*; import org.springframework.data.mongodb.core.mapping.Document; @@ -58,9 +54,10 @@ public UserGroupEntity(UserGroupOperations userGroup) { @FieldNameConstants.Include private String modifiedBy; - + @NoArgsConstructor(access = AccessLevel.NONE) + @AllArgsConstructor(access = AccessLevel.NONE) public static class Fields { - public static String id = org.springframework.data.mongodb.core.aggregation.Fields.UNDERSCORE_ID; + public static final String ID = org.springframework.data.mongodb.core.aggregation.Fields.UNDERSCORE_ID; } } diff --git a/apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/model/UserGroupFilter.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/UserGroupFilter.java similarity index 93% rename from apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/model/UserGroupFilter.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/UserGroupFilter.java index 28f6132d..148cadcc 100644 --- a/apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/model/UserGroupFilter.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/UserGroupFilter.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.connector.model; +package it.pagopa.selfcare.user_group.model; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/UserGroupResource.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/UserGroupResource.java similarity index 92% rename from apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/UserGroupResource.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/UserGroupResource.java index 30fe95b8..7dfbed65 100644 --- a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/UserGroupResource.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/UserGroupResource.java @@ -1,7 +1,6 @@ -package it.pagopa.selfcare.user_group.web.model; +package it.pagopa.selfcare.user_group.model; import io.swagger.annotations.ApiModelProperty; -import it.pagopa.selfcare.user_group.connector.model.UserGroupStatus; import lombok.Data; import javax.validation.constraints.NotBlank; diff --git a/apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/model/UserGroupStatus.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/UserGroupStatus.java similarity index 56% rename from apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/model/UserGroupStatus.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/UserGroupStatus.java index 5cea8344..0fc589ac 100644 --- a/apps/user-group-ms/connector-api/src/main/java/it/pagopa/selfcare/user_group/connector/model/UserGroupStatus.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/UserGroupStatus.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.connector.model; +package it.pagopa.selfcare.user_group.model; public enum UserGroupStatus { ACTIVE, diff --git a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/mapper/UserGroupMapper.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/mapper/UserGroupMapper.java similarity index 78% rename from apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/mapper/UserGroupMapper.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/mapper/UserGroupMapper.java index 01f6e6af..77c5afe5 100644 --- a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/model/mapper/UserGroupMapper.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/model/mapper/UserGroupMapper.java @@ -1,10 +1,10 @@ -package it.pagopa.selfcare.user_group.web.model.mapper; +package it.pagopa.selfcare.user_group.model.mapper; -import it.pagopa.selfcare.user_group.connector.api.UserGroupOperations; -import it.pagopa.selfcare.user_group.web.model.CreateUserGroupDto; -import it.pagopa.selfcare.user_group.web.model.GroupDto; -import it.pagopa.selfcare.user_group.web.model.UpdateUserGroupDto; -import it.pagopa.selfcare.user_group.web.model.UserGroupResource; +import it.pagopa.selfcare.user_group.api.UserGroupOperations; +import it.pagopa.selfcare.user_group.model.CreateUserGroupDto; +import it.pagopa.selfcare.user_group.model.GroupDto; +import it.pagopa.selfcare.user_group.model.UpdateUserGroupDto; +import it.pagopa.selfcare.user_group.model.UserGroupResource; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Named; diff --git a/apps/user-group-ms/core/src/main/java/it/pagopa/selfcare/user_group/core/UserGroupService.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/service/UserGroupService.java similarity index 79% rename from apps/user-group-ms/core/src/main/java/it/pagopa/selfcare/user_group/core/UserGroupService.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/service/UserGroupService.java index cc6661c2..eb10e483 100644 --- a/apps/user-group-ms/core/src/main/java/it/pagopa/selfcare/user_group/core/UserGroupService.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/service/UserGroupService.java @@ -1,7 +1,7 @@ -package it.pagopa.selfcare.user_group.core; +package it.pagopa.selfcare.user_group.service; -import it.pagopa.selfcare.user_group.connector.api.UserGroupOperations; -import it.pagopa.selfcare.user_group.connector.model.UserGroupFilter; +import it.pagopa.selfcare.user_group.api.UserGroupOperations; +import it.pagopa.selfcare.user_group.model.UserGroupFilter; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; diff --git a/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/service/UserGroupServiceImpl.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/service/UserGroupServiceImpl.java new file mode 100644 index 00000000..28ece021 --- /dev/null +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/service/UserGroupServiceImpl.java @@ -0,0 +1,358 @@ +package it.pagopa.selfcare.user_group.service; + +import com.mongodb.client.result.UpdateResult; +import it.pagopa.selfcare.commons.base.security.SelfCareUser; +import it.pagopa.selfcare.user_group.api.UserGroupOperations; +import it.pagopa.selfcare.user_group.dao.UserGroupRepository; +import it.pagopa.selfcare.user_group.exception.ResourceAlreadyExistsException; +import it.pagopa.selfcare.user_group.exception.ResourceNotFoundException; +import it.pagopa.selfcare.user_group.exception.ResourceUpdateException; +import it.pagopa.selfcare.user_group.model.CriteriaBuilder; +import it.pagopa.selfcare.user_group.model.UserGroupEntity; +import it.pagopa.selfcare.user_group.model.UserGroupFilter; +import it.pagopa.selfcare.user_group.model.UserGroupStatus; +import lombok.extern.slf4j.Slf4j; +import org.owasp.encoder.Encode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.data.domain.AuditorAware; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.data.support.PageableExecutionUtils; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +import javax.validation.ValidationException; +import java.util.*; +import java.util.function.Function; + +@Slf4j +@Service +public class UserGroupServiceImpl implements UserGroupService { + + private static final String USER_GROUP_ID_REQUIRED_MESSAGE = "A user group id is required"; + private static final String TRYING_TO_MODIFY_SUSPENDED_GROUP = "Trying to modify suspended group"; + private static final String MEMBER_ID_REQUIRED = "A member id is required"; + private static final String GROUP_NAME_ALREADY_EXISTS = "A group with the same name already exists in ACTIVE or SUSPENDED state"; + private final List allowedSortingParams; + private final UserGroupRepository repository; + private final MongoTemplate mongoTemplate; + private final AuditorAware auditorAware; + private static final String COULD_NOT_UPDATE_MESSAGE = "Couldn't update resource"; + + @Autowired + UserGroupServiceImpl(@Value("${user-group.allowed.sorting.parameters}") String[] allowedSortingParams, + UserGroupRepository repository, MongoTemplate mongoTemplate, AuditorAware auditorAware) { + this.allowedSortingParams = Arrays.asList(allowedSortingParams); + this.repository = repository; + this.mongoTemplate = mongoTemplate; + this.auditorAware = auditorAware; + } + + @Override + public UserGroupOperations createGroup(UserGroupOperations group) { + log.trace("createGroup start"); + log.debug("createGroup group = {}", group); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Assert.state(authentication != null, "Authentication is required"); + Assert.state(authentication.getPrincipal() instanceof SelfCareUser, "Not SelfCareUser principal"); + Assert.notNull(group, "A group is required"); + + checkNameUniqueness(group.getId(), group.getName(), group.getProductId(), group.getInstitutionId()); + return insertUserGroupEntity(group); + } + + @Override + public void addMember(String id, UUID memberId) { + log.trace("addMember start"); + log.debug("addMember id = {}, memberId ={}", Encode.forJava(id), memberId); + Assert.hasText(id, USER_GROUP_ID_REQUIRED_MESSAGE); + Assert.notNull(memberId, MEMBER_ID_REQUIRED); + UserGroupOperations foundGroup = findById(id).orElseThrow(ResourceNotFoundException::new); + if (UserGroupStatus.SUSPENDED.equals(foundGroup.getStatus())) { + throw new ResourceUpdateException(TRYING_TO_MODIFY_SUSPENDED_GROUP); + } + insertMember(id, memberId.toString()); + log.trace("addMember end"); + } + + @Override + public void deleteMember(String groupId, String memberId) { + log.trace("deleteMember start"); + log.debug("deleteMember groupId = {}, memberId = {}", Encode.forJava(groupId), Encode.forJava(memberId)); + Assert.hasText(groupId, USER_GROUP_ID_REQUIRED_MESSAGE); + Assert.hasText(memberId, MEMBER_ID_REQUIRED); + UserGroupOperations foundGroup = findById(groupId).orElseThrow(ResourceNotFoundException::new); + if (UserGroupStatus.SUSPENDED.equals(foundGroup.getStatus())) { + throw new ResourceUpdateException(TRYING_TO_MODIFY_SUSPENDED_GROUP); + } + removeMemberFromActiveGroup(groupId, memberId); + log.trace("deleteMember end"); + } + + @Override + public void deleteMembers(String memberId, String institutionId, String productId) { + log.trace("deleteMembers start"); + log.debug("deleteMembers memberId = {}, institutionId = {}, productId= {}", Encode.forJava(memberId), Encode.forJava(institutionId), Encode.forJava(productId)); + Assert.hasText(memberId, MEMBER_ID_REQUIRED); + Assert.hasText(institutionId, "A institution id is required"); + Assert.hasText(productId, "A product id is required"); + removeMembers(memberId, institutionId, productId); + log.trace("deleteMembers end"); + } + + @Override + public UserGroupOperations getUserGroup(String id) { + log.trace("getUserGroup start"); + log.debug("getUserGroup id = {}", id); + Assert.hasText(id, USER_GROUP_ID_REQUIRED_MESSAGE); + UserGroupOperations foundGroup = findById(id).orElseThrow(ResourceNotFoundException::new); + log.debug("getUserGroup result = {}", foundGroup); + log.trace("getUserGroup end"); + + return foundGroup; + } + + @Override + public Page getUserGroups(UserGroupFilter filter, Pageable pageable) { + log.trace("getUserGroups start"); + log.debug("getUserGroups filter = {}, pageable = {}", filter, pageable); + boolean match = pageable.getSort().stream().allMatch(order -> allowedSortingParams.contains(order.getProperty())); + if (!match) { + throw new ValidationException("Given sort parameters aren't valid"); + } + Page result = findAll(filter, pageable); + log.debug("getUserGroups result = {}", result); + log.trace("getUserGroups end"); + return result; + } + + @Override + public void deleteGroup(String id) { + log.trace("deleteGroup start"); + log.debug("deleteGroup id = {}", Encode.forJava(id)); + Assert.hasText(id, USER_GROUP_ID_REQUIRED_MESSAGE); + deleteById(id); + log.trace("deleteProduct end"); + } + + @Override + public void suspendGroup(String id) { + log.trace("suspendGroup start"); + log.debug("suspendGroup id = {}", Encode.forJava(id)); + Assert.hasText(id, USER_GROUP_ID_REQUIRED_MESSAGE); + suspendById(id); + log.trace("suspendGroup end"); + } + + @Override + public void activateGroup(String id) { + log.trace("activateGroup start"); + log.debug("activateGroup id = {}", Encode.forJava(id)); + Assert.hasText(id, USER_GROUP_ID_REQUIRED_MESSAGE); + activateById(id); + log.trace("activateGroup end"); + } + + @Override + public UserGroupOperations updateGroup(String id, UserGroupOperations group) { + log.trace("updateGroup start"); + log.debug("updateGroup id = {}, group = {}", Encode.forJava(id), group); + Assert.hasText(id, USER_GROUP_ID_REQUIRED_MESSAGE); + Assert.notNull(group, "A user group is required"); + UserGroupOperations foundGroup = findById(id).orElseThrow(ResourceNotFoundException::new); + if (UserGroupStatus.SUSPENDED.equals(foundGroup.getStatus())) { + throw new ResourceUpdateException(TRYING_TO_MODIFY_SUSPENDED_GROUP); + } + checkNameUniqueness(id, group.getName(), foundGroup.getProductId(), foundGroup.getInstitutionId()); + + foundGroup.setMembers(group.getMembers()); + foundGroup.setName(group.getName()); + foundGroup.setDescription(group.getDescription()); + UserGroupOperations updatedGroup = save(foundGroup); + log.debug("updateGroup updatedGroup = {}", updatedGroup); + log.trace("updateGroup end"); + return updatedGroup; + } + + private UserGroupEntity insertUserGroupEntity(UserGroupOperations group) { + log.trace("insert start"); + log.debug("insert entity = {}", group); + UserGroupEntity insert; + try { + insert = repository.insert(new UserGroupEntity(group)); + } catch (DuplicateKeyException e) { + throw new ResourceAlreadyExistsException("Failed _id or unique index constraint.", e); + } + log.debug("insert = {}", insert); + log.trace("createGroup end"); + return insert; + } + + private void checkNameUniqueness(String currentGroupId, String groupName, String productId, String institutionId) { + UserGroupFilter filter = new UserGroupFilter(); + filter.setProductId(productId); + filter.setInstitutionId(institutionId); + filter.setStatus(Arrays.asList(UserGroupStatus.ACTIVE, UserGroupStatus.SUSPENDED)); + + Page existingGroups = findAll(filter, Pageable.unpaged()); + boolean isDuplicate = existingGroups.stream() + .anyMatch(g -> g.getName().equals(groupName) && !g.getId().equals(currentGroupId)); + + if (isDuplicate) { + log.warn("Attempted to create/update group with duplicate name: {}", groupName); + throw new ResourceAlreadyExistsException(GROUP_NAME_ALREADY_EXISTS); + } + } + + private Query createActiveGroupQuery(String id) { + return Query.query(Criteria.where(UserGroupEntity.Fields.ID).is(id) + .and(UserGroupEntity.Fields.status).is(UserGroupStatus.ACTIVE)); + } + + private void insertMember(String id, String memberId) { + log.trace("insertMember start"); + log.debug("insertMember id = {}, memberId = {}", id, memberId); + UpdateResult updateResult = mongoTemplate.updateFirst( + createActiveGroupQuery(id), + new Update().push(UserGroupEntity.Fields.members, memberId) + .set(UserGroupEntity.Fields.modifiedBy, auditorAware.getCurrentAuditor().orElse(null)) + .currentDate(UserGroupEntity.Fields.modifiedAt), + UserGroupEntity.class); + if (updateResult.getModifiedCount() == 0) { + throw new ResourceUpdateException(COULD_NOT_UPDATE_MESSAGE); + } + log.trace("insertMember end"); + } + + private void removeMemberFromActiveGroup(String id, String memberId) { + log.trace("deleteMember start"); + log.debug("deleteMember id = {}, memberId = {}", id, memberId); + + UpdateResult updateResult = mongoTemplate.updateFirst( + createActiveGroupQuery(id), + new Update().pull(UserGroupEntity.Fields.members, memberId) + .set(UserGroupEntity.Fields.modifiedBy, auditorAware.getCurrentAuditor().orElse(null)) + .currentTimestamp(UserGroupEntity.Fields.modifiedAt), + UserGroupEntity.class); + if (updateResult.getModifiedCount() == 0) { + throw new ResourceUpdateException(COULD_NOT_UPDATE_MESSAGE); + } + log.trace("deleteMember end"); + } + + private void removeMembers(String memberId, String institutionId, String productId) { + log.trace("deleteMembers start"); + log.debug("deleteMembers id = {}, institutionId = {}, productId= {}", memberId, institutionId, productId); + + UpdateResult updateResult = mongoTemplate.updateMulti( + Query.query(Criteria.where(UserGroupEntity.Fields.members).is(memberId) + .and(UserGroupEntity.Fields.institutionId).is(institutionId) + .and(UserGroupEntity.Fields.productId).is(productId)), + new Update().pull(UserGroupEntity.Fields.members, memberId) + .set(UserGroupEntity.Fields.modifiedBy, auditorAware.getCurrentAuditor().orElse(null)) + .currentTimestamp(UserGroupEntity.Fields.modifiedAt), + UserGroupEntity.class); + if (updateResult.getModifiedCount() == 0) { + log.warn("No user to delete from UserGroup"); + } + log.trace("deleteMembers end"); + } + + private Optional findById(String id) { + log.trace("findById start"); + log.debug("findById id = {} ", id); + Optional result = repository.findById(id).map(Function.identity()); + log.debug("findById result = {}", result); + log.trace("findById end"); + + return result; + } + + private Page findAll(UserGroupFilter filter, Pageable pageable) { + log.trace("findAll start"); + log.debug("findAll institutionId= {} , productId = {}, userId = {}, pageable = {}", filter.getInstitutionId(), filter.getProductId(), filter.getUserId(), pageable); + if (pageable.getSort().isSorted() && !StringUtils.hasText(filter.getProductId()) && !StringUtils.hasText(filter.getInstitutionId())) { + throw new ValidationException("Sorting not allowed without productId or institutionId"); + } + if (filter.getStatus().size() == 1 && !StringUtils.hasText(filter.getUserId()) && !StringUtils.hasText(filter.getProductId()) && !StringUtils.hasText(filter.getInstitutionId())) { + throw new ValidationException("At least one of productId, institutionId and userId must be provided with status filter"); + } + Query query = new Query(constructCriteria(filter)); + long count = this.mongoTemplate.count(query, UserGroupEntity.class); + List userGroupOperations = new ArrayList<>(mongoTemplate.find(query.with(pageable), UserGroupEntity.class)); + final Page result = PageableExecutionUtils.getPage(userGroupOperations, pageable, () -> count); + log.debug("findAll result = {}", result); + log.trace("findAll end"); + return result; + } + + private Criteria constructCriteria(UserGroupFilter filter) { + return CriteriaBuilder.builder() + .isIfNotNull(UserGroupEntity.Fields.institutionId, filter.getInstitutionId()) + .isIfNotNull(UserGroupEntity.Fields.productId, filter.getProductId()) + .isIfNotNull(UserGroupEntity.Fields.members, filter.getUserId()) + .inIfNotEmpty(UserGroupEntity.Fields.status, filter.getStatus()) + .build(); + + } + + private void activateById(String id) { + log.trace("activateById start"); + log.debug("activateById id = {} ", id); + updateUserById(id, UserGroupStatus.ACTIVE); + log.trace("activateById end"); + + } + + private void deleteById(String id) { + log.trace("deleteById start"); + log.debug("deleteById id = {} ", id); + updateUserById(id, UserGroupStatus.DELETED); + log.trace("deleteById end"); + } + + private void suspendById(String id) { + log.trace("suspendById start"); + log.debug("suspendById id = {} ", id); + updateUserById(id, UserGroupStatus.SUSPENDED); + log.trace("suspendById end"); + } + + private void updateUserById(String id, UserGroupStatus status) { + log.trace("updateUserById start"); + log.debug("updateUserById id = {}, status = {}", id, status); + UpdateResult updateResult = mongoTemplate.updateFirst( + Query.query(Criteria.where(UserGroupEntity.Fields.ID).is(id)), + Update.update(UserGroupEntity.Fields.status, status) + .set(UserGroupEntity.Fields.modifiedBy, auditorAware.getCurrentAuditor().orElse(null)) + .currentTimestamp(UserGroupEntity.Fields.modifiedAt), + UserGroupEntity.class); + if (updateResult.getMatchedCount() == 0) { + throw new ResourceNotFoundException(); + } + log.trace("updateUserById end"); + } + + private UserGroupOperations save(UserGroupOperations group) { + log.trace("save start"); + log.debug("save entity = {}", group); + UserGroupEntity result; + try { + result = repository.save(new UserGroupEntity(group)); + } catch (DuplicateKeyException e) { + throw new ResourceAlreadyExistsException("Failed _id or unique index constraint.", e); + } + log.debug("save result = {}", result); + log.trace("save end"); + return result; + } +} \ No newline at end of file diff --git a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/validator/UserGroupControllerResponseValidator.java b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/validator/UserGroupControllerResponseValidator.java similarity index 93% rename from apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/validator/UserGroupControllerResponseValidator.java rename to apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/validator/UserGroupControllerResponseValidator.java index d461704e..1571b690 100644 --- a/apps/user-group-ms/web/src/main/java/it/pagopa/selfcare/user_group/web/validator/UserGroupControllerResponseValidator.java +++ b/apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/validator/UserGroupControllerResponseValidator.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.web.validator; +package it.pagopa.selfcare.user_group.validator; import it.pagopa.selfcare.commons.web.validator.ControllerResponseValidator; import org.aspectj.lang.annotation.Aspect; diff --git a/apps/user-group-ms/app/src/main/resources/config/application.yml b/apps/user-group-ms/src/main/resources/config/application.yml similarity index 100% rename from apps/user-group-ms/app/src/main/resources/config/application.yml rename to apps/user-group-ms/src/main/resources/config/application.yml diff --git a/apps/user-group-ms/src/main/resources/config/core-config.properties b/apps/user-group-ms/src/main/resources/config/core-config.properties new file mode 100644 index 00000000..6e45af83 --- /dev/null +++ b/apps/user-group-ms/src/main/resources/config/core-config.properties @@ -0,0 +1,5 @@ +user-group.allowed.sorting.parameters=${ALLOWED_SORTING_PARAMETERS:name} +spring.data.mongodb.uri=${MONGODB_CONNECTION_URI:mongodb://localhost:27017} +spring.data.mongodb.database=${MONGODB_NAME:selcUserGroup} +rest-assured.base-url=http://localhost +rest-assured.port=8082 \ No newline at end of file diff --git a/apps/user-group-ms/web/src/main/resources/swagger/swagger_en.properties b/apps/user-group-ms/src/main/resources/swagger/swagger_en.properties similarity index 100% rename from apps/user-group-ms/web/src/main/resources/swagger/swagger_en.properties rename to apps/user-group-ms/src/main/resources/swagger/swagger_en.properties diff --git a/apps/user-group-ms/core/src/test/java/it/pagopa/selfcare/user_group/core/config/CoreTestConfig.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/config/CoreTestConfig.java similarity index 79% rename from apps/user-group-ms/core/src/test/java/it/pagopa/selfcare/user_group/core/config/CoreTestConfig.java rename to apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/config/CoreTestConfig.java index 9b294139..0e694d97 100644 --- a/apps/user-group-ms/core/src/test/java/it/pagopa/selfcare/user_group/core/config/CoreTestConfig.java +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/config/CoreTestConfig.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.core.config; +package it.pagopa.selfcare.user_group.config; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Import; diff --git a/apps/user-group-ms/app/src/test/java/it/pagopa/selfcare/user_group/web/config/SwaggerConfigTest.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/config/SwaggerConfigTest.java similarity index 91% rename from apps/user-group-ms/app/src/test/java/it/pagopa/selfcare/user_group/web/config/SwaggerConfigTest.java rename to apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/config/SwaggerConfigTest.java index 112eeef6..01c31f58 100644 --- a/apps/user-group-ms/app/src/test/java/it/pagopa/selfcare/user_group/web/config/SwaggerConfigTest.java +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/config/SwaggerConfigTest.java @@ -1,8 +1,8 @@ -package it.pagopa.selfcare.user_group.web.config; +package it.pagopa.selfcare.user_group.config; import com.fasterxml.jackson.databind.ObjectMapper; -import it.pagopa.selfcare.user_group.core.UserGroupService; -import it.pagopa.selfcare.user_group.web.model.mapper.UserGroupMapper; +import it.pagopa.selfcare.user_group.model.mapper.UserGroupMapper; +import it.pagopa.selfcare.user_group.service.UserGroupService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -31,7 +31,7 @@ }) @EnableOpenApi @EnableWebMvc -@ComponentScan(basePackages = "it.pagopa.selfcare.user_group.web.controller") +@ComponentScan(basePackages = "it.pagopa.selfcare.user_group.controller") @TestPropertySource(locations = "classpath:config/application.yml") class SwaggerConfigTest { diff --git a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/config/WebTestConfig.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/config/WebTestConfig.java similarity index 79% rename from apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/config/WebTestConfig.java rename to apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/config/WebTestConfig.java index f7ce419c..f35005ba 100644 --- a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/config/WebTestConfig.java +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/config/WebTestConfig.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.web.config; +package it.pagopa.selfcare.user_group.config; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Import; diff --git a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/controller/DummyController.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/controller/DummyController.java similarity index 80% rename from apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/controller/DummyController.java rename to apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/controller/DummyController.java index 5cdeb06c..962bcfd7 100644 --- a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/controller/DummyController.java +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/controller/DummyController.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.web.controller; +package it.pagopa.selfcare.user_group.controller; import org.springframework.web.bind.annotation.RestController; diff --git a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/controller/UserGroupV1ControllerTest.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/controller/UserGroupV1ControllerTest.java similarity index 95% rename from apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/controller/UserGroupV1ControllerTest.java rename to apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/controller/UserGroupV1ControllerTest.java index 03d67b17..d9578e0a 100644 --- a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/controller/UserGroupV1ControllerTest.java +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/controller/UserGroupV1ControllerTest.java @@ -1,15 +1,13 @@ -package it.pagopa.selfcare.user_group.web.controller; +package it.pagopa.selfcare.user_group.controller; import com.fasterxml.jackson.databind.ObjectMapper; -import it.pagopa.selfcare.user_group.connector.api.UserGroupOperations; -import it.pagopa.selfcare.user_group.connector.exception.ResourceNotFoundException; -import it.pagopa.selfcare.user_group.connector.model.UserGroupFilter; -import it.pagopa.selfcare.user_group.connector.model.UserGroupStatus; -import it.pagopa.selfcare.user_group.core.UserGroupService; -import it.pagopa.selfcare.user_group.web.config.WebTestConfig; -import it.pagopa.selfcare.user_group.web.handler.UserGroupExceptionHandler; -import it.pagopa.selfcare.user_group.web.model.*; -import it.pagopa.selfcare.user_group.web.model.mapper.UserGroupMapperImpl; +import it.pagopa.selfcare.user_group.api.UserGroupOperations; +import it.pagopa.selfcare.user_group.config.WebTestConfig; +import it.pagopa.selfcare.user_group.exception.ResourceNotFoundException; +import it.pagopa.selfcare.user_group.handler.UserGroupExceptionHandler; +import it.pagopa.selfcare.user_group.model.*; +import it.pagopa.selfcare.user_group.model.mapper.UserGroupMapperImpl; +import it.pagopa.selfcare.user_group.service.UserGroupService; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; @@ -23,6 +21,8 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import it.pagopa.selfcare.user_group.model.DummyCreateUserGroupDto; +import it.pagopa.selfcare.user_group.model.DummyUpdateUserGroupDto; import java.util.List; import java.util.Set; diff --git a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/handler/UserGroupExceptionHandlerTest.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/handler/UserGroupExceptionHandlerTest.java similarity index 89% rename from apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/handler/UserGroupExceptionHandlerTest.java rename to apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/handler/UserGroupExceptionHandlerTest.java index 1bc2ebdd..e0299198 100644 --- a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/handler/UserGroupExceptionHandlerTest.java +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/handler/UserGroupExceptionHandlerTest.java @@ -1,9 +1,9 @@ -package it.pagopa.selfcare.user_group.web.handler; +package it.pagopa.selfcare.user_group.handler; +import it.pagopa.selfcare.user_group.exception.ResourceAlreadyExistsException; +import it.pagopa.selfcare.user_group.exception.ResourceNotFoundException; +import it.pagopa.selfcare.user_group.exception.ResourceUpdateException; import it.pagopa.selfcare.commons.web.model.Problem; -import it.pagopa.selfcare.user_group.connector.exception.ResourceAlreadyExistsException; -import it.pagopa.selfcare.user_group.connector.exception.ResourceNotFoundException; -import it.pagopa.selfcare.user_group.connector.exception.ResourceUpdateException; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.springframework.http.ResponseEntity; diff --git a/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/CucumberConfig.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/CucumberConfig.java new file mode 100644 index 00000000..10ae6d7c --- /dev/null +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/CucumberConfig.java @@ -0,0 +1,15 @@ +package it.pagopa.selfcare.user_group.integration_test; + +import io.restassured.RestAssured; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class CucumberConfig { + + public CucumberConfig( @Value("${rest-assured.base-url}") String restAssuredBaseUrl, @Value("${rest-assured.port}")int restAssuredPort) { + RestAssured.baseURI = restAssuredBaseUrl; + RestAssured.port = restAssuredPort; + } + +} diff --git a/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/CucumberSuite.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/CucumberSuite.java new file mode 100644 index 00000000..5ef02773 --- /dev/null +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/CucumberSuite.java @@ -0,0 +1,19 @@ +package it.pagopa.selfcare.user_group.integration_test; + +import io.cucumber.spring.CucumberContextConfiguration; +import it.pagopa.selfcare.user_group.SelfCareUserGroupApplication; +import org.junit.platform.suite.api.*; +import org.springframework.boot.test.context.SpringBootTest; + +import static io.cucumber.junit.platform.engine.Constants.PLUGIN_PROPERTY_NAME; + +@Suite +@IncludeEngines("cucumber") +@SelectClasspathResource("features") +@ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty") +@CucumberContextConfiguration +@SpringBootTest(classes = {SelfCareUserGroupApplication.class}) +@ExcludeTags({"FeatureCreate","FeatureRetrieve", "FeatureUpdate", "FeatureMembers"}) +public class CucumberSuite { +} + diff --git a/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/CreateUserGroupSteps.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/CreateUserGroupSteps.java new file mode 100644 index 00000000..2fefe49b --- /dev/null +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/CreateUserGroupSteps.java @@ -0,0 +1,140 @@ +package it.pagopa.selfcare.user_group.integration_test.steps; + +import io.cucumber.java.After; +import io.cucumber.java.Before; +import io.cucumber.java.DataTableType; +import io.cucumber.java.en.And; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import io.restassured.RestAssured; +import io.restassured.response.ExtractableResponse; +import io.restassured.specification.RequestSpecification; +import it.pagopa.selfcare.user_group.model.UserGroupEntity; +import it.pagopa.selfcare.user_group.model.UserGroupStatus; +import org.junit.jupiter.api.Assertions; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +public class CreateUserGroupSteps extends UserGroupSteps { + + @Before("@DuplicateGroupName") + public void beforeScenarioOfCreateDuplicatedGroup() throws IOException { + initializeCollection(); + } + + @After("@DuplicateGroupName") + public void afterScenarioOfCreateDuplicatedGroup() { + userGroupRepository.deleteAllById(userGroupsIds); + } + + @After("@CreateNewGroup") + public void afterScenarioOfCreateGroup() { + userGroupRepository.deleteById(userGroupId); + } + + @Override + @Then("[CREATE] the response status should be {int}") + public void verifyResponseStatus(int expectedStatusCode) { + super.verifyResponseStatus(expectedStatusCode); + } + + @Override + @Then("[CREATE] the response should contain an error message {string}") + public void verifyErrorMessage(String expectedErrorMessage) { + super.verifyErrorMessage(expectedErrorMessage); + } + + @DataTableType + public UserGroupEntity convertRequest(Map entry) { + UserGroupEntity userGroupEntity = new UserGroupEntity(); + userGroupEntity.setInstitutionId(entry.get("institutionId")); + userGroupEntity.setProductId(entry.get("productId")); + userGroupEntity.setName(entry.get("name")); + userGroupEntity.setDescription(entry.get("description")); + userGroupEntity.setStatus(Optional.ofNullable(entry.get("status")).map(s -> UserGroupStatus.valueOf(entry.get("status"))).orElse(null)); + userGroupEntity.setMembers(Optional.ofNullable(entry.get("members")).map(s -> Set.of(entry.get("members").split(","))).orElse(null)); + return userGroupEntity; + } + + @When("I send a POST request to {string} with the given details, with authentication {string}") + public void iSendAPOSTRequestToWithTheGivenDetails(String url, String isAuthenticated) { + RequestSpecification requestSpecification = RestAssured.given() + .contentType("application/json"); + + if(Boolean.parseBoolean(isAuthenticated)){ + requestSpecification.header("Authorization", "Bearer " + token); + } + + ExtractableResponse response = requestSpecification + .body(userGroupDetails) + .when() + .post(url) + .then() + .extract(); + + status = response.statusCode(); + if(status == 201) { + userGroupEntityResponse = response.body().as(UserGroupEntity.class); + userGroupId = userGroupEntityResponse.getId(); + }else { + errorMessage = response.body().asString(); + } + } + + @Given("the following user group details:") + public void givenUserGroupDetails(List userGroupEntityList) { + if (userGroupEntityList != null && userGroupEntityList.size() == 1) + this.userGroupDetails = userGroupEntityList.get(0); + } + + @Then("the response should contain a valid user group resource with name {string}") + public void verifyUserGroupName(String expectedName) { + Assertions.assertEquals(expectedName, userGroupEntityResponse.getName()); + } + + @Then("the response should contain the productId {string}") + public void verifyProductId(String expectedProductId) { + Assertions.assertEquals(expectedProductId, userGroupEntityResponse.getProductId()); + } + + @Then("the response should contain the institutionId {string}") + public void verifyInstitutionId(String expectedInstitutionId) { + Assertions.assertEquals(expectedInstitutionId, userGroupEntityResponse.getInstitutionId()); + } + + @And("the response should contain the status {string}") + public void theResponseShouldContainTheStatus(String expectedStatus) { + Assertions.assertEquals(expectedStatus, userGroupEntityResponse.getStatus().name()); + } + + @And("the response should contain {int} members") + public void theResponseShouldContainMembers(int expectedMembersCount) { + Assertions.assertEquals(expectedMembersCount, userGroupEntityResponse.getMembers().size()); + } + + @And("the response should contain the createdBy {string}") + public void theResponseShouldContainTheCreatedBy(String expectedCreatedBy) { + Assertions.assertEquals(expectedCreatedBy, userGroupEntityResponse.getCreatedBy()); + } + + @And("the response should contain the createdAt notNull") + public void theResponseShouldContainTheCreatedAtNotNull() { + verifyNotNull(userGroupEntityResponse.getCreatedAt()); + } + + @And("the response should contain the modified data null") + public void theResponseShouldContainTheModifiedDataNull() { + verifyNull(userGroupEntityResponse.getModifiedAt(), userGroupEntityResponse.getModifiedBy()); + } + + @And("the response should contain the description {string}") + public void theResponseShouldContainTheDescription(String expectedDescription) { + Assertions.assertEquals(expectedDescription, userGroupEntityResponse.getDescription()); + } +} + diff --git a/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/FakeSteps.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/FakeSteps.java new file mode 100644 index 00000000..cbc6f917 --- /dev/null +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/FakeSteps.java @@ -0,0 +1,20 @@ +package it.pagopa.selfcare.user_group.integration_test.steps; + +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; + +public class FakeSteps extends UserGroupSteps { + + + + @Override + @Then("[FAKE] the response status should be {int}") + public void verifyResponseStatus(int expectedStatusCode) { + super.verifyResponseStatus(expectedStatusCode); + } + + @When("I send a request to {string}") + public void iSendARequestTo(String url) { + status = 200; + } +} diff --git a/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/RetrieveUserGroupSteps.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/RetrieveUserGroupSteps.java new file mode 100644 index 00000000..92349197 --- /dev/null +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/RetrieveUserGroupSteps.java @@ -0,0 +1,198 @@ +package it.pagopa.selfcare.user_group.integration_test.steps; + +import io.cucumber.java.After; +import io.cucumber.java.Before; +import io.cucumber.java.en.And; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import io.restassured.RestAssured; +import io.restassured.common.mapper.TypeRef; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import io.restassured.response.ResponseOptions; +import io.restassured.specification.RequestSpecification; +import it.pagopa.selfcare.user_group.model.UserGroupEntity; +import it.pagopa.selfcare.user_group.model.UserGroupStatus; +import org.junit.jupiter.api.Assertions; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + + +public class RetrieveUserGroupSteps extends UserGroupSteps { + + @Before("@FirstRetrieveGroupScenario") + public void beforeFeature() throws IOException { + initializeCollection(); + } + + @After("@LastRetrieveGroupScenario") + public void afterFeature() { + userGroupRepository.deleteAllById(userGroupsIds); + } + + @Override + @Then("[RETRIEVE] the response status should be {int}") + public void verifyResponseStatus(int status) { + super.verifyResponseStatus(status); + } + + @Override + @Then("[RETRIEVE] the response should contain an error message {string}") + public void verifyErrorMessage(String expectedErrorMessage) { + super.verifyErrorMessage(expectedErrorMessage); + } + + + @Given("I have a valid group ID to retrieve: {string}") + public void iHaveAValidGroupId(String validGroupId) { + userGroupId = validGroupId; + } + + @Given("I have a non-existent group ID to retrieve {string}") + public void iHaveANonExistentGroupId(String nonExistentGroupId) { + userGroupId = nonExistentGroupId; + } + + @Given("I have a filter with status {string} but no productId, institutionId or userId") + public void iHaveAFilterWithStatusButNoOr(String status) { + userGroupEntityFilter = new UserGroupEntity(); + userGroupEntityFilter.setStatus(UserGroupStatus.valueOf(status)); + } + + @Given("I have a filter with sorting by {string} but no filter") + public void iHaveAFilterWithSortingByButNoFilter(String sortBy) { + Sort sort = Sort.by(Sort.Order.asc(sortBy)); + pageable = PageRequest.of(0, 10, sort); + } + + @And("I set the page number to {int} and page size to {int}") + public void iSetThePageNumberToAndPageSizeTo(int page, int size) { + pageable = Pageable.ofSize(size).withPage(page); + } + + @Given("I have no filters") + public void iHaveNoFilters() { + userGroupEntityFilter = new UserGroupEntity(); + } + + @When("I send a GET request to {string}") + public void iSendAGETRequestTo(String url) { + ResponseOptions response = RestAssured.given() + .pathParam("id", userGroupId) + .header("Authorization", "Bearer " + token) + .when() + .get(url); + status = response.statusCode(); + if (status == 200) { + userGroupEntityResponse = response.getBody().as(UserGroupEntity.class); + } else { + errorMessage = response.getBody().asString(); + } + } + + @When("I send a GET request to {string} to retrieve userGroups") + public void iSendAGETRequestToRetrieveUserGroups(String url) { + RequestSpecification requestSpecification = RestAssured.given() + .contentType("application/json") + .header("Authorization", "Bearer " + token); + + if (Objects.nonNull(userGroupEntityFilter)) { + if (Objects.nonNull(userGroupEntityFilter.getProductId())) { + requestSpecification.queryParam("productId", userGroupEntityFilter.getProductId()); + } + if (Objects.nonNull(userGroupEntityFilter.getInstitutionId())) { + requestSpecification.queryParam("institutionId", userGroupEntityFilter.getInstitutionId()); + } + if (Objects.nonNull(userGroupEntityFilter.getStatus())) { + requestSpecification.queryParam("status", userGroupEntityFilter.getStatus()); + } + } + + if (Objects.nonNull(pageable)) { + requestSpecification.queryParam("size",pageable.getPageSize()); + requestSpecification.queryParam("page",pageable.getPageNumber()); + if(pageable.getSort().isSorted()){ + requestSpecification.queryParam("sort", pageable.getSort().toString()); + } + } + + ExtractableResponse response = requestSpecification + .when() + .get(url) + .then() + .extract(); + + status = response.statusCode(); + if (status == 200) { + userGroupEntityResponsePage = response.body().as(new TypeRef<>() { + }); + if (Objects.nonNull(userGroupEntityResponsePage) && !userGroupEntityResponsePage.getContent().isEmpty()) { + userGroupEntityResponse = userGroupEntityResponsePage.getContent().get(0); + userGroupId = userGroupEntityResponse.getId(); + } + } else { + errorMessage = response.body().asString(); + } + } + + @Then("the response should contain the group details") + public void the_response_should_contain_the_group_details() { + Assertions.assertEquals(userGroupId, userGroupEntityResponse.getId()); + Assertions.assertEquals("io group", userGroupEntityResponse.getName()); + Assertions.assertEquals("io group description", userGroupEntityResponse.getDescription()); + Assertions.assertEquals("9c8ae123-d990-4400-b043-67a60aff31bc", userGroupEntityResponse.getInstitutionId()); + Assertions.assertEquals("prod-test", userGroupEntityResponse.getProductId()); + Assertions.assertEquals("ACTIVE", userGroupEntityResponse.getStatus().name()); + Assertions.assertEquals(1, userGroupEntityResponse.getMembers().size()); + Assertions.assertEquals("75003d64-7b8c-4768-b20c-cf66467d44c7", userGroupEntityResponse.getMembers().iterator().next()); + Assertions.assertNotNull(userGroupEntityResponse.getCreatedAt()); + Assertions.assertEquals("4ba2832d-9c4c-40f3-9126-e1c72905ef14", userGroupEntityResponse.getCreatedBy()); + Assertions.assertNull(userGroupEntityResponse.getModifiedBy()); + } + + @And("the response should contain a paginated list of user groups of {int} items on page {int}") + public void theResponseShouldContainAPaginatedListOfUserGroups(int count, int page) { + Assertions.assertEquals(count, userGroupEntityResponsePage.getContent().size()); + Assertions.assertEquals(3, userGroupEntityResponsePage.getTotalElements()); + Assertions.assertEquals(2, userGroupEntityResponsePage.getTotalPages()); + Assertions.assertEquals(2, userGroupEntityResponsePage.getSize()); + Assertions.assertEquals(page, userGroupEntityResponsePage.getNumber()); + } + + @Given("I have valid filters institutionId {string} productId {string} and status {string}") + public void iHaveValidFiltersAndAnd(String institutionId, String productId, String status) { + userGroupEntityFilter = new UserGroupEntity(); + userGroupEntityFilter.setInstitutionId(institutionId); + userGroupEntityFilter.setProductId(productId); + userGroupEntityFilter.setStatus(UserGroupStatus.valueOf(status)); + } + + @And("the response should contains groupIds {string}") + public void theResponseShouldContainGroupIds(String ids) { + List idsList = Arrays.asList(ids.split(",")); + Assertions.assertEquals(idsList, userGroupEntityResponsePage.getContent().stream().map(UserGroupEntity::getId).toList()); + } + + @And("the response should contain an empty list") + public void theResponseShouldContainAnEmptyList() { + Assertions.assertEquals(0, userGroupEntityResponsePage.getContent().size()); + } + + @And("the response should contain {int} item") + public void theResponseShouldContainOneItem(int expectedItemsCount) { + Assertions.assertEquals(expectedItemsCount, userGroupEntityResponsePage.getContent().size()); + } + + @Then("I should receive a response of retrieve user group operation with status code {int}") + public void iShouldReceiveAResponseWithStatusCode(int expectedStatusCode) { + Assertions.assertEquals(expectedStatusCode, status); + } +} + diff --git a/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/UpdateUserGroupSteps.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/UpdateUserGroupSteps.java new file mode 100644 index 00000000..4bfbd9be --- /dev/null +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/UpdateUserGroupSteps.java @@ -0,0 +1,172 @@ +package it.pagopa.selfcare.user_group.integration_test.steps; + +import io.cucumber.java.After; +import io.cucumber.java.Before; +import io.cucumber.java.en.And; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import io.restassured.RestAssured; +import io.restassured.common.mapper.TypeRef; +import io.restassured.response.ExtractableResponse; +import io.restassured.specification.RequestSpecification; +import it.pagopa.selfcare.user_group.model.UserGroupEntity; +import org.junit.jupiter.api.Assertions; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Set; + +public class UpdateUserGroupSteps extends UserGroupSteps { + + @Before("@FirstUpdateScenario") + public void beforeFeature() throws IOException { + List groupsToInsert = objectMapper.readValue(new File("src/test/resources/dataPopulation/groupEntities.json"), + objectMapper.getTypeFactory().constructCollectionType(List.class, UserGroupEntity.class)); + userGroupRepository.insert(groupsToInsert); + } + + @After("@LastUpdateScenario") + public void afterFeature() { + userGroupRepository.deleteAllById(userGroupsIds); + } + + @Override + @Then("[UPDATE] the response status should be {int}") + public void verifyResponseStatus(int status) { + super.verifyResponseStatus(status); + } + + @Override + @Then("[UPDATE] the response should contain an error message {string}") + public void verifyErrorMessage(String expectedErrorMessage) { + super.verifyErrorMessage(expectedErrorMessage); + } + + @Given("I have a valid group ID to update: {string}") + public void iHaveAValidGroupIDToUpdate(String groupId) { + userGroupId = groupId; + } + + @Given("I have a non-existent group ID {string}") + public void i_have_a_non_existent_group_ID(String nonExistentGroupId) { + userGroupId = nonExistentGroupId; + } + + @And("I have data to update:") + public void iHaveDataToUpdate(List userGroupEntityList) { + if (userGroupEntityList != null && userGroupEntityList.size() == 1) + this.userGroupDetails = userGroupEntityList.get(0); + } + + @When("I send a POST request to {string} with authentication {string}") + public void iSendAPOSTRequestTo(String url, String isAuthenticated) { + RequestSpecification requestSpecification = RestAssured.given() + .contentType("application/json"); + + if(Boolean.parseBoolean(isAuthenticated)){ + requestSpecification.header("Authorization", "Bearer " + token); + } + + ExtractableResponse response = requestSpecification + .pathParam("groupId", userGroupId) + .when() + .post(url) + .then() + .extract(); + + this.status = response.statusCode(); + if(status != 204) { + errorMessage = response.body().asString(); + } + } + + @When("I send a PUT request to {string} with authentication {string}") + public void iSendAPUTRequestTo(String url, String isAuthenticated) { + RequestSpecification requestSpecification = RestAssured.given() + .contentType("application/json"); + + if(Boolean.parseBoolean(isAuthenticated)){ + requestSpecification.header("Authorization", "Bearer " + token); + } + + ExtractableResponse response = requestSpecification + .pathParam("groupId", userGroupId) + .when() + .body(userGroupDetails) + .put(url) + .then() + .extract(); + + this.status = response.statusCode(); + if(status != 204) { + errorMessage = response.body().asString(); + } + } + + @When("I send a DELETE request to {string} with authentication {string}") + public void iSendADeleteRequestTo(String url, String isAuthenticated) { + RequestSpecification requestSpecification = RestAssured.given() + .contentType("application/json"); + + if(Boolean.parseBoolean(isAuthenticated)){ + requestSpecification.header("Authorization", "Bearer " + token); + } + + ExtractableResponse response = requestSpecification + .pathParam("groupId", userGroupId) + .when() + .delete(url) + .then() + .extract(); + + this.status = response.statusCode(); + if(status != 204) { + errorMessage = response.body().asString(); + } + } + + @And("the retrieved group should be updated") + public void theRetrievedGroupShouldBeUpdated() { + ExtractableResponse response = RestAssured.given() + .contentType("application/json") + .header("Authorization", "Bearer " + token) + .when() + .get("/v1/user-groups/" + userGroupId) + .then() + .extract(); + + status = response.statusCode(); + if (status == 200) { + updatedUserGroupEntity = response.body().as(new TypeRef<>() { + }); + Assertions.assertNotEquals("io group", updatedUserGroupEntity.getName()); + Assertions.assertNotEquals("io group description", updatedUserGroupEntity.getDescription()); + Assertions.assertNotEquals(Set.of("75003d64-7b8c-4768-b20c-cf66467d44c7"), updatedUserGroupEntity.getMembers()); + Assertions.assertNotNull(updatedUserGroupEntity.getModifiedAt()); + Assertions.assertNotNull(updatedUserGroupEntity.getModifiedBy()); + } + } + + @And("the retrieved group should be changed status to {string}") + public void theRetrievedGroupShouldBeChangedStatusTo(String changedStatus) { + ExtractableResponse response = RestAssured.given() + .contentType("application/json") + .header("Authorization", "Bearer " + token) + .when() + .get("/v1/user-groups/" + userGroupId) + .then() + .extract(); + + status = response.statusCode(); + if (status == 200) { + updatedUserGroupEntity = response.body().as(new TypeRef<>() { + }); + Assertions.assertEquals(changedStatus, updatedUserGroupEntity.getStatus().name()); + Assertions.assertNotNull(updatedUserGroupEntity.getModifiedAt()); + Assertions.assertNotNull(updatedUserGroupEntity.getModifiedBy()); + } + } + +} diff --git a/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/UserGroupMemberSteps.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/UserGroupMemberSteps.java new file mode 100644 index 00000000..a4b36aef --- /dev/null +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/UserGroupMemberSteps.java @@ -0,0 +1,130 @@ +package it.pagopa.selfcare.user_group.integration_test.steps; + +import io.cucumber.java.After; +import io.cucumber.java.Before; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import io.restassured.RestAssured; +import io.restassured.response.Response; +import io.restassured.response.ResponseOptions; +import io.restassured.specification.RequestSpecification; +import it.pagopa.selfcare.user_group.model.UserGroupEntity; + +import java.io.IOException; +import java.util.UUID; + +public class UserGroupMemberSteps extends UserGroupSteps { + + @Before("@FirstGroupMembersScenario") + public void beforeFeature() throws IOException { + initializeCollection(); + } + + @After("@LastGroupMembersScenario") + public void afterFeature() { + userGroupRepository.deleteAllById(userGroupsIds); + } + + @Override + @Then("[MEMBERS] the response status should be {int}") + public void verifyResponseStatus(int status) { + super.verifyResponseStatus(status); + } + + @Override + @Then("[MEMBERS] the response should contain an error message {string}") + public void verifyErrorMessage(String expectedErrorMessage) { + super.verifyErrorMessage(expectedErrorMessage); + } + + + @Given("I have group ID {string} and member ID {string}") + public void iHaveGroupIdMemberId(String groupId, String memberId) { + userGroupId = groupId; + userGroupMemberId = UUID.fromString(memberId); + } + + @Given("I have a missing group ID and a valid member ID {string}") + public void i_have_a_missing_group_ID_and_a_valid_member_ID(String memberId) { + userGroupMemberId = UUID.fromString(memberId); + } + + @Given("I have a member id {string}, institution id {string} and product id {string}") + public void iHaveAValidMemberIDInstitutionIDAndProductID(String memberId, String institutionId, String productId) { + userGroupMemberId = UUID.fromString(memberId); + userGroupEntityFilter = new UserGroupEntity(); + userGroupEntityFilter.setInstitutionId(institutionId); + userGroupEntityFilter.setProductId(productId); + } + + @Given("I have a member id {string} and institution id {string}") + public void iHaveAValidMemberIDAndInstitutionIDAndAMissingProductID(String memberId, String institutionId) { + userGroupMemberId = UUID.fromString(memberId); + userGroupEntityFilter = new UserGroupEntity(); + userGroupEntityFilter.setInstitutionId(institutionId); + } + + @Given("I have a member id {string} and product id {string}") + public void iHaveAValidMemberIDAndAMissingInstitutionIDAndProductID(String memberId, String productId) { + userGroupMemberId = UUID.fromString(memberId); + userGroupEntityFilter = new UserGroupEntity(); + userGroupEntityFilter.setProductId(productId); + } + + + @When("I send a PUT request to {string}") + public void iSendAPutRequestTo(String url) { + ResponseOptions response = RestAssured.given() + .header("Authorization", "Bearer " + token) + .pathParam("id", userGroupId) + .pathParam("memberId", userGroupMemberId) + .when() + .put(url); + + status = response.statusCode(); + if (status != 204) { + errorMessage = response.body().asString(); + } + } + + @When("I send a DELETE request to {string}") + public void iSendADELETERequestTo(String url) { + ResponseOptions response = RestAssured.given() + .header("Authorization", "Bearer " + token) + .pathParam("id", userGroupId) + .pathParam("memberId", userGroupMemberId) + .when() + .delete(url); + + status = response.statusCode(); + if (status != 204) { + errorMessage = response.body().asString(); + } + } + + @When("I send a DELETE request to {string} with query parameters") + public void iSendADELETERequestToWithQueryParameters(String url) { + RequestSpecification requestSpecification = RestAssured.given() + .header("Authorization", "Bearer " + token) + .pathParam("memberId", userGroupMemberId); + + if (userGroupEntityFilter.getInstitutionId() != null) { + requestSpecification.queryParam("institutionId", userGroupEntityFilter.getInstitutionId()); + } + if (userGroupEntityFilter.getProductId() != null) { + requestSpecification.queryParam("productId", userGroupEntityFilter.getProductId()); + } + + ResponseOptions response = requestSpecification + .queryParam("institutionId", userGroupEntityFilter.getInstitutionId()) + .queryParam("productId", userGroupEntityFilter.getProductId()) + .when() + .delete(url); + + status = response.statusCode(); + if (status != 204) { + errorMessage = response.body().asString(); + } + } +} diff --git a/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/UserGroupSteps.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/UserGroupSteps.java new file mode 100644 index 00000000..a732ba3b --- /dev/null +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/UserGroupSteps.java @@ -0,0 +1,77 @@ +package it.pagopa.selfcare.user_group.integration_test.steps; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.restassured.RestAssured; +import it.pagopa.selfcare.user_group.model.TestProperties; +import it.pagopa.selfcare.user_group.model.UserGroupEntityPageable; +import it.pagopa.selfcare.user_group.dao.UserGroupRepository; +import it.pagopa.selfcare.user_group.model.UserGroupEntity; +import org.junit.jupiter.api.Assertions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.domain.Pageable; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +public class UserGroupSteps { + + @Autowired + protected UserGroupRepository userGroupRepository; + + @Autowired + protected ObjectMapper objectMapper; + + protected String userGroupId; + protected UUID userGroupMemberId; + protected UserGroupEntity userGroupDetails; + protected UserGroupEntity userGroupEntityResponse; + protected UserGroupEntity updatedUserGroupEntity; + protected UserGroupEntityPageable userGroupEntityResponsePage; + protected Pageable pageable; + protected UserGroupEntity userGroupEntityFilter; + protected int status; + protected String errorMessage; + protected List userGroupsIds = List.of("6759f8df78b6af202b222d29", "6759f8df78b6af202b222d2a", "6759f8df78b6af202b222d2b"); + protected String token = readDataPopulation().getToken(); + + public TestProperties readDataPopulation() { + TestProperties testProperties = null; + ObjectMapper objectMapper = new ObjectMapper(); + try { + testProperties = objectMapper.readValue(new File("src/test/resources/dataPopulation/data.json"), new TypeReference<>() { + }); + } catch (IOException e) { + e.printStackTrace(); + } + return testProperties; + } + + public void verifyErrorMessage(String expectedErrorMessage) { + String[] errorMessageArray = expectedErrorMessage.split(","); + Arrays.stream(errorMessageArray).forEach(s -> Assertions.assertTrue(errorMessage.contains(s))); + } + + public void verifyResponseStatus(int expectedStatusCode) { + Assertions.assertEquals(expectedStatusCode, status); + } + + public void verifyNotNull(Object... objects) { + Arrays.stream(objects).forEach(Assertions::assertNotNull); + } + + public void verifyNull(Object... objects) { + Arrays.stream(objects).forEach(Assertions::assertNull); + } + + public void initializeCollection() throws IOException { + List groupsToInsert = objectMapper.readValue(new File("src/test/resources/dataPopulation/groupEntities.json"), + objectMapper.getTypeFactory().constructCollectionType(List.class, UserGroupEntity.class)); + userGroupRepository.insert(groupsToInsert); + } + +} diff --git a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/model/CreateUserGroupDtoTest.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/CreateUserGroupDtoTest.java similarity index 98% rename from apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/model/CreateUserGroupDtoTest.java rename to apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/CreateUserGroupDtoTest.java index 51828516..24fb557d 100644 --- a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/model/CreateUserGroupDtoTest.java +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/CreateUserGroupDtoTest.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.web.model; +package it.pagopa.selfcare.user_group.model; import it.pagopa.selfcare.commons.utils.TestUtils; import org.junit.jupiter.api.BeforeEach; diff --git a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/model/DummyCreateUserGroupDto.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/DummyCreateUserGroupDto.java similarity index 73% rename from apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/model/DummyCreateUserGroupDto.java rename to apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/DummyCreateUserGroupDto.java index 0c88bc5c..e0ea7346 100644 --- a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/model/DummyCreateUserGroupDto.java +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/DummyCreateUserGroupDto.java @@ -1,6 +1,5 @@ -package it.pagopa.selfcare.user_group.web.model; +package it.pagopa.selfcare.user_group.model; -import it.pagopa.selfcare.user_group.connector.model.UserGroupStatus; import lombok.Data; import java.util.List; diff --git a/apps/user-group-ms/connector-api/src/test/java/it/pagopa/selfcare/user_group/connector/DummyGroup.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/DummyGroup.java similarity index 73% rename from apps/user-group-ms/connector-api/src/test/java/it/pagopa/selfcare/user_group/connector/DummyGroup.java rename to apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/DummyGroup.java index d1b18345..7469d808 100644 --- a/apps/user-group-ms/connector-api/src/test/java/it/pagopa/selfcare/user_group/connector/DummyGroup.java +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/DummyGroup.java @@ -1,7 +1,6 @@ -package it.pagopa.selfcare.user_group.connector; +package it.pagopa.selfcare.user_group.model; -import it.pagopa.selfcare.user_group.connector.api.UserGroupOperations; -import it.pagopa.selfcare.user_group.connector.model.UserGroupStatus; +import it.pagopa.selfcare.user_group.api.UserGroupOperations; import lombok.Data; import java.time.Instant; diff --git a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/model/DummyUpdateUserGroupDto.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/DummyUpdateUserGroupDto.java similarity index 82% rename from apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/model/DummyUpdateUserGroupDto.java rename to apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/DummyUpdateUserGroupDto.java index 4ec3d794..c7f74db3 100644 --- a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/model/DummyUpdateUserGroupDto.java +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/DummyUpdateUserGroupDto.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.web.model; +package it.pagopa.selfcare.user_group.model; import lombok.Data; diff --git a/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/TestProperties.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/TestProperties.java new file mode 100644 index 00000000..98daa47c --- /dev/null +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/TestProperties.java @@ -0,0 +1,8 @@ +package it.pagopa.selfcare.user_group.model; + +import lombok.Data; + +@Data +public class TestProperties { + private String token; +} diff --git a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/model/UpdateUserGroupDtoTest.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/UpdateUserGroupDtoTest.java similarity index 98% rename from apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/model/UpdateUserGroupDtoTest.java rename to apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/UpdateUserGroupDtoTest.java index 2afd0828..2d4bff0b 100644 --- a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/model/UpdateUserGroupDtoTest.java +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/UpdateUserGroupDtoTest.java @@ -1,4 +1,4 @@ -package it.pagopa.selfcare.user_group.web.model; +package it.pagopa.selfcare.user_group.model; import it.pagopa.selfcare.commons.utils.TestUtils; import org.junit.jupiter.api.BeforeEach; diff --git a/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/UserGroupEntityPageable.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/UserGroupEntityPageable.java new file mode 100644 index 00000000..818fc961 --- /dev/null +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/model/UserGroupEntityPageable.java @@ -0,0 +1,14 @@ +package it.pagopa.selfcare.user_group.model; + +import lombok.Data; + +import java.util.List; + +@Data +public class UserGroupEntityPageable { + private List content; + private Integer totalElements; + private Integer totalPages; + private Integer size; + private Integer number; +} diff --git a/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/service/UserGroupServiceImplTest.java b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/service/UserGroupServiceImplTest.java new file mode 100644 index 00000000..3607458d --- /dev/null +++ b/apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/service/UserGroupServiceImplTest.java @@ -0,0 +1,856 @@ +package it.pagopa.selfcare.user_group.service; + +import com.mongodb.client.result.UpdateResult; +import it.pagopa.selfcare.user_group.api.UserGroupOperations; +import it.pagopa.selfcare.user_group.config.CoreTestConfig; +import it.pagopa.selfcare.user_group.dao.UserGroupRepository; +import it.pagopa.selfcare.user_group.exception.ResourceAlreadyExistsException; +import it.pagopa.selfcare.user_group.exception.ResourceNotFoundException; +import it.pagopa.selfcare.user_group.exception.ResourceUpdateException; +import it.pagopa.selfcare.user_group.model.DummyGroup; +import it.pagopa.selfcare.user_group.model.UserGroupEntity; +import it.pagopa.selfcare.user_group.model.UserGroupFilter; +import it.pagopa.selfcare.user_group.model.UserGroupStatus; +import it.pagopa.selfcare.commons.base.security.SelfCareUser; +import it.pagopa.selfcare.commons.utils.TestUtils; +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.junit.jupiter.api.function.Executable; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.data.domain.*; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.security.authentication.TestingAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.test.context.TestSecurityContextHolder; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import javax.validation.ValidationException; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = {UserGroupServiceImpl.class, CoreTestConfig.class, UserGroupRepository.class, MongoTemplate.class}) +@TestPropertySource(properties = { + "ALLOWED_SORTING_PARAMETERS=name" +}) +class UserGroupServiceImplTest { + + @BeforeEach + void beforeEach() { + TestSecurityContextHolder.clearContext(); + } + + @MockBean + private UserGroupRepository userGroupRepository; + + @MockBean + private AuditorAware auditorAware; + + @MockBean + private MappingMongoConverter mappingMongoConverter; + + @MockBean + private MongoTemplate mongoTemplateMock; + + @Autowired + private UserGroupServiceImpl groupService; + + @Captor + private ArgumentCaptor filter; + + @Test + void createGroup_nullAuth() { + //given + UserGroupOperations input = null; + //when + Executable executable = () -> groupService.createGroup(input); + //then + IllegalStateException e = assertThrows(IllegalStateException.class, executable); + assertEquals("Authentication is required", e.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void createGroup_nullPrincipal() { + //given + UserGroupOperations input = null; + Authentication authentication = new TestingAuthenticationToken(null, null); + TestSecurityContextHolder.setAuthentication(authentication); + //when + Executable executable = () -> groupService.createGroup(input); + //then + IllegalStateException illegalStateException = Assertions.assertThrows(IllegalStateException.class, executable); + Assertions.assertEquals("Not SelfCareUser principal", illegalStateException.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void createGroup_nullGroup() { + //given + SelfCareUser selfCareUser = SelfCareUser.builder("id") + .email("test@example.com") + .name("name") + .surname("surname") + .build(); + TestingAuthenticationToken authenticationToken = new TestingAuthenticationToken(selfCareUser, null); + TestSecurityContextHolder.setAuthentication(authenticationToken); + UserGroupOperations input = null; + //when + Executable executable = () -> groupService.createGroup(input); + //then + IllegalArgumentException illegalArgumentException = Assertions.assertThrows(IllegalArgumentException.class, executable); + Assertions.assertEquals("A group is required", illegalArgumentException.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void createGroup_ok() { + //given + SelfCareUser selfCareUser = SelfCareUser.builder("userId") + .email("test@example.com") + .name("name") + .surname("surname") + .build(); + TestingAuthenticationToken authenticationToken = new TestingAuthenticationToken(selfCareUser, null); + TestSecurityContextHolder.setAuthentication(authenticationToken); + UserGroupOperations input = TestUtils.mockInstance(new DummyGroup(), "setId", "setCreateAt", "setModifiedAt"); + + when(userGroupRepository.insert(any(UserGroupEntity.class))).thenReturn(new UserGroupEntity()); + when(mongoTemplateMock.find(any(Query.class), eq(UserGroupEntity.class))).thenReturn(Collections.emptyList()); + + //when + UserGroupOperations output = groupService.createGroup(input); + //then + assertNotNull(output); + verify(userGroupRepository).insert(any(UserGroupEntity.class)); + verify(mongoTemplateMock).find(any(Query.class), eq(UserGroupEntity.class)); + } + + @Test + void createGroup_duplicateKey() { + //given + SelfCareUser selfCareUser = SelfCareUser.builder("userId") + .email("test@example.com") + .name("name") + .surname("surname") + .build(); + TestingAuthenticationToken authenticationToken = new TestingAuthenticationToken(selfCareUser, null); + TestSecurityContextHolder.setAuthentication(authenticationToken); + UserGroupOperations input = TestUtils.mockInstance(new DummyGroup(), "setId", "setCreateAt", "setModifiedAt"); + + when(userGroupRepository.insert(any(UserGroupEntity.class))).thenThrow(new DuplicateKeyException("Duplicate key")); + when(mongoTemplateMock.find(any(Query.class), eq(UserGroupEntity.class))).thenReturn(Collections.emptyList()); + + //when + Executable executable = () -> groupService.createGroup(input); + + //then + ResourceAlreadyExistsException exception = assertThrows(ResourceAlreadyExistsException.class, executable); + assertEquals("Failed _id or unique index constraint.", exception.getMessage()); + verify(userGroupRepository).insert(any(UserGroupEntity.class)); + verify(mongoTemplateMock).find(any(Query.class), eq(UserGroupEntity.class)); + } + + @Test + void addMember_nullId() { + //given + UUID memberId = UUID.randomUUID(); + //when + Executable executable = () -> groupService.addMember(null, memberId); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A user group id is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void addMember_nullMemberId() { + //given + String groupId = "groupId"; + //when + Executable executable = () -> groupService.addMember(groupId, null); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A member id is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void addMember_groupNotFound() { + //given + String groupId = "groupId"; + UUID memberId = UUID.randomUUID(); + when(userGroupRepository.findById(groupId)).thenReturn(Optional.empty()); + //when + Executable executable = () -> groupService.addMember(groupId, memberId); + //then + assertThrows(ResourceNotFoundException.class, executable); + verify(userGroupRepository).findById(groupId); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void addMember_groupSuspended() { + //given + String groupId = "groupId"; + UUID memberId = UUID.randomUUID(); + UserGroupEntity group = mock(UserGroupEntity.class); + when(group.getStatus()).thenReturn(UserGroupStatus.SUSPENDED); + when(userGroupRepository.findById(groupId)).thenReturn(Optional.of(group)); + //when + Executable executable = () -> groupService.addMember(groupId, memberId); + //then + ResourceUpdateException exception = assertThrows(ResourceUpdateException.class, executable); + assertEquals("Trying to modify suspended group", exception.getMessage()); + verify(userGroupRepository).findById(groupId); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void addMember_success() { + //given + String groupId = "groupId"; + UUID memberId = UUID.randomUUID(); + UserGroupEntity group = mock(UserGroupEntity.class); + when(group.getStatus()).thenReturn(UserGroupStatus.ACTIVE); + when(userGroupRepository.findById(groupId)).thenReturn(Optional.of(group)); + UpdateResult updateResult = mock(UpdateResult.class); + when(updateResult.getModifiedCount()).thenReturn(1L); + when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class))).thenReturn(updateResult); + //when + groupService.addMember(groupId, memberId); + //then + verify(userGroupRepository).findById(groupId); + verify(mongoTemplateMock).updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class)); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void addMember_insertMemberFails() { + //given + String groupId = "groupId"; + UUID memberId = UUID.randomUUID(); + UserGroupEntity group = mock(UserGroupEntity.class); + when(group.getStatus()).thenReturn(UserGroupStatus.ACTIVE); + when(userGroupRepository.findById(groupId)).thenReturn(Optional.of(group)); + UpdateResult updateResult = mock(UpdateResult.class); + when(updateResult.getModifiedCount()).thenReturn(0L); + when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class))).thenReturn(updateResult); + //when + Executable executable = () -> groupService.addMember(groupId, memberId); + //then + ResourceUpdateException exception = assertThrows(ResourceUpdateException.class, executable); + assertEquals("Couldn't update resource", exception.getMessage()); + verify(userGroupRepository).findById(groupId); + verify(mongoTemplateMock).updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class)); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void deleteMember_nullGroupId() { + //given + String memberId = "memberId"; + //when + Executable executable = () -> groupService.deleteMember(null, memberId); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A user group id is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void deleteMember_nullMemberId() { + //given + String groupId = "groupId"; + //when + Executable executable = () -> groupService.deleteMember(groupId, null); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A member id is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void deleteMember_groupNotFound() { + //given + String groupId = "groupId"; + String memberId = "memberId"; + when(userGroupRepository.findById(groupId)).thenReturn(Optional.empty()); + //when + Executable executable = () -> groupService.deleteMember(groupId, memberId); + //then + assertThrows(ResourceNotFoundException.class, executable); + verify(userGroupRepository).findById(groupId); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void deleteMember_groupSuspended() { + //given + String groupId = "groupId"; + String memberId = "memberId"; + UserGroupEntity group = mock(UserGroupEntity.class); + when(group.getStatus()).thenReturn(UserGroupStatus.SUSPENDED); + when(userGroupRepository.findById(groupId)).thenReturn(Optional.of(group)); + //when + Executable executable = () -> groupService.deleteMember(groupId, memberId); + //then + ResourceUpdateException exception = assertThrows(ResourceUpdateException.class, executable); + assertEquals("Trying to modify suspended group", exception.getMessage()); + verify(userGroupRepository).findById(groupId); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void deleteMember_success() { + //given + String groupId = "groupId"; + String memberId = "memberId"; + UserGroupEntity group = mock(UserGroupEntity.class); + when(group.getStatus()).thenReturn(UserGroupStatus.ACTIVE); + when(userGroupRepository.findById(groupId)).thenReturn(Optional.of(group)); + UpdateResult updateResult = mock(UpdateResult.class); + when(updateResult.getModifiedCount()).thenReturn(1L); + when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class))).thenReturn(updateResult); + //when + groupService.deleteMember(groupId, memberId); + //then + verify(userGroupRepository).findById(groupId); + verify(mongoTemplateMock).updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class)); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void deleteMember_updateFails() { + //given + String groupId = "groupId"; + String memberId = "memberId"; + UserGroupEntity group = mock(UserGroupEntity.class); + when(group.getStatus()).thenReturn(UserGroupStatus.ACTIVE); + when(userGroupRepository.findById(groupId)).thenReturn(Optional.of(group)); + UpdateResult updateResult = mock(UpdateResult.class); + when(updateResult.getModifiedCount()).thenReturn(0L); + when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class))).thenReturn(updateResult); + //when + Executable executable = () -> groupService.deleteMember(groupId, memberId); + //then + ResourceUpdateException exception = assertThrows(ResourceUpdateException.class, executable); + assertEquals("Couldn't update resource", exception.getMessage()); + verify(userGroupRepository).findById(groupId); + verify(mongoTemplateMock).updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class)); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void deleteMembers_nullMemberId() { + //given + String institutionId = "institutionId"; + String productId = "productId"; + //when + Executable executable = () -> groupService.deleteMembers(null, institutionId, productId); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A member id is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void deleteMembers_nullInstitutionId() { + //given + String memberId = "memberId"; + String productId = "productId"; + //when + Executable executable = () -> groupService.deleteMembers(memberId, null, productId); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A institution id is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void deleteMembers_nullProductId() { + //given + String memberId = "memberId"; + String institutionId = "institutionId"; + //when + Executable executable = () -> groupService.deleteMembers(memberId, institutionId, null); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A product id is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void deleteMembers_success() { + //given + String memberId = "memberId"; + String institutionId = "institutionId"; + String productId = "productId"; + UpdateResult updateResult = mock(UpdateResult.class); + when(updateResult.getModifiedCount()).thenReturn(1L); + when(mongoTemplateMock.updateMulti(any(Query.class), any(Update.class), eq(UserGroupEntity.class))).thenReturn(updateResult); + //when + groupService.deleteMembers(memberId, institutionId, productId); + //then + verify(mongoTemplateMock).updateMulti(any(Query.class), any(Update.class), eq(UserGroupEntity.class)); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void deleteMembers_noModification() { + //given + String memberId = "memberId"; + String institutionId = "institutionId"; + String productId = "productId"; + UpdateResult updateResult = mock(UpdateResult.class); + when(updateResult.getModifiedCount()).thenReturn(0L); + when(mongoTemplateMock.updateMulti(any(Query.class), any(Update.class), eq(UserGroupEntity.class))).thenReturn(updateResult); + //when + groupService.deleteMembers(memberId, institutionId, productId); + //then + verify(mongoTemplateMock).updateMulti(any(Query.class), any(Update.class), eq(UserGroupEntity.class)); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void getUserGroup_nullId() { + //when + Executable executable = () -> groupService.getUserGroup(null); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A user group id is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void getUserGroup_emptyId() { + //when + Executable executable = () -> groupService.getUserGroup(""); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A user group id is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void getUserGroup_groupNotFound() { + //given + String groupId = "groupId"; + when(userGroupRepository.findById(groupId)).thenReturn(Optional.empty()); + //when + Executable executable = () -> groupService.getUserGroup(groupId); + //then + assertThrows(ResourceNotFoundException.class, executable); + verify(userGroupRepository).findById(groupId); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void getUserGroup_success() { + //given + String groupId = "groupId"; + UserGroupEntity group = mock(UserGroupEntity.class); + when(userGroupRepository.findById(groupId)).thenReturn(Optional.of(group)); + //when + UserGroupOperations result = groupService.getUserGroup(groupId); + //then + assertNotNull(result); + verify(userGroupRepository).findById(groupId); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void getUserGroups_invalidSortParameter() { + //given + UserGroupFilter filter = new UserGroupFilter(); + Pageable pageable = PageRequest.of(0, 10, Sort.by("invalidParam")); + //when + Executable executable = () -> groupService.getUserGroups(filter, pageable); + //then + ValidationException exception = assertThrows(ValidationException.class, executable); + assertEquals("Given sort parameters aren't valid", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void getUserGroups_validSortParameter() { + //given + UserGroupFilter filter = new UserGroupFilter(); + filter.setProductId("productId"); // Aggiungi un productId per soddisfare la condizione + Pageable pageable = PageRequest.of(0, 10, Sort.by("name")); + List userGroups = Collections.singletonList(mock(UserGroupEntity.class)); + Page page = new PageImpl<>(userGroups, pageable, userGroups.size()); + when(mongoTemplateMock.find(any(Query.class), eq(UserGroupEntity.class))).thenReturn(userGroups); + when(mongoTemplateMock.count(any(Query.class), eq(UserGroupEntity.class))).thenReturn((long) userGroups.size()); + //when + Page result = groupService.getUserGroups(filter, pageable); + //then + assertNotNull(result); + assertEquals(1, result.getTotalElements()); + verify(mongoTemplateMock).find(any(Query.class), eq(UserGroupEntity.class)); + verify(mongoTemplateMock).count(any(Query.class), eq(UserGroupEntity.class)); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void getUserGroups_sortingNotAllowedWithoutProductIdOrInstitutionId() { + //given + UserGroupFilter filter = new UserGroupFilter(); + Pageable pageable = PageRequest.of(0, 10, Sort.by("name")); + //when + Executable executable = () -> groupService.getUserGroups(filter, pageable); + //then + ValidationException exception = assertThrows(ValidationException.class, executable); + assertEquals("Sorting not allowed without productId or institutionId", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void getUserGroups_statusFilterWithoutRequiredFields() { + //given + UserGroupFilter filter = new UserGroupFilter(); + filter.setStatus(Collections.singletonList(UserGroupStatus.ACTIVE)); + Pageable pageable = PageRequest.of(0, 10); + //when + Executable executable = () -> groupService.getUserGroups(filter, pageable); + //then + ValidationException exception = assertThrows(ValidationException.class, executable); + assertEquals("At least one of productId, institutionId and userId must be provided with status filter", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void deleteGroup_nullId() { + //when + Executable executable = () -> groupService.deleteGroup(null); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A user group id is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void deleteGroup_emptyId() { + //when + Executable executable = () -> groupService.deleteGroup(""); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A user group id is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void deleteGroup_success() { + //given + String groupId = "groupId"; + UpdateResult updateResult = mock(UpdateResult.class); + when(updateResult.getMatchedCount()).thenReturn(1L); + when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class))).thenReturn(updateResult); + //when + groupService.deleteGroup(groupId); + //then + verify(mongoTemplateMock).updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class)); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void suspendGroup_nullId() { + //when + Executable executable = () -> groupService.suspendGroup(null); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A user group id is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void suspendGroup_emptyId() { + //when + Executable executable = () -> groupService.suspendGroup(""); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A user group id is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void suspendGroup_success() { + //given + String groupId = "groupId"; + UpdateResult updateResult = mock(UpdateResult.class); + when(updateResult.getMatchedCount()).thenReturn(1L); + when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class))).thenReturn(updateResult); + //when + groupService.suspendGroup(groupId); + //then + verify(mongoTemplateMock).updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class)); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void activateGroup_nullId() { + //when + Executable executable = () -> groupService.activateGroup(null); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A user group id is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void activateGroup_emptyId() { + //when + Executable executable = () -> groupService.activateGroup(""); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A user group id is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void activateGroup_success() { + //given + String groupId = "groupId"; + UpdateResult updateResult = mock(UpdateResult.class); + when(updateResult.getMatchedCount()).thenReturn(1L); + when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class))).thenReturn(updateResult); + //when + groupService.activateGroup(groupId); + //then + verify(mongoTemplateMock).updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class)); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void activateGroup_groupNotFound() { + //given + String groupId = "groupId"; + UpdateResult updateResult = mock(UpdateResult.class); + when(updateResult.getMatchedCount()).thenReturn(0L); + when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class))).thenReturn(updateResult); + //when + Executable executable = () -> groupService.activateGroup(groupId); + //then + assertThrows(ResourceNotFoundException.class, executable); + verify(mongoTemplateMock).updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class)); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void deleteGroup_groupNotFound() { + //given + String groupId = "groupId"; + UpdateResult updateResult = mock(UpdateResult.class); + when(updateResult.getMatchedCount()).thenReturn(0L); + when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class))).thenReturn(updateResult); + //when + Executable executable = () -> groupService.deleteGroup(groupId); + //then + assertThrows(ResourceNotFoundException.class, executable); + verify(mongoTemplateMock).updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class)); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void suspendGroup_groupNotFound() { + //given + String groupId = "groupId"; + UpdateResult updateResult = mock(UpdateResult.class); + when(updateResult.getMatchedCount()).thenReturn(0L); + when(mongoTemplateMock.updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class))).thenReturn(updateResult); + //when + Executable executable = () -> groupService.suspendGroup(groupId); + //then + assertThrows(ResourceNotFoundException.class, executable); + verify(mongoTemplateMock).updateFirst(any(Query.class), any(Update.class), eq(UserGroupEntity.class)); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void updateGroup_nullId() { + //given + UserGroupOperations group = mock(UserGroupOperations.class); + //when + Executable executable = () -> groupService.updateGroup(null, group); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A user group id is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void updateGroup_emptyId() { + //given + UserGroupOperations group = mock(UserGroupOperations.class); + //when + Executable executable = () -> groupService.updateGroup("", group); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A user group id is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void updateGroup_nullGroup() { + //given + String groupId = "groupId"; + //when + Executable executable = () -> groupService.updateGroup(groupId, null); + //then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, executable); + assertEquals("A user group is required", exception.getMessage()); + verifyNoInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void updateGroup_groupNotFound() { + //given + String groupId = "groupId"; + UserGroupOperations group = mock(UserGroupOperations.class); + when(userGroupRepository.findById(groupId)).thenReturn(Optional.empty()); + //when + Executable executable = () -> groupService.updateGroup(groupId, group); + //then + assertThrows(ResourceNotFoundException.class, executable); + verify(userGroupRepository).findById(groupId); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void updateGroup_groupSuspended() { + //given + String groupId = "groupId"; + UserGroupOperations group = mock(UserGroupOperations.class); + UserGroupEntity foundGroup = mock(UserGroupEntity.class); + when(foundGroup.getStatus()).thenReturn(UserGroupStatus.SUSPENDED); + when(userGroupRepository.findById(groupId)).thenReturn(Optional.of(foundGroup)); + //when + Executable executable = () -> groupService.updateGroup(groupId, group); + //then + ResourceUpdateException exception = assertThrows(ResourceUpdateException.class, executable); + assertEquals("Trying to modify suspended group", exception.getMessage()); + verify(userGroupRepository).findById(groupId); + verifyNoMoreInteractions(mongoTemplateMock, userGroupRepository); + } + + @Test + void updateGroup_success() { + //given + String groupId = "groupId"; + UserGroupOperations group = mock(UserGroupOperations.class); + UserGroupEntity foundGroup = mock(UserGroupEntity.class); + when(foundGroup.getStatus()).thenReturn(UserGroupStatus.ACTIVE); + when(userGroupRepository.findById(groupId)).thenReturn(Optional.of(foundGroup)); + when(userGroupRepository.save(any(UserGroupEntity.class))).thenReturn(foundGroup); + //when + UserGroupOperations result = groupService.updateGroup(groupId, group); + //then + assertNotNull(result); + verify(userGroupRepository).findById(groupId); + verify(userGroupRepository).save(any(UserGroupEntity.class)); + } + + @Test + void updateGroup_duplicateKey() { + //given + String groupId = "groupId"; + UserGroupOperations group = mock(UserGroupOperations.class); + UserGroupEntity foundGroup = mock(UserGroupEntity.class); + when(foundGroup.getStatus()).thenReturn(UserGroupStatus.ACTIVE); + when(userGroupRepository.findById(groupId)).thenReturn(Optional.of(foundGroup)); + when(userGroupRepository.save(any(UserGroupEntity.class))).thenThrow(new DuplicateKeyException("Duplicate key")); + //when + Executable executable = () -> groupService.updateGroup(groupId, group); + //then + ResourceAlreadyExistsException exception = assertThrows(ResourceAlreadyExistsException.class, executable); + assertEquals("Failed _id or unique index constraint.", exception.getMessage()); + verify(userGroupRepository).findById(groupId); + verify(userGroupRepository).save(any(UserGroupEntity.class)); + } + + @Test + void createGroup_duplicateName() { + //given + SelfCareUser selfCareUser = SelfCareUser.builder("userId") + .email("test@example.com") + .name("name") + .surname("surname") + .build(); + TestingAuthenticationToken authenticationToken = new TestingAuthenticationToken(selfCareUser, null); + TestSecurityContextHolder.setAuthentication(authenticationToken); + UserGroupOperations input = TestUtils.mockInstance(new DummyGroup(), "setId", "setCreateAt", "setModifiedAt"); + input.setName("duplicateName"); + input.setProductId("productId"); + input.setInstitutionId("institutionId"); + + UserGroupEntity existingGroup = new UserGroupEntity(); + existingGroup.setId("existingGroupId"); + existingGroup.setName("duplicateName"); + existingGroup.setProductId("productId"); + existingGroup.setInstitutionId("institutionId"); + existingGroup.setStatus(UserGroupStatus.ACTIVE); + + when(mongoTemplateMock.find(any(Query.class), eq(UserGroupEntity.class))).thenReturn(Collections.singletonList(existingGroup)); + when(mongoTemplateMock.count(any(Query.class), eq(UserGroupEntity.class))).thenReturn(1L); + + //when + Executable executable = () -> groupService.createGroup(input); + + //then + ResourceAlreadyExistsException exception = assertThrows(ResourceAlreadyExistsException.class, executable); + assertEquals("A group with the same name already exists in ACTIVE or SUSPENDED state", exception.getMessage()); + verify(mongoTemplateMock).find(any(Query.class), eq(UserGroupEntity.class)); + verify(mongoTemplateMock).count(any(Query.class), eq(UserGroupEntity.class)); + } + + @Test + void updateGroup_duplicateName() { + //given + String groupId = "groupId"; + UserGroupOperations group = mock(UserGroupOperations.class); + when(group.getName()).thenReturn("duplicateName"); + UserGroupEntity foundGroup = mock(UserGroupEntity.class); + when(foundGroup.getStatus()).thenReturn(UserGroupStatus.ACTIVE); + when(foundGroup.getProductId()).thenReturn("productId"); + when(foundGroup.getInstitutionId()).thenReturn("institutionId"); + when(userGroupRepository.findById(groupId)).thenReturn(Optional.of(foundGroup)); + + UserGroupEntity existingGroup = new UserGroupEntity(); + existingGroup.setId("existingGroupId"); + existingGroup.setName("duplicateName"); + existingGroup.setProductId("productId"); + existingGroup.setInstitutionId("institutionId"); + existingGroup.setStatus(UserGroupStatus.ACTIVE); + + when(mongoTemplateMock.find(any(Query.class), eq(UserGroupEntity.class))).thenReturn(Collections.singletonList(existingGroup)); + when(mongoTemplateMock.count(any(Query.class), eq(UserGroupEntity.class))).thenReturn(1L); + + //when + Executable executable = () -> groupService.updateGroup(groupId, group); + + //then + ResourceAlreadyExistsException exception = assertThrows(ResourceAlreadyExistsException.class, executable); + assertEquals("A group with the same name already exists in ACTIVE or SUSPENDED state", exception.getMessage()); + verify(userGroupRepository).findById(groupId); + verify(mongoTemplateMock).find(any(Query.class), eq(UserGroupEntity.class)); + verify(mongoTemplateMock).count(any(Query.class), eq(UserGroupEntity.class)); + verify(group).getName(); + } +} \ No newline at end of file diff --git a/apps/user-group-ms/src/test/resources/application-test.properties b/apps/user-group-ms/src/test/resources/application-test.properties new file mode 100644 index 00000000..a94cfa2a --- /dev/null +++ b/apps/user-group-ms/src/test/resources/application-test.properties @@ -0,0 +1,5 @@ +user-group.allowed.sorting.parameters=name +spring.data.mongodb.uri=mongodb://localhost:27017 +spring.data.mongodb.database=selcUserGroup +rest-assured.base-url=http://localhost +rest-assured.port=8082 diff --git a/apps/user-group-ms/src/test/resources/dataPopulation/data.json b/apps/user-group-ms/src/test/resources/dataPopulation/data.json new file mode 100644 index 00000000..06eb0a47 --- /dev/null +++ b/apps/user-group-ms/src/test/resources/dataPopulation/data.json @@ -0,0 +1,3 @@ +{ + "token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Imp3dF9hMjo3YTo0NjozYjoyYTo2MDo1Njo0MDo4ODphMDo1ZDphNDpmODowMToxZTozZSJ9.eyJmYW1pbHlfbmFtZSI6IkJhbGJvYSIsImZpc2NhbF9udW1iZXIiOiJCTEJSS1k2N0MzMEg1MDFCIiwibmFtZSI6IlJvY2t5Iiwic3BpZF9sZXZlbCI6Imh0dHBzOi8vd3d3LnNwaWQuZ292Lml0L1NwaWRMMiIsImZyb21fYWEiOmZhbHNlLCJ1aWQiOiI0YmEyODMyZC05YzRjLTQwZjMtOTEyNi1lMWM3MjkwNWVmMTQiLCJsZXZlbCI6IkwyIiwiaWF0IjoxNzM0MDc4MzQ3LCJleHAiOjE3MzQxMTA3NDcsImF1ZCI6ImFwaS5kZXYuc2VsZmNhcmUucGFnb3BhLml0IiwiaXNzIjoiU1BJRCIsImp0aSI6Il8yZjYwM2E4YmMzNmIxMjMxYjFhNiJ9.MCSiqjxLAkdLiGE_1MAznFnKe0sfPS3V8nNL6PU07tUH6VStn2QwSENkGFcepeatQ7aNBsh9GFjQXdDfa00nSDmWJRaDeQ-aRwUWWcgf_3WxL6De6k9Ou4e8v8_jdOQ4bqkWMESCNLEgZiD-NuzbWemJnGSv6ysyU9iaL-38eQ3wrMn9xIVXmNkILpkuiAHLMnoPO82BMQ_ldTCfBRM9kfoo3JyAPf9bHqslOD_VRU6lGULV9gzJ_D6ZQVIyZNs_Wvx6KN0j3feDcfViURBQruE_UZ3SvsnYmqcTL7IOk4wLI_GdXOXjN49SmceLMM3tHYN9yfzyzA-yDaYJvg0QIA" +} \ No newline at end of file diff --git a/apps/user-group-ms/src/test/resources/dataPopulation/groupEntities.json b/apps/user-group-ms/src/test/resources/dataPopulation/groupEntities.json new file mode 100644 index 00000000..4867ac7c --- /dev/null +++ b/apps/user-group-ms/src/test/resources/dataPopulation/groupEntities.json @@ -0,0 +1,44 @@ +[ + { + "id": "6759f8df78b6af202b222d29", + "institutionId": "9c8ae123-d990-4400-b043-67a60aff31bc", + "productId": "prod-test", + "name": "io group", + "description": "io group description", + "status": "ACTIVE", + "members": [ + "75003d64-7b8c-4768-b20c-cf66467d44c7" + ], + "createdAt": "2020-07-01T00:00:00.000Z", + "createdBy": "4ba2832d-9c4c-40f3-9126-e1c72905ef14", + "modifiedAt": null + }, + { + "id": "6759f8df78b6af202b222d2a", + "institutionId": "9c8ae123-d990-4400-b043-67a60aff31bc", + "productId": "prod-test", + "name": "io group 2", + "description": "pagopa group description", + "status": "SUSPENDED", + "members": [ + "75003d64-7b8c-4768-b20c-cf66467d44c7" + ], + "createdAt": "2020-07-01T00:00:00.000Z", + "createdBy": "4ba2832d-9c4c-40f3-9126-e1c72905ef14", + "modifiedAt": null + }, + { + "id": "6759f8df78b6af202b222d2b", + "institutionId": "9c8ae123-d990-4400-b043-67a60aff31bc", + "productId": "prod-test2", + "name": "interop group", + "description": "interop group description", + "status": "SUSPENDED", + "members": [ + "75003d64-7b8c-4768-b20c-cf66467d44c7" + ], + "createdAt": "2020-07-01T00:00:00.000Z", + "createdBy": "4ba2832d-9c4c-40f3-9126-e1c72905ef14", + "modifiedAt": null + } +] \ No newline at end of file diff --git a/apps/user-group-ms/src/test/resources/features/createGroup.feature b/apps/user-group-ms/src/test/resources/features/createGroup.feature new file mode 100644 index 00000000..0e02b65d --- /dev/null +++ b/apps/user-group-ms/src/test/resources/features/createGroup.feature @@ -0,0 +1,91 @@ +@FeatureCreate +Feature: Create User Group + + @CreateNewGroup + Scenario: Successfully create a new user group + Given the following user group details: + | name | description | productId | institutionId | status | members | + | Group Name | TestGroup | product123 | inst123 | ACTIVE | 525db33f-967f-4a82-8984-c606225e714a,a1b7c86b-d195-41d8-8291-7c3467abfd30 | + When I send a POST request to "/v1/user-groups" with the given details, with authentication "true" + Then [CREATE] the response status should be 201 + And the response should contain a valid user group resource with name "Group Name" + And the response should contain the description "TestGroup" + And the response should contain the productId "product123" + And the response should contain the institutionId "inst123" + And the response should contain the status "ACTIVE" + And the response should contain 2 members + And the response should contain the createdBy "4ba2832d-9c4c-40f3-9126-e1c72905ef14" + And the response should contain the createdAt notNull + And the response should contain the modified data null + + # Scenario negativo: Nome del gruppo giĆ  esistente (conflitto) + @DuplicateGroupName + Scenario: Attempt to create a user group with a duplicate name + Given the following user group details: + | name | description | productId | institutionId | status | members | + | io group | TestGroup | prod-test | 9c8ae123-d990-4400-b043-67a60aff31bc | ACTIVE | 525db33f-967f-4a82-8984-c606225e714a,a1b7c86b-d195-41d8-8291-7c3467abfd30 | + When I send a POST request to "/v1/user-groups" with the given details, with authentication "true" + Then [CREATE] the response status should be 409 + And [CREATE] the response should contain an error message "A group with the same name already exists in ACTIVE or SUSPENDED state" + + # Scenario negativo: Dettagli del gruppo mancanti (name non fornito) + Scenario: Attempt to create a user group with missing required fields + Given the following user group details: + | description | productId | institutionId | status | members | + | TestGroup | product123 | inst123 | ACTIVE | 525db33f-967f-4a82-8984-c606225e714a,a1b7c86b-d195-41d8-8291-7c3467abfd30 | + When I send a POST request to "/v1/user-groups" with the given details, with authentication "true" + Then [CREATE] the response status should be 400 + And [CREATE] the response should contain an error message "createUserGroupDto.name,must not be blank" + + # Scenario negativo: Dettagli del gruppo mancanti (institutionId non fornito) + Scenario: Attempt to create a user group with missing required fields + Given the following user group details: + | name | description | productId | status | members | + | Group Name | TestGroup | product123 | ACTIVE | 525db33f-967f-4a82-8984-c606225e714a,a1b7c86b-d195-41d8-8291-7c3467abfd30 | + When I send a POST request to "/v1/user-groups" with the given details, with authentication "true" + Then [CREATE] the response status should be 400 + And [CREATE] the response should contain an error message "createUserGroupDto.institutionId,must not be blank" + + # Scenario negativo: Dettagli del gruppo mancanti (productId non fornito) + Scenario: Attempt to create a user group with missing required fields + Given the following user group details: + | name | description | institutionId | status | members | + | Group Name | TestGroup | inst123 | ACTIVE | 525db33f-967f-4a82-8984-c606225e714a,a1b7c86b-d195-41d8-8291-7c3467abfd30 | + When I send a POST request to "/v1/user-groups" with the given details, with authentication "true" + Then [CREATE] the response status should be 400 + And [CREATE] the response should contain an error message "createUserGroupDto.productId,must not be blank" + + # Scenario negativo: Dettagli del gruppo mancanti (description non fornito) + Scenario: Attempt to create a user group with missing required fields + Given the following user group details: + | name | productId | institutionId | status | members | + | Group Name | product123 | inst123 | ACTIVE | 525db33f-967f-4a82-8984-c606225e714a,a1b7c86b-d195-41d8-8291-7c3467abfd30 | + When I send a POST request to "/v1/user-groups" with the given details, with authentication "true" + Then [CREATE] the response status should be 400 + And [CREATE] the response should contain an error message "createUserGroupDto.description,must not be blank" + + # Scenario negativo: Dettagli del gruppo mancanti (status non fornito) + Scenario: Attempt to create a user group with missing required fields + Given the following user group details: + | name | description | productId | institutionId | members | + | Group Name | TestGroup | product123 | inst123 | 525db33f-967f-4a82-8984-c606225e714a,a1b7c86b-d195-41d8-8291-7c3467abfd30 | + When I send a POST request to "/v1/user-groups" with the given details, with authentication "true" + Then [CREATE] the response status should be 400 + And [CREATE] the response should contain an error message "createUserGroupDto.status,must not be null" + + # Scenario negativo: Dettagli del gruppo mancanti (members vuoto) + Scenario: Attempt to create a user group with missing required fields + Given the following user group details: + | name | description | productId | institutionId | status | members | + | Group Name | TestGroup | product123 | inst123 | ACTIVE | | + When I send a POST request to "/v1/user-groups" with the given details, with authentication "true" + Then [CREATE] the response status should be 400 + And [CREATE] the response should contain an error message "createUserGroupDto.members,must not be empty" + + # Scenario negativo: Autenticazione mancante (utente non autenticato) + Scenario: Attempt to create a user group without authentication + Given the following user group details: + | name | description | productId | institutionId | status | members | + | Group Name | Test Group | product123 | inst123 | ACTIVE | | + When I send a POST request to "/v1/user-groups" with the given details, with authentication "false" + Then [CREATE] the response status should be 401 diff --git a/apps/user-group-ms/src/test/resources/features/fake.feature b/apps/user-group-ms/src/test/resources/features/fake.feature new file mode 100644 index 00000000..1e03e932 --- /dev/null +++ b/apps/user-group-ms/src/test/resources/features/fake.feature @@ -0,0 +1,5 @@ +Feature: fake + +Scenario: Successfully execute fake test +When I send a request to "/fake" +Then [FAKE] the response status should be 200 \ No newline at end of file diff --git a/apps/user-group-ms/src/test/resources/features/retrieveUserGroup.feature b/apps/user-group-ms/src/test/resources/features/retrieveUserGroup.feature new file mode 100644 index 00000000..7211fe6d --- /dev/null +++ b/apps/user-group-ms/src/test/resources/features/retrieveUserGroup.feature @@ -0,0 +1,69 @@ +@FeatureRetrieve +Feature: Get User Group + + @FirstRetrieveGroupScenario + Scenario: Successfully retrieve a group with a valid ID + Given I have a valid group ID to retrieve: "6759f8df78b6af202b222d29" + When I send a GET request to "/v1/user-groups/{id}" + Then [RETRIEVE] the response status should be 200 + And the response should contain the group details + + Scenario: Attempt to retrieve a non-existent group + Given I have a non-existent group ID to retrieve "99999" + When I send a GET request to "/v1/user-groups/{id}" + Then [RETRIEVE] the response status should be 404 + And [RETRIEVE] the response should contain an error message "Not Found" + + Scenario: Successfully retrieve user groups with valid filters + Given I have valid filters institutionId "9c8ae123-d990-4400-b043-67a60aff31bc" productId "prod-test" and status "ACTIVE" + When I send a GET request to "/v1/user-groups" to retrieve userGroups + Then [RETRIEVE] the response status should be 200 + And the response should contain 1 item + And the response should contain the group details + + Scenario: Successfully retrieve user groups without any filters + Given I have no filters + When I send a GET request to "/v1/user-groups" to retrieve userGroups + Then [RETRIEVE] the response status should be 200 + And the response should contain 3 item + And the response should contains groupIds "6759f8df78b6af202b222d29,6759f8df78b6af202b222d2a,6759f8df78b6af202b222d2b" + + Scenario: Attempt to retrieve user groups with a sorting parameter but no productId or institutionId + Given I have a filter with sorting by "name" but no filter + When I send a GET request to "/v1/user-groups" to retrieve userGroups + Then [RETRIEVE] the response status should be 400 + And [RETRIEVE] the response should contain an error message "Given sort parameters aren't valid" + + Scenario: Attempt to retrieve user groups with a sorting parameter but no productId or institutionId + Given I have a filter with sorting by "invalidSort" but no filter + When I send a GET request to "/v1/user-groups" to retrieve userGroups + Then [RETRIEVE] the response status should be 400 + And [RETRIEVE] the response should contain an error message "Given sort parameters aren't valid" + + Scenario: Attempt to retrieve user groups with status filter but no productId, institutionId, or userId + Given I have a filter with status "ACTIVE" but no productId, institutionId or userId + When I send a GET request to "/v1/user-groups" to retrieve userGroups + Then [RETRIEVE] the response status should be 400 + And [RETRIEVE] the response should contain an error message "At least one of productId, institutionId and userId must be provided with status filter" + + Scenario: Successfully retrieve a paginated list of user groups + Given I have no filters + And I set the page number to 0 and page size to 2 + When I send a GET request to "/v1/user-groups" to retrieve userGroups + Then [RETRIEVE] the response status should be 200 + And the response should contain a paginated list of user groups of 2 items on page 0 + + Scenario: Successfully retrieve a paginated list of user groups + Given I have no filters + And I set the page number to 1 and page size to 2 + When I send a GET request to "/v1/user-groups" to retrieve userGroups + Then [RETRIEVE] the response status should be 200 + And the response should contain a paginated list of user groups of 1 items on page 1 + + @LastRetrieveGroupScenario + Scenario: No user groups found for the provided filters + Given I have valid filters institutionId "9c8ae123-d990-4400-b043-67a60affabcd" productId "prod-test" and status "ACTIVE" + When I send a GET request to "/v1/user-groups" to retrieve userGroups + Then [RETRIEVE] the response status should be 200 + And the response should contain an empty list + diff --git a/apps/user-group-ms/src/test/resources/features/updateUserGroup.feature b/apps/user-group-ms/src/test/resources/features/updateUserGroup.feature new file mode 100644 index 00000000..8cc540d1 --- /dev/null +++ b/apps/user-group-ms/src/test/resources/features/updateUserGroup.feature @@ -0,0 +1,70 @@ +@FeatureUpdate +Feature: Update User Group + + @FirstUpdateScenario + Scenario: Successfully suspend a group with a valid ID + Given I have a valid group ID to update: "6759f8df78b6af202b222d29" + When I send a POST request to "/v1/user-groups/{groupId}/suspend" with authentication "true" + Then [UPDATE] the response status should be 204 + And the retrieved group should be changed status to "SUSPENDED" + + Scenario: Attempt to suspend a group with a non-existent ID + Given I have a non-existent group ID "99999" + When I send a POST request to "/v1/user-groups/{groupId}/suspend" with authentication "true" + Then [UPDATE] the response status should be 404 + And [UPDATE] the response should contain an error message "Not Found" + + Scenario: Successfully activate a group with a valid ID + Given I have a valid group ID to update: "6759f8df78b6af202b222d29" + When I send a POST request to "/v1/user-groups/{groupId}/activate" with authentication "true" + Then [UPDATE] the response status should be 204 + And the retrieved group should be changed status to "ACTIVE" + + Scenario: Attempt to activate a group with a non-existent ID + Given I have a non-existent group ID "99999" + When I send a POST request to "/v1/user-groups/{groupId}/activate" with authentication "true" + Then [UPDATE] the response status should be 404 + And [UPDATE] the response should contain an error message "Not Found" + + Scenario: Successfully delete a group with a valid ID + Given I have a valid group ID to update: "6759f8df78b6af202b222d29" + When I send a DELETE request to "/v1/user-groups/{groupId}" with authentication "true" + Then [UPDATE] the response status should be 204 + And the retrieved group should be changed status to "DELETED" + + Scenario: Attempt to delete a group with a non-existent ID + Given I have a non-existent group ID "99999" + When I send a DELETE request to "/v1/user-groups/{groupId}" with authentication "true" + Then [UPDATE] the response status should be 404 + And [UPDATE] the response should contain an error message "Not Found" + + Scenario: Successfully update a group with a valid ID and valid data + Given I have a valid group ID to update: "6759f8df78b6af202b222d29" + And I have data to update: + | name | description | members | + | updated Name | updatedDescription | 525db33f-967f-4a82-8984-c606225e714a,a1b7c86b-d195-41d8-8291-7c3467abfd30 | + When I send a PUT request to "/v1/user-groups/{groupId}" with authentication "true" + Then [UPDATE] the response status should be 200 + And the retrieved group should be updated + + Scenario: Attempt to update a non-existent group + Given I have a non-existent group ID "99999" + And I have data to update: + | name | description | members | + | Group Name | TestGroup | 525db33f-967f-4a82-8984-c606225e714a,a1b7c86b-d195-41d8-8291-7c3467abfd30 | + When I send a PUT request to "/v1/user-groups/{groupId}" with authentication "true" + Then [UPDATE] the response status should be 404 + And [UPDATE] the response should contain an error message "Not Found" + + @LastUpdateScenario + Scenario: Attempt to update a suspended group + Given I have a valid group ID to update: "6759f8df78b6af202b222d2a" + And I have data to update: + | name | description | members | + | Group Name | TestGroup | 525db33f-967f-4a82-8984-c606225e714a,a1b7c86b-d195-41d8-8291-7c3467abfd30 | + When I send a PUT request to "/v1/user-groups/{groupId}" with authentication "true" + Then [UPDATE] the response status should be 400 + And [UPDATE] the response should contain an error message "Trying to modify suspended group" + + + diff --git a/apps/user-group-ms/src/test/resources/features/userGroupMembers.feature b/apps/user-group-ms/src/test/resources/features/userGroupMembers.feature new file mode 100644 index 00000000..090af0e8 --- /dev/null +++ b/apps/user-group-ms/src/test/resources/features/userGroupMembers.feature @@ -0,0 +1,66 @@ +@FeatureMembers +Feature: User Group Members + + @FirstGroupMembersScenario + Scenario: Successfully add a member to a group + Given I have group ID "6759f8df78b6af202b222d29" and member ID "78bb7f07-0464-4ff9-a0ee-82568902b7bf" + When I send a PUT request to "/v1/user-groups/{id}/members/{memberId}" + Then [MEMBERS] the response status should be 204 + + Scenario: Attempt to add a member to a non-existent group + Given I have group ID "99999" and member ID "78bb7f07-0464-4ff9-a0ee-82568902b7bf" + When I send a PUT request to "/v1/user-groups/{id}/members/{memberId}" + Then [MEMBERS] the response status should be 404 + And [MEMBERS] the response should contain an error message "Not Found" + + Scenario: Attempt to add a member to a suspended group + Given I have group ID "6759f8df78b6af202b222d2b" and member ID "78bb7f07-0464-4ff9-a0ee-82568902b7bf" + When I send a PUT request to "/v1/user-groups/{id}/members/{memberId}" + Then [MEMBERS] the response status should be 400 + And [MEMBERS] the response should contain an error message "Trying to modify suspended group" + + Scenario: Successfully delete a member from a group + Given I have group ID "6759f8df78b6af202b222d29" and member ID "78bb7f07-0464-4ff9-a0ee-82568902b7bf" + When I send a DELETE request to "/v1/user-groups/{id}/members/{memberId}" + Then [MEMBERS] the response status should be 204 + + Scenario: Attempt to delete a member from a non-existent group + Given I have group ID "99999" and member ID "78bb7f07-0464-4ff9-a0ee-82568902b7bf" + When I send a DELETE request to "/v1/user-groups/{id}/members/{memberId}" + Then [MEMBERS] the response status should be 404 + And [MEMBERS] the response should contain an error message "Not Found" + + Scenario: Attempt to delete a member from a suspended group + Given I have group ID "6759f8df78b6af202b222d2b" and member ID "78bb7f07-0464-4ff9-a0ee-82568902b7bf" + When I send a DELETE request to "/v1/user-groups/{id}/members/{memberId}" + Then [MEMBERS] the response status should be 400 + And [MEMBERS] the response should contain an error message "Trying to modify suspended group" + + Scenario: Attempt to delete a member with non-existent member ID + Given I have group ID "6759f8df78b6af202b222d29" and member ID "f71dcad0-3374-4b51-91b8-75a9b36a5696" + When I send a DELETE request to "/v1/user-groups/{id}/members/{memberId}" + Then [MEMBERS] the response status should be 204 + + Scenario: Successfully delete a member from all groups associated with institutionId and productId + Given I have a member id "75003d64-7b8c-4768-b20c-cf66467d44c7", institution id "9c8ae123-d990-4400-b043-67a60aff31bc" and product id "prod-test" + When I send a DELETE request to "/v1/user-groups/members/{memberId}" with query parameters + Then [MEMBERS] the response status should be 204 + + Scenario: Attempt to delete a member with a missing institution ID + Given I have a member id "75003d64-7b8c-4768-b20c-cf66467d44c7" and product id "prod-test" + When I send a DELETE request to "/v1/user-groups/members/{memberId}" with query parameters + Then [MEMBERS] the response status should be 500 + And [MEMBERS] the response should contain an error message "A institution id is required" + + Scenario: Attempt to delete a member with a missing product ID + Given I have a member id "75003d64-7b8c-4768-b20c-cf66467d44c7" and institution id "9c8ae123-d990-4400-b043-67a60aff31bc" + When I send a DELETE request to "/v1/user-groups/members/{memberId}" with query parameters + Then [MEMBERS] the response status should be 500 + And [MEMBERS] the response should contain an error message "A product id is required" + + @LastGroupMembersScenario + Scenario: Attempt to delete a member who is not in any group associated with the given institutionId and productId + Given I have a member id "19017fde-142a-4e11-9498-a12a746d0f15", institution id "9c8ae123-d990-4400-b043-67a60aff31bc" and product id "prod-test" + When I send a DELETE request to "/v1/user-groups/members/{memberId}" with query parameters + Then [MEMBERS] the response status should be 204 + diff --git a/apps/user-group-ms/web/pom.xml b/apps/user-group-ms/web/pom.xml deleted file mode 100644 index 64f4a30a..00000000 --- a/apps/user-group-ms/web/pom.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - user-group-ms - it.pagopa.selfcare - 1.0.0-SNAPSHOT - - 4.0.0 - - user-group-ms-web - - - - it.pagopa.selfcare - selc-commons-web - - - it.pagopa.selfcare - selc-commons-web - test-jar - test - - - it.pagopa.selfcare - user-group-ms-core - - - io.springfox - springfox-boot-starter - - - - diff --git a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/validator/UserGroupControllerResponseValidatorTest.java b/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/validator/UserGroupControllerResponseValidatorTest.java deleted file mode 100644 index f1482767..00000000 --- a/apps/user-group-ms/web/src/test/java/it/pagopa/selfcare/user_group/web/validator/UserGroupControllerResponseValidatorTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package it.pagopa.selfcare.user_group.web.validator; - -import it.pagopa.selfcare.commons.web.validator.ControllerResponseValidator; -import it.pagopa.selfcare.commons.web.validator.PointcutControllerResponseValidatorBaseTest; -import it.pagopa.selfcare.user_group.web.controller.DummyController; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.SpyBean; -import org.springframework.context.annotation.EnableAspectJAutoProxy; - -@SpringBootTest(classes = { - ValidationAutoConfiguration.class, - DummyController.class, - UserGroupControllerResponseValidator.class -}) -@EnableAspectJAutoProxy -class UserGroupControllerResponseValidatorTest extends PointcutControllerResponseValidatorBaseTest { - @Autowired - private DummyController controller; - - @SpyBean - private UserGroupControllerResponseValidator validator; - - @Override - protected ControllerResponseValidator getValidatorSpy() { - return validator; - } - - @Override - protected void invokeNotVoidMethod() { - controller.notVoidMethod(); - } - - @Override - protected void invokeVoidMethod() { - controller.voidMethod(); - } -} \ No newline at end of file diff --git a/test-coverage/pom.xml b/test-coverage/pom.xml index 7656c10c..bd32a231 100644 --- a/test-coverage/pom.xml +++ b/test-coverage/pom.xml @@ -91,27 +91,7 @@ it.pagopa.selfcare - user-group-ms-app - 1.0.0-SNAPSHOT - - - it.pagopa.selfcare - user-group-ms-web - 1.0.0-SNAPSHOT - - - it.pagopa.selfcare - user-group-ms-core - 1.0.0-SNAPSHOT - - - it.pagopa.selfcare - user-group-ms-connector-dao - 1.0.0-SNAPSHOT - - - it.pagopa.selfcare - user-group-ms-connector-api + user-group-ms 1.0.0-SNAPSHOT