Skip to content

Commit

Permalink
feat: enable setting of tenant id on consultant creation
Browse files Browse the repository at this point in the history
  • Loading branch information
tkuzynow committed Sep 13, 2023
1 parent e6701d1 commit e243f52
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 14 deletions.
1 change: 1 addition & 0 deletions api/useradminservice.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1227,6 +1227,7 @@ components:
maxLength: 10000
tenantId:
type: integer
format: int64
example: "1"
isGroupchatConsultant:
$ref: '#/components/schemas/IsGroupchatConsultant'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -39,6 +42,7 @@
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class ConsultantCreatorService {

private final @NonNull IdentityClient identityClient;
Expand All @@ -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.
Expand All @@ -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.
*
Expand Down Expand Up @@ -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());
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@
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;

/** Service class to provide message transmission to Rocket.Chat via the MessageService. */
@Service
@RequiredArgsConstructor
@Slf4j
public class MessageServiceProvider {

private final @NonNull MessageServiceApiControllerFactory messageServiceApiControllerFactory;
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "[email protected]";
private static final int TENANT_ID = 1;
private static final long TENANT_ID = 1L;

@Autowired private ConsultantCreatorService consultantCreatorService;

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
Expand All @@ -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 = "[email protected]";
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() {
Expand All @@ -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);
Expand Down

0 comments on commit e243f52

Please sign in to comment.