Skip to content

Commit

Permalink
[SELC-5956] feat: added check of uniqueness group name in creation an…
Browse files Browse the repository at this point in the history
…d editing api (#216)
  • Loading branch information
empassaro authored Nov 7, 2024
1 parent e41c42e commit a855fb0
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ public class ResourceAlreadyExistsException extends RuntimeException {
public ResourceAlreadyExistsException(String msg, Throwable cause) {
super(msg, cause);
}

public ResourceAlreadyExistsException(String msg) {
super(msg);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
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;
Expand Down Expand Up @@ -31,6 +32,7 @@ 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<String> allowedSortingParams;

@Autowired
Expand All @@ -49,12 +51,28 @@ public UserGroupOperations createGroup(UserGroupOperations group) {
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<UserGroupOperations> 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) {
Expand Down Expand Up @@ -160,6 +178,8 @@ public UserGroupOperations updateGroup(String id, UserGroupOperations group) {
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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
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;
Expand Down Expand Up @@ -33,8 +34,6 @@

import javax.validation.ValidationException;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.UUID.randomUUID;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
Expand Down Expand Up @@ -117,10 +116,10 @@ void createGroup_ok() {
.build();
TestingAuthenticationToken authenticationToken = new TestingAuthenticationToken(selfCareUser, null);
TestSecurityContextHolder.setAuthentication(authenticationToken);
Set<UUID> members = Set.of(randomUUID(), randomUUID());
UserGroupOperations input = TestUtils.mockInstance(new DummyGroup(), "setId", "setCreateAt", "setModifiedAt");
input.setId("id");
input.setMembers(members.stream().map(UUID::toString).collect(Collectors.toSet()));
Page<UserGroupOperations> 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
Expand All @@ -130,6 +129,39 @@ void createGroup_ok() {

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("[email protected]")
.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<UserGroupOperations> 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);
}

Expand Down Expand Up @@ -266,28 +298,106 @@ void updateGroup_notExists() {
}

@Test
void updateGroup_exists() {
void updateGroup_exists_ok() {
//given
String id = "id";
UserGroupOperations group = TestUtils.mockInstance(new DummyGroup(), "setId");
UserGroupOperations foundGroup = TestUtils.mockInstance(new DummyGroup());
Page<UserGroupOperations> 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<UserGroupOperations> 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<UserGroupOperations> 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
Expand Down

0 comments on commit a855fb0

Please sign in to comment.