You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2023/04/26 16:10:45 UTC
[airavata-data-catalog] 06/09: Simple implementation of hierarchical sharing of data products
This is an automated email from the ASF dual-hosted git repository.
machristie pushed a commit to branch custos-integration
in repository https://gitbox.apache.org/repos/asf/airavata-data-catalog.git
commit 032c659769b4e78d199ee67a03e2dc402fa8cb89
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Tue Apr 25 15:41:21 2023 -0400
Simple implementation of hierarchical sharing of data products
---
.../server/src/main/resources/schema.sql | 31 +++++--
.../api/sharing/SimpleSharingManagerImplTest.java | 103 +++++++++++++++++++++
2 files changed, 128 insertions(+), 6 deletions(-)
diff --git a/data-catalog-api/server/src/main/resources/schema.sql b/data-catalog-api/server/src/main/resources/schema.sql
index faad468..162f1af 100644
--- a/data-catalog-api/server/src/main/resources/schema.sql
+++ b/data-catalog-api/server/src/main/resources/schema.sql
@@ -1,8 +1,26 @@
-- TODO: move this to Liquibase or some other schema migration management tool
CREATE
-OR REPLACE VIEW simple_data_product_sharing_view AS
+OR REPLACE VIEW simple_data_product_sharing_view AS --
+WITH recursive data_product_hierarchy(data_product_id, root) AS (
+ SELECT
+ -- include self with the root
+ dp.data_product_id,
+ dp.data_product_id AS root
+ FROM
+ data_product dp
+ UNION
+ ALL
+ SELECT
+ dp.data_product_id,
+ h.root
+ FROM
+ data_product_hierarchy h,
+ data_product dp
+ WHERE
+ dp.parent_data_product_id = h.data_product_id
+)
SELECT
- s.data_product_id AS data_product_id,
+ dph.data_product_id AS data_product_id,
su.user_id AS user_id,
CASE
WHEN s.permission_id = 'OWNER' THEN 0
@@ -15,10 +33,11 @@ SELECT
END AS permission_id
FROM
simple_user_sharing s
- INNER JOIN simple_user su ON su.simple_user_id = s.simple_user_id -- INNER JOIN user_table u ON u.user_id = su.user_id
+ INNER JOIN simple_user su ON su.simple_user_id = s.simple_user_id
+ INNER JOIN data_product_hierarchy dph ON dph.root = s.data_product_id
UNION
SELECT
- s.data_product_id AS data_product_id,
+ dph.data_product_id AS data_product_id,
su.user_id AS user_id,
CASE
WHEN s.permission_id = 'OWNER' THEN 0
@@ -32,5 +51,5 @@ SELECT
FROM
simple_group_sharing s
INNER JOIN simple_group_membership gm ON gm.simple_group_id = s.simple_group_id
- INNER JOIN simple_user su ON su.simple_user_id = gm.simple_user_id -- INNER JOIN user_table u ON u.user_id = su.user_id
-;
+ INNER JOIN simple_user su ON su.simple_user_id = gm.simple_user_id
+ INNER JOIN data_product_hierarchy dph ON dph.root = s.data_product_id;
diff --git a/data-catalog-api/server/src/test/java/org/apache/airavata/datacatalog/api/sharing/SimpleSharingManagerImplTest.java b/data-catalog-api/server/src/test/java/org/apache/airavata/datacatalog/api/sharing/SimpleSharingManagerImplTest.java
index 6fe117f..74df1c4 100644
--- a/data-catalog-api/server/src/test/java/org/apache/airavata/datacatalog/api/sharing/SimpleSharingManagerImplTest.java
+++ b/data-catalog-api/server/src/test/java/org/apache/airavata/datacatalog/api/sharing/SimpleSharingManagerImplTest.java
@@ -320,4 +320,107 @@ public class SimpleSharingManagerImplTest {
assertFalse(simpleSharingManagerImpl.hasPublicAccess(dataProduct, Permission.READ));
}
+
+ @Test
+ public void testUserHasAccessViaCascade() throws SharingException {
+
+ UserInfo userA = UserInfo.newBuilder().setTenantId("tenantId").setUserId("userA").build();
+ UserEntity testUserA = simpleSharingManagerImpl.resolveUser(userA);
+ UserInfo userB = UserInfo.newBuilder().setTenantId("tenantId").setUserId("userB").build();
+
+ DataProductEntity dp1 = new DataProductEntity();
+ dp1.setExternalId(UUID.randomUUID().toString());
+ dp1.setOwner(testUserA);
+ dp1.setName("test data product 1");
+ dataProductRepository.save(dp1);
+
+ DataProductEntity dp2 = new DataProductEntity();
+ dp2.setExternalId(UUID.randomUUID().toString());
+ dp2.setOwner(testUserA);
+ dp2.setName("test data product 2");
+ dp2.setParentDataProductEntity(dp1);
+ dataProductRepository.save(dp2);
+
+ DataProductEntity dp3 = new DataProductEntity();
+ dp3.setExternalId(UUID.randomUUID().toString());
+ dp3.setOwner(testUserA);
+ dp3.setName("test data product 3");
+ dp3.setParentDataProductEntity(dp2);
+ dataProductRepository.save(dp3);
+
+ // Check that userB doesn't have READ access to the data products 1, 2 or 3
+ DataProduct dataProduct = DataProduct.newBuilder()
+ .setDataProductId(dp1.getExternalId()) // only need the data product id
+ .build();
+ assertFalse(simpleSharingManagerImpl.userHasAccess(userB, dataProduct, Permission.READ));
+
+ // Grant READ access to userB for the data product
+ simpleSharingManagerImpl.grantPermissionToUser(userB, dataProduct, Permission.READ, userA);
+
+ // Check that userB does now have READ access to the data product 1, 2 and 3
+ assertTrue(simpleSharingManagerImpl.userHasAccess(userB, dataProduct, Permission.READ));
+ assertTrue(simpleSharingManagerImpl.userHasAccess(userB,
+ DataProduct.newBuilder().setDataProductId(dp2.getExternalId()).build(), Permission.READ));
+ assertTrue(simpleSharingManagerImpl.userHasAccess(userB,
+ DataProduct.newBuilder().setDataProductId(dp3.getExternalId()).build(), Permission.READ));
+ }
+
+ @Test
+ public void testUserHasAccessViaGroupMembershipAndCascade() throws SharingException {
+
+ UserInfo userA = UserInfo.newBuilder().setTenantId("tenantId").setUserId("userA").build();
+ UserEntity testUserA = simpleSharingManagerImpl.resolveUser(userA);
+ UserInfo userB = UserInfo.newBuilder().setTenantId("tenantId").setUserId("userB").build();
+
+ GroupInfo testGroup = GroupInfo.newBuilder().setGroupId("groupId").setTenantId("tenantId").build();
+
+ // Create data products
+ DataProductEntity dp1 = new DataProductEntity();
+ dp1.setExternalId(UUID.randomUUID().toString());
+ dp1.setOwner(testUserA);
+ dp1.setName("test data product 1");
+ dataProductRepository.save(dp1);
+
+ DataProductEntity dp2 = new DataProductEntity();
+ dp2.setExternalId(UUID.randomUUID().toString());
+ dp2.setOwner(testUserA);
+ dp2.setName("test data product 2");
+ dp2.setParentDataProductEntity(dp1);
+ dataProductRepository.save(dp2);
+
+ DataProductEntity dp3 = new DataProductEntity();
+ dp3.setExternalId(UUID.randomUUID().toString());
+ dp3.setOwner(testUserA);
+ dp3.setName("test data product 3");
+ dp3.setParentDataProductEntity(dp2);
+ dataProductRepository.save(dp3);
+
+ // Add user B to the testGroup
+ simpleSharingManagerImpl.resolveUser(userB);
+ Optional<SimpleUserEntity> userBEntity = simpleUserRepository
+ .findByExternalIdAndSimpleTenant_ExternalId(userB.getUserId(), userB.getTenantId());
+ assertTrue(userBEntity.isPresent());
+ SimpleGroupEntity testGroupEntity = new SimpleGroupEntity();
+ testGroupEntity.setName(testGroup.getGroupId());
+ testGroupEntity.setExternalId(testGroup.getGroupId());
+ testGroupEntity.getMemberUsers().addAll(Arrays.asList(userBEntity.get()));
+ testGroupEntity.setSimpleTenant(userBEntity.get().getSimpleTenant());
+ simpleGroupRepository.save(testGroupEntity);
+
+ // Check that user B doesn't have READ access to the data product
+ DataProduct dataProduct = DataProduct.newBuilder()
+ .setDataProductId(dp1.getExternalId()) // only need the data product id
+ .build();
+ assertFalse(simpleSharingManagerImpl.userHasAccess(userB, dataProduct, Permission.READ));
+
+ // Grant READ access to testGroup for the data product
+ simpleSharingManagerImpl.grantPermissionToGroup(testGroup, dataProduct, Permission.READ, userA);
+
+ // Check that users B now has READ access to the data products 1, 2, and 3
+ assertTrue(simpleSharingManagerImpl.userHasAccess(userB, dataProduct, Permission.READ));
+ assertTrue(simpleSharingManagerImpl.userHasAccess(userB,
+ DataProduct.newBuilder().setDataProductId(dp2.getExternalId()).build(), Permission.READ));
+ assertTrue(simpleSharingManagerImpl.userHasAccess(userB,
+ DataProduct.newBuilder().setDataProductId(dp3.getExternalId()).build(), Permission.READ));
+ }
}