This is an automated email from the ASF dual-hosted git repository. nic pushed a commit to branch 2.6.x in repository https://gitbox.apache.org/repos/asf/kylin.git
commit 560deef12ea6173644e8250958e5f17d0ee0fcab Author: yaqian.zhang <598593...@qq.com> AuthorDate: Fri Aug 30 20:24:27 2019 +0800 KYLIN-4034 Table not in Insight when user have no access to the table --- .../org/apache/kylin/metadata/acl/TableACL.java | 6 +++ .../kylin/rest/controller/QueryController.java | 4 +- .../apache/kylin/rest/service/QueryService.java | 8 ++++ .../apache/kylin/rest/service/TableACLService.java | 44 ++++++++++++++++++++++ .../kylin/rest/controller/QueryControllerTest.java | 4 +- 5 files changed, 63 insertions(+), 3 deletions(-) diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/acl/TableACL.java b/core-metadata/src/main/java/org/apache/kylin/metadata/acl/TableACL.java index 57ebb61..b110064 100644 --- a/core-metadata/src/main/java/org/apache/kylin/metadata/acl/TableACL.java +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/acl/TableACL.java @@ -34,6 +34,7 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; +import com.google.common.collect.Sets; @SuppressWarnings("serial") @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, @@ -86,6 +87,11 @@ public class TableACL extends RootPersistentEntity { return currentEntry(type).getCanAccessList(table, allIdentifiers); } + public Set<String> getBlockedTablesByUser(String username, String type) { + return currentEntry(type).get(username) == null ? Sets.<String>newHashSet() + : currentEntry(type).get(username).getTables(); + } + public TableACL add(String name, String table, String type) { currentEntry(type).add(name, table); return this; diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/QueryController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/QueryController.java index b89772b..6b56e91 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/controller/QueryController.java +++ b/server-base/src/main/java/org/apache/kylin/rest/controller/QueryController.java @@ -186,9 +186,9 @@ public class QueryController extends BasicController { @RequestMapping(value = "/tables_and_columns", method = RequestMethod.GET, produces = { "application/json" }) @ResponseBody - public List<TableMeta> getMetadata(MetaRequest metaRequest) { + public List<TableMeta> getMetadata(MetaRequest metaRequest) throws IOException { try { - return queryService.getMetadata(metaRequest.getProject()); + return queryService.getMetadataFilterByUser(metaRequest.getProject()); } catch (SQLException e) { throw new InternalErrorException(e.getLocalizedMessage(), e); } diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java b/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java index da4fcb6..bf8082e 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java +++ b/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java @@ -156,6 +156,10 @@ public class QueryService extends BasicService { private ModelService modelService; @Autowired + @Qualifier("TableAclService") + private TableACLService tableAclService; + + @Autowired private AclEvaluate aclEvaluate; private GenericKeyedObjectPool<PreparedContextKey, PreparedContext> preparedContextPool; @@ -195,6 +199,10 @@ public class QueryService extends BasicService { Preconditions.checkNotNull(cacheManager, "cacheManager is not injected yet"); } + public List<TableMeta> getMetadataFilterByUser(String project) throws SQLException, IOException { + return tableAclService.filterTableMetasByAcl(getMetadata(project), project); + } + public List<TableMeta> getMetadata(String project) throws SQLException { return getMetadata(getCubeManager(), project); } diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/TableACLService.java b/server-base/src/main/java/org/apache/kylin/rest/service/TableACLService.java index c054ba0..964e9d6 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/service/TableACLService.java +++ b/server-base/src/main/java/org/apache/kylin/rest/service/TableACLService.java @@ -18,16 +18,24 @@ package org.apache.kylin.rest.service; +import static org.apache.kylin.metadata.MetadataConstants.TYPE_USER; + import java.io.IOException; import java.util.List; import java.util.Set; +import org.apache.kylin.common.KylinConfig; +import org.apache.kylin.metadata.project.ProjectManager; +import org.apache.kylin.metadata.querymeta.TableMeta; import org.apache.kylin.metadata.acl.TableACL; import org.apache.kylin.rest.util.AclEvaluate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.security.core.context.SecurityContextHolder; + +import com.google.common.collect.Lists; @Component("TableAclService") public class TableACLService extends BasicService { @@ -74,4 +82,40 @@ public class TableACLService extends BasicService { aclEvaluate.checkProjectAdminPermission(project); getTableACLManager().deleteTableACLByTbl(project, table); } + + public List<TableMeta> filterTableMetasByAcl(List<TableMeta> tableMeta, String project) throws IOException { + return filterByAcl(tableMeta, project, new AclFilter<TableMeta>() { + @Override + public boolean filter(TableMeta table, Set<String> blockedTables) { + String identity = table.getTABLE_SCHEM() + "." + table.getTABLE_NAME(); + return !blockedTables.contains(identity); + } + }); + } + + private interface AclFilter<T> { + boolean filter(T table, Set<String> blockedTables); + } + + private <T> List<T> filterByAcl(List<T> tables, String project, AclFilter filter) throws IOException { + ProjectManager projectManager = ProjectManager.getInstance(KylinConfig.getInstanceFromEnv()); + + if (aclEvaluate.hasProjectAdminPermission(projectManager.getProject(project))) { + return tables; + } + + String username = SecurityContextHolder.getContext().getAuthentication().getName(); + Set<String> blockedTables = getBlockedTablesByUser(project, username, TYPE_USER); + List<T> result = Lists.newArrayList(); + for (T table : tables) { + if (filter.filter(table, blockedTables)) { + result.add(table); + } + } + return result; + } + + private Set<String> getBlockedTablesByUser(String project, String username, String type) throws IOException { + return getTableACLByProject(project).getBlockedTablesByUser(username, type); + } } diff --git a/server/src/test/java/org/apache/kylin/rest/controller/QueryControllerTest.java b/server/src/test/java/org/apache/kylin/rest/controller/QueryControllerTest.java index 2225096..d18c2ed 100644 --- a/server/src/test/java/org/apache/kylin/rest/controller/QueryControllerTest.java +++ b/server/src/test/java/org/apache/kylin/rest/controller/QueryControllerTest.java @@ -33,6 +33,8 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.cache.CacheManager; +import java.io.IOException; + /** * @author xduo */ @@ -77,7 +79,7 @@ public class QueryControllerTest extends ServiceTestBase { } @Test - public void testGetMetadata() { + public void testGetMetadata() throws IOException { queryController.getMetadata(new MetaRequest(ProjectInstance.DEFAULT_PROJECT_NAME)); }