From d53e08bc8ca2e89f2cb21187af9bc27e908d9c02 Mon Sep 17 00:00:00 2001
From: Deepa Kumari <deepa_kumari@epam.com>
Date: Tue, 13 Aug 2024 07:13:36 +0000
Subject: [PATCH] Added system level restrictions for partition apis

---
 provider/partition-azure/pom.xml              |  5 +++
 .../provider/azure/config/AzureConfig.java    |  6 +++
 .../azure/service/PartitionServiceImpl.java   | 16 +++++++
 .../src/main/resources/application.properties |  4 +-
 .../PartitionServiceImplCacheTest.java        |  5 +++
 .../service/PartitionServiceImplTest.java     | 27 +++++++++++-
 .../partition/api/TestDeletePartition.java    | 43 +++++++++++++++++++
 .../partition/api/TestListPartitions.java     | 37 ++++++++++++++++
 8 files changed, 141 insertions(+), 2 deletions(-)

diff --git a/provider/partition-azure/pom.xml b/provider/partition-azure/pom.xml
index 64583de9e..f723fb7a4 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 530890193..1902c4641 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 f433b65c1..e4009eb96 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 f96aefda1..2a452f30e 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 0c5daaba3..6d5b22fab 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 85c6b1480..1e19e5be9 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 709a99001..cfd4402b8 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 c21da9aaa..13375f9d2 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;
+    }
+
 }
-- 
GitLab