Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable setting of tenant id on consultant creation #671

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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