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 a0c86b28e7f92cf47cf892482d9594a478a704b7
Author: Marcus Christie <[email protected]>
AuthorDate: Tue Apr 25 09:57:10 2023 -0400

    Initial simple sharing implementation with user sharing implemented
---
 .../api/DataCatalogApiServiceApplication.java      |  16 ++
 .../model/{UserEntity.java => GroupEntity.java}    |  41 ++--
 .../airavata/datacatalog/api/model/UserEntity.java |   1 +
 .../model/sharing/simple/SimpleGroupEntity.java    | 103 ++++++++
 .../sharing/simple/SimpleGroupSharingEntity.java   | 109 +++++++++
 .../simple/SimpleTenantEntity.java}                |  43 ++--
 .../api/model/sharing/simple/SimpleUserEntity.java | 108 +++++++++
 .../sharing/simple/SimpleUserSharingEntity.java    | 109 +++++++++
 .../api/repository/GroupRepository.java            |  13 ++
 .../api/repository/TenantRepository.java           |   3 +
 .../datacatalog/api/repository/UserRepository.java |  14 ++
 .../sharing/simple/SimpleGroupRepository.java      |  12 +
 .../simple/SimpleGroupSharingRepository.java       |  13 ++
 .../sharing/simple/SimpleTenantRepository.java     |  11 +
 .../sharing/simple/SimpleUserRepository.java       |  12 +
 .../simple/SimpleUserSharingRepository.java        |  13 ++
 .../api/sharing/SimpleSharingManagerImpl.java      | 259 +++++++++++++++++++++
 .../src/main/resources/application.properties      |   5 +
 .../server/src/main/resources/schema.sql           |  36 +++
 .../api/sharing/SimpleSharingManagerImplTest.java  | 138 +++++++++++
 20 files changed, 1014 insertions(+), 45 deletions(-)

diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/DataCatalogApiServiceApplication.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/DataCatalogApiServiceApplication.java
index 7b6bd4e..fb35723 100644
--- 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/DataCatalogApiServiceApplication.java
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/DataCatalogApiServiceApplication.java
@@ -1,9 +1,15 @@
 package org.apache.airavata.datacatalog.api;
 
+import org.apache.airavata.datacatalog.api.sharing.SharingManager;
+import org.apache.airavata.datacatalog.api.sharing.SharingManagerImpl;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Primary;
 import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 
 @ComponentScan(basePackages = { "org.apache.airavata.datacatalog.api", 
"org.apache.custos.sharing.core" })
@@ -14,8 +20,18 @@ import 
org.springframework.data.jpa.repository.config.EnableJpaRepositories;
         "org.apache.custos.sharing.core.persistance.model" })
 public class DataCatalogApiServiceApplication {
 
+    @Autowired
+    private ApplicationContext applicationContext;
+
     public static void main(String[] args) {
         SpringApplication.run(DataCatalogApiServiceApplication.class, args);
     }
 
+    @Bean
+    @Primary
+    public SharingManager getSharingManager() {
+        // TODO: externalize bean name to a property
+        // return (SharingManager) 
applicationContext.getBean("simpleSharingManager");
+        return applicationContext.getBean(SharingManagerImpl.class);
+    }
 }
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/UserEntity.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/GroupEntity.java
similarity index 68%
copy from 
data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/UserEntity.java
copy to 
data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/GroupEntity.java
index 20a4a3c..4c6caf7 100644
--- 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/UserEntity.java
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/GroupEntity.java
@@ -11,26 +11,23 @@ import jakarta.persistence.ManyToOne;
 import jakarta.persistence.SequenceGenerator;
 import jakarta.persistence.Table;
 
+// TODO: not needed?
+// TODO: need a unique constraint on (tenant, externalId)
 @Entity
-// 'user' is a reserved word, so naming this table 'user_table'
-@Table(name = "user_table")
-public class UserEntity {
+@Table(name = "user_group")
+public class GroupEntity {
 
     @Id
-    @SequenceGenerator(name = "user_user_id_seq", sequenceName = 
"user_user_id_seq", allocationSize = 1)
-    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = 
"user_user_id_seq")
-    @Column(name = "user_id")
-    private Long userId;
-
-    /**
-     * The identifier for the user. This external identifier comes from the 
user
-     * management service that data catalog is configured to use.
-     */
+    @SequenceGenerator(name = "user_group_group_id", sequenceName = 
"user_group_group_id", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = 
"user_group_group_id")
+    @Column(name = "group_id")
+    private Long groupId;
+
     @Basic
     @Column(name = "external_id", nullable = false)
     private String externalId;
-
     @Basic
+
     @Column(name = "name", nullable = false)
     private String name;
 
@@ -38,12 +35,12 @@ public class UserEntity {
     @JoinColumn(name = "tenant_id", referencedColumnName = "tenant_id", 
nullable = false, updatable = false)
     private TenantEntity tenant;
 
-    public Long getUserId() {
-        return userId;
+    public Long getGroupId() {
+        return groupId;
     }
 
-    public void setUserId(Long userId) {
-        this.userId = userId;
+    public void setGroupId(Long groupId) {
+        this.groupId = groupId;
     }
 
     public String getExternalId() {
@@ -74,7 +71,7 @@ public class UserEntity {
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = prime * result + ((userId == null) ? 0 : userId.hashCode());
+        result = prime * result + ((groupId == null) ? 0 : groupId.hashCode());
         return result;
     }
 
@@ -86,11 +83,11 @@ public class UserEntity {
             return false;
         if (getClass() != obj.getClass())
             return false;
-        UserEntity other = (UserEntity) obj;
-        if (userId == null) {
-            if (other.userId != null)
+        GroupEntity other = (GroupEntity) obj;
+        if (groupId == null) {
+            if (other.groupId != null)
                 return false;
-        } else if (!userId.equals(other.userId))
+        } else if (!groupId.equals(other.groupId))
             return false;
         return true;
     }
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/UserEntity.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/UserEntity.java
index 20a4a3c..3cff66a 100644
--- 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/UserEntity.java
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/UserEntity.java
@@ -11,6 +11,7 @@ import jakarta.persistence.ManyToOne;
 import jakarta.persistence.SequenceGenerator;
 import jakarta.persistence.Table;
 
+// TODO: need a unique constraint on (tenant, externalId)
 @Entity
 // 'user' is a reserved word, so naming this table 'user_table'
 @Table(name = "user_table")
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimpleGroupEntity.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimpleGroupEntity.java
new file mode 100644
index 0000000..26416a3
--- /dev/null
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimpleGroupEntity.java
@@ -0,0 +1,103 @@
+package org.apache.airavata.datacatalog.api.model.sharing.simple;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import jakarta.persistence.Basic;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.SequenceGenerator;
+import jakarta.persistence.Table;
+
+// TODO: need a unique constraint on (tenant, externalId)
+@Entity
+@Table(name = "simple_group")
+public class SimpleGroupEntity {
+
+    @Id
+    @SequenceGenerator(name = "simple_group_simple_group_id", sequenceName = 
"simple_group_simple_group_id", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = 
"simple_group_simple_group_id")
+    @Column(name = "simple_group_id")
+    private Long simpleGroupId;
+
+    @Basic
+    @Column(name = "external_id", nullable = false)
+    private String externalId;
+
+    @Basic
+    @Column(name = "name", nullable = false)
+    private String name;
+
+    @ManyToOne(optional = false)
+    @JoinColumn(name = "simple_tenant_id", referencedColumnName = 
"simple_tenant_id", nullable = false, updatable = false)
+    private SimpleTenantEntity simpleTenant;
+
+    @ManyToMany
+    @JoinTable(name = "simple_group_membership", joinColumns = 
@JoinColumn(name = "simple_group_id"), inverseJoinColumns = @JoinColumn(name = 
"simple_user_id"))
+    private Set<SimpleUserEntity> memberUsers = new HashSet<>();
+
+    public Long getSimpleGroupId() {
+        return simpleGroupId;
+    }
+
+    public void setSimpleGroupId(Long simpleGroupId) {
+        this.simpleGroupId = simpleGroupId;
+    }
+
+    public String getExternalId() {
+        return externalId;
+    }
+
+    public void setExternalId(String externalId) {
+        this.externalId = externalId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public SimpleTenantEntity getSimpleTenant() {
+        return simpleTenant;
+    }
+
+    public void setSimpleTenant(SimpleTenantEntity simpleTenant) {
+        this.simpleTenant = simpleTenant;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((simpleGroupId == null) ? 0 : 
simpleGroupId.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        SimpleGroupEntity other = (SimpleGroupEntity) obj;
+        if (simpleGroupId == null) {
+            if (other.simpleGroupId != null)
+                return false;
+        } else if (!simpleGroupId.equals(other.simpleGroupId))
+            return false;
+        return true;
+    }
+
+}
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimpleGroupSharingEntity.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimpleGroupSharingEntity.java
new file mode 100644
index 0000000..bf5d0fd
--- /dev/null
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimpleGroupSharingEntity.java
@@ -0,0 +1,109 @@
+package org.apache.airavata.datacatalog.api.model.sharing.simple;
+
+import org.apache.airavata.datacatalog.api.Permission;
+import org.apache.airavata.datacatalog.api.model.DataProductEntity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.SequenceGenerator;
+import jakarta.persistence.Table;
+
+@Entity
+@Table(name = "simple_group_sharing")
+public class SimpleGroupSharingEntity {
+
+    @Id
+    @SequenceGenerator(name = "simple_group_sharing_sharing_id", sequenceName 
= "simple_group_sharing_sharing_id", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = 
"simple_group_sharing_sharing_id")
+    @Column(name = "sharing_id")
+    private Long sharingId;
+
+    @ManyToOne(optional = false)
+    @JoinColumn(name = "simple_group_id", referencedColumnName = 
"simple_group_id", nullable = false, updatable = false)
+    private SimpleGroupEntity simpleGroup;
+
+    @ManyToOne(optional = false)
+    @JoinColumn(name = "data_product_id", referencedColumnName = 
"data_product_id", nullable = false, updatable = false)
+    private DataProductEntity dataProduct;
+
+    @Column(name = "permission_id")
+    @Enumerated(EnumType.STRING)
+    private Permission permission;
+
+    @ManyToOne
+    @JoinColumn(name = "shared_by_user_id", referencedColumnName = "user_id")
+    private SimpleUserEntity sharedByUser;
+
+    public Long getSharingId() {
+        return sharingId;
+    }
+
+    public void setSharingId(Long sharingId) {
+        this.sharingId = sharingId;
+    }
+
+    public SimpleGroupEntity getSimpleGroup() {
+        return simpleGroup;
+    }
+
+    public void setSimpleGroup(SimpleGroupEntity simpleGroup) {
+        this.simpleGroup = simpleGroup;
+    }
+
+    public DataProductEntity getDataProduct() {
+        return dataProduct;
+    }
+
+    public void setDataProduct(DataProductEntity dataProduct) {
+        this.dataProduct = dataProduct;
+    }
+
+    public Permission getPermission() {
+        return permission;
+    }
+
+    public void setPermission(Permission permission) {
+        this.permission = permission;
+    }
+
+    public SimpleUserEntity getSharedByUser() {
+        return sharedByUser;
+    }
+
+    public void setSharedByUser(SimpleUserEntity sharedByUser) {
+        this.sharedByUser = sharedByUser;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((sharingId == null) ? 0 : 
sharingId.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        SimpleGroupSharingEntity other = (SimpleGroupSharingEntity) obj;
+        if (sharingId == null) {
+            if (other.sharingId != null)
+                return false;
+        } else if (!sharingId.equals(other.sharingId))
+            return false;
+        return true;
+    }
+
+}
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/UserEntity.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimpleTenantEntity.java
similarity index 61%
copy from 
data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/UserEntity.java
copy to 
data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimpleTenantEntity.java
index 20a4a3c..eabadcb 100644
--- 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/UserEntity.java
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimpleTenantEntity.java
@@ -1,4 +1,6 @@
-package org.apache.airavata.datacatalog.api.model;
+package org.apache.airavata.datacatalog.api.model.sharing.simple;
+
+import org.apache.airavata.datacatalog.api.model.TenantEntity;
 
 import jakarta.persistence.Basic;
 import jakarta.persistence.Column;
@@ -12,20 +14,15 @@ import jakarta.persistence.SequenceGenerator;
 import jakarta.persistence.Table;
 
 @Entity
-// 'user' is a reserved word, so naming this table 'user_table'
-@Table(name = "user_table")
-public class UserEntity {
+@Table(name = "simple_tenant")
+public class SimpleTenantEntity {
 
     @Id
-    @SequenceGenerator(name = "user_user_id_seq", sequenceName = 
"user_user_id_seq", allocationSize = 1)
-    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = 
"user_user_id_seq")
-    @Column(name = "user_id")
-    private Long userId;
-
-    /**
-     * The identifier for the user. This external identifier comes from the 
user
-     * management service that data catalog is configured to use.
-     */
+    @SequenceGenerator(name = "simple_tenant_simple_tenant_id_seq", 
sequenceName = "simple_tenant_simple_tenant_id_seq", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = 
"simple_tenant_simple_tenant_id_seq")
+    @Column(name = "simple_tenant_id")
+    private Long simpleTenantId;
+
     @Basic
     @Column(name = "external_id", nullable = false)
     private String externalId;
@@ -35,15 +32,15 @@ public class UserEntity {
     private String name;
 
     @ManyToOne(optional = false)
-    @JoinColumn(name = "tenant_id", referencedColumnName = "tenant_id", 
nullable = false, updatable = false)
+    @JoinColumn(name = "tenant_id", nullable = false, updatable = false)
     private TenantEntity tenant;
 
-    public Long getUserId() {
-        return userId;
+    public Long getSimpleTenantId() {
+        return simpleTenantId;
     }
 
-    public void setUserId(Long userId) {
-        this.userId = userId;
+    public void setSimpleTenantId(Long simpleTenantId) {
+        this.simpleTenantId = simpleTenantId;
     }
 
     public String getExternalId() {
@@ -74,7 +71,7 @@ public class UserEntity {
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = prime * result + ((userId == null) ? 0 : userId.hashCode());
+        result = prime * result + ((simpleTenantId == null) ? 0 : 
simpleTenantId.hashCode());
         return result;
     }
 
@@ -86,11 +83,11 @@ public class UserEntity {
             return false;
         if (getClass() != obj.getClass())
             return false;
-        UserEntity other = (UserEntity) obj;
-        if (userId == null) {
-            if (other.userId != null)
+        SimpleTenantEntity other = (SimpleTenantEntity) obj;
+        if (simpleTenantId == null) {
+            if (other.simpleTenantId != null)
                 return false;
-        } else if (!userId.equals(other.userId))
+        } else if (!simpleTenantId.equals(other.simpleTenantId))
             return false;
         return true;
     }
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimpleUserEntity.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimpleUserEntity.java
new file mode 100644
index 0000000..83114f7
--- /dev/null
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimpleUserEntity.java
@@ -0,0 +1,108 @@
+package org.apache.airavata.datacatalog.api.model.sharing.simple;
+
+import org.apache.airavata.datacatalog.api.model.UserEntity;
+
+import jakarta.persistence.Basic;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.SequenceGenerator;
+import jakarta.persistence.Table;
+
+// TODO: need a unique constraint on (tenant, externalId)
+@Entity
+@Table(name = "simple_user")
+public class SimpleUserEntity {
+
+    @Id
+    @SequenceGenerator(name = "simple_user_simple_user_id_seq", sequenceName = 
"simple_user_simple_user_id_seq", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = 
"simple_user_simple_user_id_seq")
+    @Column(name = "simple_user_id")
+    private Long simpleUserId;
+
+    @Basic
+    @Column(name = "external_id", nullable = false)
+    private String externalId;
+
+    @Basic
+    @Column(name = "name", nullable = false)
+    private String name;
+
+    @ManyToOne(optional = false)
+    @JoinColumn(name = "simple_tenant_id", referencedColumnName = 
"simple_tenant_id", nullable = false, updatable = false)
+    private SimpleTenantEntity simpleTenant;
+
+    @ManyToOne(optional = false)
+    @JoinColumn(name = "user_id", nullable = false, updatable = false)
+    private UserEntity user;
+
+    public Long getSimpleUserId() {
+        return simpleUserId;
+    }
+
+    public void setSimpleUserId(Long simpleUserId) {
+        this.simpleUserId = simpleUserId;
+    }
+
+    public String getExternalId() {
+        return externalId;
+    }
+
+    public void setExternalId(String externalId) {
+        this.externalId = externalId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public SimpleTenantEntity getSimpleTenant() {
+        return simpleTenant;
+    }
+
+    public void setSimpleTenant(SimpleTenantEntity tenant) {
+        this.simpleTenant = tenant;
+    }
+
+    public UserEntity getUser() {
+        return user;
+    }
+
+    public void setUser(UserEntity user) {
+        this.user = user;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((simpleUserId == null) ? 0 : 
simpleUserId.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        SimpleUserEntity other = (SimpleUserEntity) obj;
+        if (simpleUserId == null) {
+            if (other.simpleUserId != null)
+                return false;
+        } else if (!simpleUserId.equals(other.simpleUserId))
+            return false;
+        return true;
+    }
+
+}
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimpleUserSharingEntity.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimpleUserSharingEntity.java
new file mode 100644
index 0000000..428537e
--- /dev/null
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimpleUserSharingEntity.java
@@ -0,0 +1,109 @@
+package org.apache.airavata.datacatalog.api.model.sharing.simple;
+
+import org.apache.airavata.datacatalog.api.Permission;
+import org.apache.airavata.datacatalog.api.model.DataProductEntity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.SequenceGenerator;
+import jakarta.persistence.Table;
+
+@Entity
+@Table(name = "simple_user_sharing")
+public class SimpleUserSharingEntity {
+
+    @Id
+    @SequenceGenerator(name = "simple_user_sharing_sharing_id", sequenceName = 
"simple_user_sharing_sharing_id", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = 
"simple_user_sharing_sharing_id")
+    @Column(name = "sharing_id")
+    private Long sharingId;
+
+    @ManyToOne(optional = false)
+    @JoinColumn(name = "simple_user_id", nullable = false, updatable = false)
+    private SimpleUserEntity simpleUser;
+
+    @ManyToOne(optional = false)
+    @JoinColumn(name = "data_product_id", nullable = false, updatable = false)
+    private DataProductEntity dataProduct;
+
+    @Column(name = "permission_id")
+    @Enumerated(EnumType.STRING)
+    private Permission permission;
+
+    @ManyToOne
+    @JoinColumn(name = "shared_by_user_id")
+    private SimpleUserEntity sharedByUser;
+
+    public Long getSharingId() {
+        return sharingId;
+    }
+
+    public void setSharingId(Long sharingId) {
+        this.sharingId = sharingId;
+    }
+
+    public SimpleUserEntity getSimpleUser() {
+        return simpleUser;
+    }
+
+    public void setSimpleUser(SimpleUserEntity simpleUser) {
+        this.simpleUser = simpleUser;
+    }
+
+    public DataProductEntity getDataProduct() {
+        return dataProduct;
+    }
+
+    public void setDataProduct(DataProductEntity dataProduct) {
+        this.dataProduct = dataProduct;
+    }
+
+    public Permission getPermission() {
+        return permission;
+    }
+
+    public void setPermission(Permission permission) {
+        this.permission = permission;
+    }
+
+    public SimpleUserEntity getSharedByUser() {
+        return sharedByUser;
+    }
+
+    public void setSharedByUser(SimpleUserEntity sharedByUser) {
+        this.sharedByUser = sharedByUser;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((sharingId == null) ? 0 : 
sharingId.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        SimpleUserSharingEntity other = (SimpleUserSharingEntity) obj;
+        if (sharingId == null) {
+            if (other.sharingId != null)
+                return false;
+        } else if (!sharingId.equals(other.sharingId))
+            return false;
+        return true;
+    }
+
+}
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/GroupRepository.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/GroupRepository.java
new file mode 100644
index 0000000..f821fd9
--- /dev/null
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/GroupRepository.java
@@ -0,0 +1,13 @@
+package org.apache.airavata.datacatalog.api.repository;
+
+import java.util.Optional;
+
+import org.apache.airavata.datacatalog.api.model.GroupEntity;
+import org.apache.airavata.datacatalog.api.model.TenantEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+// TODO: not needed?
+public interface GroupRepository extends JpaRepository<GroupEntity, Long> {
+
+    Optional<GroupEntity> findByExternalIdAndTenant(String externalId, 
TenantEntity tenantEntity);
+}
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/TenantRepository.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/TenantRepository.java
index a90d0db..0964017 100644
--- 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/TenantRepository.java
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/TenantRepository.java
@@ -1,5 +1,7 @@
 package org.apache.airavata.datacatalog.api.repository;
 
+import java.util.Optional;
+
 import org.apache.airavata.datacatalog.api.model.TenantEntity;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.transaction.annotation.Transactional;
@@ -7,4 +9,5 @@ import org.springframework.transaction.annotation.Transactional;
 @Transactional
 public interface TenantRepository extends JpaRepository<TenantEntity, Long> {
 
+    Optional<TenantEntity> findByExternalId(String externalId);
 }
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/UserRepository.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/UserRepository.java
new file mode 100644
index 0000000..301f2ee
--- /dev/null
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/UserRepository.java
@@ -0,0 +1,14 @@
+package org.apache.airavata.datacatalog.api.repository;
+
+import java.util.Optional;
+
+import org.apache.airavata.datacatalog.api.model.TenantEntity;
+import org.apache.airavata.datacatalog.api.model.UserEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface UserRepository extends JpaRepository<UserEntity, Long> {
+
+    Optional<UserEntity> findByExternalIdAndTenant(String externalId, 
TenantEntity tenantEntity);
+
+    Optional<UserEntity> findByExternalIdAndTenant_ExternalId(String 
externalId, String tenantExternalId);
+}
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/sharing/simple/SimpleGroupRepository.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/sharing/simple/SimpleGroupRepository.java
new file mode 100644
index 0000000..855736f
--- /dev/null
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/sharing/simple/SimpleGroupRepository.java
@@ -0,0 +1,12 @@
+package org.apache.airavata.datacatalog.api.repository.sharing.simple;
+
+import java.util.Optional;
+
+import 
org.apache.airavata.datacatalog.api.model.sharing.simple.SimpleGroupEntity;
+import 
org.apache.airavata.datacatalog.api.model.sharing.simple.SimpleTenantEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface SimpleGroupRepository extends 
JpaRepository<SimpleGroupEntity, Long> {
+
+    Optional<SimpleGroupEntity> findByExternalIdAndSimpleTenant(String 
externalId, SimpleTenantEntity simpleTenant);
+}
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/sharing/simple/SimpleGroupSharingRepository.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/sharing/simple/SimpleGroupSharingRepository.java
new file mode 100644
index 0000000..1fea593
--- /dev/null
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/sharing/simple/SimpleGroupSharingRepository.java
@@ -0,0 +1,13 @@
+package org.apache.airavata.datacatalog.api.repository.sharing.simple;
+
+import java.util.Optional;
+
+import org.apache.airavata.datacatalog.api.Permission;
+import 
org.apache.airavata.datacatalog.api.model.sharing.simple.SimpleGroupSharingEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface SimpleGroupSharingRepository extends 
JpaRepository<SimpleGroupSharingEntity, Long> {
+
+    Optional<SimpleGroupSharingEntity> 
findBySimpleGroup_SimpleGroupIdAndDataProduct_DataProductIdAndPermission(
+            long groupId, long dataProductId, Permission permission);
+}
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/sharing/simple/SimpleTenantRepository.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/sharing/simple/SimpleTenantRepository.java
new file mode 100644
index 0000000..d45dd2a
--- /dev/null
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/sharing/simple/SimpleTenantRepository.java
@@ -0,0 +1,11 @@
+package org.apache.airavata.datacatalog.api.repository.sharing.simple;
+
+import java.util.Optional;
+
+import 
org.apache.airavata.datacatalog.api.model.sharing.simple.SimpleTenantEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface SimpleTenantRepository extends 
JpaRepository<SimpleTenantEntity, Long> {
+
+    Optional<SimpleTenantEntity> findByExternalId(String externalId);
+}
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/sharing/simple/SimpleUserRepository.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/sharing/simple/SimpleUserRepository.java
new file mode 100644
index 0000000..515da5a
--- /dev/null
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/sharing/simple/SimpleUserRepository.java
@@ -0,0 +1,12 @@
+package org.apache.airavata.datacatalog.api.repository.sharing.simple;
+
+import java.util.Optional;
+
+import 
org.apache.airavata.datacatalog.api.model.sharing.simple.SimpleTenantEntity;
+import 
org.apache.airavata.datacatalog.api.model.sharing.simple.SimpleUserEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface SimpleUserRepository extends JpaRepository<SimpleUserEntity, 
Long> {
+
+    Optional<SimpleUserEntity> findByExternalIdAndSimpleTenant(String 
externalId, SimpleTenantEntity simpleTenant);
+}
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/sharing/simple/SimpleUserSharingRepository.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/sharing/simple/SimpleUserSharingRepository.java
new file mode 100644
index 0000000..a94f809
--- /dev/null
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/sharing/simple/SimpleUserSharingRepository.java
@@ -0,0 +1,13 @@
+package org.apache.airavata.datacatalog.api.repository.sharing.simple;
+
+import java.util.Optional;
+
+import org.apache.airavata.datacatalog.api.Permission;
+import 
org.apache.airavata.datacatalog.api.model.sharing.simple.SimpleUserSharingEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface SimpleUserSharingRepository extends 
JpaRepository<SimpleUserSharingEntity, Long> {
+
+    Optional<SimpleUserSharingEntity> 
findBySimpleUser_SimpleUserIdAndDataProduct_DataProductIdAndPermission(
+            long userId, long dataProductId, Permission permission);
+}
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/sharing/SimpleSharingManagerImpl.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/sharing/SimpleSharingManagerImpl.java
new file mode 100644
index 0000000..f5d42d3
--- /dev/null
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/sharing/SimpleSharingManagerImpl.java
@@ -0,0 +1,259 @@
+package org.apache.airavata.datacatalog.api.sharing;
+
+import java.util.Optional;
+
+import org.apache.airavata.datacatalog.api.DataProduct;
+import org.apache.airavata.datacatalog.api.GroupInfo;
+import org.apache.airavata.datacatalog.api.Permission;
+import org.apache.airavata.datacatalog.api.UserInfo;
+import org.apache.airavata.datacatalog.api.exception.SharingException;
+import org.apache.airavata.datacatalog.api.model.DataProductEntity;
+import org.apache.airavata.datacatalog.api.model.TenantEntity;
+import org.apache.airavata.datacatalog.api.model.UserEntity;
+import 
org.apache.airavata.datacatalog.api.model.sharing.simple.SimpleGroupEntity;
+import 
org.apache.airavata.datacatalog.api.model.sharing.simple.SimpleGroupSharingEntity;
+import 
org.apache.airavata.datacatalog.api.model.sharing.simple.SimpleTenantEntity;
+import 
org.apache.airavata.datacatalog.api.model.sharing.simple.SimpleUserEntity;
+import 
org.apache.airavata.datacatalog.api.model.sharing.simple.SimpleUserSharingEntity;
+import org.apache.airavata.datacatalog.api.repository.DataProductRepository;
+import org.apache.airavata.datacatalog.api.repository.TenantRepository;
+import org.apache.airavata.datacatalog.api.repository.UserRepository;
+import 
org.apache.airavata.datacatalog.api.repository.sharing.simple.SimpleGroupRepository;
+import 
org.apache.airavata.datacatalog.api.repository.sharing.simple.SimpleGroupSharingRepository;
+import 
org.apache.airavata.datacatalog.api.repository.sharing.simple.SimpleTenantRepository;
+import 
org.apache.airavata.datacatalog.api.repository.sharing.simple.SimpleUserRepository;
+import 
org.apache.airavata.datacatalog.api.repository.sharing.simple.SimpleUserSharingRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.Query;
+
+@Component("simpleSharingManager")
+public class SimpleSharingManagerImpl implements SharingManager {
+
+    @Autowired
+    private TenantRepository tenantRepository;
+
+    @Autowired
+    private UserRepository userRepository;
+
+    @Autowired
+    private DataProductRepository dataProductRepository;
+
+    @Autowired
+    private SimpleUserSharingRepository simpleUserSharingRepository;
+
+    @Autowired
+    private SimpleGroupSharingRepository simpleGroupSharingRepository;
+
+    @Autowired
+    private SimpleTenantRepository simpleTenantRepository;
+
+    @Autowired
+    private SimpleUserRepository simpleUserRepository;
+
+    @Autowired
+    private SimpleGroupRepository simpleGroupRepository;
+
+    @PersistenceContext
+    private EntityManager entityManager;
+
+    @Override
+    public void initialize(String tenantId) throws SharingException {
+        // TODO: create a public group for the tenantId
+    }
+
+    @Override
+    public UserEntity resolveUser(UserInfo userInfo) throws SharingException {
+        SimpleUserEntity simpleUser = resolveSimpleUser(userInfo);
+        return simpleUser.getUser();
+    }
+
+    @Override
+    public boolean userHasAccess(UserInfo userInfo, DataProduct dataProduct, 
Permission permission)
+            throws SharingException {
+        UserEntity user = resolveUser(userInfo);
+        DataProductEntity dataProductEntity = resolveDataProduct(dataProduct);
+        Query query = entityManager.createNativeQuery("select 1 from " + 
getDataProductSharingView()
+                + " where user_id = :user_id and data_product_id = 
:data_product_id and permission_id = :permission_id");
+        query.setParameter("user_id", user.getUserId());
+        query.setParameter("data_product_id", 
dataProductEntity.getDataProductId());
+        query.setParameter("permission_id", permission.getNumber());
+
+        return query.getResultList().size() > 0;
+    }
+
+    @Override
+    public String getDataProductSharingView() {
+        return "simple_data_product_sharing_view";
+    }
+
+    @Override
+    public void grantPermissionToUser(UserInfo userInfo, DataProduct 
dataProduct, Permission permission,
+            UserInfo sharedByUser) throws SharingException {
+        SimpleUserEntity simpleUser = resolveSimpleUser(userInfo);
+        DataProductEntity dataProductEntity = resolveDataProduct(dataProduct);
+        SimpleUserEntity sharedByUserEntity = sharedByUser != null ? 
resolveSimpleUser(sharedByUser) : null;
+
+        Optional<SimpleUserSharingEntity> maybeSimpleUserSharingEntity = 
simpleUserSharingRepository
+                
.findBySimpleUser_SimpleUserIdAndDataProduct_DataProductIdAndPermission(simpleUser.getSimpleUserId(),
+                        dataProductEntity.getDataProductId(), permission);
+
+        if (maybeSimpleUserSharingEntity.isEmpty()) {
+            SimpleUserSharingEntity simpleUserSharingEntity = new 
SimpleUserSharingEntity();
+            simpleUserSharingEntity.setDataProduct(dataProductEntity);
+            simpleUserSharingEntity.setPermission(permission);
+            simpleUserSharingEntity.setSimpleUser(simpleUser);
+            simpleUserSharingEntity.setSharedByUser(sharedByUserEntity);
+            simpleUserSharingRepository.save(simpleUserSharingEntity);
+        }
+    }
+
+    @Override
+    public void revokePermissionFromUser(UserInfo userInfo, DataProduct 
dataProduct, Permission permission)
+            throws SharingException {
+
+        SimpleUserEntity simpleUser = resolveSimpleUser(userInfo);
+        DataProductEntity dataProductEntity = resolveDataProduct(dataProduct);
+
+        Optional<SimpleUserSharingEntity> maybeSimpleUserSharingEntity = 
simpleUserSharingRepository
+                
.findBySimpleUser_SimpleUserIdAndDataProduct_DataProductIdAndPermission(simpleUser.getSimpleUserId(),
+                        dataProductEntity.getDataProductId(), permission);
+        maybeSimpleUserSharingEntity.ifPresent(simpleUserSharingEntity -> {
+            simpleUserSharingRepository.delete(simpleUserSharingEntity);
+        });
+    }
+
+    @Override
+    public void grantPermissionToGroup(GroupInfo groupInfo, DataProduct 
dataProduct, Permission permission,
+            UserInfo sharedByUser) throws SharingException {
+
+        SimpleGroupEntity groupEntity = resolveGroup(groupInfo);
+        DataProductEntity dataProductEntity = resolveDataProduct(dataProduct);
+        SimpleUserEntity sharedByUserEntity = sharedByUser != null
+                ? resolveSimpleUser(sharedByUser, 
groupEntity.getSimpleTenant())
+                : null;
+
+        Optional<SimpleGroupSharingEntity> maybeSimpleGroupSharingEntity = 
simpleGroupSharingRepository
+                
.findBySimpleGroup_SimpleGroupIdAndDataProduct_DataProductIdAndPermission(
+                        groupEntity.getSimpleGroupId(),
+                        dataProductEntity.getDataProductId(), permission);
+
+        if (maybeSimpleGroupSharingEntity.isEmpty()) {
+            SimpleGroupSharingEntity simpleGroupSharingEntity = new 
SimpleGroupSharingEntity();
+            simpleGroupSharingEntity.setDataProduct(dataProductEntity);
+            simpleGroupSharingEntity.setPermission(permission);
+            simpleGroupSharingEntity.setSimpleGroup(groupEntity);
+            simpleGroupSharingEntity.setSharedByUser(sharedByUserEntity);
+            simpleGroupSharingRepository.save(simpleGroupSharingEntity);
+        }
+    }
+
+    @Override
+    public void revokePermissionFromGroup(GroupInfo groupInfo, DataProduct 
dataProduct, Permission permission)
+            throws SharingException {
+        SimpleGroupEntity groupEntity = resolveGroup(groupInfo);
+        DataProductEntity dataProductEntity = resolveDataProduct(dataProduct);
+
+        Optional<SimpleGroupSharingEntity> maybeSimpleGroupSharingEntity = 
simpleGroupSharingRepository
+                
.findBySimpleGroup_SimpleGroupIdAndDataProduct_DataProductIdAndPermission(
+                        groupEntity.getSimpleGroupId(), 
dataProductEntity.getDataProductId(), permission);
+        maybeSimpleGroupSharingEntity.ifPresent(simpleUserSharingEntity -> {
+            simpleGroupSharingRepository.delete(simpleUserSharingEntity);
+        });
+    }
+
+    @Override
+    public boolean hasPublicAccess(DataProduct dataProduct, Permission 
permission) throws SharingException {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException("Unimplemented method 
'hasPublicAccess'");
+    }
+
+    @Override
+    public void grantPublicAccess(DataProduct dataProduct, Permission 
permission) throws SharingException {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException("Unimplemented method 
'grantPublicAccess'");
+    }
+
+    @Override
+    public void revokePublicAccess(DataProduct dataProduct, Permission 
permission) throws SharingException {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException("Unimplemented method 
'revokePublicAccess'");
+    }
+
+    private SimpleGroupEntity resolveGroup(GroupInfo groupInfo) {
+
+        final String tenantId = groupInfo.hasTenantId() ? 
groupInfo.getTenantId() : "default";
+        SimpleTenantEntity tenant = resolveTenant(tenantId);
+
+        // Create the group if missing
+        Optional<SimpleGroupEntity> maybeSimpleGroup = simpleGroupRepository
+                .findByExternalIdAndSimpleTenant(groupInfo.getGroupId(), 
tenant);
+        SimpleGroupEntity simpleGroup = maybeSimpleGroup.orElseGet(() -> {
+            SimpleGroupEntity newGroup = new SimpleGroupEntity();
+            newGroup.setExternalId(groupInfo.getGroupId());
+            newGroup.setName(groupInfo.getGroupId());
+            newGroup.setSimpleTenant(tenant);
+            return simpleGroupRepository.save(newGroup);
+        });
+
+        return simpleGroup;
+    }
+
+    private SimpleTenantEntity resolveTenant(String tenantId) {
+
+        Optional<SimpleTenantEntity> maybeSimpleTenant = 
simpleTenantRepository.findByExternalId(tenantId);
+        return maybeSimpleTenant.orElseGet(() -> {
+            TenantEntity newTenant = new TenantEntity();
+            newTenant.setExternalId(tenantId);
+            newTenant.setName(tenantId);
+            newTenant = tenantRepository.save(newTenant);
+
+            SimpleTenantEntity newSimpleTenant = new SimpleTenantEntity();
+            newSimpleTenant.setExternalId(tenantId);
+            newSimpleTenant.setName(tenantId);
+            newSimpleTenant.setTenant(newTenant);
+            return simpleTenantRepository.save(newSimpleTenant);
+        });
+    }
+
+    private SimpleUserEntity resolveSimpleUser(UserInfo userInfo) {
+
+        final String tenantId = userInfo.hasTenantId() ? 
userInfo.getTenantId() : "default";
+        SimpleTenantEntity tenant = resolveTenant(tenantId);
+
+        return resolveSimpleUser(userInfo, tenant);
+    }
+
+    private SimpleUserEntity resolveSimpleUser(UserInfo userInfo, 
SimpleTenantEntity tenant) {
+        Optional<SimpleUserEntity> maybeSimpleUser = simpleUserRepository
+                .findByExternalIdAndSimpleTenant(userInfo.getUserId(), tenant);
+
+        SimpleUserEntity simpleUser = maybeSimpleUser.orElseGet(() -> {
+            UserEntity newUser = new UserEntity();
+            newUser.setExternalId(userInfo.getUserId());
+            newUser.setName(userInfo.getUserId());
+            newUser.setTenant(tenant.getTenant());
+            newUser = userRepository.save(newUser);
+
+            SimpleUserEntity newSimpleUser = new SimpleUserEntity();
+            newSimpleUser.setExternalId(userInfo.getUserId());
+            newSimpleUser.setName(userInfo.getUserId());
+            newSimpleUser.setSimpleTenant(tenant);
+            newSimpleUser.setUser(newUser);
+            return simpleUserRepository.save(newSimpleUser);
+        });
+        return simpleUser;
+    }
+
+    private DataProductEntity resolveDataProduct(DataProduct dataProduct) 
throws SharingException {
+        Optional<DataProductEntity> maybeDataProduct = dataProductRepository
+                .findByExternalId(dataProduct.getDataProductId());
+        DataProductEntity dataProductEntity = maybeDataProduct.orElseThrow(() 
-> {
+            return new SharingException("No data product exists with id " + 
dataProduct.getDataProductId());
+        });
+        return dataProductEntity;
+    }
+}
diff --git a/data-catalog-api/server/src/main/resources/application.properties 
b/data-catalog-api/server/src/main/resources/application.properties
index 2064c00..914f6da 100644
--- a/data-catalog-api/server/src/main/resources/application.properties
+++ b/data-catalog-api/server/src/main/resources/application.properties
@@ -3,3 +3,8 @@ spring.datasource.username=postgres
 spring.datasource.password=example
 spring.jpa.hibernate.ddl-auto=update
 spring.jpa.show-sql=true
+
+# Run schema.sql after schema creation performed by Hibernate
+# 
https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.data-initialization.using-basic-sql-scripts
+spring.jpa.defer-datasource-initialization=true
+spring.sql.init.mode=always
diff --git a/data-catalog-api/server/src/main/resources/schema.sql 
b/data-catalog-api/server/src/main/resources/schema.sql
new file mode 100644
index 0000000..e890d2e
--- /dev/null
+++ b/data-catalog-api/server/src/main/resources/schema.sql
@@ -0,0 +1,36 @@
+-- TODO: move this to Liquibase or some other schema migration management tool
+CREATE
+OR REPLACE VIEW simple_data_product_sharing_view AS
+SELECT
+    s.data_product_id AS data_product_id,
+    u.user_id AS user_id,
+    CASE
+        WHEN s.permission_id = 'OWNER' THEN 0
+        WHEN s.permission_id = 'READ' THEN 1
+        WHEN s.permission_id = 'READ_METADATA' THEN 2
+        WHEN s.permission_id = 'WRITE' THEN 3
+        WHEN s.permission_id = 'WRITE_METADATA' THEN 4
+        WHEN s.permission_id = 'MANAGE_SHARING' THEN 5
+        ELSE NULL
+    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 -- UNION
+    -- SELECT
+    --     dp.data_product_id AS data_product_id,
+    --     u.user_id AS user_id,
+    --     CASE
+    --         WHEN s.permission_id = 'OWNER' THEN 0
+    --         WHEN s.permission_id = 'READ' THEN 1
+    --         WHEN s.permission_id = 'READ_METADATA' THEN 2
+    --         WHEN s.permission_id = 'WRITE' THEN 3
+    --         WHEN s.permission_id = 'WRITE_METADATA' THEN 4
+    --         WHEN s.permission_id = 'MANAGE_SHARING' THEN 5
+    --         ELSE NULL
+    --     END AS permission_id
+    -- FROM
+    --     simple_group_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
+;
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
new file mode 100644
index 0000000..91f485b
--- /dev/null
+++ 
b/data-catalog-api/server/src/test/java/org/apache/airavata/datacatalog/api/sharing/SimpleSharingManagerImplTest.java
@@ -0,0 +1,138 @@
+package org.apache.airavata.datacatalog.api.sharing;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Optional;
+import java.util.UUID;
+
+import org.apache.airavata.datacatalog.api.DataProduct;
+import org.apache.airavata.datacatalog.api.Permission;
+import org.apache.airavata.datacatalog.api.UserInfo;
+import org.apache.airavata.datacatalog.api.exception.SharingException;
+import org.apache.airavata.datacatalog.api.model.DataProductEntity;
+import org.apache.airavata.datacatalog.api.model.TenantEntity;
+import org.apache.airavata.datacatalog.api.model.UserEntity;
+import 
org.apache.airavata.datacatalog.api.model.sharing.simple.SimpleTenantEntity;
+import 
org.apache.airavata.datacatalog.api.model.sharing.simple.SimpleUserEntity;
+import org.apache.airavata.datacatalog.api.repository.DataProductRepository;
+import org.apache.airavata.datacatalog.api.repository.TenantRepository;
+import org.apache.airavata.datacatalog.api.repository.UserRepository;
+import 
org.apache.airavata.datacatalog.api.repository.sharing.simple.SimpleTenantRepository;
+import 
org.apache.airavata.datacatalog.api.repository.sharing.simple.SimpleUserRepository;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import 
org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import 
org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+
+@DataJpaTest
+@AutoConfigureTestDatabase(replace = Replace.NONE)
+public class SimpleSharingManagerImplTest {
+    @Autowired
+    SimpleSharingManagerImpl simpleSharingManagerImpl;
+
+    @Autowired
+    UserRepository userRepository;
+    @Autowired
+    TenantRepository tenantRepository;
+    @Autowired
+    SimpleUserRepository simpleUserRepository;
+    @Autowired
+    SimpleTenantRepository simpleTenantRepository;
+    @Autowired
+    DataProductRepository dataProductRepository;
+
+    @Test
+    void testResolveUserCreatesUserAndTenantIfMissing() throws 
SharingException {
+
+        Optional<UserEntity> maybeUserEntity = 
userRepository.findByExternalIdAndTenant_ExternalId("userId",
+                "tenantId");
+        assertFalse(maybeUserEntity.isPresent());
+        Optional<TenantEntity> maybeTenantEntity = 
tenantRepository.findByExternalId("tenantId");
+        assertFalse(maybeTenantEntity.isPresent());
+
+        UserInfo userInfo = 
UserInfo.newBuilder().setUserId("userId").setTenantId("tenantId").build();
+        UserEntity userEntity = 
this.simpleSharingManagerImpl.resolveUser(userInfo);
+
+        assertEquals(userEntity.getExternalId(), "userId");
+        assertEquals(userEntity.getName(), "userId");
+        assertEquals(userEntity.getTenant().getExternalId(), "tenantId");
+
+        maybeUserEntity = 
userRepository.findByExternalIdAndTenant_ExternalId("userId", "tenantId");
+        assertTrue(maybeUserEntity.isPresent());
+
+        maybeTenantEntity = tenantRepository.findByExternalId("tenantId");
+        assertTrue(maybeTenantEntity.isPresent());
+    }
+
+    @Test
+    void testResolveUserFindsExistingUserAndTenant() throws SharingException {
+
+        String userId = "userId";
+        String tenantId = "tenantId";
+
+        TenantEntity tenantEntity = new TenantEntity();
+        tenantEntity.setExternalId(tenantId);
+        tenantEntity.setName("tenant name");
+        tenantRepository.save(tenantEntity);
+        SimpleTenantEntity simpleTenantEntity = new SimpleTenantEntity();
+        simpleTenantEntity.setExternalId(tenantId);
+        simpleTenantEntity.setName(tenantId);
+        simpleTenantEntity.setTenant(tenantEntity);
+        simpleTenantRepository.save(simpleTenantEntity);
+
+        UserEntity testUserEntity = new UserEntity();
+        testUserEntity.setExternalId(userId);
+        testUserEntity.setName("user name");
+        testUserEntity.setTenant(tenantEntity);
+        UserEntity savedUserEntity = userRepository.save(testUserEntity);
+        SimpleUserEntity simpleUserEntity = new SimpleUserEntity();
+        simpleUserEntity.setExternalId(userId);
+        simpleUserEntity.setName(userId);
+        simpleUserEntity.setUser(testUserEntity);
+        simpleUserEntity.setSimpleTenant(simpleTenantEntity);
+        simpleUserRepository.save(simpleUserEntity);
+
+        UserInfo userInfo = 
UserInfo.newBuilder().setUserId(userId).setTenantId(tenantId).build();
+        UserEntity userEntity = 
this.simpleSharingManagerImpl.resolveUser(userInfo);
+
+        assertEquals(userEntity.getExternalId(), userId);
+        assertEquals(userEntity.getName(), "user name");
+        assertEquals(userEntity.getTenant().getExternalId(), tenantId);
+        // Double check same database record
+        assertEquals(userEntity.getUserId(), savedUserEntity.getUserId());
+    }
+
+    @Test
+    public void testUserHasAccess() 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();
+        // UserEntity testUserB = simpleSharingManagerImpl
+        // .resolveUser(userB);
+
+        DataProductEntity dataProductEntity = new DataProductEntity();
+        dataProductEntity.setExternalId(UUID.randomUUID().toString());
+        dataProductEntity.setOwner(testUserA);
+        dataProductEntity.setName("test data product");
+        dataProductRepository.save(dataProductEntity);
+
+        // Check that userB doesn't have READ access to the data product
+        DataProduct dataProduct = DataProduct.newBuilder()
+                .setDataProductId(dataProductEntity.getExternalId()) // only 
need the data product id
+                .build();
+        boolean hasAccess = simpleSharingManagerImpl.userHasAccess(userB, 
dataProduct, Permission.READ);
+        assertFalse(hasAccess);
+
+        // 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
+        hasAccess = simpleSharingManagerImpl.userHasAccess(userB, dataProduct, 
Permission.READ);
+        assertTrue(hasAccess);
+    }
+
+}

Reply via email to