diff --git a/src/main/java/com/knecon/fforesight/tenantusermanagement/api/external/TenantsResource.java b/src/main/java/com/knecon/fforesight/tenantusermanagement/api/external/TenantsResource.java index 89f593c..bf605a1 100644 --- a/src/main/java/com/knecon/fforesight/tenantusermanagement/api/external/TenantsResource.java +++ b/src/main/java/com/knecon/fforesight/tenantusermanagement/api/external/TenantsResource.java @@ -7,8 +7,8 @@ import org.springframework.http.MediaType; 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.RequestMapping; import org.springframework.web.bind.annotation.ResponseStatus; import com.knecon.fforesight.tenantcommons.model.TenantResponse; @@ -44,6 +44,10 @@ public interface TenantsResource { @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")}) TenantResponse getTenant(@PathVariable("tenantId") String tenantId); + @PutMapping(value = "/tenants/{tenantId}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Update existing tenant", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")}) + TenantResponse updateTenant(@PathVariable("tenantId") String tenantId, @RequestBody TenantRequest tenantRequest); @GetMapping(value = "/tenants/simple", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Gets all existing tenant in a simplified format", description = "None") diff --git a/src/main/java/com/knecon/fforesight/tenantusermanagement/api/internal/InternalTenantsResource.java b/src/main/java/com/knecon/fforesight/tenantusermanagement/api/internal/InternalTenantsResource.java index 31e5f9b..6604bda 100644 --- a/src/main/java/com/knecon/fforesight/tenantusermanagement/api/internal/InternalTenantsResource.java +++ b/src/main/java/com/knecon/fforesight/tenantusermanagement/api/internal/InternalTenantsResource.java @@ -7,8 +7,8 @@ import org.springframework.http.MediaType; 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.RequestMapping; import org.springframework.web.bind.annotation.ResponseStatus; import com.knecon.fforesight.tenantcommons.model.TenantResponse; @@ -51,6 +51,11 @@ public interface InternalTenantsResource { @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")}) TenantResponse getTenant(@PathVariable("tenantId") String tenantId); + @PutMapping(value = "/tenants/{tenantId}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Update existing tenant", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")}) + TenantResponse updateTenant(@PathVariable("tenantId") String tenantId, @RequestBody TenantRequest tenantRequest); + @GetMapping(value = "/tenants/simple", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Gets all existing tenant in a simplified format", description = "None") diff --git a/src/main/java/com/knecon/fforesight/tenantusermanagement/controller/external/TenantsController.java b/src/main/java/com/knecon/fforesight/tenantusermanagement/controller/external/TenantsController.java index 6e91034..8e897e5 100644 --- a/src/main/java/com/knecon/fforesight/tenantusermanagement/controller/external/TenantsController.java +++ b/src/main/java/com/knecon/fforesight/tenantusermanagement/controller/external/TenantsController.java @@ -3,6 +3,7 @@ package com.knecon.fforesight.tenantusermanagement.controller.external; import static com.knecon.fforesight.tenantusermanagement.permissions.UserManagementPermissions.CREATE_TENANT; import static com.knecon.fforesight.tenantusermanagement.permissions.UserManagementPermissions.DEPLOYMENT_INFO; import static com.knecon.fforesight.tenantusermanagement.permissions.UserManagementPermissions.GET_TENANTS; +import static com.knecon.fforesight.tenantusermanagement.permissions.UserManagementPermissions.UPDATE_TENANT; import java.util.List; @@ -63,6 +64,13 @@ public class TenantsController implements TenantsResource, PublicResource { return tenantManagementService.getTenants().stream().map(t -> new SimpleTenantResponse(t.getTenantId(), t.getDisplayName(), t.getGuid())).toList(); } + @PreAuthorize("hasAuthority('" + UPDATE_TENANT + "')") + public TenantResponse updateTenant(String tenantId, + @RequestBody TenantRequest tenantRequest) { + + return tenantManagementService.updateTenant(tenantId, tenantRequest); + } + @PreAuthorize("hasAuthority('" + DEPLOYMENT_INFO + "')") public DeploymentKeyResponse getDeploymentKey(@PathVariable(TENANT_ID_PARAM) String tenantId) { diff --git a/src/main/java/com/knecon/fforesight/tenantusermanagement/controller/internal/InternalTenantsController.java b/src/main/java/com/knecon/fforesight/tenantusermanagement/controller/internal/InternalTenantsController.java index e3453e7..123fb38 100644 --- a/src/main/java/com/knecon/fforesight/tenantusermanagement/controller/internal/InternalTenantsController.java +++ b/src/main/java/com/knecon/fforesight/tenantusermanagement/controller/internal/InternalTenantsController.java @@ -10,7 +10,6 @@ import org.springframework.web.server.ResponseStatusException; import com.knecon.fforesight.tenantcommons.model.TenantResponse; import com.knecon.fforesight.tenantcommons.model.UpdateDetailsRequest; -import com.knecon.fforesight.tenantusermanagement.api.external.PublicResource; import com.knecon.fforesight.tenantusermanagement.api.internal.InternalResource; import com.knecon.fforesight.tenantusermanagement.api.internal.InternalTenantsResource; import com.knecon.fforesight.tenantusermanagement.model.DeploymentKeyResponse; @@ -59,6 +58,13 @@ public class InternalTenantsController implements InternalTenantsResource, Inter } + @Override + public TenantResponse updateTenant(String tenantId, TenantRequest tenantRequest) { + + return tenantManagementService.updateTenant(tenantId, tenantRequest); + } + + public List getSimpleTenants() { return tenantManagementService.getTenants().stream().map(t -> new SimpleTenantResponse(t.getTenantId(), t.getDisplayName(), t.getGuid())).toList(); diff --git a/src/main/java/com/knecon/fforesight/tenantusermanagement/permissions/UserManagementPermissions.java b/src/main/java/com/knecon/fforesight/tenantusermanagement/permissions/UserManagementPermissions.java index 93433f0..7d02967 100644 --- a/src/main/java/com/knecon/fforesight/tenantusermanagement/permissions/UserManagementPermissions.java +++ b/src/main/java/com/knecon/fforesight/tenantusermanagement/permissions/UserManagementPermissions.java @@ -18,6 +18,7 @@ public class UserManagementPermissions { // Multitenancy 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 DEPLOYMENT_INFO = "fforesight-deployment-info"; // SMTP diff --git a/src/main/java/com/knecon/fforesight/tenantusermanagement/service/TenantManagementService.java b/src/main/java/com/knecon/fforesight/tenantusermanagement/service/TenantManagementService.java index a365be5..142b4c5 100644 --- a/src/main/java/com/knecon/fforesight/tenantusermanagement/service/TenantManagementService.java +++ b/src/main/java/com/knecon/fforesight/tenantusermanagement/service/TenantManagementService.java @@ -82,7 +82,7 @@ public class TenantManagementService implements TenantProvider { @SneakyThrows public TenantResponse createTenant(TenantRequest tenantRequest) { - log.info("Tenants are: {}", tenantRepository.findAll().stream().map(t -> t.getTenantId()).collect(Collectors.toList())); + log.info("Tenants are: {}", tenantRepository.findAll().stream().map(TenantEntity::getTenantId).collect(Collectors.toList())); log.info("Requested to create tenant for: {}", tenantRequest.getTenantId()); try { @@ -352,6 +352,69 @@ public class TenantManagementService implements TenantProvider { return tenantRepository.findById(tenantId).map(this::convert).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Tenant does not exist")); } + public TenantResponse updateTenant(String tenantId, TenantRequest tenantRequest) { + + var tenant = tenantRepository.findById(tenantId); + if (tenant.isPresent()) { + var tenantEntity = tenant.get(); + + tenantEntity.setDisplayName(tenantRequest.getDisplayName()); + + var databaseConnection = tenantRequest.getDatabaseConnection(); + if (databaseConnection != null) { + tenantEntity.setDatabaseConnection(DatabaseConnectionEntity.builder() + .driver(databaseConnection.getDriver()) + .host(databaseConnection.getHost()) + .port(databaseConnection.getPort()) + .database(databaseConnection.getDatabase()) + .schema(databaseConnection.getSchema()) + .username(databaseConnection.getUsername()) + .password(encryptionService.encrypt(databaseConnection.getPassword())) + .params(databaseConnection.getParams()) + .build()); + } + + var searchConnection = tenantRequest.getSearchConnection(); + if (searchConnection != null) { + tenantEntity.setSearchConnection(SearchConnectionEntity.builder() + .hosts(searchConnection.getHosts()) + .port(searchConnection.getPort()) + .scheme(searchConnection.getScheme()) + .username(searchConnection.getUsername()) + .password(encryptionService.encrypt(searchConnection.getPassword())) + .numberOfShards(searchConnection.getNumberOfShards()) + .numberOfReplicas(searchConnection.getNumberOfReplicas()) + .build()); + } + + var azureStorageConnection = tenantRequest.getAzureStorageConnection(); + if (azureStorageConnection != null) { + tenantEntity + .setAzureStorageConnection(AzureStorageConnectionEntity.builder() + .connectionString(encryptionService.encrypt(azureStorageConnection.getConnectionString())) + .containerName(azureStorageConnection.getContainerName()) + .build()); + } + + var s3StorageConnection = tenantRequest.getS3StorageConnection(); + if (s3StorageConnection != null) { + tenantEntity + .setS3StorageConnection(S3StorageConnectionEntity.builder() + .key(s3StorageConnection.getKey()) + .secret(encryptionService.encrypt(s3StorageConnection.getSecret())) + .signerType(s3StorageConnection.getSignerType()) + .bucketName(s3StorageConnection.getBucketName()) + .region(s3StorageConnection.getRegion()) + .endpoint(s3StorageConnection.getEndpoint()) + .build()); + } + + return convert(tenantRepository.save(tenantEntity)); + } else { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Tenant does not exist"); + } + } + public List getTenants() { diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml index 5d34eb1..04b27fc 100644 --- a/src/main/resources/application-dev.yaml +++ b/src/main/resources/application-dev.yaml @@ -23,6 +23,7 @@ fforesight: - 'fforesight-update-my-profile' - 'fforesight-create-tenant' - 'fforesight-get-tenants' + - 'fforesight-update-tenant' - 'fforesight-deployment-info' - 'fforesight-read-smtp-configuration' - 'fforesight-write-smtp-configuration' diff --git a/src/main/resources/application-documine.yaml b/src/main/resources/application-documine.yaml index e875515..67b2695 100644 --- a/src/main/resources/application-documine.yaml +++ b/src/main/resources/application-documine.yaml @@ -13,7 +13,7 @@ fforesight: default-theme: 'scm' valid-redirect-uris: [ '/redaction-gateway-v1/*','/tenant-user-management/*','http://localhost:4200/*','/ui/*' ,'/auth/*' ] kc-role-mapping: - unmappedPermissions: [ "red-unarchive-dossier", "red-update-license", "fforesight-create-tenant" ] + unmappedPermissions: [ "red-unarchive-dossier", "red-update-license", "fforesight-create-tenant", "fforesight-update-tenant" ] compositeRoles: - name: RED_MANAGER composites: @@ -45,7 +45,7 @@ fforesight: "red-read-legal-basis", "red-read-license-report", "red-read-notification", "red-read-rules", "fforesight-read-smtp-configuration", "red-read-versions", "red-read-watermark", "red-reindex", "red-search-audit-log", "red-update-notification", "red-upload-report-template", "red-write-colors", "red-write-digital-signature", "red-write-dossier-attributes-config", "red-write-dossier-templates", "red-write-file-attributes-config", "fforesight-write-general-configuration", "red-write-legal-basis", "red-write-rules", "fforesight-write-smtp-configuration", - "red-write-watermark", "red-write-app-configuration", "red-manage-acl-permissions", "fforesight-create-tenant", "fforesight-get-tenants", "fforesight-deployment-info" ] + "red-write-watermark", "red-write-app-configuration", "red-manage-acl-permissions", "fforesight-create-tenant", "fforesight-get-tenants", "fforesight-update-tenant", "fforesight-deployment-info" ] - name: RED_MANAGER set-by-default: false rank: 200 diff --git a/src/main/resources/application-redaction.yaml b/src/main/resources/application-redaction.yaml index 1eb7502..17461a2 100644 --- a/src/main/resources/application-redaction.yaml +++ b/src/main/resources/application-redaction.yaml @@ -8,7 +8,7 @@ fforesight: default-theme: 'redaction' valid-redirect-uris: [ '/redaction-gateway-v1/*','/tenant-user-management/*','http://localhost:4200/*','/ui/*' ,'/auth/*'] kc-role-mapping: - unmappedPermissions: [ "red-unarchive-dossier", "red-update-license", "red-get-rss","fforesight-create-tenant" ] + unmappedPermissions: [ "red-unarchive-dossier", "red-update-license", "red-get-rss","fforesight-create-tenant", "fforesight-update-tenant" ] compositeRoles: - name: RED_MANAGER composites: @@ -40,7 +40,7 @@ fforesight: "red-read-legal-basis", "red-read-license-report", "red-read-notification", "red-read-rules", "fforesight-read-smtp-configuration", "red-read-versions", "red-read-watermark", "red-reindex", "red-search-audit-log", "red-update-notification", "red-upload-report-template", "red-write-colors", "red-write-digital-signature", "red-write-dossier-attributes-config", "red-write-dossier-templates", "red-write-file-attributes-config", "fforesight-write-general-configuration", "red-write-legal-basis", "red-write-rules", "fforesight-write-smtp-configuration", - "red-write-watermark", "red-write-app-configuration", "red-manage-acl-permissions", "fforesight-create-tenant", "fforesight-get-tenants", "fforesight-deployment-info" ] + "red-write-watermark", "red-write-app-configuration", "red-manage-acl-permissions", "fforesight-create-tenant", "fforesight-get-tenants", "fforesight-update-tenant", "fforesight-deployment-info" ] - name: RED_MANAGER set-by-default: false rank: 200 diff --git a/src/test/java/com/knecon/fforesight/tests/TenantsTest.java b/src/test/java/com/knecon/fforesight/tests/TenantsTest.java index d02dac2..8f4ed01 100644 --- a/src/test/java/com/knecon/fforesight/tests/TenantsTest.java +++ b/src/test/java/com/knecon/fforesight/tests/TenantsTest.java @@ -2,13 +2,21 @@ package com.knecon.fforesight.tests; import static org.assertj.core.api.Assertions.assertThat; +import java.util.Map; +import java.util.Set; + import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import com.knecon.fforesight.AbstractTenantUserManagementIntegrationTest; import com.knecon.fforesight.feigntestclients.external.TenantsClient; +import com.knecon.fforesight.tenantcommons.EncryptionDecryptionService; import com.knecon.fforesight.tenantcommons.TenantContext; -import com.knecon.fforesight.tenantusermanagement.api.external.TenantsResource; +import com.knecon.fforesight.tenantcommons.model.AzureStorageConnection; +import com.knecon.fforesight.tenantcommons.model.DatabaseConnection; +import com.knecon.fforesight.tenantcommons.model.S3StorageConnection; +import com.knecon.fforesight.tenantcommons.model.SearchConnection; +import com.knecon.fforesight.tenantusermanagement.model.TenantRequest; import com.knecon.fforesight.utils.TestTenantService; public class TenantsTest extends AbstractTenantUserManagementIntegrationTest { @@ -19,6 +27,9 @@ public class TenantsTest extends AbstractTenantUserManagementIntegrationTest { @Autowired private TestTenantService testTenantService; + @Autowired + private EncryptionDecryptionService encryptionService; + @Test public void testCreateNewTenant() { @@ -37,4 +48,62 @@ public class TenantsTest extends AbstractTenantUserManagementIntegrationTest { TenantContext.clear(); } + @Test + public void testUpdateTenant() { + + testTenantService.createTestTenantIfNotExists("new_tenant"); + TenantContext.setTenantId("new_tenant"); + + var tenantRequest = TenantRequest.builder() + .tenantId("new_tenant") + .displayName("updated_display_name") + .searchConnection(SearchConnection.builder() + .numberOfReplicas("1") + .hosts(Set.of("updated_host")) + .numberOfShards("2") + .password("updated_pwd") + .port(123) + .username("updated_username") + .scheme("updated_scheme") + .build()) + .databaseConnection(DatabaseConnection.builder() + .database("updated_db") + .driver("updated_driver") + .host("updated_host") + .port("123") + .schema("updated_schema") + .params(Map.of("key", "value")) + .password("updated_pwd") + .username("updated_username") + .build()) + .s3StorageConnection(S3StorageConnection.builder() + .key("updated_key") + .bucketName("updated_bucket") + .endpoint("updated_endpoint") + .region("updated_region") + .secret("updated_secret") + .signerType("updated_signer") + .build()) + .azureStorageConnection(AzureStorageConnection.builder() + .connectionString("updated_connection") + .containerName("updated_container") + .build()) + .build(); + + var tenantEntity = tenantsClient.updateTenant("new_tenant", tenantRequest); + + tenantRequest.getS3StorageConnection().setSecret(encryptionService.encrypt("updated_secret")); + tenantRequest.getAzureStorageConnection().setConnectionString(encryptionService.encrypt("updated_connection")); + tenantRequest.getSearchConnection().setPassword(encryptionService.encrypt("updated_pwd")); + tenantRequest.getDatabaseConnection().setPassword(encryptionService.encrypt("updated_pwd")); + + assertThat(tenantEntity.getDisplayName()).isEqualTo(tenantRequest.getDisplayName()); + assertThat(tenantEntity.getS3StorageConnection()).isEqualTo(tenantRequest.getS3StorageConnection()); + assertThat(tenantEntity.getAzureStorageConnection()).isEqualTo(tenantRequest.getAzureStorageConnection()); + assertThat(tenantEntity.getSearchConnection()).isEqualTo(tenantRequest.getSearchConnection()); + assertThat(tenantEntity.getDatabaseConnection()).isEqualTo(tenantRequest.getDatabaseConnection()); + + TenantContext.clear(); + } + } diff --git a/src/test/java/com/knecon/fforesight/utils/TokenService.java b/src/test/java/com/knecon/fforesight/utils/TokenService.java index 35d264f..b3f6b40 100644 --- a/src/test/java/com/knecon/fforesight/utils/TokenService.java +++ b/src/test/java/com/knecon/fforesight/utils/TokenService.java @@ -30,7 +30,6 @@ public class TokenService { private String password; private String accessToken; - @SuppressWarnings("PMD") public void setUser(String username, String password) { diff --git a/src/test/resources/application.yaml b/src/test/resources/application.yaml index 8455b38..b9d246d 100644 --- a/src/test/resources/application.yaml +++ b/src/test/resources/application.yaml @@ -118,6 +118,7 @@ fforesight: - 'fforesight-update-my-profile' - 'fforesight-create-tenant' - 'fforesight-get-tenants' + - 'fforesight-update-tenant' - 'fforesight-deployment-info' - 'fforesight-read-smtp-configuration' - 'fforesight-write-smtp-configuration'