diff --git a/provider/partition-azure/pom.xml b/provider/partition-azure/pom.xml index 64583de9e8412c127317121903b4d704c18a6bd7..f723fb7a46601dc95fa946bc67eab7cecdf9e4b5 100644 --- a/provider/partition-azure/pom.xml +++ b/provider/partition-azure/pom.xml @@ -184,6 +184,11 @@ <artifactId>slf4j-api</artifactId> <version>1.7.36</version> </dependency> + <dependency> + <groupId>org.redisson</groupId> + <artifactId>redisson</artifactId> + <version>3.34.1</version> + </dependency> </dependencies> <build> diff --git a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/config/AzureConfig.java b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/config/AzureConfig.java index 53089019341afe47454fd79dd6d039aea3cf0d4b..1902c46410f6b903fe19555e1cb2367cc7678da3 100644 --- a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/config/AzureConfig.java +++ b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/config/AzureConfig.java @@ -1,15 +1,21 @@ package org.opengroup.osdu.partition.provider.azure.config; import com.microsoft.applicationinsights.TelemetryClient; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AzureConfig { + @Value("${reserved_partition_name:system}") + private String reservedPartition; @Bean public TelemetryClient telemetryClient() { return new TelemetryClient(); } + public Boolean isReservedPartition(String partitionName) { + return reservedPartition.equalsIgnoreCase(partitionName); + } } diff --git a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImpl.java b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImpl.java index f433b65c192ee89d9798c6bee63a43f3b2ee4451..e4009eb96cf1fffc674fbfd2482d8ff12e833582 100644 --- a/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImpl.java +++ b/provider/partition-azure/src/main/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImpl.java @@ -19,6 +19,7 @@ import org.opengroup.osdu.core.common.cache.ICache; import org.opengroup.osdu.core.common.model.http.AppException; import org.opengroup.osdu.partition.model.PartitionInfo; import org.opengroup.osdu.partition.model.Property; +import org.opengroup.osdu.partition.provider.azure.config.AzureConfig; import org.opengroup.osdu.partition.provider.azure.persistence.PartitionTableStore; import org.opengroup.osdu.partition.provider.interfaces.IPartitionService; import org.springframework.beans.factory.annotation.Autowired; @@ -34,6 +35,8 @@ import java.util.Optional; @Service public class PartitionServiceImpl implements IPartitionService { + private static final String SYSTEM_PARTITION_DELETE_ERROR = "System partition is reserved for system and shared usage, currently it cannot Deleted"; + private static final String NOT_ALLOWED = "Not Allowed"; static final String PARTITION_LIST_KEY = "getAllPartitions"; static final String PARTITION_NOT_FOUND = "partition not found"; @@ -48,6 +51,9 @@ public class PartitionServiceImpl implements IPartitionService { @Qualifier("partitionListCache") private ICache<String, List<String>> partitionListCache; + @Autowired + private AzureConfig azureConfig; + @Override public PartitionInfo createPartition(String partitionId, PartitionInfo partitionInfo) { if (partitionServiceCache.get(partitionId) != null || tableStore.partitionExists(partitionId)) { @@ -107,6 +113,9 @@ public class PartitionServiceImpl implements IPartitionService { @Override public boolean deletePartition(String partitionId) { + if(azureConfig.isReservedPartition(partitionId)) + throw new AppException(HttpStatus.SC_FORBIDDEN, NOT_ALLOWED, SYSTEM_PARTITION_DELETE_ERROR); + if (!tableStore.partitionExists(partitionId)) { throw new AppException(HttpStatus.SC_NOT_FOUND, PARTITION_NOT_FOUND, String.format("%s partition not found", partitionId)); } @@ -131,6 +140,13 @@ public class PartitionServiceImpl implements IPartitionService { partitionListCache.put(PARTITION_LIST_KEY, partitions); } } + + if(partitions != null) { + partitions = partitions.stream() + .filter(item-> !azureConfig.isReservedPartition(item)) + .toList(); + } + return partitions; } } diff --git a/provider/partition-azure/src/main/resources/application.properties b/provider/partition-azure/src/main/resources/application.properties index f96aefda1eb7a56e1c781daf02926658d3e0a272..2a452f30e98d542d1c9977777076d5ba6a42b9af 100644 --- a/provider/partition-azure/src/main/resources/application.properties +++ b/provider/partition-azure/src/main/resources/application.properties @@ -58,4 +58,6 @@ azure.eventgrid.manager.enabled=false azure.serviceBus.manager.enabled=false # To enable the full server path url in OpenAPI Swagger -api.server.fullUrl.enabled=${swaggerFullUrlEnabled:true} \ No newline at end of file +api.server.fullUrl.enabled=${swaggerFullUrlEnabled:true} + +reserved_partition_name=${reservedPartitionName:system} diff --git a/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImplCacheTest.java b/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImplCacheTest.java index 0c5daaba375afe9abd73ff7571ba36bf6a65a33d..6d5b22fabcb13195bf29268da791d0c320c0a19c 100644 --- a/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImplCacheTest.java +++ b/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImplCacheTest.java @@ -22,6 +22,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.opengroup.osdu.core.common.cache.ICache; import org.opengroup.osdu.partition.model.PartitionInfo; import org.opengroup.osdu.partition.model.Property; +import org.opengroup.osdu.partition.provider.azure.config.AzureConfig; import org.opengroup.osdu.partition.provider.azure.persistence.PartitionTableStore; import java.util.ArrayList; @@ -51,6 +52,10 @@ public class PartitionServiceImplCacheTest { @InjectMocks private PartitionServiceImpl partitionService; + @Mock + private AzureConfig azureConfig; + + @Test public void createPartitionSucceed() { String partId = "key"; diff --git a/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImplTest.java b/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImplTest.java index 85c6b14801765b03c4957a9f0ec8bb4071ee84a9..1e19e5be946851f88f2cca9789ca61e3fdf04068 100644 --- a/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImplTest.java +++ b/provider/partition-azure/src/test/java/org/opengroup/osdu/partition/provider/azure/service/PartitionServiceImplTest.java @@ -14,6 +14,7 @@ package org.opengroup.osdu.partition.provider.azure.service; +import org.apache.http.HttpStatus; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -24,10 +25,12 @@ import org.opengroup.osdu.core.common.cache.ICache; import org.opengroup.osdu.core.common.model.http.AppException; import org.opengroup.osdu.partition.model.PartitionInfo; import org.opengroup.osdu.partition.model.Property; +import org.opengroup.osdu.partition.provider.azure.config.AzureConfig; import org.opengroup.osdu.partition.provider.azure.persistence.PartitionTableStore; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -52,7 +55,8 @@ public class PartitionServiceImplTest { private PartitionTableStore tableStore; @InjectMocks private PartitionServiceImpl sut; - + @Mock + private AzureConfig azureConfig; private final PartitionInfo partitionInfo = new PartitionInfo(); private final static String PARTITION_ID = "my-tenant"; @@ -187,6 +191,14 @@ public class PartitionServiceImplTest { assertThrows(AppException.class, () -> sut.deletePartition(null)); } + @Test + public void should_throwException_when_deletingSystemPartition() { + when(azureConfig.isReservedPartition("system")).thenReturn(true); + AppException exception = assertThrows(AppException.class, () -> sut.deletePartition("system")); + + assertEquals(HttpStatus.SC_FORBIDDEN, exception.getError().getCode()); + } + @Test public void should_returnEmptyList_when_no_partitions() { when(this.tableStore.getAllPartitions()).thenReturn(new ArrayList<>()); @@ -227,4 +239,17 @@ public class PartitionServiceImplTest { assertNotNull(partitions); assertEquals(partitionsList, partitions); } + + @Test + public void should_returnPartitionListExceptSystemPartition_when_partitionsExists() { + List<String> partitionsList = Arrays.asList("partition1", "system"); + when(this.tableStore.getAllPartitions()).thenReturn(partitionsList); + when(azureConfig.isReservedPartition("system")).thenReturn(true); + when(azureConfig.isReservedPartition("partition1")).thenReturn(false); + + List<String> partitions = sut.getAllPartitions(); + + assertNotNull(partitions); + assertEquals(Collections.singletonList("partition1"), partitions); + } } diff --git a/testing/partition-test-azure/src/test/java/org/opengroup/osdu/partition/api/TestDeletePartition.java b/testing/partition-test-azure/src/test/java/org/opengroup/osdu/partition/api/TestDeletePartition.java index 709a99001cdd4572c46252a2d2d6adcb423e1cce..cfd4402b89b95bc5a88c37b766eb5f9243eb9b49 100644 --- a/testing/partition-test-azure/src/test/java/org/opengroup/osdu/partition/api/TestDeletePartition.java +++ b/testing/partition-test-azure/src/test/java/org/opengroup/osdu/partition/api/TestDeletePartition.java @@ -14,10 +14,17 @@ package org.opengroup.osdu.partition.api; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.opengroup.osdu.partition.api.descriptor.CreatePartitionDescriptor; +import org.opengroup.osdu.partition.api.descriptor.DeletePartitionDescriptor; import org.opengroup.osdu.partition.util.AzureTestUtils; +import org.opengroup.osdu.partition.util.RestDescriptor; +import org.springframework.http.HttpStatus; + +import static org.junit.Assert.assertTrue; public class TestDeletePartition extends DeletePartitionTest { @@ -50,4 +57,40 @@ public class TestDeletePartition extends DeletePartitionTest { public void should_return401_when_makingHttpRequestWithoutToken() throws Exception { // revisit this later -- Istio is changing the response code } + + @Test + public void should_return403_when_deletingSystemPartition() throws Exception { + //check by creation of system partition should give either 201, or 409 + CloseableHttpResponse createResponse = createPartition("system"); + + assertTrue(createResponse.getCode()== HttpStatus.CREATED.value() || createResponse.getCode() == HttpStatus.CONFLICT.value()); + + CloseableHttpResponse deleteResponse = deletePartition("system"); + + assertTrue(deleteResponse.getCode() == HttpStatus.FORBIDDEN.value()); + } + + private CloseableHttpResponse deletePartition(String partitionId) throws Exception { + DeletePartitionDescriptor deletePartitionDes = new DeletePartitionDescriptor(); + deletePartitionDes.setPartitionId(partitionId); + CloseableHttpResponse response = deletePartitionDes.run(this.getId(), this.testUtils.getAccessToken()); + return response; + } + + private CloseableHttpResponse createPartition(String partitionId) throws Exception { + CreatePartitionDescriptor createPartition = new CreatePartitionDescriptor(); + + createPartition.setPartitionId(partitionId); + + RestDescriptor oldDescriptor = this.descriptor; + + this.descriptor = createPartition; + + CloseableHttpResponse createResponse = this.descriptor.run(this.getId(), this.testUtils.getAccessToken()); + + + this.descriptor = oldDescriptor; + return createResponse; + } + } diff --git a/testing/partition-test-azure/src/test/java/org/opengroup/osdu/partition/api/TestListPartitions.java b/testing/partition-test-azure/src/test/java/org/opengroup/osdu/partition/api/TestListPartitions.java index c21da9aaabc96cb1fc67f2aaf3415923c68051fd..13375f9d22f3909e32f572d81192e71ec657eb7f 100644 --- a/testing/partition-test-azure/src/test/java/org/opengroup/osdu/partition/api/TestListPartitions.java +++ b/testing/partition-test-azure/src/test/java/org/opengroup/osdu/partition/api/TestListPartitions.java @@ -14,10 +14,17 @@ package org.opengroup.osdu.partition.api; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.core5.http.io.entity.EntityUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.opengroup.osdu.partition.api.descriptor.CreatePartitionDescriptor; import org.opengroup.osdu.partition.util.AzureTestUtils; +import org.opengroup.osdu.partition.util.RestDescriptor; +import org.springframework.http.HttpStatus; + +import static org.junit.Assert.assertTrue; public class TestListPartitions extends ListPartitionsApitTest { @@ -50,4 +57,34 @@ public class TestListPartitions extends ListPartitionsApitTest { public void should_return401_when_makingHttpRequestWithoutToken() throws Exception { // revisit this later -- Istio is changing the response code } + + @Test + public void should_notReturnSystemPartition_when_listPartitionIsCalled() throws Exception { + //check by creation of system partition should give either 201, or 409 + CloseableHttpResponse createResponse = createPartition("system"); + + assertTrue(createResponse.getCode()== HttpStatus.CREATED.value() || createResponse.getCode() == HttpStatus.CONFLICT.value()); + + CloseableHttpResponse listPartitionsResponse = this.descriptor.run(this.getId(), this.testUtils.getAccessToken()); + + String responseBody = EntityUtils.toString(listPartitionsResponse.getEntity()); + assertTrue(!responseBody.contains("system")); + } + + private CloseableHttpResponse createPartition(String partitionId) throws Exception { + CreatePartitionDescriptor createPartition = new CreatePartitionDescriptor(); + + createPartition.setPartitionId(partitionId); + + RestDescriptor oldDescriptor = this.descriptor; + + this.descriptor = createPartition; + + CloseableHttpResponse createResponse = this.descriptor.run(partitionId, this.testUtils.getAccessToken()); + + + this.descriptor = oldDescriptor; + return createResponse; + } + }