From e243f523de6da133546adf8488bce14db5f5560c Mon Sep 17 00:00:00 2001 From: tkuzynow Date: Wed, 13 Sep 2023 13:28:37 +0200 Subject: [PATCH] feat: enable setting of tenant id on consultant creation --- api/useradminservice.yaml | 1 + .../api/admin/facade/AdminUserFacade.java | 4 +- .../admin/create/CreateAdminService.java | 9 ++- .../create/ConsultantCreatorService.java | 37 ++++++++-- ...eateConsultantDTOCreationInputAdapter.java | 3 +- .../message/MessageServiceProvider.java | 3 + .../create/ConsultantCreatorServiceIT.java | 2 +- ...ConsultantCreatorServiceTenantAwareIT.java | 67 +++++++++++++++++++ 8 files changed, 112 insertions(+), 14 deletions(-) diff --git a/api/useradminservice.yaml b/api/useradminservice.yaml index 3ef7337df..45ca56d05 100644 --- a/api/useradminservice.yaml +++ b/api/useradminservice.yaml @@ -1227,6 +1227,7 @@ components: maxLength: 10000 tenantId: type: integer + format: int64 example: "1" isGroupchatConsultant: $ref: '#/components/schemas/IsGroupchatConsultant' diff --git a/src/main/java/de/caritas/cob/userservice/api/admin/facade/AdminUserFacade.java b/src/main/java/de/caritas/cob/userservice/api/admin/facade/AdminUserFacade.java index ab4cbc980..57c9df3b7 100644 --- a/src/main/java/de/caritas/cob/userservice/api/admin/facade/AdminUserFacade.java +++ b/src/main/java/de/caritas/cob/userservice/api/admin/facade/AdminUserFacade.java @@ -38,8 +38,8 @@ public class AdminUserFacade { private final @NonNull AuthenticatedUser authenticatedUser; - public AdminResponseDTO createNewTenantAdmin(final CreateAdminDTO createAgencyAdminDTO) { - return this.tenantAdminUserService.createNewTenantAdmin(createAgencyAdminDTO); + public AdminResponseDTO createNewTenantAdmin(final CreateAdminDTO createTenantAdminDTO) { + return this.tenantAdminUserService.createNewTenantAdmin(createTenantAdminDTO); } public AdminResponseDTO createNewAgencyAdmin(final CreateAdminDTO createAgencyAdminDTO) { diff --git a/src/main/java/de/caritas/cob/userservice/api/admin/service/admin/create/CreateAdminService.java b/src/main/java/de/caritas/cob/userservice/api/admin/service/admin/create/CreateAdminService.java index 64f531648..fd3e51fc0 100644 --- a/src/main/java/de/caritas/cob/userservice/api/admin/service/admin/create/CreateAdminService.java +++ b/src/main/java/de/caritas/cob/userservice/api/admin/service/admin/create/CreateAdminService.java @@ -89,13 +89,12 @@ private String createKeycloakUser(final CreateAdminDTO createAgencyAdminDTO) { return response.getUserId(); } - private UserDTO buildValidatedUserDTO(final CreateAdminDTO createAgencyAdminDTO) { + private UserDTO buildValidatedUserDTO(final CreateAdminDTO createAdminDTO) { UserDTO userDto = new UserDTO(); - userDto.setUsername( - new UsernameTranscoder().encodeUsername(createAgencyAdminDTO.getUsername())); - userDto.setEmail(createAgencyAdminDTO.getEmail()); + userDto.setUsername(new UsernameTranscoder().encodeUsername(createAdminDTO.getUsername())); + userDto.setEmail(createAdminDTO.getEmail()); - Integer tenantId = createAgencyAdminDTO.getTenantId(); + Integer tenantId = createAdminDTO.getTenantId(); userDto.setTenantId(tenantId == null ? null : Long.valueOf(tenantId)); this.userAccountInputValidator.validateUserDTO(userDto); diff --git a/src/main/java/de/caritas/cob/userservice/api/admin/service/consultant/create/ConsultantCreatorService.java b/src/main/java/de/caritas/cob/userservice/api/admin/service/consultant/create/ConsultantCreatorService.java index a14aef0f8..1c5a71c38 100644 --- a/src/main/java/de/caritas/cob/userservice/api/admin/service/consultant/create/ConsultantCreatorService.java +++ b/src/main/java/de/caritas/cob/userservice/api/admin/service/consultant/create/ConsultantCreatorService.java @@ -15,10 +15,12 @@ import de.caritas.cob.userservice.api.admin.service.consultant.validation.CreateConsultantDTOAbsenceInputAdapter; import de.caritas.cob.userservice.api.admin.service.consultant.validation.UserAccountInputValidator; import de.caritas.cob.userservice.api.admin.service.tenant.TenantAdminService; +import de.caritas.cob.userservice.api.exception.httpresponses.BadRequestException; import de.caritas.cob.userservice.api.exception.httpresponses.CustomValidationHttpStatusException; import de.caritas.cob.userservice.api.exception.httpresponses.InternalServerErrorException; import de.caritas.cob.userservice.api.exception.httpresponses.customheader.HttpStatusExceptionReason; import de.caritas.cob.userservice.api.exception.rocketchat.RocketChatLoginException; +import de.caritas.cob.userservice.api.helper.AuthenticatedUser; import de.caritas.cob.userservice.api.helper.UserHelper; import de.caritas.cob.userservice.api.helper.UsernameTranscoder; import de.caritas.cob.userservice.api.model.Consultant; @@ -31,6 +33,7 @@ import java.util.Set; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -39,6 +42,7 @@ */ @Service @RequiredArgsConstructor +@Slf4j public class ConsultantCreatorService { private final @NonNull IdentityClient identityClient; @@ -51,6 +55,8 @@ public class ConsultantCreatorService { @Value("${multitenancy.enabled}") private boolean multiTenancyEnabled; + private final @NonNull AuthenticatedUser authenticatedUser; + /** * Creates a new {@link Consultant} by {@link CreateConsultantDTO} in database, keycloak and * rocket chat. @@ -72,6 +78,29 @@ public Consultant createNewConsultant(CreateConsultantDTO createConsultantDTO) { return createNewConsultant(consultantCreationInput, roles); } + private void validateTenantId(CreateConsultantDTO createConsultantDTO) { + if (authenticatedUser.isTenantSuperAdmin()) { + if (createConsultantDTO.getTenantId() == null) { + throw new BadRequestException( + "TenantId must be set if consultant is created by superadmin"); + } + } else { + checkIfTenantIdMatch(createConsultantDTO); + } + } + + private void checkIfTenantIdMatch(CreateConsultantDTO createConsultantDTO) { + if (createConsultantDTO.getTenantId() != null + && !createConsultantDTO.getTenantId().equals(TenantContext.getCurrentTenant())) { + log.error( + "TenantId of createConsultantDTO {} does not match current tenant {}", + createConsultantDTO.getTenantId(), + TenantContext.getCurrentTenant()); + throw new BadRequestException( + "TenantId of createConsultantDTO does not match current tenant"); + } + } + /** * Creates a new {@link Consultant} by {@link ImportRecord} in database, keycloak and rocket chat. * @@ -102,10 +131,10 @@ private Consultant createNewConsultant( private void assignCurrentTenantContext(CreateConsultantDTO createConsultantDTO) { if (multiTenancyEnabled) { - createConsultantDTO.setTenantId(TenantContext.getCurrentTenant().intValue()); - } else { - // TODO: replace this quick fix - createConsultantDTO.setTenantId(1); + validateTenantId(createConsultantDTO); + if (!authenticatedUser.isTenantSuperAdmin() && createConsultantDTO.getTenantId() == null) { + createConsultantDTO.setTenantId(TenantContext.getCurrentTenant()); + } } } diff --git a/src/main/java/de/caritas/cob/userservice/api/admin/service/consultant/create/CreateConsultantDTOCreationInputAdapter.java b/src/main/java/de/caritas/cob/userservice/api/admin/service/consultant/create/CreateConsultantDTOCreationInputAdapter.java index 58c51c190..098c18cca 100644 --- a/src/main/java/de/caritas/cob/userservice/api/admin/service/consultant/create/CreateConsultantDTOCreationInputAdapter.java +++ b/src/main/java/de/caritas/cob/userservice/api/admin/service/consultant/create/CreateConsultantDTOCreationInputAdapter.java @@ -123,7 +123,6 @@ public boolean isLanguageFormal() { */ @Override public Long getTenantId() { - Integer tenantId = this.createConsultantDTO.getTenantId(); - return tenantId == null ? null : Long.valueOf(tenantId); + return this.createConsultantDTO.getTenantId(); } } diff --git a/src/main/java/de/caritas/cob/userservice/api/service/message/MessageServiceProvider.java b/src/main/java/de/caritas/cob/userservice/api/service/message/MessageServiceProvider.java index 12e7225ea..737bd0f0d 100644 --- a/src/main/java/de/caritas/cob/userservice/api/service/message/MessageServiceProvider.java +++ b/src/main/java/de/caritas/cob/userservice/api/service/message/MessageServiceProvider.java @@ -26,6 +26,7 @@ import java.util.Map; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.text.StringSubstitutor; import org.springframework.stereotype.Service; import org.springframework.web.client.RestClientException; @@ -33,6 +34,7 @@ /** Service class to provide message transmission to Rocket.Chat via the MessageService. */ @Service @RequiredArgsConstructor +@Slf4j public class MessageServiceProvider { private final @NonNull MessageServiceApiControllerFactory messageServiceApiControllerFactory; @@ -108,6 +110,7 @@ public void postWelcomeMessageIfConfigured( this.postMessageAsSystemUser(welcomeMessage, rcGroupId); } catch (RestClientException | RocketChatUserNotInitializedException exception) { + log.error("Exception calling RocketChat API: {}", exception.getMessage()); throw new RocketChatPostWelcomeMessageException( String.format("Could not post welcome message in Rocket.Chat group %s", rcGroupId), exception, diff --git a/src/test/java/de/caritas/cob/userservice/api/admin/service/consultant/create/ConsultantCreatorServiceIT.java b/src/test/java/de/caritas/cob/userservice/api/admin/service/consultant/create/ConsultantCreatorServiceIT.java index 7b5ec2eb1..938b89388 100644 --- a/src/test/java/de/caritas/cob/userservice/api/admin/service/consultant/create/ConsultantCreatorServiceIT.java +++ b/src/test/java/de/caritas/cob/userservice/api/admin/service/consultant/create/ConsultantCreatorServiceIT.java @@ -49,7 +49,7 @@ public class ConsultantCreatorServiceIT { private static final String DUMMY_RC_ID = "rcUserId"; private static final String VALID_USERNAME = "validUsername"; private static final String VALID_EMAILADDRESS = "valid@emailaddress.de"; - private static final int TENANT_ID = 1; + private static final long TENANT_ID = 1L; @Autowired private ConsultantCreatorService consultantCreatorService; diff --git a/src/test/java/de/caritas/cob/userservice/api/admin/service/consultant/create/ConsultantCreatorServiceTenantAwareIT.java b/src/test/java/de/caritas/cob/userservice/api/admin/service/consultant/create/ConsultantCreatorServiceTenantAwareIT.java index 323b646ac..1bcce37cf 100644 --- a/src/test/java/de/caritas/cob/userservice/api/admin/service/consultant/create/ConsultantCreatorServiceTenantAwareIT.java +++ b/src/test/java/de/caritas/cob/userservice/api/admin/service/consultant/create/ConsultantCreatorServiceTenantAwareIT.java @@ -1,12 +1,26 @@ package de.caritas.cob.userservice.api.admin.service.consultant.create; +import static de.caritas.cob.userservice.api.config.auth.UserRole.CONSULTANT; +import static de.caritas.cob.userservice.api.config.auth.UserRole.GROUP_CHAT_CONSULTANT; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.notNullValue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import com.neovisionaries.i18n.LanguageCode; import de.caritas.cob.userservice.api.UserServiceApplication; +import de.caritas.cob.userservice.api.adapters.keycloak.KeycloakService; +import de.caritas.cob.userservice.api.adapters.keycloak.dto.KeycloakCreateUserResponseDTO; +import de.caritas.cob.userservice.api.adapters.rocketchat.RocketChatService; import de.caritas.cob.userservice.api.adapters.web.dto.CreateConsultantDTO; import de.caritas.cob.userservice.api.admin.service.tenant.TenantAdminService; import de.caritas.cob.userservice.api.exception.httpresponses.CustomValidationHttpStatusException; +import de.caritas.cob.userservice.api.exception.rocketchat.RocketChatLoginException; import de.caritas.cob.userservice.api.model.Consultant; import de.caritas.cob.userservice.api.port.out.ConsultantRepository; import de.caritas.cob.userservice.api.tenant.TenantContext; @@ -15,7 +29,9 @@ import de.caritas.cob.userservice.tenantadminservice.generated.web.model.TenantDTO; import org.jeasy.random.EasyRandom; import org.junit.Test; +import org.junit.jupiter.api.AfterEach; import org.junit.runner.RunWith; +import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace; @@ -34,14 +50,28 @@ @Transactional public class ConsultantCreatorServiceTenantAwareIT { + private static final String DUMMY_RC_ID = "rcUserId"; + private static final String VALID_USERNAME = "validUsername"; + private static final String VALID_EMAILADDRESS = "valid@emailaddress.de"; + private static final long TENANT_ID = 1; + @Autowired private ConsultantCreatorService consultantCreatorService; @Autowired private ConsultantRepository consultantRepository; @MockBean private TenantAdminService tenantAdminService; + @MockBean private RocketChatService rocketChatService; + + @MockBean private KeycloakService keycloakService; + private final EasyRandom easyRandom = new EasyRandom(); + @AfterEach + public void tearDown() { + TenantContext.clear(); + } + @Test(expected = CustomValidationHttpStatusException.class) public void createNewConsultant_Should_throwCustomValidationHttpStatusException_When_LicensesAreExceeded() { @@ -54,6 +84,43 @@ public class ConsultantCreatorServiceTenantAwareIT { rollbackDBState(); } + @Test + public void + createNewConsultant_Should_addConsultantAndGroupChatConsultantRole_When_isGroupChatConsultantFlagIsEnabled() + throws RocketChatLoginException { + // given + TenantContext.setCurrentTenant(1L); + when(rocketChatService.getUserID(anyString(), anyString(), anyBoolean())) + .thenReturn(DUMMY_RC_ID); + when(keycloakService.createKeycloakUser(any(), anyString(), any())) + .thenReturn(easyRandom.nextObject(KeycloakCreateUserResponseDTO.class)); + var tenant = + new TenantDTO() + .licensing(new Licensing().allowedNumberOfUsers(1)) + .settings( + new de.caritas.cob.userservice.tenantadminservice.generated.web.model.Settings() + .featureGroupChatV2Enabled(false)); + when(tenantAdminService.getTenantById(Mockito.anyLong())).thenReturn(tenant); + + CreateConsultantDTO createConsultantDTO = this.easyRandom.nextObject(CreateConsultantDTO.class); + createConsultantDTO.setTenantId(TENANT_ID); + createConsultantDTO.setUsername(VALID_USERNAME); + createConsultantDTO.setEmail(VALID_EMAILADDRESS); + createConsultantDTO.setIsGroupchatConsultant(true); + createConsultantDTO.setTenantId(1L); + + // when + Consultant consultant = consultantCreatorService.createNewConsultant(createConsultantDTO); + + // then + verify(keycloakService, times(2)).updateRole(anyString(), anyString()); + verify(keycloakService).updateRole(anyString(), eq(CONSULTANT.getValue())); + verify(keycloakService).updateRole(anyString(), eq(GROUP_CHAT_CONSULTANT.getValue())); + + assertThat(consultant, notNullValue()); + assertThat(consultant.getId(), notNullValue()); + } + private void createConsultant(String username) { Consultant consultant = new Consultant(); consultant.setAppointments(null);