This is an automated email from the ASF dual-hosted git repository.
xxyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kylin.git
The following commit(s) were added to refs/heads/master by this push:
new a603716 KYLIN-4551 Provide interfaces to transfer cube/model/project
ownership
a603716 is described below
commit a603716b4ab5f0fda9509c7c487d22729813d139
Author: Guangxu Cheng <[email protected]>
AuthorDate: Sun Jun 28 15:44:21 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 | 55 +++++++++++++++++++++
.../kylin/rest/controller/ProjectController.java | 57 ++++++++++++++++++++++
.../org/apache/kylin/rest/service/CubeService.java | 13 +++++
.../apache/kylin/rest/service/ProjectService.java | 13 +++++
.../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, 334 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 6e9452d..2acad37 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
@@ -315,6 +315,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 11df5c1..a96cdda 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
@@ -129,6 +129,10 @@ public class CubeController extends BasicController {
private QueryService queryService;
@Autowired
+ @Qualifier("validateUtil")
+ private ValidateUtil validateUtil;
+
+ @Autowired
private AclEvaluate aclEvaluate;
@RequestMapping(value = "{cubeName}/validate", method = RequestMethod.GET,
produces = { "application/json" })
@@ -261,6 +265,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) {
@@ -1061,4 +1089,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..960b381 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
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
import org.apache.commons.lang.StringUtils;
import org.apache.kylin.common.KylinConfig;
@@ -75,6 +76,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 +229,56 @@ 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..");
+ }
+
+ if (Objects.equals(desc.getOwner(), owner)) {
+ modelDesc = desc;
+ } else {
+ 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 410ff11..07a70bd 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;
@@ -40,6 +43,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.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
@@ -67,6 +72,11 @@ public class ProjectController extends BasicController {
@Autowired
@Qualifier("cubeMgmtService")
private CubeService cubeService;
+
+ @Autowired
+ @Qualifier("validateUtil")
+ private ValidateUtil validateUtil;
+
@Autowired
private AclEvaluate aclEvaluate;
@@ -204,6 +214,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;
}
@@ -215,4 +268,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 e6210f4..21df411 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
@@ -26,6 +26,7 @@ import java.util.EnumSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import org.apache.commons.collections.CollectionUtils;
@@ -582,6 +583,18 @@ public class CubeService extends BasicService implements
InitializingBean {
getCubeDescManager().updateCubeDesc(desc);
}
+ public CubeInstance updateCubeOwner(CubeInstance cube, String owner)
throws IOException {
+ aclEvaluate.checkProjectWritePermission(cube);
+ if (Objects.equals(cube.getOwner(), 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..40805a9 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
@@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
import java.util.Set;
import javax.annotation.Nullable;
@@ -111,6 +112,18 @@ 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 {
+ if (Objects.equals(currentProject.getOwner(), newOwner)) {
+ // Do nothing
+ return currentProject;
+ }
+ 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("[email protected]");
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("[email protected]"));
- 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 0d48dbc..fe84851 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 522d043..597cc87 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 b747e84..39edb3e 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>
@@ -100,7 +104,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>