diff --git a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/ControllerAdvice.java b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/ControllerAdvice.java index 0a8515b48..992905dab 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/ControllerAdvice.java +++ b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/ControllerAdvice.java @@ -1,8 +1,8 @@ package com.iqser.red.service.peristence.v1.server.controller; +import java.sql.SQLException; import java.time.OffsetDateTime; -import org.postgresql.util.PSQLException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.MethodArgumentNotValidException; @@ -83,8 +83,8 @@ public class ControllerAdvice { @ResponseBody - @ExceptionHandler(value = PSQLException.class) - public ResponseEntity handleSQLException(PSQLException e) { + @ExceptionHandler(value = SQLException.class) + public ResponseEntity handleSQLException(SQLException e) { if (e.getMessage().contains("violates unique constraint")) { return new ResponseEntity<>(new ErrorMessage(OffsetDateTime.now(), "Unique constraint violation"), HttpStatus.CONFLICT); diff --git a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/service/TenantManagementService.java b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/service/TenantManagementService.java index cb18c6aa8..d52907f26 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/service/TenantManagementService.java +++ b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/service/TenantManagementService.java @@ -1,8 +1,10 @@ package com.iqser.red.service.peristence.v1.server.service; +import java.net.URI; import java.sql.Connection; import java.sql.DriverManager; import java.util.List; +import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; @@ -16,7 +18,6 @@ import org.springframework.core.io.ResourceLoader; import org.springframework.jdbc.datasource.SingleConnectionDataSource; import org.springframework.stereotype.Service; -import com.iqser.red.service.persistence.management.v1.processor.exception.BadRequestException; import com.iqser.red.service.persistence.management.v1.processor.exception.ConflictException; import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException; import com.iqser.red.service.persistence.management.v1.processor.multitenancy.entity.TenantEntity; @@ -28,11 +29,15 @@ import com.iqser.red.service.persistence.service.v1.api.model.multitenancy.Tenan import liquibase.exception.LiquibaseException; import liquibase.integration.spring.SpringLiquibase; import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +@Slf4j @Service @EnableConfigurationProperties(LiquibaseProperties.class) public class TenantManagementService { + private static final Set SQL_CONNECTION_ERROR_CODES = Set.of("08000", "08003", "08006"); + private final EncryptionDecryptionService encryptionService; private final LiquibaseProperties liquibaseProperties; @@ -58,13 +63,16 @@ public class TenantManagementService { if (tenantRepository.findById(tenantRequest.getTenantId()).isEmpty()) { + validateJdbcUrl(tenantRequest.getJdbcUrl()); + String encryptedPassword = encryptionService.encrypt(tenantRequest.getPassword()); try (Connection connection = DriverManager.getConnection(tenantRequest.getJdbcUrl(), tenantRequest.getUser(), tenantRequest.getPassword())) { DataSource tenantDataSource = new SingleConnectionDataSource(connection, false); runLiquibase(tenantDataSource); } catch (PSQLException e) { - throw new BadRequestException(e.getMessage(), e); + handleClientException(e); + handleInternalException(e); } TenantEntity tenantEntity = TenantEntity.builder() @@ -82,6 +90,25 @@ public class TenantManagementService { } + private void handleInternalException(PSQLException e) { + + log.error(String.format("Connection to tenant DB failed with SQL state %s. Please check if the tenant DB is still running. " + // + "If yes please check the connection configuration.", e.getSQLState()), e); + throw new RuntimeException("Could not connect to the tenant DB. This is an internal error.", e); + } + + + private void handleClientException(PSQLException e) { + + if (e.getSQLState().equals("28000") || e.getSQLState().equals("28P01")) { + throw new IllegalArgumentException("Database credentials are not correct. Please check them.", e); + } + if (SQL_CONNECTION_ERROR_CODES.contains(e.getSQLState())) { + throw new IllegalArgumentException("Error when connecting to tenant database. Please check the jdbcUrl parameter.", e); + } + } + + public List getTenants() { return tenantRepository.findAll().stream().map(this::convert).collect(Collectors.toList()); @@ -94,6 +121,14 @@ public class TenantManagementService { } + @SneakyThrows + private void validateJdbcUrl(String jdbcUrl) { + // just create a URI object to check if the string is a valid URI + new URI(jdbcUrl); + + } + + private TenantResponse convert(TenantEntity entity) { return TenantResponse.builder()