minor, refine acl
Project: http://git-wip-us.apache.org/repos/asf/kylin/repo Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/c490e6cf Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/c490e6cf Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/c490e6cf Branch: refs/heads/kylin-2.1.x Commit: c490e6cf7c01e0e1443fa93fac681300f96680d6 Parents: 8e1a7d5 Author: Roger Shi <rogershijich...@hotmail.com> Authored: Thu Jun 29 16:34:52 2017 +0800 Committer: liyang-gmt8 <liy...@apache.org> Committed: Thu Jun 29 16:36:57 2017 +0800 ---------------------------------------------------------------------- .../kylin/rest/controller/CubeController.java | 15 ++- .../rest/controller2/AccessControllerV2.java | 16 ++- .../kylin/rest/service/AccessService.java | 26 +++-- .../apache/kylin/rest/service/CubeService.java | 109 +++++++++++++++---- 4 files changed, 131 insertions(+), 35 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kylin/blob/c490e6cf/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java ---------------------------------------------------------------------- diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java index 6916dd8..a370292 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java +++ b/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java @@ -352,7 +352,7 @@ public class CubeController extends BasicController { @ResponseBody public CubeInstance cloneCube(@PathVariable String cubeName, @RequestBody CubeRequest cubeRequest) { String newCubeName = cubeRequest.getCubeName(); - String project = cubeRequest.getProject(); + String projectName = cubeRequest.getProject(); CubeInstance cube = cubeService.getCubeManager().getCube(cubeName); if (cube == null) { @@ -366,6 +366,11 @@ public class CubeController extends BasicController { throw new BadRequestException("Invalid Cube name, only letters, numbers and underline supported."); } + ProjectInstance project = cubeService.getProjectManager().getProject(projectName); + if (project == null) { + throw new BadRequestException("Project " + projectName + " doesn't exist"); + } + CubeDesc cubeDesc = cube.getDescriptor(); CubeDesc newCubeDesc = CubeDesc.getCopyOf(cubeDesc); @@ -373,7 +378,7 @@ public class CubeController extends BasicController { CubeInstance newCube; try { - newCube = cubeService.createCubeAndDesc(newCubeName, project, newCubeDesc); + newCube = cubeService.createCubeAndDesc(project, newCubeDesc); //reload to avoid shallow clone cubeService.getCubeDescManager().reloadCubeDescLocal(newCubeName); @@ -449,7 +454,11 @@ public class CubeController extends BasicController { try { desc.setUuid(UUID.randomUUID().toString()); String projectName = (null == cubeRequest.getProject()) ? ProjectInstance.DEFAULT_PROJECT_NAME : cubeRequest.getProject(); - cubeService.createCubeAndDesc(name, projectName, desc); + ProjectInstance project = cubeService.getProjectManager().getProject(projectName); + if (project == null) { + throw new BadRequestException("Project " + projectName + " doesn't exist"); + } + cubeService.createCubeAndDesc(project, desc); } catch (Exception e) { logger.error("Failed to deal with the request.", e); throw new InternalErrorException(e.getLocalizedMessage(), e); http://git-wip-us.apache.org/repos/asf/kylin/blob/c490e6cf/server-base/src/main/java/org/apache/kylin/rest/controller2/AccessControllerV2.java ---------------------------------------------------------------------- diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller2/AccessControllerV2.java b/server-base/src/main/java/org/apache/kylin/rest/controller2/AccessControllerV2.java index 255e312..a61e321 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/controller2/AccessControllerV2.java +++ b/server-base/src/main/java/org/apache/kylin/rest/controller2/AccessControllerV2.java @@ -58,7 +58,6 @@ public class AccessControllerV2 extends BasicController { * @return * @throws IOException */ - @RequestMapping(value = "/{type}/{uuid}", method = { RequestMethod.GET }, produces = { "application/vnd.apache.kylin-v2+json" }) @ResponseBody @@ -70,6 +69,21 @@ public class AccessControllerV2 extends BasicController { } /** + * List access entry list of a domain object including its parent + * @param type + * @param uuid + * @return + */ + @RequestMapping(value = "all/{type}/{uuid}", method = { RequestMethod.GET }, produces = { + "application/vnd.apache.kylin-v2+json" }) + @ResponseBody + public EnvelopeResponse listAccessEntitiesV2(@PathVariable String type, @PathVariable String uuid) { + AclEntity ae = accessService.getAclEntity(type, uuid); + Acl acl = accessService.getAcl(ae); + return new EnvelopeResponse(ResponseCode.CODE_SUCCESS, accessService.generateListAceResponses(acl), ""); + } + + /** * Grant a new access on a domain object to a user/role * * @param accessRequest http://git-wip-us.apache.org/repos/asf/kylin/blob/c490e6cf/server-base/src/main/java/org/apache/kylin/rest/service/AccessService.java ---------------------------------------------------------------------- diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/AccessService.java b/server-base/src/main/java/org/apache/kylin/rest/service/AccessService.java index e5cd793..3a6d723 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/service/AccessService.java +++ b/server-base/src/main/java/org/apache/kylin/rest/service/AccessService.java @@ -20,9 +20,7 @@ package org.apache.kylin.rest.service; import java.util.ArrayList; import java.util.List; -import java.util.Set; -import com.google.common.collect.Sets; import org.apache.kylin.common.persistence.AclEntity; import org.apache.kylin.common.persistence.RootPersistentEntity; import org.apache.kylin.rest.constant.Constant; @@ -300,16 +298,9 @@ public class AccessService { public List<AccessEntryResponse> generateAceResponses(Acl acl) { List<AccessEntryResponse> result = new ArrayList<AccessEntryResponse>(); - Set<Sid> sidSet = Sets.newHashSet(); - while (acl != null) { - for (AccessControlEntry ace : acl.getEntries()) { - if (!sidSet.contains(ace.getSid())) { - result.add(new AccessEntryResponse(ace.getId(), ace.getSid(), ace.getPermission(), ace.isGranting())); - sidSet.add(ace.getSid()); - } - } - acl = acl.getParentAcl(); + for (AccessControlEntry ace : acl.getEntries()) { + result.add(new AccessEntryResponse(ace.getId(), ace.getSid(), ace.getPermission(), ace.isGranting())); } return result; @@ -330,4 +321,17 @@ public class AccessService { throw new ForbiddenException(msg.getREVOKE_ADMIN_PERMISSION()); } } + + public Object generateListAceResponses(Acl acl) { + List<AccessEntryResponse> result = new ArrayList<AccessEntryResponse>(); + + while (acl != null) { + for (AccessControlEntry ace : acl.getEntries()) { + result.add(new AccessEntryResponse(ace.getId(), ace.getSid(), ace.getPermission(), ace.isGranting())); + } + acl = acl.getParentAcl(); + } + + return result; + } } http://git-wip-us.apache.org/repos/asf/kylin/blob/c490e6cf/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java ---------------------------------------------------------------------- diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java b/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java index a5fc36a..b2e44f6 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java +++ b/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java @@ -58,6 +58,7 @@ import org.apache.kylin.rest.request.MetricsRequest; import org.apache.kylin.rest.response.HBaseResponse; import org.apache.kylin.rest.response.MetricsResponse; import org.apache.kylin.rest.security.AclPermission; +import org.apache.kylin.rest.util.AclUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -96,6 +97,9 @@ public class CubeService extends BasicService { @Qualifier("modelMgmtService") private ModelService modelService; + @Autowired + private AclUtil aclUtil; + @PostFilter(Constant.ACCESS_POST_FILTER_READ) public List<CubeInstance> listAllCubes(final String cubeName, final String projectName, final String modelName, boolean exactMatch) { List<CubeInstance> cubeInstances = null; @@ -153,9 +157,11 @@ public class CubeService extends BasicService { return getCubeManager().updateCube(cubeBuilder); } - @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN) - public CubeInstance createCubeAndDesc(String cubeName, String projectName, CubeDesc desc) throws IOException { + @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + + " or hasPermission(#project, 'ADMINISTRATION') or hasPermission(#project, 'MANAGEMENT')") + public CubeInstance createCubeAndDesc(ProjectInstance project, CubeDesc desc) throws IOException { Message msg = MsgPicker.getMsg(); + String cubeName = desc.getName(); if (getCubeManager().getCube(cubeName) != null) { throw new BadRequestException(String.format(msg.getCUBE_ALREADY_EXIST(), cubeName)); @@ -178,10 +184,9 @@ public class CubeService extends BasicService { int cuboidCount = CuboidCLI.simulateCuboidGeneration(createdDesc, false); logger.info("New cube " + cubeName + " has " + cuboidCount + " cuboids"); - createdCube = getCubeManager().createCube(cubeName, projectName, createdDesc, owner); + createdCube = getCubeManager().createCube(cubeName, project.getName(), createdDesc, owner); accessService.init(createdCube, AclPermission.ADMINISTRATION); - ProjectInstance project = getProjectManager().getProject(projectName); accessService.inherit(createdCube, project); return createdCube; @@ -611,32 +616,69 @@ public class CubeService extends BasicService { } } - public CubeDesc updateCubeToResourceStore(CubeDesc desc, String projectName) throws IOException { + @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + + " or hasPermission(#project, 'ADMINISTRATION') or hasPermission(#project, 'MANAGEMENT')") + public CubeDesc saveCube(CubeDesc desc, ProjectInstance project) throws IOException { Message msg = MsgPicker.getMsg(); desc.setDraft(false); if (desc.getUuid() == null) desc.updateRandomUuid(); - String cubeName = desc.getName(); try { - if (desc.getLastModified() == 0) { - // new - createCubeAndDesc(cubeName, projectName, desc); - } else { - // update - CubeInstance cube = getCubeManager().getCube(desc.getName()); + createCubeAndDesc(project, desc); + } catch (AccessDeniedException accessDeniedException) { + throw new ForbiddenException(msg.getUPDATE_CUBE_NO_RIGHT()); + } - if (cube == null) { - throw new BadRequestException(String.format(msg.getCUBE_NOT_FOUND(), desc.getName())); - } + if (!desc.getError().isEmpty()) { + throw new BadRequestException(desc.getErrorMsg()); + } - if (cube.getSegments().size() != 0 && !cube.getDescriptor().consistentWith(desc)) { - throw new BadRequestException(String.format(msg.getINCONSISTENT_CUBE_DESC(), desc.getName())); - } + return desc; + } + + @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'MANAGEMENT')") + public void saveDraft(ProjectInstance project, CubeInstance cube, String uuid, RootPersistentEntity... entities) + throws IOException { + Draft draft = new Draft(); + draft.setProject(project.getName()); + draft.setUuid(uuid); + draft.setEntities(entities); + getDraftManager().save(draft); + } + + @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + + " or hasPermission(#project, 'ADMINISTRATION') or hasPermission(#project, 'MANAGEMENT')") + public void saveDraft(ProjectInstance project, String uuid, RootPersistentEntity... entities) throws IOException { + Draft draft = new Draft(); + draft.setProject(project.getName()); + draft.setUuid(uuid); + draft.setEntities(entities); + getDraftManager().save(draft); + } + + @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + + " or hasPermission(#draft, 'ADMINISTRATION') or hasPermission(#draft, 'MANAGEMENT')") + public void deleteDraft(Draft draft) throws IOException { + getDraftManager().delete(draft.getUuid()); + } - desc = updateCubeAndDesc(cube, desc, projectName, true); + @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'MANAGEMENT')") + public CubeDesc updateCube(CubeInstance cube, CubeDesc desc, ProjectInstance project) throws IOException { + Message msg = MsgPicker.getMsg(); + String projectName = project.getName(); + + desc.setDraft(false); + + try { + if (cube.getSegments().size() != 0 && !cube.getDescriptor().consistentWith(desc)) { + throw new BadRequestException(String.format(msg.getINCONSISTENT_CUBE_DESC(), desc.getName())); } + + desc = updateCubeAndDesc(cube, desc, projectName, true); } catch (AccessDeniedException accessDeniedException) { throw new ForbiddenException(msg.getUPDATE_CUBE_NO_RIGHT()); } @@ -671,6 +713,33 @@ public class CubeService extends BasicService { } } - return result; + List<Draft> filtered = new ArrayList<>(); + + // if cube's there, follow cube permission. otherwise follow project permission + for (Draft d : result) { + CubeDesc desc = (CubeDesc) d.getEntity(); + CubeInstance cube = getCubeManager().getCube(desc.getName()); + + if (cube == null) { + try { + project = project == null ? d.getProject() : project; + if (aclUtil.hasProjectReadPermission(getProjectManager().getProject(project))) { + filtered.add(d); + } + } catch (Exception e) { + // do nothing + } + } else { + try { + if (aclUtil.hasCubeReadPermission(cube)) { + filtered.add(d); + } + } catch (Exception e) { + // do nothing + } + } + } + + return filtered; } }