From e84cfae2c620484cea960d008c352cc4b2b51f4b Mon Sep 17 00:00:00 2001 From: flaminiaScarciofolo <113031535+flaminiaScarciofolo@users.noreply.github.com> Date: Tue, 12 Nov 2024 14:25:35 +0100 Subject: [PATCH] [SELC-5971] Feat: Added API to createUser by userID from onboarding (#223) --- apps/user-ms/src/main/docs/openapi.json | 45 ++++ apps/user-ms/src/main/docs/openapi.yaml | 33 +++ .../user/controller/UserController.java | 24 ++ .../UserRoleAlreadyPresentException.java | 8 + .../selfcare/user/service/UserService.java | 2 + .../user/service/UserServiceImpl.java | 66 ++++- .../user/controller/UserControllerTest.java | 65 +++++ .../user/service/UserServiceTest.java | 233 +++++++++++++++++- 8 files changed, 471 insertions(+), 5 deletions(-) create mode 100644 apps/user-ms/src/main/java/it/pagopa/selfcare/user/exception/UserRoleAlreadyPresentException.java diff --git a/apps/user-ms/src/main/docs/openapi.json b/apps/user-ms/src/main/docs/openapi.json index 29b611bd..a2addf06 100644 --- a/apps/user-ms/src/main/docs/openapi.json +++ b/apps/user-ms/src/main/docs/openapi.json @@ -1306,6 +1306,51 @@ "SecurityScheme" : [ ] } ] } + }, + "/users/{userId}/onboarding" : { + "post" : { + "tags" : [ "User" ], + "summary" : "Check if the user is manager or Update/create a user by userId with a new role", + "description" : "Checks if the user is already a manager for the specified product and, if not, creates or updates the user with a new role.", + "operationId" : "createUserByUserId", + "parameters" : [ { + "name" : "userId", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AddUserRoleDto" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The user is already a manager for the specified product.", + "content" : { + "application/json" : { } + } + }, + "201" : { + "description" : "The user has been created or updated with a new role." + }, + "401" : { + "description" : "Not Authorized" + }, + "403" : { + "description" : "Not Allowed" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } } }, "components" : { diff --git a/apps/user-ms/src/main/docs/openapi.yaml b/apps/user-ms/src/main/docs/openapi.yaml index e46ae2ea..3c3a0a0c 100644 --- a/apps/user-ms/src/main/docs/openapi.yaml +++ b/apps/user-ms/src/main/docs/openapi.yaml @@ -933,6 +933,39 @@ paths: description: Not Allowed security: - SecurityScheme: [] + /users/{userId}/onboarding: + post: + tags: + - User + summary: Check if the user is manager or Update/create a user by userId with + a new role + description: "Checks if the user is already a manager for the specified product\ + \ and, if not, creates or updates the user with a new role." + operationId: createUserByUserId + parameters: + - name: userId + in: path + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/AddUserRoleDto" + responses: + "200": + description: The user is already a manager for the specified product. + content: + application/json: {} + "201": + description: The user has been created or updated with a new role. + "401": + description: Not Authorized + "403": + description: Not Allowed + security: + - SecurityScheme: [] components: schemas: AddUserRoleDto: diff --git a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/controller/UserController.java b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/controller/UserController.java index ebf936ad..2f97c2da 100644 --- a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/controller/UserController.java +++ b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/controller/UserController.java @@ -11,6 +11,7 @@ import it.pagopa.selfcare.user.controller.response.*; import it.pagopa.selfcare.user.controller.response.product.SearchUserDto; import it.pagopa.selfcare.user.exception.InvalidRequestException; +import it.pagopa.selfcare.user.exception.UserRoleAlreadyPresentException; import it.pagopa.selfcare.user.mapper.UserMapper; import it.pagopa.selfcare.user.model.LoggedUser; import it.pagopa.selfcare.user.model.UpdateUserRequest; @@ -319,6 +320,29 @@ public Uni createOrUpdateByUserId(@PathParam("userId") String userId, } + /** + * + * @param userId String + * @param userDto AddUserRoleDto + */ + @Operation(description = "Checks if the user is already a manager for the specified product and, if not, creates or updates the user with a new role.", summary = "Check if the user is manager or Update/create a user by userId with a new role") + @APIResponses({ + @APIResponse(responseCode = "200", description = "The user is already a manager for the specified product."), + @APIResponse(responseCode = "201", description = "The user has been created or updated with a new role."), + }) + @POST + @Path("/{userId}/onboarding") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Uni createUserByUserId(@PathParam("userId") String userId, + @Valid AddUserRoleDto userDto, + @Context SecurityContext ctx) { + return readUserIdFromToken(ctx) + .onItem().transformToUni(loggedUser -> userService.createUserByUserId(userDto, userId, loggedUser)) + .onItem().transform(ignore -> Response.status(HttpStatus.SC_CREATED).entity(userId).build()) + .onFailure(UserRoleAlreadyPresentException.class).recoverWithUni(throwable -> Uni.createFrom().item(Response.status(HttpStatus.SC_OK).entity(userId).build())); + } + /** * The createOrUpdateByFiscalCode function is used to create a new user or update an existing one. * The function takes in a CreateUserDto object, which contains the following fields: diff --git a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/exception/UserRoleAlreadyPresentException.java b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/exception/UserRoleAlreadyPresentException.java new file mode 100644 index 00000000..79e71828 --- /dev/null +++ b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/exception/UserRoleAlreadyPresentException.java @@ -0,0 +1,8 @@ +package it.pagopa.selfcare.user.exception; + +public class UserRoleAlreadyPresentException extends RuntimeException{ + + public UserRoleAlreadyPresentException(String message) { + super(message); + } +} diff --git a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserService.java b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserService.java index cc232e88..a83e7dd2 100644 --- a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserService.java +++ b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserService.java @@ -50,6 +50,8 @@ public interface UserService { Uni createOrUpdateUserByUserId(AddUserRoleDto userDto, String userId, LoggedUser loggedUser); + Uni createUserByUserId(AddUserRoleDto userDto, String userId, LoggedUser loggedUser); + Multi retrieveUsersData(String institutionId, String personId, List roles, List states, List products, List productRoles, String userId); Uni updateInstitutionDescription(String institutionId, UpdateDescriptionDto descriptionDto); diff --git a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserServiceImpl.java b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserServiceImpl.java index 9c4c3010..6b7da1ec 100644 --- a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserServiceImpl.java +++ b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserServiceImpl.java @@ -17,6 +17,7 @@ import it.pagopa.selfcare.user.entity.filter.UserInstitutionFilter; import it.pagopa.selfcare.user.exception.InvalidRequestException; import it.pagopa.selfcare.user.exception.ResourceNotFoundException; +import it.pagopa.selfcare.user.exception.UserRoleAlreadyPresentException; import it.pagopa.selfcare.user.mapper.OnboardedProductMapper; import it.pagopa.selfcare.user.mapper.UserInstitutionMapper; import it.pagopa.selfcare.user.mapper.UserMapper; @@ -56,8 +57,7 @@ import static it.pagopa.selfcare.user.model.constants.EventsMetric.EVENTS_USER_INSTITUTION_FAILURE; import static it.pagopa.selfcare.user.model.constants.EventsMetric.EVENTS_USER_INSTITUTION_SUCCESS; import static it.pagopa.selfcare.user.model.constants.EventsName.EVENT_USER_MS_NAME; -import static it.pagopa.selfcare.user.model.constants.OnboardedProductState.ACTIVE; -import static it.pagopa.selfcare.user.model.constants.OnboardedProductState.PENDING; +import static it.pagopa.selfcare.user.model.constants.OnboardedProductState.*; import static it.pagopa.selfcare.user.util.GeneralUtils.formatQueryParameterList; import static it.pagopa.selfcare.user.util.UserUtils.VALID_USER_PRODUCT_STATES_FOR_NOTIFICATION; @@ -453,6 +453,68 @@ public Uni createOrUpdateUserByUserId(AddUserRoleDto userDto, String use .onFailure().invoke(exception -> log.error("Error during retrieve user from userRegistry: {} ", exception.getMessage(), exception)); } + public Uni createUserByUserId(AddUserRoleDto userDto, String userId, LoggedUser loggedUser) { + var userInstitutionFilters = UserInstitutionFilter.builder().userId(userId).institutionId(userDto.getInstitutionId()).build().constructMap(); + var productFilters = OnboardedProductFilter.builder().productId(userDto.getProduct().getProductId()).status(List.of(ACTIVE)).build().constructMap(); + Map queryParameter = userUtils.retrieveMapForFilter(userInstitutionFilters, productFilters); + return userInstitutionService.retrieveFirstFilteredUserInstitution(queryParameter) + .onItem().transformToUni(userInstitution -> { + if (Objects.nonNull(userInstitution)) { + log.info("User with userId: {} has already onboarded for product {}. Proceeding with check role", userId, userDto.getProduct().getProductId()); + PartyRole roleOnProduct = retrieveUserRoleOnProduct(userInstitution, userDto.getProduct().getProductId()); + return evaluateRoleAndCreateOrUpdateUserByUserId(userDto, userId, loggedUser, roleOnProduct); + } else { + log.info("User with userId: {} has not onboarded for product {}. Proceeding with create", userId, userDto.getProduct().getProductId()); + return createOrUpdateUserByUserId(userDto, userId, loggedUser); + } + }) + .onFailure().invoke(exception -> log.error("Error during createOrUpdateManagerByUserId for userId: {}, institutionId: {}: {}", userId, userDto.getInstitutionId(), exception.getMessage(), exception)); + } + + /** + * The evaluateRoleAndCreateOrUpdateUserByUserId method is designed to evaluate the role of a user for a specific product + * and either create or update the user's role based on certain conditions. + * First, the method checks if the roleOnProduct is null. If it is, we need to create new role for the user on selected product. + * Next, the method compares the role specified in userDto with the existing roleOnProduct. + * If the new role is lower than the existing role (es. new role DELEGATE, old role MANAGER), it then calls + * we have to delete the old role, and subsequently we create new role for the user on selected product. + * If the new role is equals or higher than the existing role, throw a UserRoleAlreadyPresentException to indicate that we need to keep the old role. + */ + private Uni evaluateRoleAndCreateOrUpdateUserByUserId(AddUserRoleDto userDto, String userId, LoggedUser loggedUser, PartyRole roleOnProduct) { + PartyRole newRole; + try { + newRole = PartyRole.valueOf(userDto.getProduct().getRole()); + } catch (IllegalArgumentException e) { + throw new InvalidRequestException("Invalid role: " + userDto.getProduct().getRole() + ". Allowed value are: " + Arrays.toString(PartyRole.values())); + } + if (Objects.isNull(roleOnProduct)) { + return createOrUpdateUserByUserId(userDto, userId, loggedUser); + } else if (newRole.compareTo(roleOnProduct) < 0) { + log.info("User {}, for product {}, has role {}, which is lower than {}. The old role will be deleted, and the new role will be created.", userId, userDto.getProduct().getProductId(), roleOnProduct, userDto.getProduct().getRole()); + return userInstitutionService.updateUserStatusWithOptionalFilterByInstitutionAndProduct(userId, userDto.getInstitutionId(), userDto.getProduct().getProductId(), null, null, DELETED) + .onItem().transformToUni(longValue -> createOrUpdateUserByUserId(userDto, userId, loggedUser)); + } else { + log.info("User {}, for product {}, has role {}, which is equals or biggest than {}. The old role is kept.", userId, userDto.getProduct().getProductId(), roleOnProduct, userDto.getProduct().getRole()); + return Uni.createFrom().failure(new UserRoleAlreadyPresentException(String.format("User already has a role equals or bigger than %s for the product [%s] we cannot create %s role", + roleOnProduct, userDto.getProduct().getProductId(), userDto.getProduct().getRole()))); + } + } + + /** + * This method retrieve the user role on a specific product if exists (status = ACTIVE). + */ + private PartyRole retrieveUserRoleOnProduct(UserInstitution userInstitution, String productId) { + if (Objects.nonNull(userInstitution.getProducts()) && !userInstitution.getProducts().isEmpty()) { + return userInstitution.getProducts().stream() + .filter(onboardedProduct -> productId.equalsIgnoreCase(onboardedProduct.getProductId())) + .filter(onboardedProduct -> ACTIVE.equals(onboardedProduct.getStatus())) + .findFirst() + .map(OnboardedProduct::getRole) + .orElse(null); + } + return null; + } + /** * Updates or creates a UserInstitution by userId and institutionId, persists the changes, * and sends notifications if needed. If the productRole already exists return nullItem. diff --git a/apps/user-ms/src/test/java/it/pagopa/selfcare/user/controller/UserControllerTest.java b/apps/user-ms/src/test/java/it/pagopa/selfcare/user/controller/UserControllerTest.java index 44e3dea9..07e3134e 100644 --- a/apps/user-ms/src/test/java/it/pagopa/selfcare/user/controller/UserControllerTest.java +++ b/apps/user-ms/src/test/java/it/pagopa/selfcare/user/controller/UserControllerTest.java @@ -16,6 +16,7 @@ import it.pagopa.selfcare.user.entity.UserInstitutionRole; import it.pagopa.selfcare.user.exception.InvalidRequestException; import it.pagopa.selfcare.user.exception.ResourceNotFoundException; +import it.pagopa.selfcare.user.exception.UserRoleAlreadyPresentException; import it.pagopa.selfcare.user.model.LoggedUser; import it.pagopa.selfcare.user.model.UpdateUserRequest; import it.pagopa.selfcare.user.model.UserNotificationToSend; @@ -684,6 +685,49 @@ void testCreateOrUpdateUserWithInvalidBodyByUserId() { .statusCode(400); } + @Test + @TestSecurity(user = "userJwt") + void testCheckRoleOrCreateOrUpdateByUserIdWhenUserIsManager() { + AddUserRoleDto userDto = buildAddUserRoleDto(); + when(userService.createUserByUserId(any(AddUserRoleDto.class), anyString(), any())) + .thenReturn(Uni.createFrom().failure(new UserRoleAlreadyPresentException("test"))); + given() + .when() + .contentType(ContentType.JSON) + .body(userDto) + .post("/userId/onboarding") + .then() + .statusCode(200); + } + + @Test + @TestSecurity(user = "userJwt") + void testCheckRoleOrCreateOrUpdateByUserIdWhenUserIsNotManager() { + AddUserRoleDto userDto = buildAddUserRoleDtoWithOtherRole(); + when(userService.createUserByUserId(any(AddUserRoleDto.class), anyString(), any())) + .thenReturn(Uni.createFrom().nullItem()); + given() + .when() + .contentType(ContentType.JSON) + .body(userDto) + .post("/userId/onboarding") + .then() + .statusCode(201); + } + + @Test + @TestSecurity(user = "userJwt") + void testCheckRoleOrCreateOrUpdateByUserIdWithInvalidBody() { + AddUserRoleDto userDto = new AddUserRoleDto(); + given() + .when() + .contentType(ContentType.JSON) + .body(userDto) + .post("/userId/onboarding") + .then() + .statusCode(400); + } + @Test @TestSecurity(user = "userJwt") void retrieveUsers() { @@ -763,4 +807,25 @@ private AddUserRoleDto buildAddUserRoleDto() { userDto.setProduct(product); return userDto; } + + private AddUserRoleDto buildAddUserRoleDtoWithOtherRole() { + AddUserRoleDto userDto = new AddUserRoleDto(); + userDto.setInstitutionId("institutionId"); + userDto.setInstitutionDescription("institutionDescription"); + userDto.setInstitutionRootName("institutionRootName"); + CreateUserDto.User user = new CreateUserDto.User(); + user.setBirthDate("birthDate"); + user.setFamilyName("familyName"); + user.setFiscalCode("fiscalCode"); + user.setName("name"); + user.setInstitutionEmail("institutionEmail"); + AddUserRoleDto.Product product = new AddUserRoleDto.Product(); + product.setProductId("productId"); + product.setRole(PartyRole.DELEGATE.name()); + product.setTokenId("tokenId"); + product.setProductRoles(Collections.singletonList("productRole")); + product.setDelegationId("delegationId"); + userDto.setProduct(product); + return userDto; + } } \ No newline at end of file diff --git a/apps/user-ms/src/test/java/it/pagopa/selfcare/user/service/UserServiceTest.java b/apps/user-ms/src/test/java/it/pagopa/selfcare/user/service/UserServiceTest.java index d6d845d4..8199cb74 100644 --- a/apps/user-ms/src/test/java/it/pagopa/selfcare/user/service/UserServiceTest.java +++ b/apps/user-ms/src/test/java/it/pagopa/selfcare/user/service/UserServiceTest.java @@ -27,9 +27,9 @@ import it.pagopa.selfcare.user.entity.filter.OnboardedProductFilter; import it.pagopa.selfcare.user.entity.filter.UserInstitutionFilter; import it.pagopa.selfcare.user.exception.InvalidRequestException; +import it.pagopa.selfcare.user.exception.UserRoleAlreadyPresentException; import it.pagopa.selfcare.user.exception.ResourceNotFoundException; import it.pagopa.selfcare.user.mapper.UserMapper; -import it.pagopa.selfcare.user.mapper.UserMapperImpl; import it.pagopa.selfcare.user.model.LoggedUser; import it.pagopa.selfcare.user.model.OnboardedProduct; import it.pagopa.selfcare.user.model.UserNotificationToSend; @@ -58,8 +58,7 @@ import java.time.OffsetDateTime; import java.util.*; -import static it.pagopa.selfcare.onboarding.common.PartyRole.MANAGER; -import static it.pagopa.selfcare.onboarding.common.PartyRole.OPERATOR; +import static it.pagopa.selfcare.onboarding.common.PartyRole.*; import static it.pagopa.selfcare.user.constant.CustomError.*; import static it.pagopa.selfcare.user.model.constants.EventsMetric.EVENTS_USER_INSTITUTION_SUCCESS; import static it.pagopa.selfcare.user.model.constants.EventsName.EVENT_USER_MS_NAME; @@ -1266,6 +1265,234 @@ void testCreateOrUpdateUser_UpdateUser_UserInstitutionUpdateFailedByUserId_userI verify(userRegistryApi).findByIdUsingGET(any(), eq("userId")); } + @Test + void createUserFromOnboardingByUserIdUserIsAlreadyManager() { + AddUserRoleDto addUserRoleDto = new AddUserRoleDto(); + addUserRoleDto.setInstitutionId("institutionId"); + AddUserRoleDto.Product addUserRoleProduct = new AddUserRoleDto.Product(); + addUserRoleProduct.setProductId("test"); + addUserRoleProduct.setRole(MANAGER.name()); + addUserRoleDto.setProduct(addUserRoleProduct); + + LoggedUser loggedUser = LoggedUser.builder().build(); + OnboardedProduct product = new OnboardedProduct(); + product.setProductId("test"); + product.setProductRole("admin"); + product.setRole(MANAGER); + product.setStatus(OnboardedProductState.ACTIVE); + + UserInstitution userInstitution = new UserInstitution(); + OnboardedProduct onboardedProduct = new OnboardedProduct(); + onboardedProduct.setStatus(OnboardedProductState.ACTIVE); + List products = new ArrayList<>(); + products.add(product); + products.add(onboardedProduct); + userInstitution.setProducts(products); + + when(userInstitutionService.retrieveFirstFilteredUserInstitution(anyMap())) + .thenReturn(Uni.createFrom().item(userInstitution)); + + userService.createUserByUserId(addUserRoleDto, "userId", loggedUser) + .subscribe().withSubscriber(UniAssertSubscriber.create()) + .assertFailedWith(UserRoleAlreadyPresentException.class, "User already has a role equals or bigger than MANAGER for the product [test] we cannot create MANAGER role"); + } + + @Test + void createUserFromOnboardingByUserIdInvalidRole() { + AddUserRoleDto addUserRoleDto = new AddUserRoleDto(); + addUserRoleDto.setInstitutionId("institutionId"); + AddUserRoleDto.Product addUserRoleProduct = new AddUserRoleDto.Product(); + addUserRoleProduct.setProductId("test"); + addUserRoleProduct.setRole("INVALID"); + addUserRoleDto.setProduct(addUserRoleProduct); + + LoggedUser loggedUser = LoggedUser.builder().build(); + OnboardedProduct product = new OnboardedProduct(); + product.setProductId("test"); + product.setProductRole("admin"); + product.setRole(MANAGER); + product.setStatus(OnboardedProductState.ACTIVE); + + UserInstitution userInstitution = new UserInstitution(); + OnboardedProduct onboardedProduct = new OnboardedProduct(); + onboardedProduct.setStatus(OnboardedProductState.ACTIVE); + List products = new ArrayList<>(); + products.add(product); + products.add(onboardedProduct); + userInstitution.setProducts(products); + + when(userInstitutionService.retrieveFirstFilteredUserInstitution(anyMap())) + .thenReturn(Uni.createFrom().item(userInstitution)); + + userService.createUserByUserId(addUserRoleDto, "userId", loggedUser) + .subscribe().withSubscriber(UniAssertSubscriber.create()) + .assertFailedWith(InvalidRequestException.class, "Invalid role: INVALID. Allowed value are: [MANAGER, DELEGATE, SUB_DELEGATE, OPERATOR, ADMIN_EA]"); + } + + + @Test + void createUserFromOnboardingByUserIdUserWithBiggestActiveRoleOnProduct() { + AddUserRoleDto addUserRoleDto = new AddUserRoleDto(); + addUserRoleDto.setInstitutionId("institutionId"); + AddUserRoleDto.Product addUserRoleProduct = new AddUserRoleDto.Product(); + addUserRoleProduct.setProductId("test"); + addUserRoleProduct.setRole(SUB_DELEGATE.name()); + addUserRoleDto.setProduct(addUserRoleProduct); + + LoggedUser loggedUser = LoggedUser.builder().build(); + OnboardedProduct product = new OnboardedProduct(); + product.setProductId("test"); + product.setProductRole("admin"); + product.setRole(MANAGER); + product.setStatus(OnboardedProductState.ACTIVE); + + UserInstitution userInstitution = new UserInstitution(); + OnboardedProduct onboardedProduct = new OnboardedProduct(); + onboardedProduct.setStatus(OnboardedProductState.ACTIVE); + List products = new ArrayList<>(); + products.add(product); + products.add(onboardedProduct); + userInstitution.setProducts(products); + + when(userInstitutionService.retrieveFirstFilteredUserInstitution(anyMap())) + .thenReturn(Uni.createFrom().item(userInstitution)); + + userService.createUserByUserId(addUserRoleDto, "userId", loggedUser) + .subscribe().withSubscriber(UniAssertSubscriber.create()) + .assertFailedWith(UserRoleAlreadyPresentException.class, "User already has a role equals or bigger than MANAGER for the product [test] we cannot create SUB_DELEGATE role"); + } + + @Test + void createManagerByUserIdUserWithSmallestActiveRoleOnProduct() { + AddUserRoleDto addUserRoleDto = new AddUserRoleDto(); + addUserRoleDto.setInstitutionId("institutionId"); + AddUserRoleDto.Product addUserRoleProduct = new AddUserRoleDto.Product(); + addUserRoleProduct.setProductId("test"); + addUserRoleProduct.setRole(MANAGER.name()); + addUserRoleProduct.setProductRoles(List.of("admin2")); + addUserRoleProduct.setDelegationId("delegationId"); + addUserRoleDto.setProduct(addUserRoleProduct); + LoggedUser loggedUser = LoggedUser.builder().build(); + + UserInstitution userInstitution = createUserInstitutionWithoutManagerRole(); + + Product product = new Product(); + product.setDescription("description"); + + UserToNotify userToNotify = new UserToNotify(); + userToNotify.setUserId(userId.toString()); + + UserNotificationToSend userNotificationToSend = new UserNotificationToSend(); + userNotificationToSend.setUser(userToNotify); + + when(userInstitutionService.retrieveFirstFilteredUserInstitution(anyMap())).thenReturn(Uni.createFrom().item(userInstitution)); + when(userRegistryApi.findByIdUsingGET(any(), eq("userId"))).thenReturn(Uni.createFrom().item(userResource)); + when(userInstitutionService.updateUserStatusWithOptionalFilterByInstitutionAndProduct("userId", addUserRoleDto.getInstitutionId(), + addUserRoleProduct.getProductId(), null, null, DELETED)).thenReturn(Uni.createFrom().item(1L)); + when(userInstitutionService.persistOrUpdate(any())).thenReturn(Uni.createFrom().item(createUserInstitutionWithoutManagerRole())); + when(productService.getProduct(any())).thenReturn(product); + when(userNotificationService.sendCreateUserNotification(any(), any(), any(), any(), any(), any())).thenReturn(Uni.createFrom().voidItem()); + when(userUtils.buildUsersNotificationResponse(any(), any())).thenReturn(List.of(userNotificationToSend)); + when(userNotificationService.sendKafkaNotification(any())).thenReturn(Uni.createFrom().item(userNotificationToSend)); + + UniAssertSubscriber subscriber = userService.createUserByUserId(addUserRoleDto, "userId", loggedUser) + .subscribe().withSubscriber(UniAssertSubscriber.create()); + + subscriber.awaitItem().assertCompleted(); + verify(userRegistryApi).findByIdUsingGET(any(), eq("userId")); + verify(userInstitutionService).persistOrUpdate(any()); + } + + @Test + void createManagerByUserIdUserWithoutRoleOnProduct() { + AddUserRoleDto addUserRoleDto = new AddUserRoleDto(); + addUserRoleDto.setInstitutionId("institutionId"); + AddUserRoleDto.Product addUserRoleProduct = new AddUserRoleDto.Product(); + addUserRoleProduct.setProductId("test"); + addUserRoleProduct.setRole(MANAGER.name()); + addUserRoleProduct.setProductRoles(List.of("admin2")); + addUserRoleProduct.setDelegationId("delegationId"); + addUserRoleDto.setProduct(addUserRoleProduct); + LoggedUser loggedUser = LoggedUser.builder().build(); + + UserInstitution userInstitution = createUserInstitutionWithoutManagerRole(); + userInstitution.getProducts().forEach(onboardedProduct -> onboardedProduct.setRole(null)); + + Product product = new Product(); + product.setDescription("description"); + + UserToNotify userToNotify = new UserToNotify(); + userToNotify.setUserId(userId.toString()); + + UserNotificationToSend userNotificationToSend = new UserNotificationToSend(); + userNotificationToSend.setUser(userToNotify); + + when(userInstitutionService.retrieveFirstFilteredUserInstitution(anyMap())).thenReturn(Uni.createFrom().item(userInstitution)); + when(userRegistryApi.findByIdUsingGET(any(), eq("userId"))).thenReturn(Uni.createFrom().item(userResource)); + when(userInstitutionService.updateUserStatusWithOptionalFilterByInstitutionAndProduct("userId", addUserRoleDto.getInstitutionId(), + addUserRoleProduct.getProductId(), null, null, DELETED)).thenReturn(Uni.createFrom().item(1L)); + when(userInstitutionService.persistOrUpdate(any())).thenReturn(Uni.createFrom().item(createUserInstitutionWithoutManagerRole())); + when(productService.getProduct(any())).thenReturn(product); + when(userNotificationService.sendCreateUserNotification(any(), any(), any(), any(), any(), any())).thenReturn(Uni.createFrom().voidItem()); + when(userUtils.buildUsersNotificationResponse(any(), any())).thenReturn(List.of(userNotificationToSend)); + when(userNotificationService.sendKafkaNotification(any())).thenReturn(Uni.createFrom().item(userNotificationToSend)); + + UniAssertSubscriber subscriber = userService.createUserByUserId(addUserRoleDto, "userId", loggedUser) + .subscribe().withSubscriber(UniAssertSubscriber.create()); + + subscriber.awaitItem().assertCompleted(); + verify(userRegistryApi).findByIdUsingGET(any(), eq("userId")); + verify(userInstitutionService).persistOrUpdate(any()); + } + + @Test + void createManagerByUserIdUserInstitutionNotFound() { + AddUserRoleDto addUserRoleDto = new AddUserRoleDto(); + addUserRoleDto.setInstitutionId("institutionId"); + AddUserRoleDto.Product addUserRoleProduct = new AddUserRoleDto.Product(); + addUserRoleProduct.setProductId("test"); + addUserRoleProduct.setRole(MANAGER.name()); + addUserRoleDto.setProduct(addUserRoleProduct); + LoggedUser loggedUser = LoggedUser.builder().build(); + + Product product = new Product(); + product.setDescription("description"); + + UserToNotify userToNotify = new UserToNotify(); + userToNotify.setUserId(userId.toString()); + + UserNotificationToSend userNotificationToSend = new UserNotificationToSend(); + userNotificationToSend.setUser(userToNotify); + + + when(userInstitutionService.retrieveFirstFilteredUserInstitution(anyMap())) + .thenReturn(Uni.createFrom().nullItem()); + when(userRegistryApi.findByIdUsingGET(any(), eq(userResource.getId().toString()))).thenReturn(Uni.createFrom().item(userResource)); + when(userInstitutionService.updateUserStatusWithOptionalFilterByInstitutionAndProduct(userResource.getId().toString(), addUserRoleDto.getInstitutionId(), + addUserRoleProduct.getProductId(), null, null, DELETED)).thenReturn(Uni.createFrom().item(1L)); + when(userInstitutionService.persistOrUpdate(any())).thenReturn(Uni.createFrom().item(createUserInstitutionWithoutManagerRole())); + when(productService.getProduct(any())).thenReturn(product); + when(userNotificationService.sendCreateUserNotification(any(), any(), any(), any(), any(), any())).thenReturn(Uni.createFrom().voidItem()); + when(userUtils.buildUsersNotificationResponse(any(), any())).thenReturn(List.of(userNotificationToSend)); + when(userNotificationService.sendKafkaNotification(any())).thenReturn(Uni.createFrom().item(userNotificationToSend)); + + + userService.createUserByUserId(addUserRoleDto, userResource.getId().toString(), loggedUser) + .subscribe().withSubscriber(UniAssertSubscriber.create()) + .assertItem(userResource.getId().toString()) + .assertCompleted(); + } + + private UserInstitution createUserInstitutionWithoutManagerRole() { + UserInstitution userInstitution = new UserInstitution(); + OnboardedProduct onboardedProduct = new OnboardedProduct(); + onboardedProduct.setProductId("test"); + onboardedProduct.setRole(OPERATOR); + onboardedProduct.setStatus(ACTIVE); + userInstitution.setProducts(List.of(onboardedProduct)); + return userInstitution; + } + @Test void testRetrieveUsersData() { // Prepare test data