Skip to content

Commit 6dc4301

Browse files
[SELC-7128] feat: add new API checkUser (#269)
1 parent 37921f2 commit 6dc4301

File tree

15 files changed

+448
-29
lines changed

15 files changed

+448
-29
lines changed

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

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,93 @@
164164
} ]
165165
}
166166
},
167+
"/institutions/{institutionId}/product/{productId}/check-user" : {
168+
"post" : {
169+
"tags" : [ "Institution" ],
170+
"summary" : "Verify if a user is already onboarded on an institution and product given its fiscal code",
171+
"description" : "Verify if a user is already onboarded on an institution and product given its fiscal code",
172+
"operationId" : "checkUserUsingPOST",
173+
"parameters" : [ {
174+
"name" : "institutionId",
175+
"in" : "path",
176+
"required" : true,
177+
"schema" : {
178+
"type" : "string"
179+
}
180+
}, {
181+
"name" : "productId",
182+
"in" : "path",
183+
"required" : true,
184+
"schema" : {
185+
"type" : "string"
186+
}
187+
} ],
188+
"requestBody" : {
189+
"content" : {
190+
"application/json" : {
191+
"schema" : {
192+
"$ref" : "#/components/schemas/SearchUserDto"
193+
}
194+
}
195+
}
196+
},
197+
"responses" : {
198+
"200" : {
199+
"description" : "OK",
200+
"content" : {
201+
"application/json" : {
202+
"schema" : {
203+
"type" : "boolean"
204+
}
205+
}
206+
}
207+
},
208+
"400" : {
209+
"description" : "Bad Request",
210+
"content" : {
211+
"application/problem+json" : {
212+
"schema" : {
213+
"$ref" : "#/components/schemas/Problem"
214+
}
215+
}
216+
}
217+
},
218+
"401" : {
219+
"description" : "Not Authorized",
220+
"content" : {
221+
"application/problem+json" : {
222+
"schema" : {
223+
"$ref" : "#/components/schemas/Problem"
224+
}
225+
}
226+
}
227+
},
228+
"403" : {
229+
"description" : "Forbidden",
230+
"content" : {
231+
"application/problem+json" : {
232+
"schema" : {
233+
"$ref" : "#/components/schemas/Problem"
234+
}
235+
}
236+
}
237+
},
238+
"404" : {
239+
"description" : "Not Found",
240+
"content" : {
241+
"application/problem+json" : {
242+
"schema" : {
243+
"$ref" : "#/components/schemas/Problem"
244+
}
245+
}
246+
}
247+
}
248+
},
249+
"security" : [ {
250+
"SecurityScheme" : [ ]
251+
} ]
252+
}
253+
},
167254
"/institutions/{institutionId}/products/{productId}/created-at" : {
168255
"put" : {
169256
"tags" : [ "Institution" ],

apps/user-ms/src/main/docs/openapi.yaml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,64 @@ paths:
118118
description: Not Allowed
119119
security:
120120
- SecurityScheme: []
121+
/institutions/{institutionId}/product/{productId}/check-user:
122+
post:
123+
tags:
124+
- Institution
125+
summary: Verify if a user is already onboarded on an institution and product
126+
given its fiscal code
127+
description: Verify if a user is already onboarded on an institution and product
128+
given its fiscal code
129+
operationId: checkUserUsingPOST
130+
parameters:
131+
- name: institutionId
132+
in: path
133+
required: true
134+
schema:
135+
type: string
136+
- name: productId
137+
in: path
138+
required: true
139+
schema:
140+
type: string
141+
requestBody:
142+
content:
143+
application/json:
144+
schema:
145+
$ref: "#/components/schemas/SearchUserDto"
146+
responses:
147+
"200":
148+
description: OK
149+
content:
150+
application/json:
151+
schema:
152+
type: boolean
153+
"400":
154+
description: Bad Request
155+
content:
156+
application/problem+json:
157+
schema:
158+
$ref: "#/components/schemas/Problem"
159+
"401":
160+
description: Not Authorized
161+
content:
162+
application/problem+json:
163+
schema:
164+
$ref: "#/components/schemas/Problem"
165+
"403":
166+
description: Forbidden
167+
content:
168+
application/problem+json:
169+
schema:
170+
$ref: "#/components/schemas/Problem"
171+
"404":
172+
description: Not Found
173+
content:
174+
application/problem+json:
175+
schema:
176+
$ref: "#/components/schemas/Problem"
177+
security:
178+
- SecurityScheme: []
121179
/institutions/{institutionId}/products/{productId}/created-at:
122180
put:
123181
tags:

apps/user-ms/src/main/java/it/pagopa/selfcare/user/controller/InstitutionController.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import it.pagopa.selfcare.user.controller.response.UserInstitutionResponse;
1010
import it.pagopa.selfcare.user.controller.response.UserProductResponse;
1111
import it.pagopa.selfcare.user.controller.response.UsersCountResponse;
12+
import it.pagopa.selfcare.user.controller.response.product.SearchUserDto;
1213
import it.pagopa.selfcare.user.model.constants.OnboardedProductState;
1314
import it.pagopa.selfcare.user.service.UserService;
1415
import it.pagopa.selfcare.user.util.GeneralUtils;
@@ -145,4 +146,25 @@ public Uni<DeletedUserCountResponse> deleteUserInstitutionProductUsers(@PathPara
145146
productId.replaceAll("[^a-zA-Z0-9-_]", ""));
146147
}
147148

149+
@Operation(
150+
summary = "Verify if a user is already onboarded on an institution and product given its fiscal code",
151+
operationId = "checkUserUsingPOST",
152+
description = "Verify if a user is already onboarded on an institution and product given its fiscal code"
153+
)
154+
@APIResponses(value = {
155+
@APIResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = Boolean.class), mediaType = "application/json")),
156+
@APIResponse(responseCode = "400", description = "Bad Request", content = @Content(schema = @Schema(implementation = Problem.class), mediaType = "application/problem+json")),
157+
@APIResponse(responseCode = "401", description = "Not Authorized", content = @Content(schema = @Schema(implementation = Problem.class), mediaType = "application/problem+json")),
158+
@APIResponse(responseCode = "403", description = "Forbidden", content = @Content(schema = @Schema(implementation = Problem.class), mediaType = "application/problem+json")),
159+
@APIResponse(responseCode = "404", description = "Not Found", content = @Content(schema = @Schema(implementation = Problem.class), mediaType = "application/problem+json"))
160+
})
161+
@POST
162+
@Path(value = "/{institutionId}/product/{productId}/check-user")
163+
@Produces(MediaType.APPLICATION_JSON)
164+
public Uni<Boolean> checkUser(@PathParam(value = "institutionId") String institutionId,
165+
@PathParam(value = "productId") String productId,
166+
@Valid SearchUserDto searchUserDto) {
167+
return userService.checkUser(searchUserDto.getFiscalCode(), institutionId, productId);
168+
}
169+
148170
}
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
package it.pagopa.selfcare.user.controller.response.product;
22

33
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import jakarta.validation.constraints.NotNull;
45
import lombok.AllArgsConstructor;
56
import lombok.Getter;
67
import lombok.NoArgsConstructor;
78

8-
import javax.validation.constraints.NotNull;
9-
109
@AllArgsConstructor
1110
@NoArgsConstructor
1211
@Getter
1312
public class SearchUserDto {
1413
@JsonProperty(required = true)
15-
@NotNull
14+
@NotNull(message = "Fiscal code is required")
1615
private String fiscalCode;
1716
}

apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public interface UserInstitutionService {
4545

4646
Uni<UserInstitution> persistOrUpdate(UserInstitution userInstitution);
4747

48-
Uni<Boolean> existsValidUserProduct(String userId, String institutionId, String productId, PermissionTypeEnum permission);
48+
Uni<Boolean> existsValidUserProduct(String userId, String institutionId, String productId, PermissionTypeEnum permission, List<OnboardedProductState> status);
4949

5050
Uni<Long> updateInstitutionDescription(String institutionId, UpdateDescriptionDto updateDescriptionDto);
5151

apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionServiceDefault.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,10 +240,10 @@ public Uni<UserInstitution> persistOrUpdate(UserInstitution userInstitution) {
240240
}
241241

242242
@Override
243-
public Uni<Boolean> existsValidUserProduct(String userId, String institutionId, String productId, PermissionTypeEnum permission) {
243+
public Uni<Boolean> existsValidUserProduct(String userId, String institutionId, String productId, PermissionTypeEnum permission, List<OnboardedProductState> status) {
244244

245245
Map<String, Object> userInstitutionFilterMap = UserInstitutionFilter.builder().userId(userId).institutionId(institutionId).build().constructMap();
246-
OnboardedProductFilter.OnboardedProductFilterBuilder builder = OnboardedProductFilter.builder().productId(productId).status(List.of(ACTIVE, PENDING, TOBEVALIDATED));
246+
OnboardedProductFilter.OnboardedProductFilterBuilder builder = OnboardedProductFilter.builder().productId(productId).status(status);
247247
if (permission.equals(PermissionTypeEnum.ADMIN)) {
248248
builder.role(SelfCareRole.fromSelfCareAuthority(permission.name()));
249249
}

apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserPermissionServiceImpl.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
import lombok.RequiredArgsConstructor;
77
import lombok.extern.slf4j.Slf4j;
88

9+
import java.util.List;
10+
11+
import static it.pagopa.selfcare.user.model.constants.OnboardedProductState.*;
12+
913
@Slf4j
1014
@ApplicationScoped
1115
@RequiredArgsConstructor
@@ -18,6 +22,6 @@ public Uni<Boolean> hasPermission(String institutionId, String productId, Permis
1822
log.trace("hasPermission start");
1923
log.debug("check permission {} for userId: {}, institutionId: {} and productId: {}", permission, userId, institutionId, productId);
2024

21-
return userInstitutionService.existsValidUserProduct(userId, institutionId, productId, permission);
25+
return userInstitutionService.existsValidUserProduct(userId, institutionId, productId, permission, List.of(ACTIVE, PENDING, TOBEVALIDATED));
2226
}
2327
}

apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,6 @@ public interface UserService {
6363
Uni<UserInstitutionWithActions> getUserInstitutionWithPermission(String userId, String institutionId, String productId);
6464

6565
Uni<UsersCountResponse> getUsersCount(String institutionId, String productId, List<PartyRole> roles, List<OnboardedProductState> status);
66+
67+
Uni<Boolean> checkUser(String fiscalCode, String institutionId, String productId);
6668
}

apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserServiceImpl.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import it.pagopa.selfcare.onboarding.common.PartyRole;
88
import it.pagopa.selfcare.product.entity.Product;
99
import it.pagopa.selfcare.product.service.ProductService;
10+
import it.pagopa.selfcare.user.constant.PermissionTypeEnum;
1011
import it.pagopa.selfcare.user.controller.request.AddUserRoleDto;
1112
import it.pagopa.selfcare.user.controller.request.CreateUserDto;
1213
import it.pagopa.selfcare.user.controller.request.UpdateDescriptionDto;
@@ -34,6 +35,7 @@
3435
import it.pagopa.selfcare.user.util.ActionMapRetriever;
3536
import it.pagopa.selfcare.user.util.UserUtils;
3637
import jakarta.enterprise.context.ApplicationScoped;
38+
import jakarta.ws.rs.WebApplicationException;
3739
import lombok.RequiredArgsConstructor;
3840
import lombok.extern.slf4j.Slf4j;
3941
import org.apache.commons.lang3.StringUtils;
@@ -85,13 +87,10 @@ public class UserServiceImpl implements UserService {
8587
private final ActionMapRetriever actionMapRetriever;
8688

8789
Supplier<String> randomMailId = () -> (MAIL_ID_PREFIX + UUID.randomUUID());
88-
8990
private static final String WORK_CONTACTS = "workContacts";
90-
9191
static final String USERS_WORKS_FIELD_LIST = "fiscalCode,familyName,email,name,workContacts";
92-
9392
public static final String USERS_FIELD_LIST_WITHOUT_FISCAL_CODE = "name,familyName,email,workContacts";
94-
93+
public static final String USER_FIELD_LIST_WITHOUT_WORK_CONTACTS = "name,familyName,fiscalCode";
9594
private static final String USER_INSTITUTION_FOUNDED = "UserInstitution with userId: {} and institutionId: {} founded";
9695
private static final String USER_INSTITUTION_NOT_FOUND = "UserInstitution with userId: {} and institutionId: {} not found";
9796

@@ -853,4 +852,22 @@ public Uni<UsersCountResponse> getUsersCount(String institutionId, String produc
853852
.onItem().transform(count -> new UsersCountResponse(institutionId, productId, roleList, statusList, count));
854853
}
855854

855+
@Override
856+
public Uni<Boolean> checkUser(String fiscalCode, String institutionId, String productId) {
857+
return userRegistryService.searchUsingPOST(USER_FIELD_LIST_WITHOUT_WORK_CONTACTS, new UserSearchDto(fiscalCode))
858+
.flatMap(user -> userInstitutionService.existsValidUserProduct(
859+
user.getId().toString(),
860+
institutionId,
861+
productId,
862+
PermissionTypeEnum.ANY,
863+
List.of(ACTIVE,SUSPENDED)
864+
))
865+
.onFailure(this::isNotFound)
866+
.recoverWithItem(false);
867+
}
868+
869+
private boolean isNotFound(Throwable throwable) {
870+
return ((WebApplicationException) throwable).getResponse().getStatus() == 404;
871+
}
872+
856873
}

apps/user-ms/src/test/java/it/pagopa/selfcare/user/controller/InstitutionControllerTest.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import it.pagopa.selfcare.user.controller.response.UserInstitutionResponse;
1414
import it.pagopa.selfcare.user.controller.response.UserProductResponse;
1515
import it.pagopa.selfcare.user.controller.response.UsersCountResponse;
16+
import it.pagopa.selfcare.user.controller.response.product.SearchUserDto;
1617
import it.pagopa.selfcare.user.exception.ResourceNotFoundException;
1718
import it.pagopa.selfcare.user.model.constants.OnboardedProductState;
1819
import it.pagopa.selfcare.user.service.UserService;
@@ -286,4 +287,42 @@ void deleteUserInstitutionProductUsers_NotAuthorized() {
286287
.statusCode(401);
287288
}
288289

290+
@Test
291+
@TestSecurity(user = "userJwt")
292+
void checkUser() {
293+
final String fiscalCode = "fiscalCode";
294+
final String institutionId = "institutionId";
295+
final String productId = "productId";
296+
297+
Mockito.when(userService.checkUser(fiscalCode, institutionId, productId))
298+
.thenReturn(Uni.createFrom().item(Boolean.TRUE));
299+
300+
given()
301+
.when()
302+
.contentType(ContentType.JSON)
303+
.pathParam("institutionId", institutionId)
304+
.pathParam("productId", productId)
305+
.body(new SearchUserDto(fiscalCode))
306+
.post("/{institutionId}/product/{productId}/check-user")
307+
.then()
308+
.statusCode(200);
309+
}
310+
311+
@Test
312+
void checkUser_NotAuthorized() {
313+
final String fiscalCode = "fiscalCode";
314+
final String institutionId = "institutionId";
315+
final String productId = "productId";
316+
317+
given()
318+
.when()
319+
.contentType(ContentType.JSON)
320+
.pathParam("institutionId", institutionId)
321+
.pathParam("productId", productId)
322+
.body(new SearchUserDto(fiscalCode))
323+
.post("/{institutionId}/product/{productId}/check-user")
324+
.then()
325+
.statusCode(401);
326+
}
327+
289328
}

0 commit comments

Comments
 (0)