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 e07066340e3021bc3bd3e66ac656ab768ab90541 Author: Marcus Christie <[email protected]> AuthorDate: Wed Apr 26 11:17:04 2023 -0400 Integrated SharingManager into the Data Catalog API --- .../api/client/DataCatalogAPIClient.java | 22 ++++--- .../sharing/simple/SimpleGroupSharingEntity.java | 3 +- .../sharing/simple/SimplePublicSharingEntity.java | 3 +- .../sharing/simple/SimpleUserSharingEntity.java | 3 +- .../api/query/MetadataSchemaQueryExecutor.java | 3 +- .../api/query/MetadataSchemaQueryWriter.java | 5 +- .../impl/MetadataSchemaQueryExecutorImpl.java | 6 +- .../PostgresqlMetadataSchemaQueryWriterImpl.java | 31 +++++++-- .../api/service/DataCatalogAPIService.java | 74 ++++++++++++++++++++-- .../api/service/DataCatalogService.java | 3 +- .../api/service/impl/DataCatalogServiceImpl.java | 15 +++-- .../server/src/main/resources/schema.sql | 25 ++++++++ 12 files changed, 160 insertions(+), 33 deletions(-) diff --git a/data-catalog-api/client/src/main/java/org/apache/airavata/datacatalog/api/client/DataCatalogAPIClient.java b/data-catalog-api/client/src/main/java/org/apache/airavata/datacatalog/api/client/DataCatalogAPIClient.java index 794147b..c24fb07 100644 --- a/data-catalog-api/client/src/main/java/org/apache/airavata/datacatalog/api/client/DataCatalogAPIClient.java +++ b/data-catalog-api/client/src/main/java/org/apache/airavata/datacatalog/api/client/DataCatalogAPIClient.java @@ -33,6 +33,7 @@ import org.apache.airavata.datacatalog.api.MetadataSchemaFieldListRequest; import org.apache.airavata.datacatalog.api.MetadataSchemaFieldListResponse; import org.apache.airavata.datacatalog.api.MetadataSchemaGetRequest; import org.apache.airavata.datacatalog.api.MetadataSchemaGetResponse; +import org.apache.airavata.datacatalog.api.UserInfo; import io.grpc.Channel; import io.grpc.ManagedChannel; @@ -43,32 +44,36 @@ import io.grpc.StatusRuntimeException;; public class DataCatalogAPIClient { private final DataCatalogAPIServiceBlockingStub blockingStub; + private final UserInfo userInfo = UserInfo.newBuilder().setUserId("demoUser").setTenantId("demoTenant").build(); public DataCatalogAPIClient(Channel channel) { blockingStub = DataCatalogAPIServiceGrpc.newBlockingStub(channel); } public DataProduct createDataProduct(DataProduct dataProduct) { - DataProductCreateRequest request = DataProductCreateRequest.newBuilder().setDataProduct(dataProduct).build(); + DataProductCreateRequest request = DataProductCreateRequest.newBuilder().setDataProduct(dataProduct) + .setUserInfo(userInfo).build(); DataProductCreateResponse response = blockingStub.createDataProduct(request); return response.getDataProduct(); } public DataProduct updateDataProduct(DataProduct dataProduct) { - DataProductUpdateRequest request = DataProductUpdateRequest.newBuilder().setDataProduct(dataProduct).build(); + DataProductUpdateRequest request = DataProductUpdateRequest.newBuilder().setDataProduct(dataProduct) + .setUserInfo(userInfo).build(); DataProductUpdateResponse response = blockingStub.updateDataProduct(request); return response.getDataProduct(); } public DataProduct getDataProduct(String dataProductId) { - DataProductGetRequest request = DataProductGetRequest.newBuilder().setDataProductId(dataProductId).build(); + DataProductGetRequest request = DataProductGetRequest.newBuilder().setDataProductId(dataProductId) + .setUserInfo(userInfo).build(); DataProductGetResponse response = blockingStub.getDataProduct(request); return response.getDataProduct(); } public void deleteDataProduct(String dataProductId) { DataProductDeleteRequest request = DataProductDeleteRequest.newBuilder().setDataProductId(dataProductId) - .build(); + .setUserInfo(userInfo).build(); blockingStub.deleteDataProduct(request); } @@ -122,21 +127,22 @@ public class DataCatalogAPIClient { public DataProduct addDataProductToMetadataSchema(String dataProductId, String schemaName) { DataProductAddToMetadataSchemaRequest request = DataProductAddToMetadataSchemaRequest.newBuilder() - .setDataProductId(dataProductId).setSchemaName(schemaName).build(); + .setDataProductId(dataProductId).setSchemaName(schemaName).setUserInfo(userInfo).build(); DataProductAddToMetadataSchemaResponse response = blockingStub.addDataProductToMetadataSchema(request); return response.getDataProduct(); } public DataProduct removeDataProductFromMetadataSchema(String dataProductId, String schemaName) { DataProductRemoveFromMetadataSchemaRequest request = DataProductRemoveFromMetadataSchemaRequest.newBuilder() - .setDataProductId(dataProductId).setSchemaName(schemaName).build(); + .setDataProductId(dataProductId).setSchemaName(schemaName).setUserInfo(userInfo).build(); DataProductRemoveFromMetadataSchemaResponse response = blockingStub .removeDataProductFromMetadataSchema(request); return response.getDataProduct(); } public List<DataProduct> searchDataProducts(String sql) { - DataProductSearchRequest request = DataProductSearchRequest.newBuilder().setSql(sql).build(); + DataProductSearchRequest request = DataProductSearchRequest.newBuilder().setSql(sql).setUserInfo(userInfo) + .build(); DataProductSearchResponse response = blockingStub.searchDataProducts(request); return response.getDataProductsList(); } @@ -282,7 +288,7 @@ public class DataCatalogAPIClient { // searchResults = client.searchDataProducts(""" // select * from my_schema where not (field1 < 5 or field3 = 'bar') // """); - System.out.println(searchResults); + System.out.println("Shouldn't match anything: " + searchResults); } finally { channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS); } 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 index a4ce8bc..00c7ad0 100644 --- 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 @@ -7,6 +7,7 @@ import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; +import jakarta.persistence.ForeignKey; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @@ -32,7 +33,7 @@ public class SimpleGroupSharingEntity { private SimpleGroupEntity simpleGroup; @ManyToOne(optional = false) - @JoinColumn(name = "data_product_id", referencedColumnName = "data_product_id", nullable = false, updatable = false) + @JoinColumn(name = "data_product_id", referencedColumnName = "data_product_id", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "fk_simple_group_sharing_data_product_id")) private DataProductEntity dataProduct; @Column(name = "permission_id") diff --git a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimplePublicSharingEntity.java b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimplePublicSharingEntity.java index 88ea990..7cda70d 100644 --- a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimplePublicSharingEntity.java +++ b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/model/sharing/simple/SimplePublicSharingEntity.java @@ -7,6 +7,7 @@ import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; +import jakarta.persistence.ForeignKey; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @@ -28,7 +29,7 @@ public class SimplePublicSharingEntity { private Long sharingId; @ManyToOne(optional = false) - @JoinColumn(name = "data_product_id", referencedColumnName = "data_product_id", nullable = false, updatable = false) + @JoinColumn(name = "data_product_id", referencedColumnName = "data_product_id", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "fk_simple_public_sharing_data_product_id")) private DataProductEntity dataProduct; @Column(name = "permission_id") 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 index 57d6c9b..afb7be3 100644 --- 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 @@ -7,6 +7,7 @@ import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; +import jakarta.persistence.ForeignKey; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @@ -32,7 +33,7 @@ public class SimpleUserSharingEntity { private SimpleUserEntity simpleUser; @ManyToOne(optional = false) - @JoinColumn(name = "data_product_id", nullable = false, updatable = false) + @JoinColumn(name = "data_product_id", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "fk_simple_user_sharing_data_product_id")) private DataProductEntity dataProduct; @Column(name = "permission_id") diff --git a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/query/MetadataSchemaQueryExecutor.java b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/query/MetadataSchemaQueryExecutor.java index dcf6a35..b158662 100644 --- a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/query/MetadataSchemaQueryExecutor.java +++ b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/query/MetadataSchemaQueryExecutor.java @@ -2,9 +2,10 @@ package org.apache.airavata.datacatalog.api.query; import org.apache.airavata.datacatalog.api.exception.MetadataSchemaSqlParseException; import org.apache.airavata.datacatalog.api.exception.MetadataSchemaSqlValidateException; +import org.apache.airavata.datacatalog.api.model.UserEntity; public interface MetadataSchemaQueryExecutor { - MetadataSchemaQueryResult execute(String sql) + MetadataSchemaQueryResult execute(UserEntity userEntity, String sql) throws MetadataSchemaSqlParseException, MetadataSchemaSqlValidateException; } diff --git a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/query/MetadataSchemaQueryWriter.java b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/query/MetadataSchemaQueryWriter.java index 08ab745..5932bbd 100644 --- a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/query/MetadataSchemaQueryWriter.java +++ b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/query/MetadataSchemaQueryWriter.java @@ -4,6 +4,7 @@ import java.util.Collection; import java.util.Map; import org.apache.airavata.datacatalog.api.model.MetadataSchemaEntity; +import org.apache.airavata.datacatalog.api.model.UserEntity; import org.apache.calcite.sql.SqlNode; public interface MetadataSchemaQueryWriter { @@ -11,11 +12,13 @@ public interface MetadataSchemaQueryWriter { /** * Rewrite the query as needed to filter against metadata schema fields. * + * @param userEntity + * * @param sqlNode * @param metadataSchemas * @param tableAliases * @return */ - String rewriteQuery(SqlNode sqlNode, Collection<MetadataSchemaEntity> metadataSchemas, + String rewriteQuery(UserEntity userEntity, SqlNode sqlNode, Collection<MetadataSchemaEntity> metadataSchemas, Map<String, String> tableAliases); } diff --git a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/query/impl/MetadataSchemaQueryExecutorImpl.java b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/query/impl/MetadataSchemaQueryExecutorImpl.java index 7643a50..1dca5c0 100644 --- a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/query/impl/MetadataSchemaQueryExecutorImpl.java +++ b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/query/impl/MetadataSchemaQueryExecutorImpl.java @@ -14,6 +14,7 @@ import org.apache.airavata.datacatalog.api.mapper.DataProductMapper; import org.apache.airavata.datacatalog.api.model.DataProductEntity; import org.apache.airavata.datacatalog.api.model.MetadataSchemaEntity; import org.apache.airavata.datacatalog.api.model.MetadataSchemaFieldEntity; +import org.apache.airavata.datacatalog.api.model.UserEntity; import org.apache.airavata.datacatalog.api.query.MetadataSchemaQueryExecutor; import org.apache.airavata.datacatalog.api.query.MetadataSchemaQueryResult; import org.apache.airavata.datacatalog.api.query.MetadataSchemaQueryWriter; @@ -68,7 +69,7 @@ public class MetadataSchemaQueryExecutorImpl implements MetadataSchemaQueryExecu DataProductMapper dataProductMapper; @Override - public MetadataSchemaQueryResult execute(String sql) + public MetadataSchemaQueryResult execute(UserEntity userEntity, String sql) throws MetadataSchemaSqlParseException, MetadataSchemaSqlValidateException { // Create a schema that contains the data_product table and all of the metadata @@ -148,7 +149,8 @@ public class MetadataSchemaQueryExecutorImpl implements MetadataSchemaQueryExecu }); - String finalSql = metadataSchemaQueryWriter.rewriteQuery(validatedSqlNode, metadataSchemas, tableAliases); + String finalSql = metadataSchemaQueryWriter.rewriteQuery(userEntity, validatedSqlNode, metadataSchemas, + tableAliases); logger.debug("Metadata schema query final sql: {}", finalSql); List<DataProductEntity> dataProductEntities = entityManager.createNativeQuery(finalSql, DataProductEntity.class) diff --git a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/query/impl/PostgresqlMetadataSchemaQueryWriterImpl.java b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/query/impl/PostgresqlMetadataSchemaQueryWriterImpl.java index 8ace28a..b8e7775 100644 --- a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/query/impl/PostgresqlMetadataSchemaQueryWriterImpl.java +++ b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/query/impl/PostgresqlMetadataSchemaQueryWriterImpl.java @@ -8,9 +8,12 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.apache.airavata.datacatalog.api.Permission; import org.apache.airavata.datacatalog.api.model.MetadataSchemaEntity; import org.apache.airavata.datacatalog.api.model.MetadataSchemaFieldEntity; +import org.apache.airavata.datacatalog.api.model.UserEntity; import org.apache.airavata.datacatalog.api.query.MetadataSchemaQueryWriter; +import org.apache.airavata.datacatalog.api.sharing.SharingManager; import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; @@ -18,11 +21,15 @@ import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlSelect; import org.apache.calcite.sql.dialect.PostgresqlSqlDialect; import org.apache.calcite.sql.util.SqlShuttle; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class PostgresqlMetadataSchemaQueryWriterImpl implements MetadataSchemaQueryWriter { + @Autowired + SharingManager sharingManager; + private static final class MetadataSchemaFieldFilterRewriter extends SqlShuttle { final Collection<MetadataSchemaEntity> metadataSchemas; @@ -150,11 +157,11 @@ public class PostgresqlMetadataSchemaQueryWriterImpl implements MetadataSchemaQu } @Override - public String rewriteQuery(SqlNode sqlNode, Collection<MetadataSchemaEntity> metadataSchemas, + public String rewriteQuery(UserEntity userEntity, SqlNode sqlNode, Collection<MetadataSchemaEntity> metadataSchemas, Map<String, String> tableAliases) { StringBuilder sb = new StringBuilder(); - sb.append(writeCommonTableExpressions(metadataSchemas)); + sb.append(writeCommonTableExpressions(userEntity, metadataSchemas)); sb.append(" SELECT * FROM "); sb.append(((SqlSelect) sqlNode).getFrom().toSqlString(PostgresqlSqlDialect.DEFAULT)); sb.append(" WHERE "); @@ -170,23 +177,24 @@ public class PostgresqlMetadataSchemaQueryWriterImpl implements MetadataSchemaQu return filterRewriter.finalizeSql(); } - String writeCommonTableExpressions(Collection<MetadataSchemaEntity> metadataSchemas) { + String writeCommonTableExpressions(UserEntity userEntity, Collection<MetadataSchemaEntity> metadataSchemas) { StringBuilder sb = new StringBuilder(); List<String> commonTableExpressions = new ArrayList<>(); for (MetadataSchemaEntity metadataSchema : metadataSchemas) { - commonTableExpressions.add(writeCommonTableExpression(metadataSchema)); + commonTableExpressions.add(writeCommonTableExpression(userEntity, metadataSchema)); } sb.append("WITH "); sb.append(String.join(", ", commonTableExpressions)); return sb.toString(); } - String writeCommonTableExpression(MetadataSchemaEntity metadataSchemaEntity) { + String writeCommonTableExpression(UserEntity userEntity, MetadataSchemaEntity metadataSchemaEntity) { StringBuilder sb = new StringBuilder(); sb.append(metadataSchemaEntity.getSchemaName()); sb.append(" AS ("); - sb.append("select dp_.data_product_id, dp_.parent_data_product_id, dp_.external_id, dp_.name, dp_.metadata "); + sb.append( + "select dp_.data_product_id, dp_.parent_data_product_id, dp_.external_id, dp_.name, dp_.metadata, dp_.owner_id "); // for (MetadataSchemaFieldEntity field : // metadataSchemaEntity.getMetadataSchemaFields()) { // TODO: include each field as well? @@ -194,6 +202,17 @@ public class PostgresqlMetadataSchemaQueryWriterImpl implements MetadataSchemaQu sb.append("from data_product dp_ "); sb.append("inner join data_product_metadata_schema dpms_ on dpms_.data_product_id = dp_.data_product_id "); sb.append("inner join metadata_schema ms_ on ms_.metadata_schema_id = dpms_.metadata_schema_id "); + sb.append("inner join "); + sb.append(sharingManager.getDataProductSharingView()); + sb.append(" dpsv_ on dpsv_.data_product_id = dp_.data_product_id "); + sb.append("and dpsv_.user_id = "); + // TODO: change these to be bound parameters + sb.append(userEntity.getUserId()); + sb.append(" and dpsv_.permission_id in ("); + sb.append(Permission.OWNER.getNumber()); + sb.append(","); + sb.append(Permission.READ_METADATA.getNumber()); + sb.append(") "); sb.append("where ms_.metadata_schema_id = " + metadataSchemaEntity.getMetadataSchemaId()); sb.append(")"); return sb.toString(); diff --git a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/service/DataCatalogAPIService.java b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/service/DataCatalogAPIService.java index 92c02a7..e658fc4 100644 --- a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/service/DataCatalogAPIService.java +++ b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/service/DataCatalogAPIService.java @@ -36,11 +36,14 @@ import org.apache.airavata.datacatalog.api.MetadataSchemaFieldUpdateRequest; import org.apache.airavata.datacatalog.api.MetadataSchemaFieldUpdateResponse; import org.apache.airavata.datacatalog.api.MetadataSchemaGetRequest; import org.apache.airavata.datacatalog.api.MetadataSchemaGetResponse; +import org.apache.airavata.datacatalog.api.Permission; +import org.apache.airavata.datacatalog.api.UserInfo; import org.apache.airavata.datacatalog.api.exception.EntityNotFoundException; import org.apache.airavata.datacatalog.api.exception.MetadataSchemaSqlParseException; import org.apache.airavata.datacatalog.api.exception.MetadataSchemaSqlValidateException; import org.apache.airavata.datacatalog.api.exception.SharingException; import org.apache.airavata.datacatalog.api.query.MetadataSchemaQueryResult; +import org.apache.airavata.datacatalog.api.sharing.SharingManager; import org.lognet.springboot.grpc.GRpcService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -57,6 +60,9 @@ public class DataCatalogAPIService extends DataCatalogAPIServiceGrpc.DataCatalog @Autowired DataCatalogService dataCatalogService; + @Autowired + SharingManager sharingManager; + @Override public void createDataProduct(DataProductCreateRequest request, StreamObserver<DataProductCreateResponse> responseObserver) { @@ -83,7 +89,12 @@ public class DataCatalogAPIService extends DataCatalogAPIServiceGrpc.DataCatalog public void updateDataProduct(DataProductUpdateRequest request, StreamObserver<DataProductUpdateResponse> responseObserver) { - // TODO: check that user has access to update data product record + // check that user has access to update data product record + if (!checkHasPermission(request.getUserInfo(), request.getDataProduct(), Permission.WRITE_METADATA, + responseObserver)) { + return; + } + try { DataProduct savedDataProduct = dataCatalogService.updateDataProduct(request.getDataProduct()); @@ -97,9 +108,13 @@ public class DataCatalogAPIService extends DataCatalogAPIServiceGrpc.DataCatalog @Override public void getDataProduct(DataProductGetRequest request, StreamObserver<DataProductGetResponse> responseObserver) { - // TODO: check that user has READ access on data product record + try { DataProduct dataProduct = dataCatalogService.getDataProduct(request.getDataProductId()); + // check that user has READ_METADATA access on data product record + if (!checkHasPermission(request.getUserInfo(), dataProduct, Permission.READ_METADATA, responseObserver)) { + return; + } responseObserver.onNext(DataProductGetResponse.newBuilder().setDataProduct(dataProduct).build()); responseObserver.onCompleted(); @@ -112,11 +127,20 @@ public class DataCatalogAPIService extends DataCatalogAPIServiceGrpc.DataCatalog @Override public void deleteDataProduct(DataProductDeleteRequest request, StreamObserver<DataProductDeleteResponse> responseObserver) { - // TODO: check that user has WRITE access on data product record - dataCatalogService.deleteDataProduct(request.getDataProductId()); + try { + DataProduct dataProduct = dataCatalogService.getDataProduct(request.getDataProductId()); + // check that user has WRITE_METADATA access on data product record + if (!checkHasPermission(request.getUserInfo(), dataProduct, Permission.WRITE_METADATA, responseObserver)) { + return; + } + dataCatalogService.deleteDataProduct(request.getDataProductId()); - responseObserver.onNext(DataProductDeleteResponse.newBuilder().build()); - responseObserver.onCompleted(); + responseObserver.onNext(DataProductDeleteResponse.newBuilder().build()); + responseObserver.onCompleted(); + } catch (EntityNotFoundException e) { + responseObserver.onError(Status.NOT_FOUND.asException()); + responseObserver.onCompleted(); + } } @Override @@ -125,7 +149,14 @@ public class DataCatalogAPIService extends DataCatalogAPIServiceGrpc.DataCatalog String dataProductId = request.getDataProductId(); String schemaName = request.getSchemaName(); + try { + DataProduct checkDataProduct = dataCatalogService.getDataProduct(request.getDataProductId()); + // check that user has WRITE_METADATA access on data product record + if (!checkHasPermission(request.getUserInfo(), checkDataProduct, Permission.WRITE_METADATA, + responseObserver)) { + return; + } DataProduct dataProduct = dataCatalogService.addDataProductToMetadataSchema(dataProductId, schemaName); responseObserver @@ -144,6 +175,12 @@ public class DataCatalogAPIService extends DataCatalogAPIServiceGrpc.DataCatalog String dataProductId = request.getDataProductId(); String schemaName = request.getSchemaName(); try { + DataProduct checkDataProduct = dataCatalogService.getDataProduct(request.getDataProductId()); + // check that user has WRITE_METADATA access on data product record + if (!checkHasPermission(request.getUserInfo(), checkDataProduct, Permission.WRITE_METADATA, + responseObserver)) { + return; + } DataProduct dataProduct = dataCatalogService.removeDataProductFromMetadataSchema(dataProductId, schemaName); responseObserver @@ -161,7 +198,8 @@ public class DataCatalogAPIService extends DataCatalogAPIServiceGrpc.DataCatalog StreamObserver<DataProductSearchResponse> responseObserver) { try { - MetadataSchemaQueryResult searchResult = dataCatalogService.searchDataProducts(request.getSql()); + MetadataSchemaQueryResult searchResult = dataCatalogService.searchDataProducts(request.getUserInfo(), + request.getSql()); List<DataProduct> dataProducts = searchResult.dataProducts(); responseObserver.onNext(DataProductSearchResponse.newBuilder().addAllDataProducts(dataProducts).build()); responseObserver.onCompleted(); @@ -270,4 +308,26 @@ public class DataCatalogAPIService extends DataCatalogAPIServiceGrpc.DataCatalog MetadataSchemaFieldUpdateResponse.newBuilder().setMetadataSchemaField(metadataSchemaField).build()); responseObserver.onCompleted(); } + + private <T> boolean checkHasPermission(UserInfo userInfo, DataProduct dataProduct, Permission permission, + StreamObserver<T> responseObserver) { + try { + boolean userHasAccess = sharingManager.userHasAccess(userInfo, dataProduct, + permission); + if (!userHasAccess) { + responseObserver.onError(Status.PERMISSION_DENIED + .withDescription("user does not have " + permission + " permission") + .asException()); + responseObserver.onCompleted(); + return false; + } else { + return true; + } + } catch (SharingException e) { + responseObserver.onError(Status.INTERNAL.withDescription(e.getMessage()).asException()); + responseObserver.onCompleted(); + } + return false; + } + } diff --git a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/service/DataCatalogService.java b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/service/DataCatalogService.java index be6ff66..0e514ce 100644 --- a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/service/DataCatalogService.java +++ b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/service/DataCatalogService.java @@ -5,6 +5,7 @@ import java.util.List; import org.apache.airavata.datacatalog.api.DataProduct; import org.apache.airavata.datacatalog.api.MetadataSchema; import org.apache.airavata.datacatalog.api.MetadataSchemaField; +import org.apache.airavata.datacatalog.api.UserInfo; import org.apache.airavata.datacatalog.api.exception.MetadataSchemaSqlParseException; import org.apache.airavata.datacatalog.api.exception.MetadataSchemaSqlValidateException; import org.apache.airavata.datacatalog.api.exception.SharingException; @@ -43,6 +44,6 @@ public interface DataCatalogService { MetadataSchemaField updateMetadataSchemaField(MetadataSchemaField metadataSchemaField); - MetadataSchemaQueryResult searchDataProducts(String sql) + MetadataSchemaQueryResult searchDataProducts(UserInfo userInfo, String sql) throws MetadataSchemaSqlParseException, MetadataSchemaSqlValidateException; } diff --git a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/service/impl/DataCatalogServiceImpl.java b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/service/impl/DataCatalogServiceImpl.java index e44d10a..fb23e02 100644 --- a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/service/impl/DataCatalogServiceImpl.java +++ b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/service/impl/DataCatalogServiceImpl.java @@ -9,6 +9,7 @@ import org.apache.airavata.datacatalog.api.MetadataSchema; import org.apache.airavata.datacatalog.api.MetadataSchemaField; import org.apache.airavata.datacatalog.api.MetadataSchemaFieldListResponse; import org.apache.airavata.datacatalog.api.Permission; +import org.apache.airavata.datacatalog.api.UserInfo; import org.apache.airavata.datacatalog.api.exception.EntityNotFoundException; import org.apache.airavata.datacatalog.api.exception.MetadataSchemaSqlParseException; import org.apache.airavata.datacatalog.api.exception.MetadataSchemaSqlValidateException; @@ -70,11 +71,12 @@ public class DataCatalogServiceImpl implements DataCatalogService { dataProductEntity.setOwner(owner); dataProductMapper.mapModelToEntity(dataProduct, dataProductEntity); DataProductEntity savedDataProductEntity = dataProductRepository.save(dataProductEntity); + DataProduct savedDataProduct = toDataProduct(savedDataProductEntity); - sharingManager.grantPermissionToUser(dataProduct.getOwner(), dataProduct, Permission.OWNER, + sharingManager.grantPermissionToUser(dataProduct.getOwner(), savedDataProduct, Permission.OWNER, dataProduct.getOwner()); - return toDataProduct(savedDataProductEntity); + return savedDataProduct; } @Override @@ -121,9 +123,14 @@ public class DataCatalogServiceImpl implements DataCatalogService { } @Override - public MetadataSchemaQueryResult searchDataProducts(String sql) + public MetadataSchemaQueryResult searchDataProducts(UserInfo userInfo, String sql) throws MetadataSchemaSqlParseException, MetadataSchemaSqlValidateException { - return metadataSchemaQueryExecutor.execute(sql); + try { + UserEntity userEntity = sharingManager.resolveUser(userInfo); + return metadataSchemaQueryExecutor.execute(userEntity, sql); + } catch (SharingException e) { + throw new RuntimeException("Unable to resolve " + userInfo, e); + } } @Override diff --git a/data-catalog-api/server/src/main/resources/schema.sql b/data-catalog-api/server/src/main/resources/schema.sql index 162f1af..41371eb 100644 --- a/data-catalog-api/server/src/main/resources/schema.sql +++ b/data-catalog-api/server/src/main/resources/schema.sql @@ -53,3 +53,28 @@ FROM 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 data_product_hierarchy dph ON dph.root = s.data_product_id; + +-- Add ON DELETE CASCADE to the simple sharing tables +ALTER TABLE + simple_user_sharing DROP CONSTRAINT fk_simple_user_sharing_data_product_id; + +ALTER TABLE + simple_user_sharing +ADD + CONSTRAINT fk_simple_user_sharing_data_product_id FOREIGN KEY (data_product_id) REFERENCES data_product(data_product_id) ON DELETE CASCADE; + +ALTER TABLE + simple_group_sharing DROP CONSTRAINT fk_simple_group_sharing_data_product_id; + +ALTER TABLE + simple_group_sharing +ADD + CONSTRAINT fk_simple_group_sharing_data_product_id FOREIGN KEY (data_product_id) REFERENCES data_product(data_product_id) ON DELETE CASCADE; + +ALTER TABLE + simple_public_sharing DROP CONSTRAINT fk_simple_public_sharing_data_product_id; + +ALTER TABLE + simple_public_sharing +ADD + CONSTRAINT fk_simple_public_sharing_data_product_id FOREIGN KEY (data_product_id) REFERENCES data_product(data_product_id) ON DELETE CASCADE;
