Tenant Creation exception rework

This commit is contained in:
Timo Bejan 2023-06-28 11:39:18 +03:00
parent 1ede240122
commit 7e28e5574e
7 changed files with 109 additions and 30 deletions

View File

@ -38,7 +38,7 @@ public interface InternalTenantsResource {
@PostMapping(value = "/tenants", consumes = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Creates a new Tenant", description = "None")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
void createTenant(@RequestBody TenantRequest tenant);
TenantResponse createTenant(@RequestBody TenantRequest tenant);
@GetMapping(value = "/tenants", produces = MediaType.APPLICATION_JSON_VALUE)

View File

@ -0,0 +1,21 @@
package com.knecon.fforesight.tenantusermanagement.controller;
import javax.ws.rs.core.Response;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.server.ResponseStatusException;
import com.knecon.fforesight.tenantusermanagement.model.ErrorMessage;
@RestControllerAdvice
public class ControllerAdvice {
@ExceptionHandler(ResponseStatusException.class)
public ResponseEntity<ErrorMessage> handleResponseStatusException(ResponseStatusException e) {
return new ResponseEntity<>(new ErrorMessage(e.getMessage()), e.getStatusCode());
}
}

View File

@ -35,10 +35,10 @@ public class InternalTenantsController implements InternalTenantsResource {
}
public void createTenant(@Valid @RequestBody TenantRequest tenantRequest) {
public TenantResponse createTenant(@Valid @RequestBody TenantRequest tenantRequest) {
try {
tenantManagementService.createTenant(tenantRequest);
return tenantManagementService.createTenant(tenantRequest);
} catch (IllegalArgumentException e) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage(), e);
}

View File

@ -0,0 +1,15 @@
package com.knecon.fforesight.tenantusermanagement.model;
import java.time.OffsetDateTime;
import lombok.Data;
import lombok.RequiredArgsConstructor;
@Data
@RequiredArgsConstructor
public class ErrorMessage {
private OffsetDateTime timestamp = OffsetDateTime.now();
private final String message;
}

View File

@ -3,11 +3,15 @@ package com.knecon.fforesight.tenantusermanagement.model;
import java.util.HashSet;
import java.util.Set;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TenantUser {
private String username;

View File

@ -13,6 +13,7 @@ import java.util.UUID;
import java.util.stream.Collectors;
import javax.sql.DataSource;
import javax.ws.rs.ClientErrorException;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation;
@ -66,6 +67,7 @@ public class TenantManagementService implements TenantProvider {
private final EncryptionDecryptionService encryptionService;
private final TenantRepository tenantRepository;
private final TenantPersistenceService tenantPersistenceService;
private final GeneralConfigurationService generalConfigurationService;
private final KeyCloakRoleManagerService keyCloakRoleManagerService;
private final KeyCloakAdminClientService keycloak;
@ -78,8 +80,9 @@ public class TenantManagementService implements TenantProvider {
@SneakyThrows
public void createTenant(TenantRequest tenantRequest) {
public TenantResponse createTenant(TenantRequest tenantRequest) {
log.info("Tenants are: {}",tenantRepository.findAll().stream().map(t-> t.getTenantId()).collect(Collectors.toList()));
log.info("Requested to create tenant for: {}", tenantRequest.getTenantId());
try {
@ -134,32 +137,11 @@ public class TenantManagementService implements TenantProvider {
.build());
}
createRealm(tenantRequest.getTenantId(), tenantRequest.getDefaultUsers());
log.info("Created realm for tenant: {}", tenantRequest.getTenantId());
var waitTime = 0;
boolean realmReady;
do {
realmReady = tryToAccessRealm(tenantRequest.getTenantId());
if (realmReady) {
break;
} else {
Thread.sleep(1_000L);
waitTime += 1_000L;
}
} while (waitTime < MAX_WAIT_TIME);
if (!realmReady) {
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to create KC realm");
}
generalConfigurationService.initGeneralConfiguration(tenantRequest.getTenantId());
keyCloakRoleManagerService.updateRoles(tenantRequest.getTenantId());
propagateTenantToKeyCloak(tenantRequest);
log.info("Updated roles for tenant: {}", tenantRequest.getTenantId());
tenantRepository.save(tenantEntity);
var saved = tenantPersistenceService.save(tenantEntity);
log.info("Persisted tenant: {}", tenantRequest.getTenantId());
@ -169,17 +151,50 @@ public class TenantManagementService implements TenantProvider {
log.info("Dispatched message for tenant: {}", tenantRequest.getTenantId());
return convert(saved);
} else {
throw new ResponseStatusException(HttpStatus.CONFLICT, "Tenant exists");
}
} catch (ClientErrorException e) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Tenant creation failed: " + e.getMessage(), e);
} catch (Exception e) {
log.error("Tenant creation failed, rolling back", e);
tenantRepository.deleteById(tenantRequest.getTenantId());
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Tenant creation failed", e);
if (!(e instanceof ResponseStatusException)) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Tenant creation failed: " + e.getMessage(), e);
}else{
throw e;
}
}
}
private void propagateTenantToKeyCloak(TenantRequest tenantRequest) throws InterruptedException {
createRealm(tenantRequest.getTenantId(), tenantRequest.getDefaultUsers());
log.info("Created realm for tenant: {}", tenantRequest.getTenantId());
var waitTime = 0;
boolean realmReady;
do {
realmReady = tryToAccessRealm(tenantRequest.getTenantId());
if (realmReady) {
break;
} else {
Thread.sleep(1_000L);
waitTime += 1_000L;
}
} while (waitTime < MAX_WAIT_TIME);
if (!realmReady) {
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to create KC realm");
}
generalConfigurationService.initGeneralConfiguration(tenantRequest.getTenantId());
keyCloakRoleManagerService.updateRoles(tenantRequest.getTenantId());
}
@SneakyThrows
private void validateJdbcUrl(String jdbcUrl) {

View File

@ -0,0 +1,24 @@
package com.knecon.fforesight.tenantusermanagement.service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.knecon.fforesight.tenantusermanagement.entity.TenantEntity;
import com.knecon.fforesight.tenantusermanagement.repository.TenantRepository;
import lombok.RequiredArgsConstructor;
@Service
@RequiredArgsConstructor
public class TenantPersistenceService {
private final TenantRepository tenantRepository;
@Transactional
public TenantEntity save(TenantEntity tenant) {
return tenantRepository.save(tenant);
}
}