Skip to content

Commit 8d0691c

Browse files
[SELC-7738] feat: API to delete members from an UserGroup by institutionId, parentInstitutionId and productId (#304)
1 parent 7df54d7 commit 8d0691c

File tree

15 files changed

+418
-12
lines changed

15 files changed

+418
-12
lines changed

apps/user-group-ms/src/main/docs/openapi.json

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,59 @@
285285
"security" : [ {
286286
"bearerAuth" : [ "global" ]
287287
} ]
288+
},
289+
"delete" : {
290+
"tags" : [ "UserGroup", "internal-v1" ],
291+
"summary" : "deleteMembersFromUserGroupWithParentInstitutionId",
292+
"description" : "Service to delete members from a specific UserGroup entity by its institutionId, parentInstitutionId and productId",
293+
"operationId" : "deleteMembersFromUserGroupWithParentInstitutionIdUsingDELETE",
294+
"requestBody" : {
295+
"content" : {
296+
"application/json" : {
297+
"schema" : {
298+
"$ref" : "#/components/schemas/DeleteMembersFromUserGroupDto"
299+
}
300+
}
301+
}
302+
},
303+
"responses" : {
304+
"204" : {
305+
"description" : "No Content"
306+
},
307+
"400" : {
308+
"description" : "Bad Request",
309+
"content" : {
310+
"application/problem+json" : {
311+
"schema" : {
312+
"$ref" : "#/components/schemas/Problem"
313+
}
314+
}
315+
}
316+
},
317+
"401" : {
318+
"description" : "Unauthorized",
319+
"content" : {
320+
"application/problem+json" : {
321+
"schema" : {
322+
"$ref" : "#/components/schemas/Problem"
323+
}
324+
}
325+
}
326+
},
327+
"500" : {
328+
"description" : "Internal Server Error",
329+
"content" : {
330+
"application/problem+json" : {
331+
"schema" : {
332+
"$ref" : "#/components/schemas/Problem"
333+
}
334+
}
335+
}
336+
}
337+
},
338+
"security" : [ {
339+
"bearerAuth" : [ "global" ]
340+
} ]
288341
}
289342
},
290343
"/v1/user-groups/members/{memberId}" : {
@@ -883,6 +936,34 @@
883936
}
884937
}
885938
},
939+
"DeleteMembersFromUserGroupDto" : {
940+
"title" : "DeleteMembersFromUserGroupDto",
941+
"required" : [ "institutionId", "members", "parentInstitutionId", "productId" ],
942+
"type" : "object",
943+
"properties" : {
944+
"institutionId" : {
945+
"type" : "string",
946+
"description" : "Users group's institutionId"
947+
},
948+
"members" : {
949+
"uniqueItems" : true,
950+
"type" : "array",
951+
"description" : "List of all the members of the group",
952+
"items" : {
953+
"type" : "string",
954+
"format" : "uuid"
955+
}
956+
},
957+
"parentInstitutionId" : {
958+
"type" : "string",
959+
"description" : "Users group's parent institutionId"
960+
},
961+
"productId" : {
962+
"type" : "string",
963+
"description" : "Users group's productId"
964+
}
965+
}
966+
},
886967
"InvalidParam" : {
887968
"title" : "InvalidParam",
888969
"required" : [ "name", "reason" ],

apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/controller/UserGroupV1Controller.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,4 +242,19 @@ public void addMembersToUserGroupWithParentInstitutionId(@RequestBody
242242
log.trace("addMemberToUserGroup end");
243243
}
244244

245+
@DeleteMapping(value = "/members", produces = MediaType.ALL_VALUE)
246+
@ResponseStatus(HttpStatus.NO_CONTENT)
247+
@Tag(name = "UserGroup")
248+
@Tag(name = "internal-v1")
249+
@ApiOperation(value = "", notes = "${swagger.user-group.groups.api.deleteMembersWithParentInstitutionId}")
250+
public void deleteMembersFromUserGroupWithParentInstitutionId(@RequestBody
251+
@Valid
252+
DeleteMembersFromUserGroupDto deleteMembersFromUserGroupDto) {
253+
log.trace("deleteMembersFromUserGroupWithParentInstitutionId start");
254+
log.debug("deleteMembersFromUserGroupWithParentInstitutionId institutionId = {}, parentInstitutionId = {}, productId = {}",
255+
Encode.forJava(deleteMembersFromUserGroupDto.getInstitutionId()), Encode.forJava(deleteMembersFromUserGroupDto.getParentInstitutionId()), Encode.forJava(deleteMembersFromUserGroupDto.getProductId()));
256+
groupService.deleteMembersWithParentInstitutionId(deleteMembersFromUserGroupDto.getInstitutionId(), deleteMembersFromUserGroupDto.getParentInstitutionId(), deleteMembersFromUserGroupDto.getProductId(), deleteMembersFromUserGroupDto.getMembers());
257+
log.trace("deleteMembersFromUserGroupWithParentInstitutionId end");
258+
}
259+
245260
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package it.pagopa.selfcare.user_group.model;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import io.swagger.annotations.ApiModelProperty;
5+
import lombok.Data;
6+
7+
import javax.validation.constraints.NotBlank;
8+
import javax.validation.constraints.NotEmpty;
9+
import java.util.Set;
10+
import java.util.UUID;
11+
12+
@Data
13+
public class DeleteMembersFromUserGroupDto {
14+
15+
@ApiModelProperty(value = "${swagger.user-group.model.institutionId}", required = true)
16+
@JsonProperty(required = true)
17+
@NotBlank
18+
private String institutionId;
19+
20+
@ApiModelProperty(value = "${swagger.user-group.model.parentInstitutionId}", required = true)
21+
@JsonProperty(required = true)
22+
@NotBlank
23+
private String parentInstitutionId;
24+
25+
@ApiModelProperty(value = "${swagger.user-group.model.productId}", required = true)
26+
@JsonProperty(required = true)
27+
@NotBlank
28+
private String productId;
29+
30+
@ApiModelProperty(value = "${swagger.user-group.model.members}", required = true)
31+
@JsonProperty(required = true)
32+
@NotEmpty
33+
private Set<UUID> members;
34+
35+
}

apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/service/UserGroupService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ public interface UserGroupService {
1616

1717
void addMembers(String institutionId, String parentInstitutionId, String productId, Set<UUID> members);
1818

19+
void deleteMembersWithParentInstitutionId(String institutionId, String parentInstitutionId, String productId, Set<UUID> members);
20+
1921
void deleteMember(String groupId, String memberId);
2022

2123
void deleteMembers(String userId, String institutionId, String memberId);

apps/user-group-ms/src/main/java/it/pagopa/selfcare/user_group/service/UserGroupServiceImpl.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,24 @@ public void addMembers(String institutionId, String parentInstitutionId, String
106106
log.trace("addMembers end");
107107
}
108108

109+
@Override
110+
public void deleteMembersWithParentInstitutionId(String institutionId, String parentInstitutionId, String productId, Set<UUID> members) {
111+
log.trace("deleteMembersWithParentInstitutionId start");
112+
log.debug("deleteMembersWithParentInstitutionId institutionId = {}, parentInstitutionId = {}, members = {}",
113+
Encode.forJava(institutionId), Encode.forJava(parentInstitutionId), Encode.forJava(members.toString()));
114+
Assert.notNull(institutionId, USER_GROUP_INSTITUTION_ID_REQUIRED_MESSAGE);
115+
Assert.notNull(parentInstitutionId, USER_GROUP_PARENT_INSTITUTION_ID_REQUIRED_MESSAGE);
116+
Assert.notNull(members, MEMBERS_REQUIRED);
117+
UserGroupFilter userGroupFilter = UserGroupFilter.builder()
118+
.institutionId(institutionId)
119+
.parentInstitutionId(parentInstitutionId)
120+
.productId(productId)
121+
.build();
122+
String groupId = findGroupId(userGroupFilter);
123+
removeMembersWithParentInstitutionId(groupId, members);
124+
log.trace("deleteMembersWithParentInstitutionId end");
125+
}
126+
109127

110128
@Override
111129
public void deleteMember(String groupId, String memberId) {
@@ -305,6 +323,29 @@ private void insertMembers(String id, Set<UUID> memberIds) {
305323
log.trace("insertMembers end");
306324
}
307325

326+
private void removeMembersWithParentInstitutionId(String id, Set<UUID> memberIds) {
327+
log.trace("removeMembersWithParentInstitutionId start");
328+
log.debug("removeMembersWithParentInstitutionId id = {}, memberIds = {}", Encode.forJava(id), Encode.forJava(memberIds.toString()));
329+
330+
Object[] userIdsAsStrings = memberIds.stream()
331+
.map(UUID::toString)
332+
.toArray();
333+
334+
UpdateResult updateResult = mongoTemplate.updateFirst(
335+
createActiveGroupQuery(id),
336+
new Update()
337+
.pullAll(UserGroupEntity.Fields.members, userIdsAsStrings)
338+
.set(UserGroupEntity.Fields.modifiedBy, auditorAware.getCurrentAuditor().orElse(null))
339+
.currentDate(UserGroupEntity.Fields.modifiedAt),
340+
UserGroupEntity.class);
341+
342+
if (updateResult.getModifiedCount() == 0) {
343+
log.warn("No member to delete from UserGroup");
344+
}
345+
346+
log.trace("removeMembersWithParentInstitutionId end");
347+
}
348+
308349

309350
private void removeMemberFromActiveGroup(String id, String memberId) {
310351
log.trace("deleteMember start");

apps/user-group-ms/src/main/resources/swagger/swagger_en.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ swagger.user-group.groups.api.addMember=Service to add a member to a specific Us
1515
swagger.user-group.groups.api.addMembers=Service to add a members to a specific UserGroup entity by its institutionId, parentInstitutionId and productId
1616
swagger.user-group.groups.api.deleteMember=Service to delete a member from a specific UserGroup entity
1717
swagger.user-group.groups.api.deleteMembers=Service to delete a member from every group of a specific product of an institution
18+
swagger.user-group.groups.api.deleteMembersWithParentInstitutionId=Service to delete members from a specific UserGroup entity by its institutionId, parentInstitutionId and productId
1819
swagger.user-group.model.id=Users group's unique identifier
1920
swagger.user-group.model.institutionId=Users group's institutionId
2021
swagger.user-group.model.parentInstitutionId=Users group's parent institutionId

apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/controller/UserGroupV1ControllerTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ class UserGroupV1ControllerTest {
5050
private static final DummyCreateUserGroupDto CREATE_USER_GROUP_DTO = mockInstance(new DummyCreateUserGroupDto());
5151
private static final DummyUpdateUserGroupDto UPDATE_USER_GROUP_DTO = mockInstance(new DummyUpdateUserGroupDto());
5252
private static final DummyAddMembersToUserGroupDto ADD_MEMBERS_TO_USER_GROUP_DTO = mockInstance(new DummyAddMembersToUserGroupDto());
53+
54+
private static final DummyDeleteMembersFromUserGroupDto DELETE_MEMBERS_FROM_USER_GROUP_DTO = mockInstance(new DummyDeleteMembersFromUserGroupDto());
55+
5356
private static final String BASE_URL = "/v1/user-groups";
5457

5558
@MockBean
@@ -385,4 +388,24 @@ void addMembers() throws Exception {
385388
Mockito.verifyNoMoreInteractions(groupServiceMock);
386389
}
387390

391+
@Test
392+
void deleteMembersWithParentInstitutionId() throws Exception {
393+
394+
//when
395+
MvcResult result = mvc.perform(MockMvcRequestBuilders
396+
.delete(BASE_URL + "/members")
397+
.content(mapper.writeValueAsString(DELETE_MEMBERS_FROM_USER_GROUP_DTO))
398+
.contentType(APPLICATION_JSON_VALUE)
399+
.accept(APPLICATION_JSON_VALUE))
400+
.andExpect(status().is2xxSuccessful())
401+
.andReturn();
402+
//then
403+
assertEquals(0, result.getResponse().getContentLength());
404+
verify(groupServiceMock, times(1))
405+
.deleteMembersWithParentInstitutionId(anyString(), anyString(), anyString(), anySet());
406+
Mockito.verifyNoMoreInteractions(groupServiceMock);
407+
}
408+
409+
410+
388411
}

apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/RetrieveUserGroupSteps.java

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import io.restassured.response.ResponseOptions;
1515
import io.restassured.specification.RequestSpecification;
1616
import it.pagopa.selfcare.user_group.model.AddMembersToUserGroupDto;
17+
import it.pagopa.selfcare.user_group.model.DeleteMembersFromUserGroupDto;
1718
import it.pagopa.selfcare.user_group.model.UserGroupEntity;
1819
import it.pagopa.selfcare.user_group.model.UserGroupStatus;
1920
import org.junit.jupiter.api.Assertions;
@@ -55,6 +56,23 @@ public AddMembersToUserGroupDto convertAddMembersRequest(Map<String, String> ent
5556
return request;
5657
}
5758

59+
@DataTableType
60+
public DeleteMembersFromUserGroupDto convertDeleteMembersRequest(Map<String, String> entry) {
61+
DeleteMembersFromUserGroupDto request = new DeleteMembersFromUserGroupDto();
62+
request.setInstitutionId(entry.get("institutionId"));
63+
request.setParentInstitutionId(entry.get("parentInstitutionId"));
64+
request.setProductId(entry.get("productId"));
65+
66+
Set<UUID> members = Optional.ofNullable(entry.get("members"))
67+
.map(s -> Arrays.stream(s.split(","))
68+
.map(UUID::fromString)
69+
.collect(Collectors.toSet()))
70+
.orElse(Set.of());
71+
request.setMembers(members);
72+
73+
return request;
74+
}
75+
5876

5977
@Override
6078
@Then("[RETRIEVE] the response status should be {int}")
@@ -195,8 +213,8 @@ public void the_response_should_contain_the_group_details_with_parent_institutio
195213
@And("the response should contain a paginated list of user groups of {int} items on page {int}")
196214
public void theResponseShouldContainAPaginatedListOfUserGroups(int count, int page) {
197215
Assertions.assertEquals(count, userGroupEntityResponsePage.getContent().size());
198-
Assertions.assertEquals(4, userGroupEntityResponsePage.getTotalElements());
199-
Assertions.assertEquals(2, userGroupEntityResponsePage.getTotalPages());
216+
Assertions.assertEquals(5, userGroupEntityResponsePage.getTotalElements());
217+
Assertions.assertEquals(3, userGroupEntityResponsePage.getTotalPages());
200218
Assertions.assertEquals(2, userGroupEntityResponsePage.getSize());
201219
Assertions.assertEquals(page, userGroupEntityResponsePage.getNumber());
202220
}
@@ -239,10 +257,11 @@ public void theResponseShouldContainOneItem(int expectedItemsCount) {
239257
Assertions.assertEquals(expectedItemsCount, userGroupEntityResponsePage.getContent().size());
240258
}
241259

242-
@Then("the response should contain all members")
243-
public void the_response_should_contain_all_members() {
244-
Assertions.assertEquals(3, userGroupEntityResponse.getMembers().size());
245-
Assertions.assertEquals("[525db33f-967f-4a82-8984-c606225e714a, 75003d64-7b8c-4768-b20c-cf66467d44c7, a1b7c86b-d195-41d8-8291-7c3467abfd30]", userGroupEntityResponse.getMembers().toString());
260+
@Then("the response should contain the following list of members:")
261+
public void the_response_should_contain_all_members(List<String> expectedValues) {
262+
Set<String> expectedMembers = new HashSet<>(expectedValues);
263+
Set<String> actualMembers = userGroupEntityResponse.getMembers();
264+
Assertions.assertEquals(expectedMembers, actualMembers);
246265
}
247266

248267
@Then("I should receive a response of retrieve user group operation with status code {int}")

apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/UserGroupMemberSteps.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
import io.restassured.response.ResponseOptions;
1212
import io.restassured.specification.RequestSpecification;
1313
import it.pagopa.selfcare.user_group.model.AddMembersToUserGroupDto;
14+
import it.pagopa.selfcare.user_group.model.DeleteMembersFromUserGroupDto;
1415
import it.pagopa.selfcare.user_group.model.UserGroupEntity;
1516
import org.apache.commons.lang3.StringUtils;
16-
import org.junit.jupiter.api.Assertions;
1717

1818
import java.io.IOException;
1919
import java.util.List;
@@ -83,6 +83,12 @@ public void givenAddMembersToUserGroupRequestDetails(List<AddMembersToUserGroupD
8383
this.addMembersRequest = addMembersToUserGroupDtos.get(0);
8484
}
8585

86+
@Given("the following members to delete from user group request details:")
87+
public void givenMembersToDeleteFromUserGroupRequestDetails(List<DeleteMembersFromUserGroupDto> deleteMembersFromUserGroupDtos) {
88+
if (deleteMembersFromUserGroupDtos != null && deleteMembersFromUserGroupDtos.size() == 1)
89+
this.deleteMembersRequest = deleteMembersFromUserGroupDtos.get(0);
90+
}
91+
8692
@When("I send a PUT request to {string}")
8793
public void iSendAPutRequestTo(String url) {
8894
ResponseOptions<Response> response = RestAssured.given()
@@ -123,6 +129,28 @@ public void iSendAPUTRequestToAddMembers(String url) {
123129
}
124130
}
125131

132+
@When("I send a DELETE request to {string} to delete members from a group")
133+
public void iSendADELETERequestToDeleteMembers(String url) {
134+
RequestSpecification requestSpecification = RestAssured.given()
135+
.contentType("application/json");
136+
137+
if(StringUtils.isNotBlank(token)){
138+
requestSpecification.header("Authorization", "Bearer " + token);
139+
}
140+
141+
ExtractableResponse<?> response = requestSpecification
142+
.body(deleteMembersRequest)
143+
.when()
144+
.delete(url)
145+
.then()
146+
.extract();
147+
148+
status = response.statusCode();
149+
if(status != 204) {
150+
errorMessage = response.body().asString();
151+
}
152+
}
153+
126154
@When("[MEMBERS] I send a DELETE request to {string}")
127155
public void iSendADELETERequestTo(String url) {
128156
ResponseOptions<Response> response = RestAssured.given()

apps/user-group-ms/src/test/java/it/pagopa/selfcare/user_group/integration_test/steps/UserGroupSteps.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import it.pagopa.selfcare.user_group.dao.UserGroupRepository;
1010
import it.pagopa.selfcare.user_group.integration_test.KeyGenerator;
1111
import it.pagopa.selfcare.user_group.model.AddMembersToUserGroupDto;
12+
import it.pagopa.selfcare.user_group.model.DeleteMembersFromUserGroupDto;
1213
import it.pagopa.selfcare.user_group.model.UserGroupEntity;
1314
import it.pagopa.selfcare.user_group.model.UserGroupEntityPageable;
1415
import lombok.extern.slf4j.Slf4j;
@@ -41,11 +42,12 @@ public class UserGroupSteps {
4142
protected UserGroupEntity updatedUserGroupEntity;
4243
protected UserGroupEntityPageable userGroupEntityResponsePage;
4344
protected AddMembersToUserGroupDto addMembersRequest;
45+
protected DeleteMembersFromUserGroupDto deleteMembersRequest;
4446
protected Pageable pageable;
4547
protected UserGroupEntity userGroupEntityFilter;
4648
protected int status;
4749
protected String errorMessage;
48-
protected List<String> userGroupsIds = List.of("6759f8df78b6af202b222d29", "6759f8df78b6af202b222d2a", "6759f8df78b6af202b222d2b", "6759f8df78b6af202b222d2c");
50+
protected List<String> userGroupsIds = List.of("6759f8df78b6af202b222d29", "6759f8df78b6af202b222d2a", "6759f8df78b6af202b222d2b", "6759f8df78b6af202b222d2c", "6759f8df78b6af202b222d2d");
4951
protected String token;
5052

5153
protected void login(String user, String pass) {

0 commit comments

Comments
 (0)