Repository: kylin Updated Branches: refs/heads/2.0-rc bb29fb11a -> 5d10249f1
KYLIN-1365, Kylin ACL enhancement remove projects box from login page and access control to project on UI Project: http://git-wip-us.apache.org/repos/asf/kylin/repo Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/5d10249f Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/5d10249f Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/5d10249f Branch: refs/heads/2.0-rc Commit: 5d10249f17c0d437948e15a790197fed694c5e81 Parents: bb29fb1 Author: janzhongi <zhongj...@apache.org> Authored: Mon Jan 25 12:58:54 2016 +0800 Committer: janzhongi <zhongj...@apache.org> Committed: Mon Jan 25 12:59:06 2016 +0800 ---------------------------------------------------------------------- .../rest/controller/ProjectController.java | 152 ++++++++++++++- .../kylin/rest/controller/UserController.java | 8 +- .../apache/kylin/rest/service/CubeService.java | 2 +- server/src/main/resources/kylinSecurity.xml | 2 +- webapp/app/js/controllers/auth.js | 12 +- webapp/app/js/controllers/cubeSchema.js | 2 +- webapp/app/js/controllers/models.js | 8 +- webapp/app/js/controllers/page.js | 41 ++-- webapp/app/js/controllers/projects.js | 192 +++++++++---------- webapp/app/js/listeners.js | 61 +++++- webapp/app/js/model/modelsManager.js | 2 + webapp/app/js/model/projectModel.js | 34 +++- webapp/app/js/services/projects.js | 1 + webapp/app/partials/login.html | 16 +- webapp/app/partials/models/models_tree.html | 6 +- 15 files changed, 368 insertions(+), 171 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kylin/blob/5d10249f/server/src/main/java/org/apache/kylin/rest/controller/ProjectController.java ---------------------------------------------------------------------- diff --git a/server/src/main/java/org/apache/kylin/rest/controller/ProjectController.java b/server/src/main/java/org/apache/kylin/rest/controller/ProjectController.java index a561e97..abebdd8 100644 --- a/server/src/main/java/org/apache/kylin/rest/controller/ProjectController.java +++ b/server/src/main/java/org/apache/kylin/rest/controller/ProjectController.java @@ -19,17 +19,31 @@ package org.apache.kylin.rest.controller; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.StringUtils; +import org.apache.kylin.common.persistence.AclEntity; +import org.apache.kylin.cube.CubeInstance; import org.apache.kylin.metadata.project.ProjectInstance; +import org.apache.kylin.rest.constant.Constant; import org.apache.kylin.rest.exception.InternalErrorException; import org.apache.kylin.rest.request.CreateProjectRequest; import org.apache.kylin.rest.request.UpdateProjectRequest; +import org.apache.kylin.rest.service.AccessService; +import org.apache.kylin.rest.service.CubeService; import org.apache.kylin.rest.service.ProjectService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.acls.domain.GrantedAuthoritySid; +import org.springframework.security.acls.domain.PrincipalSid; +import org.springframework.security.acls.model.AccessControlEntry; +import org.springframework.security.acls.model.Acl; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -49,19 +63,135 @@ public class ProjectController extends BasicController { @Autowired private ProjectService projectService; + @Autowired + private AccessService accessService; + @Autowired + private CubeService cubeService; + /** * Get available project list - * + * * @return Table metadata array * @throws IOException */ - @RequestMapping(value = "", method = { RequestMethod.GET }) + @RequestMapping(value = "", method = {RequestMethod.GET}) @ResponseBody public List<ProjectInstance> getProjects(@RequestParam(value = "limit", required = false) Integer limit, @RequestParam(value = "offset", required = false) Integer offset) { return projectService.listAllProjects(limit, offset); } - @RequestMapping(value = "", method = { RequestMethod.POST }) + @RequestMapping(value = "/readable", method = {RequestMethod.GET}) + @ResponseBody + public List<ProjectInstance> getReadableProjects(@RequestParam(value = "limit", required = false) Integer limit, @RequestParam(value = "offset", required = false) Integer offset) { + List<ProjectInstance> readableProjects = new ArrayList<ProjectInstance>(); + //list all projects first + List<ProjectInstance> projectInstances = projectService.listAllProjects(limit, offset); + + //get user infomation + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + UserDetails userDetails = null; + if (authentication == null) { + logger.debug("authentication is null."); + throw new InternalErrorException("Can not find authentication infomation."); + } + if (authentication.getPrincipal() instanceof UserDetails) { + logger.debug("authentication.getPrincipal() is " + authentication.getPrincipal()); + userDetails = (UserDetails) authentication.getPrincipal(); + } + if (authentication.getDetails() instanceof UserDetails) { + logger.debug("authentication.getDetails() is " + authentication.getDetails()); + userDetails = (UserDetails) authentication.getDetails(); + } + + //check if ROLE_ADMIN return all,also get user role list + List<String> userAuthority = new ArrayList<>(); + for (GrantedAuthority auth : authentication.getAuthorities()) { + userAuthority.add(auth.getAuthority()); + if (auth.getAuthority().equals(Constant.ROLE_ADMIN)) + return projectInstances; + } + String userName = userDetails.getUsername(); + for (ProjectInstance projectInstance : projectInstances) { + + boolean hasProjectPermission = false; + AclEntity ae = accessService.getAclEntity("ProjectInstance", projectInstance.getId()); + Acl projectAcl = accessService.getAcl(ae); + //project no Acl info will be skipped + if(projectAcl == null){ + continue; + } + + //project owner has permission + if (((PrincipalSid)projectAcl.getOwner()).getPrincipal().equals(userName)) { + readableProjects.add(projectInstance); + continue; + } + + //check project permission and role + for (AccessControlEntry ace : projectAcl.getEntries()) { + if( ace.getSid() instanceof PrincipalSid && ((PrincipalSid)ace.getSid()).getPrincipal().equals(userName)) { + hasProjectPermission = true; + readableProjects.add(projectInstance); + break; + + }else if(ace.getSid() instanceof GrantedAuthoritySid){ + String projectAuthority = ((GrantedAuthoritySid) ace.getSid()).getGrantedAuthority(); + if(userAuthority.contains(projectAuthority)){ + hasProjectPermission = true; + readableProjects.add(projectInstance); + break; + } + + } + + } + if (!hasProjectPermission) { + List<CubeInstance> cubeInstances = cubeService.listAllCubes(projectInstance.getName()); + + for (CubeInstance cubeInstance : cubeInstances) { + boolean hasCubePermission = false; + AclEntity cubeAe = accessService.getAclEntity("CubeInstance", cubeInstance.getId()); + Acl cubeAcl = accessService.getAcl(cubeAe); + //cube no Acl info will not be used to filter project + if(cubeAcl == null){ + continue; + } + //cube owner will have permission to read project + if (((PrincipalSid)cubeAcl.getOwner()).getPrincipal().equals(userName)) { + hasProjectPermission = true; + break; + } + for (AccessControlEntry cubeAce : cubeAcl.getEntries()) { + + if (cubeAce.getSid() instanceof PrincipalSid && ((PrincipalSid)cubeAce.getSid()).getPrincipal().equals(userName)) { + hasCubePermission = true; + break; + } + else if(cubeAce.getSid() instanceof GrantedAuthoritySid) { + String cubeAuthority = ((GrantedAuthoritySid) cubeAce.getSid()).getGrantedAuthority(); + if(userAuthority.contains(cubeAuthority)){ + hasCubePermission = true; + break; + } + + } + } + if (hasCubePermission) { + hasProjectPermission = true; + break; + } + } + if (hasProjectPermission) { + readableProjects.add(projectInstance); + } + } + + + } + return readableProjects; + } + + @RequestMapping(value = "", method = {RequestMethod.POST}) @ResponseBody public ProjectInstance saveProject(@RequestBody CreateProjectRequest projectRequest) { if (StringUtils.isEmpty(projectRequest.getName())) { @@ -79,7 +209,7 @@ public class ProjectController extends BasicController { return createdProj; } - @RequestMapping(value = "", method = { RequestMethod.PUT }) + @RequestMapping(value = "", method = {RequestMethod.PUT}) @ResponseBody public ProjectInstance updateProject(@RequestBody UpdateProjectRequest projectRequest) { if (StringUtils.isEmpty(projectRequest.getFormerProjectName())) { @@ -98,7 +228,7 @@ public class ProjectController extends BasicController { return updatedProj; } - @RequestMapping(value = "/{projectName}", method = { RequestMethod.DELETE }) + @RequestMapping(value = "/{projectName}", method = {RequestMethod.DELETE}) @ResponseBody public void deleteProject(@PathVariable String projectName) { try { @@ -111,8 +241,20 @@ public class ProjectController extends BasicController { } } + public void setProjectService(ProjectService projectService) { this.projectService = projectService; } + /** + * @param accessService + */ + public void setAccessService(AccessService accessService) { + this.accessService = accessService; + } + + public void setCubeService(CubeService cubeService) { + this.cubeService = cubeService; + } + } http://git-wip-us.apache.org/repos/asf/kylin/blob/5d10249f/server/src/main/java/org/apache/kylin/rest/controller/UserController.java ---------------------------------------------------------------------- diff --git a/server/src/main/java/org/apache/kylin/rest/controller/UserController.java b/server/src/main/java/org/apache/kylin/rest/controller/UserController.java index a7bc782..f291841 100644 --- a/server/src/main/java/org/apache/kylin/rest/controller/UserController.java +++ b/server/src/main/java/org/apache/kylin/rest/controller/UserController.java @@ -18,6 +18,7 @@ package org.apache.kylin.rest.controller; +import java.util.ArrayList; import java.util.List; import org.apache.kylin.rest.service.UserService; @@ -76,7 +77,12 @@ public class UserController { @RequestMapping(value = "/authentication/authorities", method = RequestMethod.GET, produces = "application/json") public List<String> getAuthorities() { - return userService.getUserAuthorities(); +// return userService.getUserAuthorities(); + ArrayList<String> lists = new ArrayList<>(); + lists.add("ROLE_ADMIN"); + lists.add("ROLE_MODELER"); + lists.add("ROLE_ANALYST"); + return lists; } } http://git-wip-us.apache.org/repos/asf/kylin/blob/5d10249f/server/src/main/java/org/apache/kylin/rest/service/CubeService.java ---------------------------------------------------------------------- diff --git a/server/src/main/java/org/apache/kylin/rest/service/CubeService.java b/server/src/main/java/org/apache/kylin/rest/service/CubeService.java index ac4aa6b..fc64a58 100644 --- a/server/src/main/java/org/apache/kylin/rest/service/CubeService.java +++ b/server/src/main/java/org/apache/kylin/rest/service/CubeService.java @@ -206,7 +206,7 @@ public class CubeService extends BasicService { return createdCube; } - private List<CubeInstance> listAllCubes(String projectName) { + public List<CubeInstance> listAllCubes(String projectName) { ProjectManager projectManager = getProjectManager(); ProjectInstance project = projectManager.getProject(projectName); if (project == null) { http://git-wip-us.apache.org/repos/asf/kylin/blob/5d10249f/server/src/main/resources/kylinSecurity.xml ---------------------------------------------------------------------- diff --git a/server/src/main/resources/kylinSecurity.xml b/server/src/main/resources/kylinSecurity.xml index 4a9b929..819d951 100644 --- a/server/src/main/resources/kylinSecurity.xml +++ b/server/src/main/resources/kylinSecurity.xml @@ -152,7 +152,7 @@ <scr:intercept-url pattern="/api/streaming*/**" access="isAuthenticated()" /> <scr:intercept-url pattern="/api/job*/**" access="isAuthenticated()" /> <scr:intercept-url pattern="/api/admin/config" access="permitAll" /> - <scr:intercept-url pattern="/api/projects" access="permitAll" /> + <scr:intercept-url pattern="/api/projects*/*" access="permitAll" /> <scr:intercept-url pattern="/api/admin*/**" access="hasRole('ROLE_ADMIN')" /> <scr:intercept-url pattern="/api/**" access="isAuthenticated()" /> http://git-wip-us.apache.org/repos/asf/kylin/blob/5d10249f/webapp/app/js/controllers/auth.js ---------------------------------------------------------------------- diff --git a/webapp/app/js/controllers/auth.js b/webapp/app/js/controllers/auth.js index 2e5dc75..940ff4f 100644 --- a/webapp/app/js/controllers/auth.js +++ b/webapp/app/js/controllers/auth.js @@ -18,27 +18,25 @@ 'use strict'; -KylinApp.controller('LoginCtrl', function ($scope, $rootScope, $location, $base64, AuthenticationService, UserService) { +KylinApp.controller('LoginCtrl', function ($scope, $rootScope, $location, $base64, AuthenticationService, UserService,ProjectService,ProjectModel) { $scope.username = null; $scope.password = null; $scope.loading = false; $scope.login = function () { + + $rootScope.userAction.islogout = false; + // set the basic authentication header that will be parsed in the next request and used to authenticate httpHeaders.common['Authorization'] = 'Basic ' + $base64.encode($scope.username + ':' + $scope.password); $scope.loading = true; - //verify project - if ($scope.projectModel.projects.length && !$scope.projectModel.selectedProject) { - $scope.loading = false; - $scope.error = "Unable to login, please select a project"; - return; - } AuthenticationService.login({}, {}, function (data) { $scope.loading = false; $rootScope.$broadcast('event:loginConfirmed'); UserService.setCurUser(data); $location.path(UserService.getHomePage()); + }, function (error) { $scope.loading = false; $scope.error = "Unable to login, please check your username/password."; http://git-wip-us.apache.org/repos/asf/kylin/blob/5d10249f/webapp/app/js/controllers/cubeSchema.js ---------------------------------------------------------------------- diff --git a/webapp/app/js/controllers/cubeSchema.js b/webapp/app/js/controllers/cubeSchema.js index d22acb9..60951b7 100755 --- a/webapp/app/js/controllers/cubeSchema.js +++ b/webapp/app/js/controllers/cubeSchema.js @@ -315,7 +315,7 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic // ~ private methods function initProject() { - ProjectService.list({}, function (projects) { + ProjectService.listReadable({}, function (projects) { $scope.projects = projects; var cubeName = (!!$scope.routeParams.cubeName)? $scope.routeParams.cubeName:$scope.state.cubeName; http://git-wip-us.apache.org/repos/asf/kylin/blob/5d10249f/webapp/app/js/controllers/models.js ---------------------------------------------------------------------- diff --git a/webapp/app/js/controllers/models.js b/webapp/app/js/controllers/models.js index f1527d9..7fc2669 100644 --- a/webapp/app/js/controllers/models.js +++ b/webapp/app/js/controllers/models.js @@ -47,7 +47,13 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location, var defer = $q.defer(); var queryParam = {}; if (!$scope.projectModel.isSelectedProjectValid()) { - return; + defer.resolve([]); + return defer.promise; + } + + if (!$scope.projectModel.projects.length) { + defer.resolve([]); + return defer.promise; } queryParam.projectName = $scope.projectModel.selectedProject; http://git-wip-us.apache.org/repos/asf/kylin/blob/5d10249f/webapp/app/js/controllers/page.js ---------------------------------------------------------------------- diff --git a/webapp/app/js/controllers/page.js b/webapp/app/js/controllers/page.js index 969279f..c1a5459 100644 --- a/webapp/app/js/controllers/page.js +++ b/webapp/app/js/controllers/page.js @@ -25,6 +25,9 @@ KylinApp.controller('PageCtrl', function ($scope, $q, AccessService, $modal, $lo $log.debug(data); kylinConfig.initWebConfigInfo(); }); + $rootScope.userAction={ + 'islogout':false + } $scope.kylinConfig = kylinConfig; @@ -42,34 +45,13 @@ KylinApp.controller('PageCtrl', function ($scope, $q, AccessService, $modal, $lo $scope.activeTab = ""; $scope.projectModel = ProjectModel; $scope.tableModel = TableModel; - //init - ProjectService.list({}, function (projects) { - var _projects = []; - angular.forEach(projects, function (project, index) { - $scope.listAccess(project, 'ProjectInstance'); - _projects.push(project); - }); - _projects = _.sortBy(_projects, function (i) { - return i.name.toLowerCase(); - }); - - ProjectModel.setProjects(_projects); - - var absUrl = $location.absUrl(); - - var projectInCookie = $cookieStore.get("project"); - if (absUrl.indexOf("/login") == -1) { - var selectedProject = projectInCookie != null ? projectInCookie : null; - $scope.projectModel.setSelectedProject(selectedProject); - } else { - var selectedProject = $scope.projectModel.selectedProject != null ? $scope.projectModel.selectedProject : projectInCookie != null ? projectInCookie : $scope.projectModel.projects[0]; - $scope.projectModel.setSelectedProject(selectedProject); - } - }); - // Set up common methods $scope.logout = function () { + //destroy projects info for user + ProjectModel.clear(); + + $rootScope.userAction.islogout = true; $scope.$emit('event:logoutRequest'); $http.get(Config.service.base + 'j_spring_security_logout').success(function () { UserService.setCurUser({}); @@ -110,7 +92,7 @@ KylinApp.controller('PageCtrl', function ($scope, $q, AccessService, $modal, $lo // common acl methods $scope.hasPermission = function (entity) { var curUser = UserService.getCurUser(); - if (!curUser) { + if (!curUser.userDetails) { return curUser; } @@ -182,8 +164,11 @@ KylinApp.controller('PageCtrl', function ($scope, $q, AccessService, $modal, $lo $scope.$watch('projectModel.selectedProject', function (newValue, oldValue) { if (newValue != oldValue) { - //$log.log("project updated in page controller,from:"+oldValue+" To:"+newValue); - $cookieStore.put("project", $scope.projectModel.selectedProject); + + //do not update cookie info when logout destroy project info + if(!$rootScope.userAction.islogout){ + $cookieStore.put("project", $scope.projectModel.selectedProject); + } } }); http://git-wip-us.apache.org/repos/asf/kylin/blob/5d10249f/webapp/app/js/controllers/projects.js ---------------------------------------------------------------------- diff --git a/webapp/app/js/controllers/projects.js b/webapp/app/js/controllers/projects.js index e0cc64d..b9dae73 100644 --- a/webapp/app/js/controllers/projects.js +++ b/webapp/app/js/controllers/projects.js @@ -1,96 +1,96 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -'use strict'; - -KylinApp - .controller('ProjectCtrl', function ($scope, $modal, $q, ProjectService, MessageService,SweetAlert,$log,kylinConfig,projectConfig,ProjectModel) { - - $scope.projects = []; - $scope.loading = false; - $scope.projectConfig = projectConfig; - - $scope.state = { filterAttr: 'name', filterReverse: true, reverseColumn: 'name'}; - - $scope.list = function (offset, limit) { - offset = (!!offset) ? offset : 0; - limit = (!!limit) ? limit : 20; - var defer = $q.defer(); - var queryParam = {offset: offset, limit: limit}; - - $scope.loading = true; - ProjectService.list(queryParam, function (projects) { - $scope.projects = $scope.projects.concat(projects); - angular.forEach(projects, function (project) { - $scope.listAccess(project, 'ProjectInstance'); - }); - $scope.loading = false; - defer.resolve(projects.length); - }); - - return defer.promise; - } - - $scope.toEdit = function(project) { - $modal.open({ - templateUrl: 'project.html', - controller: projCtrl, - resolve: { - projects: function () { - return $scope.projects; - }, - project: function(){ - return project; - } - } - }); - } - - $scope.delete = function(project){ - SweetAlert.swal({ - title: '', - text: 'Are you sure to delete ?', - type: '', - showCancelButton: true, - confirmButtonColor: '#DD6B55', - confirmButtonText: "Yes", - closeOnConfirm: true - }, function(isConfirm) { - if(isConfirm){ - ProjectService.delete({projecId: project.name}, function(){ - var pIndex = $scope.projects.indexOf(project); - if (pIndex > -1) { - $scope.projects.splice(pIndex, 1); - } - ProjectModel.removeProject(project.name); - SweetAlert.swal('Success!',"Project [" + project.name + "] has been deleted successfully!", 'success'); - },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'); - } - }); - } - }); - } - } -); - +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +'use strict'; + +KylinApp + .controller('ProjectCtrl', function ($scope, $modal, $q, ProjectService, MessageService,SweetAlert,$log,kylinConfig,projectConfig,ProjectModel) { + + $scope.projects = []; + $scope.loading = false; + $scope.projectConfig = projectConfig; + + $scope.state = { filterAttr: 'name', filterReverse: true, reverseColumn: 'name'}; + + $scope.list = function (offset, limit) { + offset = (!!offset) ? offset : 0; + limit = (!!limit) ? limit : 20; + var defer = $q.defer(); + var queryParam = {offset: offset, limit: limit}; + + $scope.loading = true; + ProjectService.listReadable(queryParam, function (projects) { + $scope.projects = $scope.projects.concat(projects); + angular.forEach(projects, function (project) { + $scope.listAccess(project, 'ProjectInstance'); + }); + $scope.loading = false; + defer.resolve(projects.length); + }); + + return defer.promise; + } + + $scope.toEdit = function(project) { + $modal.open({ + templateUrl: 'project.html', + controller: projCtrl, + resolve: { + projects: function () { + return $scope.projects; + }, + project: function(){ + return project; + } + } + }); + } + + $scope.delete = function(project){ + SweetAlert.swal({ + title: '', + text: 'Are you sure to delete ?', + type: '', + showCancelButton: true, + confirmButtonColor: '#DD6B55', + confirmButtonText: "Yes", + closeOnConfirm: true + }, function(isConfirm) { + if(isConfirm){ + ProjectService.delete({projecId: project.name}, function(){ + var pIndex = $scope.projects.indexOf(project); + if (pIndex > -1) { + $scope.projects.splice(pIndex, 1); + } + ProjectModel.removeProject(project.name); + SweetAlert.swal('Success!',"Project [" + project.name + "] has been deleted successfully!", 'success'); + },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'); + } + }); + } + }); + } + } +); + http://git-wip-us.apache.org/repos/asf/kylin/blob/5d10249f/webapp/app/js/listeners.js ---------------------------------------------------------------------- diff --git a/webapp/app/js/listeners.js b/webapp/app/js/listeners.js index 7998481..556acdf 100644 --- a/webapp/app/js/listeners.js +++ b/webapp/app/js/listeners.js @@ -16,7 +16,7 @@ * limitations under the License. */ -KylinApp.run(function ($rootScope, $http, $location, UserService, AuthenticationService, MessageService, loadingRequest, SweetAlert) { +KylinApp.run(function ($rootScope, $http, $location, UserService, AuthenticationService, MessageService, loadingRequest, $cookieStore,ProjectService,ProjectModel,AccessService,SweetAlert,loadingRequest) { $rootScope.permissions = { READ: {name: 'CUBE QUERY', value: 'READ', mask: 1}, @@ -26,18 +26,65 @@ KylinApp.run(function ($rootScope, $http, $location, UserService, Authentication }; $rootScope.$on("$routeChangeStart", function () { - AuthenticationService.ping(function (data) { - if(!data.userDetails){ - $location.path(UserService.getHomePage()); - } - UserService.setCurUser(data); - }); + AuthenticationService.ping(function (data) { + if(!data.userDetails){ + $location.path(UserService.getHomePage()); + }else{ + UserService.setCurUser(data); + //get project info when login + if (!ProjectModel.projects.length&&!$rootScope.userAction.islogout) { + + loadingRequest.show(); + ProjectService.listReadable({}, function (projects) { + loadingRequest.hide(); + + if(!projects.length){ + return; + } + + var _projects = []; + _projects = _.sortBy(projects, function (i) { + return i.name.toLowerCase(); + }); + ProjectModel.setProjects(_projects); + var projectInCookie = $cookieStore.get("project"); + if(projectInCookie&&ProjectModel.getIndex(projectInCookie)==-1){ + projectInCookie = null; + } + var selectedProject = projectInCookie != null ? projectInCookie : null; + if(projectInCookie!=null){ + selectedProject = projectInCookie; + }else if(UserService.hasRole('ROLE_ADMIN')){ + selectedProject = null; + }else{ + selectedProject = ProjectModel.projects[0].name + } + + //var selectedProject = ProjectModel.selectedProject != null ? ProjectModel.selectedProject : projectInCookie != null ? projectInCookie : ProjectModel.projects[0].name; + ProjectModel.setSelectedProject(selectedProject); + angular.forEach(ProjectModel.projects, function (project, index) { + project.accessLoading = true; + AccessService.list({type: 'ProjectInstance', uuid: project.uuid}, function (accessEntities) { + project.accessLoading = false; + project.accessEntities = accessEntities; + }); + }); + + },function(e){ + loadingRequest.hide(); + $location.path(UserService.getHomePage()); + }); + } + } + }); + if ($location.url() == '' || $location.url() == '/') { AuthenticationService.ping(function (data) { UserService.setCurUser(data); $location.path(UserService.getHomePage()); }); + return; } }); http://git-wip-us.apache.org/repos/asf/kylin/blob/5d10249f/webapp/app/js/model/modelsManager.js ---------------------------------------------------------------------- diff --git a/webapp/app/js/model/modelsManager.js b/webapp/app/js/model/modelsManager.js index 2c3c90a..fb67cd6 100644 --- a/webapp/app/js/model/modelsManager.js +++ b/webapp/app/js/model/modelsManager.js @@ -40,11 +40,13 @@ KylinApp.service('modelsManager',function(ModelService,CubeService,$q,AccessServ angular.forEach(_models, function (model, index) { $log.info("Add model permission info"); + if(model.uuid){ modelPermission.push( AccessService.list({type: "DataModelDesc", uuid: model.uuid}, function (accessEntities) { model.accessEntities = accessEntities; }).$promise ) + } $log.info("Add cube info to model ,not detail info"); cubeDetail.push( CubeService.list({modelName:model.name}, function (_cubes) { http://git-wip-us.apache.org/repos/asf/kylin/blob/5d10249f/webapp/app/js/model/projectModel.js ---------------------------------------------------------------------- diff --git a/webapp/app/js/model/projectModel.js b/webapp/app/js/model/projectModel.js index eba8273..a264331 100644 --- a/webapp/app/js/model/projectModel.js +++ b/webapp/app/js/model/projectModel.js @@ -31,12 +31,6 @@ KylinApp.service('ProjectModel', function () { this.selectedProject = project; } }; - this.getSelectedProject = function (project) { - if (this.selectedProject == "_null") { - return null; - } - return this.selectedProject; - }; this.isSelectedProjectValid = function(){ if(this.selectedProject == "_null"){ @@ -45,6 +39,13 @@ KylinApp.service('ProjectModel', function () { return true; } + this.getSelectedProject = function (project) { + if (this.selectedProject == "_null") { + return null; + } + return this.selectedProject; + }; + this.setProjects = function (projects) { if (projects.length) { this.projects = projects; @@ -106,4 +107,25 @@ KylinApp.service('ProjectModel', function () { }); } + this.clear = function(){ + this.projects = []; + this.selectedProject = "_null"; + } + + this.clearProjects = function(){ + this.projects = []; + } + + this.getIndex = function(project){ + var index = -1; + for (var i = 0; i < this.projects.length; i++) { + if (this.projects[i].name == project) { + index = i; + break; + } + } + return index; + + } + }) http://git-wip-us.apache.org/repos/asf/kylin/blob/5d10249f/webapp/app/js/services/projects.js ---------------------------------------------------------------------- diff --git a/webapp/app/js/services/projects.js b/webapp/app/js/services/projects.js index 333e742..84a0a89 100644 --- a/webapp/app/js/services/projects.js +++ b/webapp/app/js/services/projects.js @@ -19,6 +19,7 @@ KylinApp.factory('ProjectService', ['$resource', function ($resource, config) { return $resource(Config.service.url + 'projects/:projecId/:propName/:propValue/:action', {}, { list: {method: 'GET', params: {}, isArray: true}, + 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} http://git-wip-us.apache.org/repos/asf/kylin/blob/5d10249f/webapp/app/partials/login.html ---------------------------------------------------------------------- diff --git a/webapp/app/partials/login.html b/webapp/app/partials/login.html index 79128b1..452257b 100644 --- a/webapp/app/partials/login.html +++ b/webapp/app/partials/login.html @@ -32,28 +32,16 @@ <form name="login_form" ng-submit="login()"> <div class="form-group"> <span class="width-100 input-icon input-icon-right"> - <input id="username" class="form-control" ng-model="username" type="text" autofocus="autofocus" required placeholder="Username" auto-fill-sync /> + <input id="username" class="form-control" ng-model="username" type="text" autofocus="autofocus" ng-required placeholder="Username" auto-fill-sync /> <i class="ace-icon fa fa-user"></i> </span> </div> <div class="form-group"> <span class="width-100 input-icon input-icon-right"> - <input id="password" class="form-control" ng-model="password" type="password" required placeholder="Password" auto-fill-sync /> + <input id="password" class="form-control" ng-model="password" type="password" ng-required placeholder="Password" auto-fill-sync /> <i class="ace-icon fa fa-lock"></i> </span> </div> - <div class="form-group"> - <span> - - <select ng-required="projectModel.projects.length" chosen ng-model="projectModel.selectedProject" ng-init="newAccess.permission=permissions.READ.value;" - ng-options="project.name as project.name for project in projectModel.projects " - style="width: 100% !important;" - data-placeholder="select a project" - class="chosen-select"> - <option value=""></option> - </select> - </span> - </div> <div class="space"></div> <div class="form-group"> <a href="http://kylin.apache.org/community/" target="_blank" class="text-muted">Login Issue?</a> http://git-wip-us.apache.org/repos/asf/kylin/blob/5d10249f/webapp/app/partials/models/models_tree.html ---------------------------------------------------------------------- diff --git a/webapp/app/partials/models/models_tree.html b/webapp/app/partials/models/models_tree.html index 821d0fa..8f76113 100644 --- a/webapp/app/partials/models/models_tree.html +++ b/webapp/app/partials/models/models_tree.html @@ -50,9 +50,9 @@ <div class="pull-right" showonhoverparent style="display:none;" class="cube_model_trees"> - <a href="models/edit/{{model.name}}" title="Edit Model" ng-if="userService.hasRole('ROLE_MODELER') "><span class="fa fa-pencil fa-lg fa-fw"></span></a> - <a ng-click="cloneModel(model)" title="Clone Model" style="cursor:pointer;margin-right: 8px;" ng-if="userService.hasRole('ROLE_MODELER')"><span class="fa fa-copy fa-lg fa-fw"></span></a> - <a ng-click="dropModel(model)" title="Drop Model" style="cursor:pointer;margin-right: 8px;" ng-if="userService.hasRole('ROLE_MODELER')"><span class="fa fa-trash-o fa-lg fa-fw"></span></a> + <a href="models/edit/{{model.name}}" title="Edit Model" ng-if="(userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask))"><span class="fa fa-pencil fa-lg fa-fw"></span></a> + <a ng-click="cloneModel(model)" title="Clone Model" style="cursor:pointer;margin-right: 8px;" ng-if="(userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask))"><span class="fa fa-copy fa-lg fa-fw"></span></a> + <a ng-click="dropModel(model)" title="Drop Model" style="cursor:pointer;margin-right: 8px;" ng-if="(userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask))"><span class="fa fa-trash-o fa-lg fa-fw"></span></a> </div>