Merge branch 'RED-6668' into 'main'
RED-6888: Add delete tenant endpoint See merge request fforesight/tenant-user-management-service!66
This commit is contained in:
commit
95778f7926
@ -4,11 +4,13 @@ import java.util.List;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
@ -33,6 +35,13 @@ public interface TenantsResource {
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
|
||||
void createTenant(@RequestBody TenantRequest tenant);
|
||||
|
||||
@ResponseBody
|
||||
@ResponseStatus(value = HttpStatus.NO_CONTENT)
|
||||
@Operation(summary = "Deletes given tenant", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "204", description = "OK"), @ApiResponse(responseCode = "405", description = "Operation is not allowed."), @ApiResponse(responseCode = "409", description = "Conflict while deleting tenant.")})
|
||||
@DeleteMapping(value = "/tenants/{tenantId}")
|
||||
void deleteTenant(@PathVariable("tenantId") String tenantId);
|
||||
|
||||
|
||||
@GetMapping(value = "/tenants", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Gets all existing tenants", description = "None")
|
||||
|
||||
@ -47,6 +47,17 @@ public class TenantsController implements TenantsResource, PublicResource {
|
||||
}
|
||||
|
||||
|
||||
public void deleteTenant(String tenantId) {
|
||||
|
||||
try {
|
||||
tenantManagementService.deleteTenant(tenantId);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage(), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@PreAuthorize("hasAuthority('" + GET_TENANTS + "')")
|
||||
public List<TenantResponse> getTenants() {
|
||||
|
||||
@ -70,8 +81,7 @@ public class TenantsController implements TenantsResource, PublicResource {
|
||||
|
||||
|
||||
@PreAuthorize("hasAuthority('" + UPDATE_TENANT + "')")
|
||||
public TenantResponse updateTenant(String tenantId,
|
||||
@RequestBody TenantRequest tenantRequest) {
|
||||
public TenantResponse updateTenant(String tenantId, @RequestBody TenantRequest tenantRequest) {
|
||||
|
||||
TenantResponse tenantResponse = tenantManagementService.updateTenant(tenantId, tenantRequest);
|
||||
return tenantManagementService.removePasswords(tenantResponse);
|
||||
|
||||
@ -20,7 +20,6 @@ public class MessagingConfiguration {
|
||||
return new TopicExchange(tenantExchangeName);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
TopicExchange userExchange(@Value("${fforesight.user-exchange.name}") String userExchangeName) {
|
||||
|
||||
|
||||
@ -19,6 +19,8 @@ public class UserManagementPermissions {
|
||||
public static final String CREATE_TENANT = "fforesight-create-tenant";
|
||||
public static final String GET_TENANTS = "fforesight-get-tenants";
|
||||
public static final String UPDATE_TENANT = "fforesight-update-tenant";
|
||||
|
||||
public static final String DELETE_TENANT="fforesight-delete-tenant";
|
||||
public static final String DEPLOYMENT_INFO = "fforesight-deployment-info";
|
||||
|
||||
// SMTP
|
||||
|
||||
@ -33,6 +33,11 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import com.azure.storage.blob.BlobClient;
|
||||
import com.azure.storage.blob.BlobContainerClient;
|
||||
import com.azure.storage.blob.BlobServiceClient;
|
||||
import com.azure.storage.blob.BlobServiceClientBuilder;
|
||||
import com.azure.storage.blob.models.BlobItem;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.knecon.fforesight.tenantcommons.EncryptionDecryptionService;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
@ -59,6 +64,12 @@ import com.knecon.fforesight.tenantusermanagement.utils.JDBCUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import software.amazon.awssdk.services.s3.S3Client;
|
||||
import software.amazon.awssdk.services.s3.model.DeleteBucketRequest;
|
||||
import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
|
||||
import software.amazon.awssdk.services.s3.model.ListObjectsRequest;
|
||||
import software.amazon.awssdk.services.s3.model.ListObjectsResponse;
|
||||
import software.amazon.awssdk.services.s3.model.S3Object;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@ -85,7 +96,6 @@ public class TenantManagementService implements TenantProvider {
|
||||
@Value("${fforesight.tenant-exchange.name}")
|
||||
private String tenantExchangeName;
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
public TenantResponse createTenant(TenantRequest tenantRequest) {
|
||||
|
||||
@ -182,6 +192,61 @@ public class TenantManagementService implements TenantProvider {
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public void deleteTenant(String tenantId) {
|
||||
|
||||
TenantResponse tenant = this.getTenant(tenantId);
|
||||
log.info("Requested to delete tenant for: {}", tenant.getTenantId());
|
||||
log.info("Deleting tenant: {}", tenant.getTenantId());
|
||||
log.info("Deleting search index for tenant: {}", tenant.getTenantId());
|
||||
TenantContext.setTenantId(tenant.getTenantId());
|
||||
rabbitTemplate.convertAndSend(tenantExchangeName, "tenant.deleted", tenant);
|
||||
TenantContext.clear();
|
||||
|
||||
log.info("Dispatched delete index message for tenant: {}", tenant.getTenantId());
|
||||
deleteSchema(tenant);
|
||||
if(tenant.getAzureStorageConnection() != null ) {
|
||||
log.info("Deleting azure blob for tenant: {}",tenantId);
|
||||
String connectionString = tenant.getAzureStorageConnection().getConnectionString();
|
||||
String containerName = tenant.getAzureStorageConnection().getContainerName();
|
||||
|
||||
BlobServiceClient blobServiceClient = new BlobServiceClientBuilder().connectionString(connectionString).buildClient();
|
||||
BlobContainerClient containerClient = blobServiceClient.getBlobContainerClient(containerName);
|
||||
|
||||
// Delete all blobs within the container
|
||||
for (BlobItem blobItem : containerClient.listBlobs()) {
|
||||
BlobClient blobClient = containerClient.getBlobClient(blobItem.getName());
|
||||
blobClient.delete();
|
||||
}
|
||||
containerClient.delete();
|
||||
}
|
||||
|
||||
if(tenant.getS3StorageConnection() != null) {
|
||||
var s3StorageConnectionTemplate = tenant.getS3StorageConnection();
|
||||
com.iqser.red.storage.commons.model.S3StorageConnection s3StorageConnection = new com.iqser.red.storage.commons.model.S3StorageConnection(s3StorageConnectionTemplate.getKey(), encryptionService.decrypt(s3StorageConnectionTemplate.getSecret()), s3StorageConnectionTemplate.getSignerType(), s3StorageConnectionTemplate.getBucketName(), s3StorageConnectionTemplate.getRegion(),s3StorageConnectionTemplate.getEndpoint());
|
||||
log.info("Deleting s3 bucket for tenant: {}",tenantId);
|
||||
S3Client client = storageConfiguration.getS3StorageService().initAmazonS3(s3StorageConnection);
|
||||
String bucketName = s3StorageConnection.getBucketName();
|
||||
ListObjectsRequest listObjects = ListObjectsRequest
|
||||
.builder()
|
||||
.bucket(bucketName)
|
||||
.build();
|
||||
ListObjectsResponse objectList = client.listObjects(listObjects);
|
||||
for (S3Object object : objectList.contents()) {
|
||||
// Delete each object
|
||||
client.deleteObject(DeleteObjectRequest.builder().bucket(bucketName).key(object.key()).build());
|
||||
}
|
||||
DeleteBucketRequest deleteBucketRequest = DeleteBucketRequest.builder()
|
||||
.bucket(bucketName)
|
||||
.expectedBucketOwner(tenantId)
|
||||
.build();
|
||||
client.deleteBucket(deleteBucketRequest);
|
||||
}
|
||||
deleteRealm(tenantId);
|
||||
tenantRepository.deleteById(tenant.getTenantId());
|
||||
|
||||
}
|
||||
|
||||
|
||||
private String buildIndexPrefix(String tenantId) {
|
||||
|
||||
@ -257,6 +322,24 @@ public class TenantManagementService implements TenantProvider {
|
||||
}
|
||||
|
||||
|
||||
private void deleteSchema(TenantResponse tenant) {
|
||||
log.info("Deleting schema for tenant: {}", tenant.getTenantId());
|
||||
var jdbcUrl = JDBCUtils.buildJdbcUrl(tenant.getDatabaseConnection());
|
||||
try (Connection connection = DriverManager.getConnection(jdbcUrl,
|
||||
tenant.getDatabaseConnection().getUsername(),
|
||||
this.encryptionService.decrypt(tenant.getDatabaseConnection().getPassword())))
|
||||
{
|
||||
DataSource tenantDataSource = new SingleConnectionDataSource(connection, false);
|
||||
JdbcTemplate jdbcTemplate = new JdbcTemplate(tenantDataSource);
|
||||
String deleteStatement = "DROP SCHEMA IF EXISTS \"" + tenant.getDatabaseConnection().getSchema() + "\" CASCADE;";
|
||||
jdbcTemplate.execute(deleteStatement);
|
||||
} catch (Exception e) {
|
||||
log.warn("Could not delete schema:", e);
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Tenant deletion failed: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void createOrUpdateRealm(String tenantId, List<TenantUser> users) {
|
||||
|
||||
if (syncRealmIfExists(tenantId)) {
|
||||
@ -281,6 +364,20 @@ public class TenantManagementService implements TenantProvider {
|
||||
keycloak.getAdminClient().realms().create(realm);
|
||||
}
|
||||
|
||||
public void deleteRealm(String tenantId) {
|
||||
|
||||
try {
|
||||
log.info("Deleting existing realms for tenant: {}", tenantId);
|
||||
keycloak.getAdminClient().realm(tenantId).remove();
|
||||
}
|
||||
|
||||
catch (Exception e) {
|
||||
log.warn("Could not delete realm:", e);
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Tenant deletion failed: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private boolean syncRealmIfExists(String tenantId) {
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user