This is an automated email from the ASF dual-hosted git repository.

nju_yaho pushed a commit to tag ebay-3.1.0-release-20200701
in repository https://gitbox.apache.org/repos/asf/kylin.git

commit c27577f98f3cd57a7d1af4ff09d38a88352566de
Author: Guangxu Cheng <gxch...@apache.org>
AuthorDate: Wed Jun 24 12:48:18 2020 +0800

    KYLIN-4551 Provide interfaces to transfer cube/model/project ownership
---
 .../java/org/apache/kylin/cube/CubeManager.java    | 10 ++++
 .../kylin/metadata/project/ProjectManager.java     | 12 +++++
 .../kylin/rest/controller/CubeController.java      | 32 ++++++++++++
 .../kylin/rest/controller/ModelController.java     | 50 +++++++++++++++++++
 .../kylin/rest/controller/ProjectController.java   | 57 ++++++++++++++++++++++
 .../org/apache/kylin/rest/service/CubeService.java | 12 +++++
 .../apache/kylin/rest/service/ProjectService.java  |  9 ++++
 .../kylin/rest/controller/CubeControllerTest.java  | 25 +++++++---
 .../rest/controller/ProjectControllerTest.java     | 42 ++++++++++++++++
 webapp/app/js/controllers/cube.js                  | 18 +++++++
 webapp/app/js/controllers/projects.js              | 23 ++++++++-
 webapp/app/js/services/cubes.js                    |  1 +
 webapp/app/js/services/projects.js                 |  3 +-
 webapp/app/partials/cubes/cube_detail.html         | 19 +++++++-
 webapp/app/partials/projects/project_detail.html   | 21 ++++++++
 15 files changed, 324 insertions(+), 10 deletions(-)

diff --git a/core-cube/src/main/java/org/apache/kylin/cube/CubeManager.java 
b/core-cube/src/main/java/org/apache/kylin/cube/CubeManager.java
index b255dd8..32b9692 100755
--- a/core-cube/src/main/java/org/apache/kylin/cube/CubeManager.java
+++ b/core-cube/src/main/java/org/apache/kylin/cube/CubeManager.java
@@ -334,6 +334,16 @@ public class CubeManager implements IRealizationProvider {
         }
     }
 
+    public CubeInstance updateCubeOwner(CubeInstance cube, String owner) 
throws IOException {
+        try (AutoLock lock = cubeMapLock.lockForWrite()) {
+            cube = cube.latestCopyForWrite(); // get a latest copy
+            CubeUpdate update = new CubeUpdate(cube);
+            update.setOwner(owner);
+            ProjectManager.getInstance(config).touchProject(cube.getProject());
+            return updateCube(update);
+        }
+    }
+
     public CubeInstance updateCubeDropSegments(CubeInstance cube, 
Collection<CubeSegment> segsToDrop)
             throws IOException {
         CubeSegment[] arr = segsToDrop.toArray(new 
CubeSegment[segsToDrop.size()]);
diff --git 
a/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
 
b/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
index ebcd45c..b3bcc0e 100644
--- 
a/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
+++ 
b/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
@@ -242,6 +242,18 @@ public class ProjectManager {
         }
     }
 
+    // update project itself
+    public ProjectInstance updateProjectOwner(ProjectInstance project, String 
newOwner) throws IOException {
+        try (AutoLock lock = prjMapLock.lockForWrite()) {
+            project.setOwner(newOwner);
+
+            if (project.getUuid() == null)
+                project.updateRandomUuid();
+
+            return save(project);
+        }
+    }
+
     public void removeProjectLocal(String proj) {
         try (AutoLock lock = prjMapLock.lockForWrite()) {
             projectMap.removeLocal(proj);
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 52b7ae5..ba5a0b4 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
@@ -149,6 +149,10 @@ public class CubeController extends BasicController {
     private TableService tableService;
 
     @Autowired
+    @Qualifier("validateUtil")
+    private ValidateUtil validateUtil;
+
+    @Autowired
     private AclEvaluate aclEvaluate;
 
     @RequestMapping(value = "{cubeName}/validate", method = RequestMethod.GET, 
produces = { "application/json" })
@@ -281,6 +285,30 @@ public class CubeController extends BasicController {
         }
     }
 
+    /**
+     * Update cube owner
+     *
+     * @param cubeName
+     * @param owner
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{cubeName}/owner", method = { RequestMethod.PUT 
}, produces = {
+        "application/json" })
+    @ResponseBody
+    public CubeInstance updateCubeOwner(@PathVariable String cubeName, 
@RequestBody String owner) {
+        checkCubeExists(cubeName);
+        try {
+            validateUtil.checkIdentifiersExists(owner, true);
+            CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
+            return cubeService.updateCubeOwner(cube, owner);
+        } catch (AccessDeniedException accessDeniedException) {
+            throw new ForbiddenException("You don't have right to update this 
cube's owner.");
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            throw new InternalErrorException(e.getLocalizedMessage(), e);
+        }
+    }
+
     @RequestMapping(value = "/{cubeName}/cost", method = { RequestMethod.PUT 
}, produces = { "application/json" })
     @ResponseBody
     public CubeInstance updateCubeCost(@PathVariable String cubeName, 
@RequestParam(value = "cost") int cost) {
@@ -1249,4 +1277,8 @@ public class CubeController extends BasicController {
     public void setJobService(JobService jobService) {
         this.jobService = jobService;
     }
+
+    public void setValidateUtil(ValidateUtil validateUtil) {
+        this.validateUtil = validateUtil;
+    }
 }
diff --git 
a/server-base/src/main/java/org/apache/kylin/rest/controller/ModelController.java
 
b/server-base/src/main/java/org/apache/kylin/rest/controller/ModelController.java
index 2f30788..388777a 100644
--- 
a/server-base/src/main/java/org/apache/kylin/rest/controller/ModelController.java
+++ 
b/server-base/src/main/java/org/apache/kylin/rest/controller/ModelController.java
@@ -75,6 +75,10 @@ public class ModelController extends BasicController {
     @Qualifier("projectService")
     private ProjectService projectService;
 
+    @Autowired
+    @Qualifier("validateUtil")
+    private ValidateUtil validateUtil;
+
     @RequestMapping(value = "/validate/{modelName}", method = 
RequestMethod.GET, produces = { "application/json" })
     @ResponseBody
     public EnvelopeResponse<Boolean> validateModelName(@PathVariable String 
modelName) {
@@ -224,6 +228,52 @@ public class ModelController extends BasicController {
         return modelRequest;
     }
 
+
+    /**
+     * Update model owner
+     *
+     * @param modelName
+     * @param owner
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{modelName}/owner", method = { RequestMethod.PUT 
}, produces = {
+        "application/json" })
+    @ResponseBody
+    public ModelRequest updateModelOwner(@PathVariable String modelName, 
@RequestBody String owner)
+        throws JsonProcessingException {
+        DataModelDesc modelDesc = null;
+        try {
+            validateUtil.checkIdentifiersExists(owner, true);
+            DataModelDesc desc = 
modelService.getDataModelManager().getDataModelDesc(modelName);
+            if (null == desc) {
+                throw new NotFoundException("Data Model with name " + 
modelName + " not found..");
+            }
+
+            DataModelDesc newModelDesc = DataModelDesc.getCopyOf(desc);
+            newModelDesc.setOwner(owner);
+            modelDesc = 
modelService.updateModelAndDesc(newModelDesc.getProject(), newModelDesc);
+        } catch (AccessDeniedException accessDeniedException) {
+            throw new ForbiddenException("You don't have right to update this 
model's owner.");
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            throw new InternalErrorException(e.getLocalizedMessage(), e);
+        }
+
+        ModelRequest modelRequest = new ModelRequest();
+        modelRequest.setProject(modelDesc.getProject());
+        modelRequest.setModelName(modelName);
+        modelRequest.setUuid(modelDesc.getUuid());
+        if (modelDesc.getError().isEmpty()) {
+            modelRequest.setSuccessful(true);
+        } else {
+            logger.warn("Model " + modelDesc.getName() + " fail to update 
because " + modelDesc.getError());
+            updateRequest(modelRequest, false, 
omitMessage(modelDesc.getError()));
+        }
+        String descData = JsonUtil.writeValueAsIndentString(modelDesc);
+        modelRequest.setModelDescData(descData);
+        return modelRequest;
+    }
+
     private DataModelDesc deserializeDataModelDesc(ModelRequest modelRequest) {
         DataModelDesc desc = null;
         try {
diff --git 
a/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
 
b/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
index 7edca34..e047752 100644
--- 
a/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
+++ 
b/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
@@ -25,12 +25,15 @@ import java.util.List;
 import java.util.Locale;
 
 import org.apache.commons.lang.StringUtils;
+import org.apache.kylin.common.persistence.AclEntity;
 import org.apache.kylin.common.util.JsonUtil;
 import org.apache.kylin.metadata.project.ProjectInstance;
 import org.apache.kylin.rest.exception.BadRequestException;
+import org.apache.kylin.rest.exception.ForbiddenException;
 import org.apache.kylin.rest.exception.InternalErrorException;
 import org.apache.kylin.rest.exception.NotFoundException;
 import org.apache.kylin.rest.request.ProjectRequest;
+import org.apache.kylin.rest.security.AclPermission;
 import org.apache.kylin.rest.service.AccessService;
 import org.apache.kylin.rest.service.CubeService;
 import org.apache.kylin.rest.service.ProjectService;
@@ -41,6 +44,8 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.acls.model.Sid;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
@@ -71,6 +76,11 @@ public class ProjectController extends BasicController {
     @Autowired
     @Qualifier("cubeMgmtService")
     private CubeService cubeService;
+
+    @Autowired
+    @Qualifier("validateUtil")
+    private ValidateUtil validateUtil;
+
     @Autowired
     private AclEvaluate aclEvaluate;
 
@@ -234,6 +244,49 @@ public class ProjectController extends BasicController {
         }
     }
 
+    @RequestMapping(value = "/{projectName}/owner", method = { 
RequestMethod.PUT }, produces = {
+        "application/json" })
+    @ResponseBody
+    public ProjectInstance updateProjectOwner(@PathVariable String 
projectName, @RequestBody String owner) {
+        ProjectInstance updatedProj;
+        ProjectInstance currentProject = null;
+        String oldOwner = null;
+        boolean updateOwnerSuccess = false;
+        boolean updateAccessSuccess = false;
+        try {
+            validateUtil.checkIdentifiersExists(owner, true);
+            currentProject = 
projectService.getProjectManager().getProject(projectName);
+            if (currentProject == null) {
+                throw new NotFoundException("The project named " + projectName 
+ " does not exists");
+            }
+            oldOwner = currentProject.getOwner();
+            // update project owner
+            updatedProj = projectService.updateProjectOwner(currentProject, 
owner);
+            updateOwnerSuccess = true;
+
+            //grant ADMINISTRATION permission to new owner
+            AclEntity ae = accessService.getAclEntity("ProjectInstance", 
currentProject.getUuid());
+            Sid sid = accessService.getSid(owner, true);
+            accessService.grant(ae, AclPermission.ADMINISTRATION, sid);
+            updateAccessSuccess = true;
+        } catch (AccessDeniedException accessDeniedException) {
+            throw new ForbiddenException("You don't have right to update this 
project's owner.");
+        } catch (Exception e) {
+            logger.error("Failed to deal with the request.", e);
+            throw new InternalErrorException(e.getLocalizedMessage(), e);
+        } finally {
+            if (!updateAccessSuccess && currentProject != null && 
updateOwnerSuccess) {
+                try {
+                    projectService.updateProjectOwner(currentProject, 
oldOwner);
+                } catch (IOException e) {
+                    logger.error("Failed to roll back the request.", e);
+                }
+            }
+        }
+
+        return updatedProj;
+    }
+
     public void setProjectService(ProjectService projectService) {
         this.projectService = projectService;
     }
@@ -245,4 +298,8 @@ public class ProjectController extends BasicController {
     public void setCubeService(CubeService cubeService) {
         this.cubeService = cubeService;
     }
+
+    public void setValidateUtil(ValidateUtil validateUtil) {
+        this.validateUtil = validateUtil;
+    }
 }
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 59781c5..57d6b84 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
@@ -579,6 +579,18 @@ public class CubeService extends BasicService implements 
InitializingBean {
         getCubeDescManager().updateCubeDesc(desc);
     }
 
+    public CubeInstance updateCubeOwner(CubeInstance cube, String owner) 
throws IOException {
+        aclEvaluate.checkProjectWritePermission(cube);
+        if (cube.getOwner().equals(owner)) {
+            // Do nothing
+            return cube;
+        }
+        cube.setOwner(owner);
+
+        CubeUpdate update = new 
CubeUpdate(cube.latestCopyForWrite()).setOwner(owner);
+        return getCubeManager().updateCube(update);
+    }
+
     public CubeInstance rebuildLookupSnapshot(CubeInstance cube, String 
segmentName, String lookupTable)
             throws IOException {
         aclEvaluate.checkProjectOperationPermission(cube);
diff --git 
a/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java 
b/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java
index 26ad077..a53f467 100644
--- 
a/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java
+++ 
b/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java
@@ -111,6 +111,15 @@ public class ProjectService extends BasicService {
         return updatedProject;
     }
 
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or 
hasPermission(#currentProject, 'ADMINISTRATION')")
+    public ProjectInstance updateProjectOwner(ProjectInstance currentProject, 
String newOwner)
+        throws IOException {
+
+        ProjectInstance updatedProject = 
getProjectManager().updateProjectOwner(currentProject, newOwner);
+        logger.debug("Project owner updated.");
+        return updatedProject;
+    }
+
     @PostFilter(Constant.ACCESS_POST_FILTER_READ)
     public List<ProjectInstance> listProjects(final Integer limit, final 
Integer offset) {
         List<ProjectInstance> projects = listAllProjects(limit, offset);
diff --git 
a/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java 
b/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java
index 9dd978f..a8adefe 100644
--- 
a/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java
+++ 
b/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java
@@ -37,6 +37,7 @@ import org.apache.kylin.rest.service.CubeService;
 import org.apache.kylin.rest.service.JobService;
 import org.apache.kylin.rest.service.ServiceTestBase;
 import org.apache.kylin.rest.service.StreamingService;
+import org.apache.kylin.rest.util.ValidateUtil;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -66,6 +67,10 @@ public class CubeControllerTest extends ServiceTestBase {
     @Qualifier("streamingMgmtService")
     StreamingService streamingService;
 
+    @Autowired
+    @Qualifier("validateUtil")
+    private ValidateUtil validateUtil;
+
     @Before
     public void setup() throws Exception {
         super.setup();
@@ -73,6 +78,7 @@ public class CubeControllerTest extends ServiceTestBase {
         cubeController = new CubeController();
         cubeController.setCubeService(cubeService);
         cubeController.setJobService(jobService);
+        cubeController.setValidateUtil(validateUtil);
 
         cubeDescController = new CubeDescController();
         cubeDescController.setCubeService(cubeService);
@@ -123,13 +129,20 @@ public class CubeControllerTest extends ServiceTestBase {
         List<String> notifyList = Lists.newArrayList();
         notifyList.add("j...@example.com");
         cubeController.updateNotifyList(newCubeName, notifyList);
-
+        try {
+            cubeController.updateCubeOwner(newCubeName, "new_user");
+        } catch (InternalErrorException e) {
+            Assert.assertEquals("Operation failed, user:new_user not exists, 
please add first.",
+                e.getMessage());
+        }
+        cubeController.updateCubeOwner(newCubeName, "MODELER");
         List<CubeInstanceResponse> cubeInstances = 
cubeController.getCubes(newCubeName, cube.getModelName(), "default",
                 1, 0);
 
         CubeInstance cubeInstance = 
cubeController.getCube(cubeInstances.get(0).getName());
         
Assert.assertTrue(cubeInstance.getDescriptor().getNotifyList().contains("j...@example.com"));
-        Assert.assertTrue(cubeInstance.getCost() == 495);
+        Assert.assertEquals("MODELER", cubeInstance.getOwner());
+        Assert.assertEquals(495, cubeInstance.getCost());
         cubeController.deleteCube(newCubeName);
     }
 
@@ -190,7 +203,7 @@ public class CubeControllerTest extends ServiceTestBase {
 
         int newSegNumber = 
cubeService.getCubeManager().getCube(cubeName).getSegments().size();
 
-        Assert.assertTrue(segNumber == newSegNumber + 1);
+        Assert.assertEquals(segNumber, newSegNumber + 1);
 
         cubeController.enableCube(cubeName);
     }
@@ -213,17 +226,17 @@ public class CubeControllerTest extends ServiceTestBase {
 
         List<CubeSegment> holes = cubeController.getHoles(cubeName);
 
-        Assert.assertTrue(holes.size() == 1);
+        Assert.assertEquals(1, holes.size());
 
         CubeSegment hole = holes.get(0);
 
-        Assert.assertTrue(hole.getTSRange().equals(new TSRange(dateEnd, 
dateEnd + ONEDAY)));
+        Assert.assertEquals(hole.getTSRange(), new TSRange(dateEnd, dateEnd + 
ONEDAY));
     }
 
     @Test
     public void testGetCubes() {
         List<CubeInstanceResponse> cubes = cubeController.getCubes(null, null, 
null, 1, 0);
-        Assert.assertTrue(cubes.size() == 1);
+        Assert.assertEquals(1, cubes.size());
     }
 
     @Test
diff --git 
a/server/src/test/java/org/apache/kylin/rest/controller/ProjectControllerTest.java
 
b/server/src/test/java/org/apache/kylin/rest/controller/ProjectControllerTest.java
index 8d08d61..40d378c 100644
--- 
a/server/src/test/java/org/apache/kylin/rest/controller/ProjectControllerTest.java
+++ 
b/server/src/test/java/org/apache/kylin/rest/controller/ProjectControllerTest.java
@@ -25,8 +25,10 @@ import org.apache.kylin.metadata.project.ProjectInstance;
 import org.apache.kylin.metadata.project.ProjectManager;
 import org.apache.kylin.rest.exception.InternalErrorException;
 import org.apache.kylin.rest.request.ProjectRequest;
+import org.apache.kylin.rest.service.AccessService;
 import org.apache.kylin.rest.service.ProjectService;
 import org.apache.kylin.rest.service.ServiceTestBase;
+import org.apache.kylin.rest.util.ValidateUtil;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -45,12 +47,22 @@ public class ProjectControllerTest extends ServiceTestBase {
     @Qualifier("projectService")
     ProjectService projectService;
 
+    @Autowired
+    @Qualifier("validateUtil")
+    private ValidateUtil validateUtil;
+
+    @Autowired
+    @Qualifier("accessService")
+    private AccessService accessService;
+
     @Before
     public void setup() throws Exception {
         super.setup();
 
         projectController = new ProjectController();
         projectController.setProjectService(projectService);
+        projectController.setValidateUtil(validateUtil);
+        projectController.setAccessService(accessService);
 
         try {
             projectController.deleteProject("new_project");
@@ -62,6 +74,11 @@ public class ProjectControllerTest extends ServiceTestBase {
         } catch (InternalErrorException e) {
             //project doesn't exist
         }
+        try {
+            projectController.deleteProject("new_project_3");
+        } catch (InternalErrorException e) {
+            //project doesn't exist
+        }
     }
 
     @Test
@@ -87,6 +104,31 @@ public class ProjectControllerTest extends ServiceTestBase {
         
Assert.assertEquals(ProjectManager.getInstance(getTestConfig()).getProject("new_project").getDescription(),
 "hello world");
     }
 
+    @Test
+    public void testUpdateProjectOwner() throws IOException {
+        int originalProjectCount = projectController.getProjects(null, 
null).size();
+
+        //test add project
+        ProjectInstance project = new ProjectInstance();
+        project.setName("new_project_3");
+        ProjectInstance ret = 
projectController.saveProject(getProjectRequest(project, null));
+
+        Assert.assertEquals(ret.getOwner(), "ADMIN");
+        
Assert.assertEquals(ProjectManager.getInstance(getTestConfig()).listAllProjects().size(),
 originalProjectCount + 1);
+
+        //test update project owner only
+        try {
+            projectController.updateProjectOwner("new_project_3", "new_user");
+        } catch (InternalErrorException e) {
+            Assert.assertTrue(e.getMessage().equals("Operation failed, 
user:new_user not exists, please add first."));
+        }
+        projectController.updateProjectOwner("new_project_3", "MODELER");
+
+        
Assert.assertEquals(ProjectManager.getInstance(getTestConfig()).listAllProjects().size(),
 originalProjectCount + 1);
+        
Assert.assertNotEquals(ProjectManager.getInstance(getTestConfig()).getProject("new_project_3"),
 null);
+        
Assert.assertEquals(ProjectManager.getInstance(getTestConfig()).getProject("new_project_3").getOwner(),
 "MODELER");
+    }
+
     @Test(expected = InternalErrorException.class)
     public void testAddExistingProject() throws IOException {
         ProjectInstance newProject = new ProjectInstance();
diff --git a/webapp/app/js/controllers/cube.js 
b/webapp/app/js/controllers/cube.js
index 89e0ea2..a28526f 100755
--- a/webapp/app/js/controllers/cube.js
+++ b/webapp/app/js/controllers/cube.js
@@ -88,6 +88,24 @@ KylinApp.controller('CubeCtrl', function ($scope, 
$rootScope, AccessService, Mes
         });
     };
 
+    $scope.getOwnerString = function (cube) {
+        cube.newOwner = cube.owner;
+    };
+
+    $scope.updateOwner = function (cube) {
+      CubeService.updateOwner({cubeId: cube.name}, cube.newOwner, function () {
+        cube.owner = cube.newOwner;
+        MessageBox.successNotify('Owner updated successfully!');
+      },function(e){
+        if(e.data&& e.data.exception){
+          var message =e.data.exception;
+          var msg = !!(message) ? message : 'Failed to take action.';
+          SweetAlert.swal('Oops...', msg, 'error');
+        }else{
+          SweetAlert.swal('Oops...', "Failed to take action.", 'error');
+        }
+      });
+    };
     $scope.getHbaseInfo = function (cube) {
         if (!cube.hbase) {
             CubeService.getHbaseInfo({cubeId: cube.name, propValue: null, 
action: null}, function (hbase) {
diff --git a/webapp/app/js/controllers/projects.js 
b/webapp/app/js/controllers/projects.js
index 885e5a2..7adc979 100644
--- a/webapp/app/js/controllers/projects.js
+++ b/webapp/app/js/controllers/projects.js
@@ -91,10 +91,29 @@ KylinApp
                 }
             });
         }
-        
+
         $scope.getMapLength = function(map) {
-               return Object.keys(map).length;
+                 return Object.keys(map).length;
         }
+
+        $scope.getOwnerString = function (project) {
+            project.newOwner = project.owner;
+        };
+
+        $scope.updateOwner = function (project) {
+            ProjectService.updateOwner({projecId: project.name}, 
project.newOwner, function () {
+                project.owner = project.newOwner;
+                MessageBox.successNotify('Owner updated successfully!');
+            },function(e){
+                if(e.data&& e.data.exception){
+                    var message =e.data.exception;
+                    var msg = !!(message) ? message : 'Failed to take action.';
+                    SweetAlert.swal('Oops...', msg, 'error');
+                } else{
+                    SweetAlert.swal('Oops...', "Failed to take action.", 
'error');
+                }
+            });
+        };
     }
 );
 
diff --git a/webapp/app/js/services/cubes.js b/webapp/app/js/services/cubes.js
index f625d67..3e3f930 100644
--- a/webapp/app/js/services/cubes.js
+++ b/webapp/app/js/services/cubes.js
@@ -42,6 +42,7 @@ KylinApp.factory('CubeService', ['$resource', function 
($resource, config) {
     getCube: {method: 'GET', params: {}, isArray: false},
     getSql: {method: 'GET', params: {action: 'sql'}, isArray: false},
     updateNotifyList: {method: 'PUT', params: {propName: 'notify_list'}, 
isArray: false},
+    updateOwner: {method: 'PUT', params: {propName: 'owner'}, isArray: false},
     cost: {method: 'PUT', params: {action: 'cost'}, isArray: false},
     rebuildLookUp: {method: 'PUT', params: {propName: 'segs', action: 
'refresh_lookup'}, isArray: false},
     rebuildCube: {method: 'PUT', params: {action: 'rebuild'}, isArray: false},
diff --git a/webapp/app/js/services/projects.js 
b/webapp/app/js/services/projects.js
index 84a0a89..1976b80 100644
--- a/webapp/app/js/services/projects.js
+++ b/webapp/app/js/services/projects.js
@@ -22,6 +22,7 @@ KylinApp.factory('ProjectService', ['$resource', function 
($resource, config) {
     listReadable: {method: 'GET', params: {action:'readable'}, isArray: true},
     save: {method: 'POST', params: {}, isArray: false},
     update: {method: 'PUT', params: {}, isArray: false},
-    delete: {method: 'DELETE', params: {}, isArray: false}
+    delete: {method: 'DELETE', params: {}, isArray: false},
+    updateOwner: {method: 'PUT', params: {propName: 'owner'}, isArray: false}
   });
 }]);
diff --git a/webapp/app/partials/cubes/cube_detail.html 
b/webapp/app/partials/cubes/cube_detail.html
index fec8f17..6cb60e1 100755
--- a/webapp/app/partials/cubes/cube_detail.html
+++ b/webapp/app/partials/cubes/cube_detail.html
@@ -37,6 +37,10 @@
             ng-if="userService.hasRole('ROLE_ADMIN') || 
hasPermission('cube',cube, permissions.ADMINISTRATION.mask) && !newAccess">
             <a href="" 
ng-click="cube.visiblePage='notification';getNotifyListString(cube);">Notification</a>
         </li>
+        <li class="{{cube.visiblePage=='owner'? 'active':''}}"
+            ng-if="userService.hasRole('ROLE_ADMIN') || 
hasPermission('cube',cube, permissions.ADMINISTRATION.mask) && !newAccess">
+            <a href="" 
ng-click="cube.visiblePage='owner';getOwnerString(cube)">Owner</a>
+        </li>
         <li class="{{cube.visiblePage=='hbase'? 'active':''}}"
             ng-if="userService.hasRole('ROLE_ADMIN')  || hasPermission('cube' 
,cube, permissions.ADMINISTRATION.mask) && !newAccess">
             <a href="" 
ng-click="cube.visiblePage='hbase';getHbaseInfo(cube)">Storage</a>
@@ -103,7 +107,20 @@
         </div>
     </div>
 
-  <div class="cube-detail" ng-show="cube.visiblePage=='hbase'">
+    <div class="cube-detail" ng-show="cube.visiblePage=='owner'">
+        <div style="margin: 15px;">
+            <h5><b>Owner:</b></h5>
+            <div class="form-group">
+                <input ng-model="cube.newOwner" class="form-control" 
placeholder="User List..." />
+            </div>
+            <div class="form-group">
+                <button class="btn btn-primary btn-sm" 
ng-click="updateOwner(cube)">Save</button>
+            </div>
+            <div class="space-4"></div>
+        </div>
+    </div>
+
+    <div class="cube-detail" ng-show="cube.visiblePage=='hbase'">
         <div style="margin: 15px; overflow: hidden;">
             <div ng-if="cube.hbase">
               <div class="hr hr8 hr-double hr-dotted"></div>
diff --git a/webapp/app/partials/projects/project_detail.html 
b/webapp/app/partials/projects/project_detail.html
index 7112da6..b023cdd 100644
--- a/webapp/app/partials/projects/project_detail.html
+++ b/webapp/app/partials/projects/project_detail.html
@@ -28,6 +28,10 @@
         <li class="{{project.visiblePage=='config'? 'active':''}}">
             <a href="" ng-click="project.visiblePage='config';">Configuration 
Overwrites</a>
         </li>
+        <li class="{{project.visiblePage=='owner'? 'active':''}}"
+            ng-if="userService.hasRole('ROLE_ADMIN') || 
hasPermission('project',project, permissions.ADMINISTRATION.mask)">
+            <a href="" 
ng-click="project.visiblePage='owner';getOwnerString(project)">Owner</a>
+        </li>
     </ul>
 
     <div class="cube-detail" ng-if="project.visiblePage=='cubes'">
@@ -91,4 +95,21 @@
             <div class="col-xs-1"></div>
         </div>
     </div>
+
+    <div class="cube-detail" ng-show="project.visiblePage=='owner'">
+        <div class="row">
+            <div class="col-xs-1"></div>
+            <div class="col-xs-10">
+                <h5><b>Owner:</b></h5>
+                <div class="form-group">
+                    <input ng-model="project.newOwner" class="form-control" 
placeholder="User List..." />
+                </div>
+                <div class="form-group">
+                    <button class="btn btn-primary btn-sm" 
ng-click="updateOwner(project)">Save</button>
+                </div>
+                <div class="space-4"></div>
+            </div>
+            <div class="col-xs-1"></div>
+        </div>
+    </div>
 </div>

Reply via email to