Repository: incubator-ranger Updated Branches: refs/heads/master 4434e4d3c -> 2a309b5c1
RANGER-244-Provide-support-to-Show-Hide-Users-Revised Signed-off-by: Velmurugan Periasamy <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/2a309b5c Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/2a309b5c Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/2a309b5c Branch: refs/heads/master Commit: 2a309b5c1a44de97cae1657278407037d0f33054 Parents: 4434e4d Author: Gautam Borad <[email protected]> Authored: Wed Mar 4 19:23:50 2015 +0530 Committer: Velmurugan Periasamy <[email protected]> Committed: Mon Mar 9 10:59:49 2015 -0400 ---------------------------------------------------------------------- .../patches/010-users-and-groups-visibility.sql | 50 ++++ .../patches/010-users-and-groups-visibility.sql | 44 ++++ .../java/org/apache/ranger/biz/XUserMgr.java | 31 +++ .../apache/ranger/common/RangerCommonEnums.java | 22 +- .../java/org/apache/ranger/entity/XXGroup.java | 26 ++ .../java/org/apache/ranger/entity/XXUser.java | 29 ++ .../java/org/apache/ranger/rest/XUserREST.java | 18 ++ .../apache/ranger/service/XGroupService.java | 17 +- .../ranger/service/XGroupServiceBase.java | 2 + .../org/apache/ranger/service/XUserService.java | 4 + .../apache/ranger/service/XUserServiceBase.java | 2 + .../java/org/apache/ranger/view/VXGroup.java | 21 ++ .../java/org/apache/ranger/view/VXUser.java | 12 +- .../scripts/collection_bases/VXGroupListBase.js | 26 +- .../scripts/collection_bases/VXUserListBase.js | 23 +- .../src/main/webapp/scripts/models/VXGroup.js | 15 +- .../src/main/webapp/scripts/models/VXUser.js | 14 + .../main/webapp/scripts/modules/XAOverrides.js | 263 +++++++++++++++++++ .../scripts/modules/globalize/message/en.js | 10 +- .../src/main/webapp/scripts/utils/XAEnums.js | 5 + .../src/main/webapp/scripts/utils/XAUtils.js | 1 + .../scripts/views/common/FormInputItemList.js | 2 +- .../scripts/views/common/UserPermissionList.js | 2 +- .../scripts/views/common/XATableLayout.js | 7 + .../scripts/views/policies/PermissionList.js | 4 +- .../scripts/views/policies/RangerPolicyForm.js | 2 +- .../scripts/views/users/UserTableLayout.js | 157 ++++++++++- security-admin/src/main/webapp/styles/xa.css | 15 ++ .../templates/users/UserTableLayout_tmpl.html | 2 + .../org/apache/ranger/biz/TestXUserMgr.java | 175 +++++++++++- 30 files changed, 959 insertions(+), 42 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/db/mysql/patches/010-users-and-groups-visibility.sql ---------------------------------------------------------------------- diff --git a/security-admin/db/mysql/patches/010-users-and-groups-visibility.sql b/security-admin/db/mysql/patches/010-users-and-groups-visibility.sql new file mode 100644 index 0000000..6d954ee --- /dev/null +++ b/security-admin/db/mysql/patches/010-users-and-groups-visibility.sql @@ -0,0 +1,50 @@ +-- 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. + +drop procedure if exists add_is_visible_column_to_x_user_table; +delimiter ;; + create procedure add_is_visible_column_to_x_user_table() begin + +/* add is visible column in x_user table if not exist */ + if exists (select * from information_schema.columns where table_schema=database() and table_name = 'x_user') then + if not exists (select * from information_schema.columns where table_schema=database() and table_name = 'x_user' and column_name = 'is_visible') then + ALTER TABLE `x_user` ADD `is_visible` INT(11) NOT NULL DEFAULT '1'; + end if; + end if; +end;; + +delimiter ; + +call add_is_visible_column_to_x_user_table(); + +drop procedure if exists add_is_visible_column_to_x_user_table; + +drop procedure if exists add_is_visible_column_to_x_group_table; +delimiter ;; + create procedure add_is_visible_column_to_x_group_table() begin + +/* add is visible column in x_group table if not exist */ + if exists (select * from information_schema.columns where table_schema=database() and table_name = 'x_group') then + if not exists (select * from information_schema.columns where table_schema=database() and table_name = 'x_group' and column_name = 'is_visible') then + ALTER TABLE `x_group` ADD `is_visible` INT(11) NOT NULL DEFAULT '1'; + end if; + end if; +end;; + +delimiter ; + +call add_is_visible_column_to_x_group_table(); + +drop procedure if exists add_is_visible_column_to_x_group_table; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/db/oracle/patches/010-users-and-groups-visibility.sql ---------------------------------------------------------------------- diff --git a/security-admin/db/oracle/patches/010-users-and-groups-visibility.sql b/security-admin/db/oracle/patches/010-users-and-groups-visibility.sql new file mode 100644 index 0000000..38dc8e4 --- /dev/null +++ b/security-admin/db/oracle/patches/010-users-and-groups-visibility.sql @@ -0,0 +1,44 @@ +-- 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. + +DECLARE + v_column_exists number := 0; +BEGIN + Select count(*) into v_column_exists + from user_tab_cols + where column_name = upper('is_visible') + and table_name = upper('x_user'); + + if (v_column_exists = 0) then + execute immediate 'ALTER TABLE x_user ADD is_visible NUMBER(11) DEFAULT 1 NOT NULL'; + commit; + end if; +end; +/ + +DECLARE + v_column_exists number := 0; +BEGIN + Select count(*) into v_column_exists + from user_tab_cols + where column_name = upper('is_visible') + and table_name = upper('x_group'); + + if (v_column_exists = 0) then + execute immediate 'ALTER TABLE x_group ADD is_visible NUMBER(11) DEFAULT 1 NOT NULL'; + commit; + end if; +end; +/ http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java b/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java index fa03f2f..3c6ef3e 100644 --- a/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java @@ -20,11 +20,18 @@ package org.apache.ranger.biz; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; + import org.apache.log4j.Logger; import org.apache.ranger.common.MessageEnums; import org.apache.ranger.common.PropertiesUtil; @@ -35,6 +42,8 @@ import org.apache.ranger.db.XXGroupUserDao; import org.apache.ranger.entity.XXGroup; import org.apache.ranger.entity.XXPortalUser; import org.apache.ranger.entity.XXTrxLog; +import org.apache.ranger.entity.XXUser; +import org.apache.ranger.service.XGroupService; import org.apache.ranger.service.XUserService; import org.apache.ranger.view.VXGroup; import org.apache.ranger.view.VXGroupList; @@ -63,6 +72,9 @@ public class XUserMgr extends XUserMgrBase { @Autowired RangerBizUtil xaBizUtil; + + @Autowired + XGroupService xGroupService; static final Logger logger = Logger.getLogger(XUserMgr.class); @@ -472,4 +484,23 @@ public class XUserMgr extends XUserMgrBase { return vXGroup; } + public void modifyUserVisibility(HashMap<Long, Integer> visibilityMap) { + Set<Long> keys = visibilityMap.keySet(); + for (Long key : keys) { + XXUser xUser = daoManager.getXXUser().getById(key); + VXUser vObj = xUserService.populateViewBean(xUser); + vObj.setIsVisible(visibilityMap.get(key)); + vObj = xUserService.updateResource(vObj); + } + } + + public void modifyGroupsVisibility(HashMap<Long, Integer> groupVisibilityMap) { + Set<Long> keys = groupVisibilityMap.keySet(); + for (Long key : keys) { + XXGroup xGroup = daoManager.getXXGroup().getById(key); + VXGroup vObj = xGroupService.populateViewBean(xGroup); + vObj.setIsVisible(groupVisibilityMap.get(key)); + vObj = xGroupService.updateResource(vObj); + } + } } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/java/org/apache/ranger/common/RangerCommonEnums.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/common/RangerCommonEnums.java b/security-admin/src/main/java/org/apache/ranger/common/RangerCommonEnums.java index 33edc28..c02998d 100644 --- a/security-admin/src/main/java/org/apache/ranger/common/RangerCommonEnums.java +++ b/security-admin/src/main/java/org/apache/ranger/common/RangerCommonEnums.java @@ -27,6 +27,18 @@ public class RangerCommonEnums { /*************************************************************** + * Enum values for VisibilityStatus + **************************************************************/ + /** + * IS_VISIBLE is an element of enum VisibilityStatus. Its value is "IS_VISIBLE". + */ + public static final int IS_VISIBLE = 1; + /** + * IS_HIDDEN is an element of enum VisibilityStatus. Its value is "IS_HIDDEN". + */ + public static final int IS_HIDDEN = 0; + + /*************************************************************** * Enum values for ActiveStatus **************************************************************/ /** @@ -884,7 +896,15 @@ public class RangerCommonEnums { */ public static final int ClassTypes_MAX = 1012; - + static public String getLabelFor_VisibilityStatus( int elementValue ) { + if( elementValue == 0 ) { + return "Hidden"; //IS_HIDDEN + } + if( elementValue == 1 ) { + return "Visible"; //IS_VISIBLE + } + return null; + } static public String getLabelFor_ActiveStatus( int elementValue ) { if( elementValue == 0 ) { http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/java/org/apache/ranger/entity/XXGroup.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/entity/XXGroup.java b/security-admin/src/main/java/org/apache/ranger/entity/XXGroup.java index 4224cc4..a31ea7b 100644 --- a/security-admin/src/main/java/org/apache/ranger/entity/XXGroup.java +++ b/security-admin/src/main/java/org/apache/ranger/entity/XXGroup.java @@ -86,6 +86,16 @@ public class XXGroup extends XXDBBase implements java.io.Serializable { */ @Column(name="STATUS" , nullable=false ) protected int status = RangerConstants.STATUS_DISABLED; + + /** + * IsVisible + * <ul> + * <li>This attribute is of type enum CommonEnums::ActiveVisiblility + * </ul> + * + */ + @Column(name="IS_VISIBLE" , nullable=false ) + protected Integer isVisible ; /** * Type of group @@ -117,6 +127,7 @@ public class XXGroup extends XXDBBase implements java.io.Serializable { status = RangerConstants.STATUS_DISABLED; groupType = AppConstants.XA_GROUP_UNKNOWN; groupSource = RangerCommonEnums.GROUP_INTERNAL; + isVisible = RangerCommonEnums.IS_VISIBLE; } @Override @@ -181,6 +192,20 @@ public class XXGroup extends XXDBBase implements java.io.Serializable { } /** + * @return the isVisible + */ + public Integer getIsVisible() { + return isVisible; + } + + /** + * @param isVisible the isVisible to set + */ + public void setIsVisible(Integer isVisible) { + this.isVisible = isVisible; + } + + /** * This method sets the value to the member attribute <b>groupType</b>. * You cannot set null to the attribute. * @param groupType Value to set member attribute <b>groupType</b> @@ -227,6 +252,7 @@ public class XXGroup extends XXDBBase implements java.io.Serializable { str += "name={" + name + "} "; str += "description={" + description + "} "; str += "status={" + status + "} "; + str += "isvisible={" + isVisible + "} "; str += "groupType={" + groupType + "} "; str += "credStoreId={" + credStoreId + "} "; str += "groupSrc={" + groupSource + "} "; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/java/org/apache/ranger/entity/XXUser.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/entity/XXUser.java b/security-admin/src/main/java/org/apache/ranger/entity/XXUser.java index af339d2..d6416ba 100644 --- a/security-admin/src/main/java/org/apache/ranger/entity/XXUser.java +++ b/security-admin/src/main/java/org/apache/ranger/entity/XXUser.java @@ -34,6 +34,7 @@ import javax.persistence.Table; import javax.xml.bind.annotation.XmlRootElement; import org.apache.ranger.common.AppConstants; +import org.apache.ranger.common.RangerCommonEnums; import org.apache.ranger.common.RangerConstants; @@ -88,6 +89,15 @@ public class XXUser extends XXDBBase implements java.io.Serializable { protected int status = RangerConstants.STATUS_DISABLED; /** + * Status + * <ul> + * <li>This attribute is of type enum CommonEnums::ActiveStatus + * </ul> + * + */ + @Column(name="IS_VISIBLE" , nullable=false ) + protected Integer isVisible ; + /** * Id of the credential store * <ul> * </ul> @@ -102,6 +112,7 @@ public class XXUser extends XXDBBase implements java.io.Serializable { */ public XXUser ( ) { status = RangerConstants.STATUS_DISABLED; + isVisible = RangerCommonEnums.IS_VISIBLE; } @Override @@ -166,6 +177,23 @@ public class XXUser extends XXDBBase implements java.io.Serializable { } /** + * This method sets the value to the member attribute <b>isVisible</b>. + * You cannot set null to the attribute. + * @param status Value to set member attribute <b>isVisible</b> + */ + public void setIsVisible(Integer isVisible) { + this.isVisible = isVisible; + } + + /** + * Returns the value for the member attribute <b>isVisible</b> + * @return int - value of member attribute <b>isVisible</b>. + */ + public Integer getIsVisible() { + return isVisible; + } + + /** * This method sets the value to the member attribute <b>credStoreId</b>. * You cannot set null to the attribute. * @param credStoreId Value to set member attribute <b>credStoreId</b> @@ -194,6 +222,7 @@ public class XXUser extends XXDBBase implements java.io.Serializable { str += "name={" + name + "} "; str += "description={" + description + "} "; str += "status={" + status + "} "; + str += "isvisible={" + isVisible + "} "; str += "credStoreId={" + credStoreId + "} "; str += "}"; return str; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/java/org/apache/ranger/rest/XUserREST.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/rest/XUserREST.java b/security-admin/src/main/java/org/apache/ranger/rest/XUserREST.java index 9ebdd63..beb4829 100644 --- a/security-admin/src/main/java/org/apache/ranger/rest/XUserREST.java +++ b/security-admin/src/main/java/org/apache/ranger/rest/XUserREST.java @@ -19,6 +19,9 @@ package org.apache.ranger.rest; +import java.util.HashMap; +import java.util.List; + import javax.servlet.http.HttpServletRequest; import javax.ws.rs.DELETE; import javax.ws.rs.GET; @@ -156,6 +159,12 @@ public class XUserREST { return xUserMgr.updateXGroup(vXGroup); } + @PUT + @Path("/secure/groups/visibility") + @Produces({ "application/xml", "application/json" }) + public void modifyGroupsVisibility(HashMap<Long, Integer> groupVisibilityMap){ + xUserMgr.modifyGroupsVisibility(groupVisibilityMap); + } @DELETE @Path("/groups/{id}") @@ -181,6 +190,7 @@ public class XUserREST { request, xGroupService.sortFields); searchUtil.extractString(request, searchCriteria, "name", "group name", StringUtil.VALIDATION_NAME); + searchUtil.extractInt(request, searchCriteria, "isVisible", "Group Visibility"); searchUtil.extractString(request, searchCriteria, "groupSource", "group source", StringUtil.VALIDATION_NAME); return xUserMgr.searchXGroups(searchCriteria); @@ -246,6 +256,13 @@ public class XUserREST { return xUserMgr.updateXUser(vXUser); } + @PUT + @Path("/secure/users/visibility") + @Produces({ "application/xml", "application/json" }) + public void modifyUserVisibility(HashMap<Long, Integer> visibilityMap){ + xUserMgr.modifyUserVisibility(visibilityMap); + } + @DELETE @Path("/users/{id}") @PreAuthorize("hasRole('ROLE_SYS_ADMIN')") @@ -274,6 +291,7 @@ public class XUserREST { searchUtil.extractString(request, searchCriteria, "emailAddress", "Email Address", null); searchUtil.extractInt(request, searchCriteria, "userSource", "User Source"); + searchUtil.extractInt(request, searchCriteria, "isVisible", "User Visibility"); searchUtil.extractString(request, searchCriteria, "userRoleList", "User Role", null); return xUserMgr.searchXUsers(searchCriteria); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/java/org/apache/ranger/service/XGroupService.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/service/XGroupService.java b/security-admin/src/main/java/org/apache/ranger/service/XGroupService.java index 6a45555..580c31c 100644 --- a/security-admin/src/main/java/org/apache/ranger/service/XGroupService.java +++ b/security-admin/src/main/java/org/apache/ranger/service/XGroupService.java @@ -36,8 +36,10 @@ import org.apache.ranger.entity.XXAsset; import org.apache.ranger.entity.XXGroup; import org.apache.ranger.entity.XXPortalUser; import org.apache.ranger.entity.XXTrxLog; +import org.apache.ranger.entity.XXUser; import org.apache.ranger.util.RangerEnumUtil; import org.apache.ranger.view.VXGroup; +import org.apache.ranger.view.VXUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; @@ -68,9 +70,13 @@ public class XGroupService extends XGroupServiceBase<XXGroup, VXGroup> { SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.PARTIAL)); searchFields.add(new SearchField("groupSource", "obj.groupSource", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL)); + + searchFields.add(new SearchField("isVisible", "obj.isVisible", + SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL )); + createdByUserId = new Long(PropertiesUtil.getIntProperty( - "xa.xuser.createdByUserId", 1)); - + "xa.xuser.createdByUserId", 1)); + sortFields.add(new SortField("name", "obj.name",true,SortField.SORT_ORDER.ASC)); } @@ -234,6 +240,13 @@ public class XGroupService extends XGroupServiceBase<XXGroup, VXGroup> { } @Override + public VXGroup populateViewBean(XXGroup xGroup) { + VXGroup vObj = super.populateViewBean(xGroup); + vObj.setIsVisible(xGroup.getIsVisible()); + return vObj; + } + + @Override protected XXGroup mapViewToEntityBean(VXGroup vObj, XXGroup mObj, int OPERATION_CONTEXT) { super.mapViewToEntityBean(vObj, mObj, OPERATION_CONTEXT); return mObj; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/java/org/apache/ranger/service/XGroupServiceBase.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/service/XGroupServiceBase.java b/security-admin/src/main/java/org/apache/ranger/service/XGroupServiceBase.java index c3eebc0..68df919 100644 --- a/security-admin/src/main/java/org/apache/ranger/service/XGroupServiceBase.java +++ b/security-admin/src/main/java/org/apache/ranger/service/XGroupServiceBase.java @@ -43,6 +43,7 @@ public abstract class XGroupServiceBase<T extends XXGroup, V extends VXGroup> @Override protected XXGroup mapViewToEntityBean(VXGroup vObj, XXGroup mObj, int OPERATION_CONTEXT) { mObj.setName( vObj.getName()); + mObj.setIsVisible(vObj.getIsVisible()); mObj.setDescription( vObj.getDescription()); mObj.setGroupType( vObj.getGroupType()); mObj.setCredStoreId( vObj.getCredStoreId()); @@ -53,6 +54,7 @@ public abstract class XGroupServiceBase<T extends XXGroup, V extends VXGroup> @Override protected VXGroup mapEntityToViewBean(VXGroup vObj, XXGroup mObj) { vObj.setName( mObj.getName()); + vObj.setIsVisible( mObj.getIsVisible()); vObj.setDescription( mObj.getDescription()); vObj.setGroupType( mObj.getGroupType()); vObj.setCredStoreId( mObj.getCredStoreId()); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/java/org/apache/ranger/service/XUserService.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/service/XUserService.java b/security-admin/src/main/java/org/apache/ranger/service/XUserService.java index 5e4875f..abac343 100644 --- a/security-admin/src/main/java/org/apache/ranger/service/XUserService.java +++ b/security-admin/src/main/java/org/apache/ranger/service/XUserService.java @@ -107,6 +107,9 @@ public class XUserService extends XUserServiceBase<XXUser, VXUser> { "XXPortalUser xXPortalUser, XXPortalUserRole xXPortalUserRole", "xXPortalUser.id=xXPortalUserRole.userId and xXPortalUser.loginId = obj.name ")); + searchFields.add(new SearchField("isVisible", "obj.isVisible", + SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL )); + createdByUserId = new Long(PropertiesUtil.getIntProperty( "xa.xuser.createdByUserId", 1)); @@ -198,6 +201,7 @@ public class XUserService extends XUserServiceBase<XXUser, VXUser> { @Override public VXUser populateViewBean(XXUser xUser) { VXUser vObj = super.populateViewBean(xUser); + vObj.setIsVisible(xUser.getIsVisible()); String userName = vObj.getName(); populateUserAttributes(userName, vObj); populateGroupList(xUser.getId(), vObj); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/java/org/apache/ranger/service/XUserServiceBase.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/service/XUserServiceBase.java b/security-admin/src/main/java/org/apache/ranger/service/XUserServiceBase.java index b8a4487..943e280 100644 --- a/security-admin/src/main/java/org/apache/ranger/service/XUserServiceBase.java +++ b/security-admin/src/main/java/org/apache/ranger/service/XUserServiceBase.java @@ -43,6 +43,7 @@ public abstract class XUserServiceBase<T extends XXUser, V extends VXUser> @Override protected XXUser mapViewToEntityBean(VXUser vObj, XXUser mObj, int OPERATION_CONTEXT) { mObj.setName( vObj.getName()); + mObj.setIsVisible(vObj.getIsVisible()); mObj.setDescription( vObj.getDescription()); mObj.setCredStoreId( vObj.getCredStoreId()); return mObj; @@ -52,6 +53,7 @@ public abstract class XUserServiceBase<T extends XXUser, V extends VXUser> @Override protected VXUser mapEntityToViewBean(VXUser vObj, XXUser mObj) { vObj.setName( mObj.getName()); + vObj.setIsVisible(mObj.getIsVisible()); vObj.setDescription( mObj.getDescription()); vObj.setCredStoreId( mObj.getCredStoreId()); return vObj; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/java/org/apache/ranger/view/VXGroup.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/view/VXGroup.java b/security-admin/src/main/java/org/apache/ranger/view/VXGroup.java index 5536b3c..5c7e6fb 100644 --- a/security-admin/src/main/java/org/apache/ranger/view/VXGroup.java +++ b/security-admin/src/main/java/org/apache/ranger/view/VXGroup.java @@ -62,10 +62,16 @@ public class VXGroup extends VXDataObject implements java.io.Serializable { protected Long credStoreId; /** + * Group visibility + */ + protected Integer isVisible; + + /** * Default constructor. This will set all the attributes to default value. */ public VXGroup ( ) { groupType = AppConstants.XA_GROUP_UNKNOWN; + isVisible = RangerCommonEnums.IS_VISIBLE; } /** @@ -136,6 +142,20 @@ public class VXGroup extends VXDataObject implements java.io.Serializable { return this.credStoreId; } + /** + * @return the isVisible + */ + public Integer getIsVisible() { + return isVisible; + } + + /** + * @param isVisible the isVisible to set + */ + public void setIsVisible(Integer isVisible) { + this.isVisible = isVisible; + } + @Override public int getMyClassType( ) { return AppConstants.CLASS_TYPE_XA_GROUP; @@ -163,6 +183,7 @@ public class VXGroup extends VXDataObject implements java.io.Serializable { str += "description={" + description + "} "; str += "groupType={" + groupType + "} "; str += "credStoreId={" + credStoreId + "} "; + str += "isVisible={" + isVisible + "} "; str += "groupSrc={" + groupSource + "} "; str += "}"; return str; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/java/org/apache/ranger/view/VXUser.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/view/VXUser.java b/security-admin/src/main/java/org/apache/ranger/view/VXUser.java index a237377..5e188a9 100644 --- a/security-admin/src/main/java/org/apache/ranger/view/VXUser.java +++ b/security-admin/src/main/java/org/apache/ranger/view/VXUser.java @@ -29,6 +29,7 @@ import java.util.Collection; import javax.xml.bind.annotation.XmlRootElement; import org.apache.ranger.common.AppConstants; +import org.apache.ranger.common.RangerCommonEnums; import org.codehaus.jackson.annotate.JsonAutoDetect; import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility; import org.codehaus.jackson.annotate.JsonIgnoreProperties; @@ -77,6 +78,7 @@ public class VXUser extends VXDataObject implements java.io.Serializable { protected Collection<String> groupNameList; protected int status; + protected Integer isVisible; protected int userSource; /** * List of roles for this user @@ -87,6 +89,7 @@ public class VXUser extends VXDataObject implements java.io.Serializable { * Default constructor. This will set all the attributes to default value. */ public VXUser ( ) { + isVisible = RangerCommonEnums.IS_VISIBLE; } /** @@ -235,11 +238,17 @@ public class VXUser extends VXDataObject implements java.io.Serializable { return status; } - public void setStatus(int status) { + public void setStatus(Integer status) { this.status = status; } + public Integer getIsVisible() { + return isVisible; + } + public void setIsVisible(Integer isVisible) { + this.isVisible = isVisible; + } public int getUserSource() { return userSource; @@ -289,6 +298,7 @@ public class VXUser extends VXDataObject implements java.io.Serializable { str += "password={" + password + "} "; str += "description={" + description + "} "; str += "credStoreId={" + credStoreId + "} "; + str += "isVisible={" + isVisible + "} "; str += "groupIdList={" + groupIdList + "} "; str += "groupNameList={" + groupNameList + "} "; str += "}"; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/webapp/scripts/collection_bases/VXGroupListBase.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/collection_bases/VXGroupListBase.js b/security-admin/src/main/webapp/scripts/collection_bases/VXGroupListBase.js index 7329c79..4b86d08 100644 --- a/security-admin/src/main/webapp/scripts/collection_bases/VXGroupListBase.js +++ b/security-admin/src/main/webapp/scripts/collection_bases/VXGroupListBase.js @@ -41,7 +41,18 @@ define(function(require){ this.modelName = 'VXGroup'; this.modelAttrName = 'vXGroups'; this.bindErrorEvents(); + this._changes = { }; + this.on('change', this._onChange); }, + + _onChange : function(m){ + this._changes[m.id] = m; + }, + + changed_models: function() { + return _.chain(this._changes).values(); + }, + /************************* * Non - CRUD operations *************************/ @@ -56,7 +67,20 @@ define(function(require){ }, options); return this.constructor.nonCrudOperation.call(this, url, 'GET', options); - } + }, + + setGroupsVisibility : function(postData , options){ + var url = XAGlobals.baseURL + 'xusers/secure/groups/visibility'; + + options = _.extend({ + data : JSON.stringify(postData), + contentType : 'application/json', + dataType : 'json' + }, options); + + return this.constructor.nonCrudOperation.call(this, url, 'PUT', options); + }, + },{ // static class members /** http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/webapp/scripts/collection_bases/VXUserListBase.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/collection_bases/VXUserListBase.js b/security-admin/src/main/webapp/scripts/collection_bases/VXUserListBase.js index 5ebcb3c..2c7f5fc 100644 --- a/security-admin/src/main/webapp/scripts/collection_bases/VXUserListBase.js +++ b/security-admin/src/main/webapp/scripts/collection_bases/VXUserListBase.js @@ -41,8 +41,17 @@ define(function(require){ this.modelName = 'VXUser'; this.modelAttrName = 'vXUsers'; this.bindErrorEvents(); + this._changes = { }; + this.on('change', this._onChange); }, + _onChange : function(m){ + this._changes[m.id] = m; + }, + + changed_models: function() { + return _.chain(this._changes).values(); + }, /************************* * Non - CRUD operations @@ -58,7 +67,19 @@ define(function(require){ }, options); return this.constructor.nonCrudOperation.call(this, url, 'GET', options); - } + }, + + setUsersVisibility : function(postData , options){ + var url = XAGlobals.baseURL + 'xusers/secure/users/visibility'; + + options = _.extend({ + data : JSON.stringify(postData), + contentType : 'application/json', + dataType : 'json' + }, options); + + return this.constructor.nonCrudOperation.call(this, url, 'PUT', options); + }, },{ /** * Table Cols to be passed to Backgrid http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/webapp/scripts/models/VXGroup.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/models/VXGroup.js b/security-admin/src/main/webapp/scripts/models/VXGroup.js index 1a97741..fdad8aa 100644 --- a/security-admin/src/main/webapp/scripts/models/VXGroup.js +++ b/security-admin/src/main/webapp/scripts/models/VXGroup.js @@ -23,6 +23,7 @@ define(function(require){ var VXGroupBase = require('model_bases/VXGroupBase'); var localization = require('utils/XALangSupport'); + var XAEnums = require('utils/XAEnums'); var VXGroup = VXGroupBase.extend( /** @lends VXGroup.prototype */ @@ -35,7 +36,19 @@ define(function(require){ initialize: function() { this.modelName = 'VXGroup'; this.bindErrorEvents(); - + this.toView(); + }, + + toView : function(){ + if(!_.isUndefined(this.get('isVisible'))){ + var visible = (this.get('isVisible') == XAEnums.VisibilityStatus.STATUS_VISIBLE.value); + this.set('isVisible', visible); + } + }, + + toServer : function(){ + var visible = this.get('isVisible') ? XAEnums.VisibilityStatus.STATUS_VISIBLE.value : XAEnums.VisibilityStatus.STATUS_HIDDEN.value; + this.set('isVisible', visible); }, /** * @function schema http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/webapp/scripts/models/VXUser.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/models/VXUser.js b/security-admin/src/main/webapp/scripts/models/VXUser.js index 9961032..b74ed5a 100644 --- a/security-admin/src/main/webapp/scripts/models/VXUser.js +++ b/security-admin/src/main/webapp/scripts/models/VXUser.js @@ -22,6 +22,7 @@ define(function(require){ 'use strict'; var VXUserBase = require('model_bases/VXUserBase'); + var XAEnums = require('utils/XAEnums'); var VXUser = VXUserBase.extend( /** @lends VXUser.prototype */ @@ -34,6 +35,19 @@ define(function(require){ initialize: function() { this.modelName = 'VXUser'; this.bindErrorEvents(); + this.toView(); + }, + + toView : function(){ + if(!_.isUndefined(this.get('isVisible'))){ + var visible = (this.get('isVisible') == XAEnums.VisibilityStatus.STATUS_VISIBLE.value); + this.set('isVisible', visible); + } + }, + + toServer : function(){ + var visible = this.get('isVisible') ? XAEnums.VisibilityStatus.STATUS_VISIBLE.value : XAEnums.VisibilityStatus.STATUS_HIDDEN.value; + this.set('isVisible', visible); }, /** This models toString() */ http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/webapp/scripts/modules/XAOverrides.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/modules/XAOverrides.js b/security-admin/src/main/webapp/scripts/modules/XAOverrides.js index df728a3..a351063 100644 --- a/security-admin/src/main/webapp/scripts/modules/XAOverrides.js +++ b/security-admin/src/main/webapp/scripts/modules/XAOverrides.js @@ -651,4 +651,267 @@ */ (function(e){function t(t,n,r){var i=n.data("dF").dirtyFieldsDataProperty;var s=e.inArray(t,i);if(r=="dirty"&&s==-1){i.push(t);n.data("dF").dirtyFieldsDataProperty=i}else if(r=="clean"&&s>-1){i.splice(s,1);n.data("dF").dirtyFieldsDataProperty=i}}function n(t){if(t.data("dF").dirtyFieldsDataProperty.length>0){t.addClass(t.data("dF").dirtyFormClass);if(e.isFunction(t.data("dF").formChangeCallback)){t.data("dF").formChangeCallback.call(t,true,t.data("dF").dirtyFieldsDataProperty)}}else{t.removeClass(t.data("dF").dirtyFormClass);if(e.isFunction(t.data("dF").formChangeCallback)){t.data("dF").formChangeCallback.call(t,false,t.data("dF").dirtyFieldsDataProperty)}}}function r(t,n,r,i){if(i.data("dF").denoteDirtyFields){var s=i.data("dF").fieldOverrides;var o=n.attr("id");var u=false;for(var a in s){if(o==a){if(r=="changed"){e("#"+s[a]).addClass(i.data("dF").dirtyFieldClass)}else{e("#"+s[a]).removeClass(i.data("dF").dirtyFieldClass)}u=true}}if(u==false){var f=i.data("dF")[t];var l=f.split( "-");switch(l[0]){case"next":if(r=="changed"){n.next(l[1]).addClass(i.data("dF").dirtyFieldClass)}else{n.next(l[1]).removeClass(i.data("dF").dirtyFieldClass)}break;case"previous":if(r=="changed"){n.prev(l[1]).addClass(i.data("dF").dirtyFieldClass)}else{n.prev(l[1]).removeClass(i.data("dF").dirtyFieldClass)}break;case"closest":if(r=="changed"){n.closest(l[1]).addClass(i.data("dF").dirtyFieldClass)}else{n.closest(l[1]).removeClass(i.data("dF").dirtyFieldClass)}break;case"self":if(r=="changed"){n.addClass(i.data("dF").dirtyFieldClass)}else{n.removeClass(i.data("dF").dirtyFieldClass)}break;default:if(l[0]=="id"||l[0]=="name"){switch(l[1]){case"class":if(r=="changed"){e("."+n.attr(l[0]),i).addClass(i.data("dF").dirtyFieldClass)}else{e("."+n.attr(l[0]),i).removeClass(i.data("dF").dirtyFieldClass)}break;case"title":if(r=="changed"){e("*[title='"+n.attr(l[0])+"']",i).addClass(i.data("dF").dirtyFieldClass)}else{e("*[title='"+n.attr(l[0])+"']",i).removeClass(i.data("dF").dirtyFieldClass)}brea k;case"for":if(r=="changed"){e("label[for='"+n.attr(l[0])+"']",i).addClass(i.data("dF").dirtyFieldClass)}else{e("label[for='"+n.attr(l[0])+"']",i).removeClass(i.data("dF").dirtyFieldClass)}break}}break}}}}function i(i,s){var o=i.attr("name");var u=false;if(s.data("dF").trimText){var a=jQuery.trim(i.val())}else{var a=i.val()}if(i.hasClass(s.data("dF").ignoreCaseClass)){var a=a.toUpperCase();var f=i.data(s.data("dF").startingValueDataProperty).toUpperCase()}else{var f=i.data(s.data("dF").startingValueDataProperty)}if(a!=f){r("textboxContext",i,"changed",s);t(o,s,"dirty");u=true}else{r("textboxContext",i,"unchanged",s);t(o,s,"clean")}if(e.isFunction(s.data("dF").fieldChangeCallback)){s.data("dF").fieldChangeCallback.call(i,i.data(s.data("dF").startingValueDataProperty),u)}if(s.data("dF").denoteDirtyForm){n(s)}}function s(i,s){var o=i.attr("name");var u=false;if(s.data("dF").denoteDirtyOptions==false&&i.attr("multiple")!=true){if(i.hasClass(s.data("dF").ignoreCaseClass)){var a=i.val().t oUpperCase();var f=i.data(s.data("dF").startingValueDataProperty).toUpperCase()}else{var a=i.val();var f=i.data(s.data("dF").startingValueDataProperty)}if(a!=f){r("selectContext",i,"changed",s);t(o,s,"dirty");u=true}else{r("selectContext",i,"unchanged",s);t(o,s,"clean")}}else{var l=false;i.children("option").each(function(t){var n=e(this);var r=n.is(":selected");if(r!=n.data(s.data("dF").startingValueDataProperty)){if(s.data("dF").denoteDirtyOptions){n.addClass(s.data("dF").dirtyOptionClass)}l=true}else{if(s.data("dF").denoteDirtyOptions){n.removeClass(s.data("dF").dirtyOptionClass)}}});if(l){r("selectContext",i,"changed",s);t(o,s,"dirty");u=true}else{r("selectContext",i,"unchanged",s);t(o,s,"clean")}}if(e.isFunction(s.data("dF").fieldChangeCallback)){s.data("dF").fieldChangeCallback.call(i,i.data(s.data("dF").startingValueDataProperty),u)}if(s.data("dF").denoteDirtyForm){n(s)}}function o(i,s){var o=i.attr("name");var u=false;var a=i.attr("type");e(":"+a+"[name='"+o+"']",s).each(fun ction(t){var n=e(this);var i=n.is(":checked");if(i!=n.data(s.data("dF").startingValueDataProperty)){r("checkboxRadioContext",n,"changed",s);u=true}else{r("checkboxRadioContext",n,"unchanged",s)}});if(u){t(o,s,"dirty")}else{t(o,s,"clean")}if(e.isFunction(s.data("dF").fieldChangeCallback)){s.data("dF").fieldChangeCallback.call(i,i.data(s.data("dF").startingValueDataProperty),u)}if(s.data("dF").denoteDirtyForm){n(s)}}e.fn.dirtyFields=function(t){var n=e.extend({},e.fn.dirtyFields.defaults,t);return this.each(function(){var t=e(this);t.data("dF",n);t.data("dF").dirtyFieldsDataProperty=new Array;e("input[type='text'],input[type='file'],input[type='password'],textarea",t).not("."+t.data("dF").exclusionClass).each(function(n){e.fn.dirtyFields.configureField(e(this),t,"text")});e("select",t).not("."+t.data("dF").exclusionClass).each(function(n){e.fn.dirtyFields.configureField(e(this),t,"select")});e(":checkbox,:radio",t).not("."+t.data("dF").exclusionClass).each(function(n){e.fn.dirtyFields .configureField(e(this),t,"checkRadio")});e.fn.dirtyFields.setStartingValues(t)})};e.fn.dirtyFields.defaults={checkboxRadioContext:"next-span",denoteDirtyOptions:false,denoteDirtyFields:true,denoteDirtyForm:false,dirtyFieldClass:"dirtyField",dirtyFieldsDataProperty:"dirtyFields",dirtyFormClass:"dirtyForm",dirtyOptionClass:"dirtyOption",exclusionClass:"dirtyExclude",fieldChangeCallback:"",fieldOverrides:{none:"none"},formChangeCallback:"",ignoreCaseClass:"dirtyIgnoreCase",preFieldChangeCallback:"",selectContext:"id-for",startingValueDataProperty:"startingValue",textboxContext:"id-for",trimText:false};e.fn.dirtyFields.configureField=function(t,n,r,u){if(!t.hasClass(n.data("dF").exclusionClass)){if(typeof u!="undefined"){n.data("dF").fieldOverrides[t.attr("id")]=u}switch(r){case"text":t.change(function(){if(e.isFunction(n.data("dF").preFieldChangeCallback)){if(n.data("dF").preFieldChangeCallback.call(t,t.data(n.data("dF").startingValueDataProperty))==false){return false}}i(t,n)});break ;case"select":t.change(function(){if(e.isFunction(n.data("dF").preFieldChangeCallback)){if(n.data("dF").preFieldChangeCallback.call(t,t.data(n.data("dF").startingValueDataProperty))==false){return false}}s(t,n)});break;case"checkRadio":t.change(function(){if(e.isFunction(n.data("dF").preFieldChangeCallback)){if(n.data("dF").preFieldChangeCallback.call(t,t.data(n.data("dF").startingValueDataProperty))==false){return false}}o(t,n)});break}}};e.fn.dirtyFields.formSaved=function(t){e.fn.dirtyFields.setStartingValues(t);e.fn.dirtyFields.markContainerFieldsClean(t)};e.fn.dirtyFields.markContainerFieldsClean=function(t){var n=new Array;t.data("dF").dirtyFieldsDataProperty=n;e("."+t.data("dF").dirtyFieldClass,t).removeClass(t.data("dF").dirtyFieldClass);if(t.data("dF").denoteDirtyOptions){e("."+t.data("dF").dirtyOptionClass,t).removeClass(t.data("dF").dirtyOptionClass)}if(t.data("dF").denoteDirtyForm){t.removeClass(t.data("dF").dirtyFormClass)}};e.fn.dirtyFields.setStartingValues=function(t ,n){e("input[type='text'],input[type='file'],input[type='password'],:checkbox,:radio,textarea",t).not("."+t.data("dF").exclusionClass).each(function(n){var r=e(this);if(r.attr("type")=="radio"||r.attr("type")=="checkbox"){e.fn.dirtyFields.setStartingCheckboxRadioValue(r,t)}else{e.fn.dirtyFields.setStartingTextValue(r,t)}});e("select",t).not("."+t.data("dF").exclusionClass).each(function(n){e.fn.dirtyFields.setStartingSelectValue(e(this),t)})};e.fn.dirtyFields.setStartingTextValue=function(t,n){return t.not("."+n.data("dF").exclusionClass).each(function(){var t=e(this);t.data(n.data("dF").startingValueDataProperty,t.val())})};e.fn.dirtyFields.setStartingCheckboxRadioValue=function(t,n){return t.not("."+n.data("dF").exclusionClass).each(function(){var t=e(this);var r;if(t.is(":checked")){t.data(n.data("dF").startingValueDataProperty,true)}else{t.data(n.data("dF").startingValueDataProperty,false)}})};e.fn.dirtyFields.setStartingSelectValue=function(t,n){return t.not("."+n.data("dF").ex clusionClass).each(function(){var t=e(this);if(n.data("dF").denoteDirtyOptions==false&&t.attr("multiple")!=true){t.data(n.data("dF").startingValueDataProperty,t.val())}else{var r=new Array;t.children("option").each(function(t){var i=e(this);if(i.is(":selected")){i.data(n.data("dF").startingValueDataProperty,true);r.push(i.val())}else{i.data(n.data("dF").startingValueDataProperty,false)}});t.data(n.data("dF").startingValueDataProperty,r)}})};e.fn.dirtyFields.rollbackTextValue=function(t,n,r){if(typeof r=="undefined"){r=true}return t.not("."+n.data("dF").exclusionClass).each(function(){var t=e(this);t.val(t.data(n.data("dF").startingValueDataProperty));if(r){i(t,n)}})};e.fn.dirtyFields.updateTextState=function(t,n){return t.not("."+n.data("dF").exclusionClass).each(function(){i(e(this),n)})};e.fn.dirtyFields.rollbackCheckboxRadioState=function(t,n,r){if(typeof r=="undefined"){r=true}return t.not("."+n.data("dF").exclusionClass).each(function(){var t=e(this);if(t.data(n.data("dF").star tingValueDataProperty)){t.attr("checked",true)}else{t.attr("checked",false)}if(r){o(t,n)}})};e.fn.dirtyFields.updateCheckboxRadioState=function(t,n){return t.not("."+n.data("dF").exclusionClass).each(function(){o(e(this),n)})};e.fn.dirtyFields.rollbackSelectState=function(t,n,r){if(typeof r=="undefined"){r=true}return t.not("."+n.data("dF").exclusionClass).each(function(){var t=e(this);if(n.data("dF").denoteDirtyOptions==false&&t.attr("multiple")!=true){t.val(t.data(n.data("dF").startingValueDataProperty))}else{t.children("option").each(function(t){var r=e(this);if(r.data(n.data("dF").startingValueDataProperty)){r.attr("selected",true)}else{r.attr("selected",false)}})}if(r){s(t,n)}})};e.fn.dirtyFields.updateSelectState=function(t,n){return t.not("."+n.data("dF").exclusionClass).each(function(){s(e(this),n)})};e.fn.dirtyFields.rollbackForm=function(t){e("input[type='text'],input[type='file'],input[type='password'],:checkbox,:radio,textarea",t).not("."+t.data("dF").exclusionClass).eac h(function(n){$object=e(this);if($object.attr("type")=="radio"||$object.attr("type")=="checkbox"){e.fn.dirtyFields.rollbackCheckboxRadioState($object,t,false)}else{e.fn.dirtyFields.rollbackTextValue($object,t,false)}});e("select",t).not("."+t.data("dF").exclusionClass).each(function(n){e.fn.dirtyFields.rollbackSelectState(e(this),t,false)});e.fn.dirtyFields.markContainerFieldsClean(t)};e.fn.dirtyFields.updateFormState=function(t){e("input[type='text'],input[type='file'],input[type='password'],:checkbox,:radio,textarea",t).not("."+t.data("dF").exclusionClass).each(function(n){$object=e(this);if($object.attr("type")=="radio"||$object.attr("type")=="checkbox"){e.fn.dirtyFields.updateCheckboxRadioState($object,t)}else{e.fn.dirtyFields.updateTextState($object,t)}});e("select",t).not("."+t.data("dF").exclusionClass).each(function(n){$object=e(this);e.fn.dirtyFields.updateSelectState($object,t)})};e.fn.dirtyFields.getDirtyFieldNames=function(e){return e.data("dF").dirtyFieldsDataProperty}; })(jQuery) + + var SelectRowCell = Backgrid.Extension.SelectRowCell = Backbone.View.extend({ + + /** @property */ + className: "select-row-cell", + + /** @property */ + tagName: "td", + + /** @property */ + events: { + "keydown input[type=checkbox]": "onKeydown", + "change input[type=checkbox]": "onChange", + "click input[type=checkbox]": "enterEditMode" + }, + + /** + Initializer. If the underlying model triggers a `select` event, this cell + will change its checked value according to the event's `selected` value. + @param {Object} options + @param {Backgrid.Column} options.column + @param {Backbone.Model} options.model + */ + initialize: function (options) { + + this.column = options.column; + if (!(this.column instanceof Backgrid.Column)) { + this.column = new Backgrid.Column(this.column); + } + + var column = this.column, model = this.model, $el = this.$el; + this.listenTo(column, "change:renderable", function (column, renderable) { + $el.toggleClass("renderable", renderable); + }); + + if (Backgrid.callByNeed(column.renderable(), column, model)) $el.addClass("renderable"); + + this.listenTo(model, "backgrid:select", function (model, selected) { + this.checkbox().prop("checked", selected).change(); + }); + }, + + /** + Returns the checkbox. + */ + checkbox: function () { + return this.$el.find("input[type=checkbox]"); + }, + + /** + Focuses the checkbox. + */ + enterEditMode: function () { + this.checkbox().focus(); + }, + + /** + Unfocuses the checkbox. + */ + exitEditMode: function () { + this.checkbox().blur(); + }, + + /** + Process keyboard navigation. + */ + onKeydown: function (e) { + var command = new Backgrid.Command(e); + if (command.passThru()) return true; // skip ahead to `change` + if (command.cancel()) { + e.stopPropagation(); + this.checkbox().blur(); + } + else if (command.save() || command.moveLeft() || command.moveRight() || + command.moveUp() || command.moveDown()) { + e.preventDefault(); + e.stopPropagation(); + this.model.trigger("backgrid:edited", this.model, this.column, command); + } + }, + + /** + When the checkbox's value changes, this method will trigger a Backbone + `backgrid:selected` event with a reference of the model and the + checkbox's `checked` value. + */ + onChange: function () { + var checked = this.checkbox().prop("checked"); + this.$el.parent().toggleClass("selected", checked); + this.model.set('isVisible', checked) + this.model.trigger("backgrid:selected", this.model, checked); + }, + + /** + Renders a checkbox in a table cell. + */ + render: function () { + var val; + if(_.has(this, 'model')) + val = (this.model.get(this.column.get('name'))) ? 'checked' : ''; + this.$el.empty().append('<input tabindex="-1" type="checkbox" '+ val +'/>'); + this.delegateEvents(); + return this; + } + + }); + + /** + Renders a checkbox to select all rows on the current page. + @class Backgrid.Extension.SelectAllHeaderCell + @extends Backgrid.Extension.SelectRowCell + */ + var SelectAllHeaderCell = Backgrid.Extension.SelectAllHeaderCell = SelectRowCell.extend({ + + /** @property */ + className: "select-all-header-cell", + + /** @property */ + tagName: "th", + + /** + Initializer. When this cell's checkbox is checked, a Backbone + `backgrid:select` event will be triggered for each model for the current + page in the underlying collection. If a `SelectRowCell` instance exists + for the rows representing the models, they will check themselves. If any + of the SelectRowCell instances trigger a Backbone `backgrid:selected` + event with a `false` value, this cell will uncheck its checkbox. In the + event of a Backbone `backgrid:refresh` event, which is triggered when the + body refreshes its rows, which can happen under a number of conditions + such as paging or the columns were reset, this cell will still remember + the previously selected models and trigger a Backbone `backgrid:select` + event on them such that the SelectRowCells can recheck themselves upon + refreshing. + @param {Object} options + @param {Backgrid.Column} options.column + @param {Backbone.Collection} options.collection + */ + initialize: function (options) { + + this.column = options.column; + if (!(this.column instanceof Backgrid.Column)) { + this.column = new Backgrid.Column(this.column); + } + + var collection = this.collection; + var selectedModels = this.selectedModels = {}; + this.listenTo(collection.fullCollection || collection, + "backgrid:selected", function (model, selected) { + if (selected) selectedModels[model.id || model.cid] = 1; + else { + delete selectedModels[model.id || model.cid]; + this.checkbox().prop("checked", false); + } + if (_.keys(selectedModels).length === (collection.fullCollection|| collection).length) { + this.checkbox().prop("checked", true); + } + }); + + this.listenTo(collection.fullCollection || collection, "remove", function (model) { + delete selectedModels[model.id || model.cid]; + if ((collection.fullCollection || collection).length === 0) { + this.checkbox().prop("checked", false); + } + }); + + this.listenTo(collection, "backgrid:refresh", function () { + if ((collection.fullCollection || collection).length === 0) { + this.checkbox().prop("checked", false); + } + else { + var checked = this.checkbox().prop("checked"); + for (var i = 0; i < collection.length; i++) { + var model = collection.at(i); + if (checked || selectedModels[model.id || model.cid]) { + model.trigger("backgrid:select", model, true); + } + } + } + }); + + var column = this.column, $el = this.$el; + this.listenTo(column, "change:renderable", function (column, renderable) { + $el.toggleClass("renderable", renderable); + }); + + if (Backgrid.callByNeed(column.renderable(), column, collection)) $el.addClass("renderable"); + }, + + /** + Propagates the checked value of this checkbox to all the models of the + underlying collection by triggering a Backbone `backgrid:select` event on + the models on the current page, passing each model and the current + `checked` value of the checkbox in each event. + A `backgrid:selected` event will also be triggered with the current + `checked` value on all the models regardless of whether they are on the + current page. + This method triggers a 'backgrid:select-all' event on the collection + afterwards. + */ + onChange: function () { + var checked = this.checkbox().prop("checked"); + + var collection = this.collection; + collection.each(function (model) { + model.trigger("backgrid:select", model, checked); + }); + + if (collection.fullCollection) { + collection.fullCollection.each(function (model) { + if (!collection.get(model.cid)) { + model.trigger("backgrid:selected", model, checked); + } + }); + } + + this.collection.trigger("backgrid:select-all", this.collection, checked); + } + + }); + + /** + Convenient method to retrieve a list of selected models. This method only + exists when the `SelectAll` extension has been included. Selected models + are retained across pagination. + @member Backgrid.Grid + @return {Array.<Backbone.Model>} + */ + Backgrid.Grid.prototype.getSelectedModels = function () { + var selectAllHeaderCell; + var headerCells = this.header.row.cells; + for (var i = 0, l = headerCells.length; i < l; i++) { + var headerCell = headerCells[i]; + if (headerCell instanceof SelectAllHeaderCell) { + selectAllHeaderCell = headerCell; + break; + } + } + + var result = []; + if (selectAllHeaderCell) { + var selectedModels = selectAllHeaderCell.selectedModels; + var collection = this.collection.fullCollection || this.collection; + for (var modelId in selectedModels) { + result.push(collection.get(modelId)); + } + } + + return result; + }; + + /** + Convenient method to deselect the selected models. This method is only + available when the `SelectAll` extension has been included. + @member Backgrid.Grid + */ + Backgrid.Grid.prototype.clearSelectedModels = function () { + var selectedModels = this.getSelectedModels(); + for (var i = 0, l = selectedModels.length; i < l; i++) { + var model = selectedModels[i]; + model.trigger("backgrid:select", model, false); + } + }; + }); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/webapp/scripts/modules/globalize/message/en.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/modules/globalize/message/en.js b/security-admin/src/main/webapp/scripts/modules/globalize/message/en.js index 6320028..1c7d803 100644 --- a/security-admin/src/main/webapp/scripts/modules/globalize/message/en.js +++ b/security-admin/src/main/webapp/scripts/modules/globalize/message/en.js @@ -142,6 +142,8 @@ define(function(require) { accountStatus : 'Account Status', ActiveStatus_STATUS_ENABLED : 'Enabled', ActiveStatus_STATUS_DISABLED : 'Disabled', + VisibilityStatus_IS_VISIBLE : 'Visible', + VisibilityStatus_IS_HIDDEN : 'Hidden', commonNameForCertificate : 'Common Name For Certificate', status : 'Status', userListing : 'User List', @@ -206,6 +208,7 @@ define(function(require) { topologyName : 'Topology Name', serivceName : 'Service Name', ipAddress : 'IP Address', + isVisible : 'Visible', delegatedAdmin : 'Delegate Admin', policyId : 'Policy ID' }, @@ -213,8 +216,8 @@ define(function(require) { add : 'Add', save : 'Save', cancel : 'Cancel', - addMore : 'Add More..' - + addMore : 'Add More..', + setVisibility : 'Set Visibility' }, // h1, h2, h3, fieldset, title @@ -301,7 +304,8 @@ define(function(require) { preventNavPolicyForm : 'Policy form edit is in progress. Please save/cancel changes before navigating away!', preventNavRepositoryForm : 'Repository form edit is in progress. Please save/cancel changes before navigating away!', preventNavUserForm : 'User form edit is in progress. Please save/cancel changes before navigating away!', - preventNavGroupForm : 'Group form edit is in progress. Please save/cancel changes before navigating away!' + preventNavGroupForm : 'Group form edit is in progress. Please save/cancel changes before navigating away!', + preventNavUserList : 'Some Users/Groups have been edited. Kindly save your changes before navigating away!' }, validationMessages : { http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/webapp/scripts/utils/XAEnums.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/utils/XAEnums.js b/security-admin/src/main/webapp/scripts/utils/XAEnums.js index 1a28c11..ce842f7 100644 --- a/security-admin/src/main/webapp/scripts/utils/XAEnums.js +++ b/security-admin/src/main/webapp/scripts/utils/XAEnums.js @@ -73,6 +73,11 @@ define(function(require) { ACT_STATUS_NO_LOGIN:{value:7, label:'No login privilege', rbkey:'xa.enum.ActivationStatus.ACT_STATUS_NO_LOGIN', tt: 'lbl.ActivationStatus_ACT_STATUS_NO_LOGIN'} }); + XAEnums.VisibilityStatus = mergeParams(XAEnums.VisibilityStatus, { + STATUS_HIDDEN:{value:0, label:'Hidden', rbkey:'xa.enum.VisibilityStatus.IS_HIDDEN', tt: 'lbl.VisibilityStatus_IS_HIDDEN'}, + STATUS_VISIBLE:{value:1, label:'Visible', rbkey:'xa.enum.VisibilityStatus.IS_VISIBLE', tt: 'lbl.VisibilityStatus_IS_VISIBLE'} + }); + XAEnums.ActiveStatus = mergeParams(XAEnums.ActiveStatus, { STATUS_DISABLED:{value:0, label:'Disabled', rbkey:'xa.enum.ActiveStatus.STATUS_DISABLED', tt: 'lbl.ActiveStatus_STATUS_DISABLED'}, STATUS_ENABLED:{value:1, label:'Enabled', rbkey:'xa.enum.ActiveStatus.STATUS_ENABLED', tt: 'lbl.ActiveStatus_STATUS_ENABLED'}, http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/webapp/scripts/utils/XAUtils.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/utils/XAUtils.js b/security-admin/src/main/webapp/scripts/utils/XAUtils.js index 2f3b3d7..fd39935 100644 --- a/security-admin/src/main/webapp/scripts/utils/XAUtils.js +++ b/security-admin/src/main/webapp/scripts/utils/XAUtils.js @@ -525,6 +525,7 @@ define(function(require) { var callbackCommon = { search : function(query, searchCollection) { + collection.VSQuery = query; search(searchCollection, serverAttrName, searchOpt,collection); }, facetMatches : function(callback) { http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/webapp/scripts/views/common/FormInputItemList.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/views/common/FormInputItemList.js b/security-admin/src/main/webapp/scripts/views/common/FormInputItemList.js index fdc6ec2..ca1ebc4 100644 --- a/security-admin/src/main/webapp/scripts/views/common/FormInputItemList.js +++ b/security-admin/src/main/webapp/scripts/views/common/FormInputItemList.js @@ -172,7 +172,7 @@ define(function(require) { url: "service/xusers/groups", dataType: 'json', data: function (term, page) { - return {name : term}; + return {name : term, isVisible : XAEnums.VisibilityStatus.STATUS_VISIBLE.value}; }, results: function (data, page) { var results = [] , selectedVals = []; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/webapp/scripts/views/common/UserPermissionList.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/views/common/UserPermissionList.js b/security-admin/src/main/webapp/scripts/views/common/UserPermissionList.js index b4f93cb..fce1963 100644 --- a/security-admin/src/main/webapp/scripts/views/common/UserPermissionList.js +++ b/security-admin/src/main/webapp/scripts/views/common/UserPermissionList.js @@ -229,7 +229,7 @@ define(function(require) { url: "service/xusers/users", dataType: 'json', data: function (term, page) { - return {name : term}; + return {name : term, isVisible : XAEnums.VisibilityStatus.STATUS_VISIBLE.value}; }, results: function (data, page) { var results = [],selectedVals=[]; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/webapp/scripts/views/common/XATableLayout.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/views/common/XATableLayout.js b/security-admin/src/main/webapp/scripts/views/common/XATableLayout.js index 35f4b4e..5556559 100644 --- a/security-admin/src/main/webapp/scripts/views/common/XATableLayout.js +++ b/security-admin/src/main/webapp/scripts/views/common/XATableLayout.js @@ -145,6 +145,13 @@ define(function(require){ initializePlugins: function(){ }, + getGridObj : function(){ + if (this.rTableList.currentView){ + return this.rTableList.currentView; + } + return null; + }, + renderTable : function(){ var that = this; this.rTableList.show(new Backgrid.Grid(this.gridOpts)); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/webapp/scripts/views/policies/PermissionList.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/views/policies/PermissionList.js b/security-admin/src/main/webapp/scripts/views/policies/PermissionList.js index fc57134..b938c66 100644 --- a/security-admin/src/main/webapp/scripts/views/policies/PermissionList.js +++ b/security-admin/src/main/webapp/scripts/views/policies/PermissionList.js @@ -198,7 +198,7 @@ define(function(require) { url: url, dataType: 'json', data: function (term, page) { - return {name : term}; + return {name : term, isVisible : XAEnums.VisibilityStatus.STATUS_VISIBLE.value}; }, results: function (data, page) { var results = [] , selectedVals = []; @@ -517,4 +517,4 @@ define(function(require) { }, }); -}); \ No newline at end of file +}); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/webapp/scripts/views/policies/RangerPolicyForm.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/views/policies/RangerPolicyForm.js b/security-admin/src/main/webapp/scripts/views/policies/RangerPolicyForm.js index 988f57c..bcbb3e0 100644 --- a/security-admin/src/main/webapp/scripts/views/policies/RangerPolicyForm.js +++ b/security-admin/src/main/webapp/scripts/views/policies/RangerPolicyForm.js @@ -151,7 +151,7 @@ define(function(require){ var that = this; var accessType = this.rangerServiceDefModel.get('accessTypes').filter(function(val) { return val !== null; }); this.userList = new VXUserList(); - var params = {sortBy : 'name'}; + var params = {sortBy : 'name', isVisible : XAEnums.VisibilityStatus.STATUS_VISIBLE.value}; this.userList.setPageSize(100,{fetch:false}); this.userList.fetch({ cache :true, http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/webapp/scripts/views/users/UserTableLayout.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/views/users/UserTableLayout.js b/security-admin/src/main/webapp/scripts/views/users/UserTableLayout.js index e1f8e70..161a09a 100644 --- a/security-admin/src/main/webapp/scripts/views/users/UserTableLayout.js +++ b/security-admin/src/main/webapp/scripts/views/users/UserTableLayout.js @@ -57,6 +57,7 @@ define(function(require){ visualSearch: '.visual_search', btnShowMore : '[data-id="showMore"]', btnShowLess : '[data-id="showLess"]', + btnSave : '[data-id="save"]' }, /** ui events hash */ @@ -65,6 +66,7 @@ define(function(require){ events['click '+this.ui.tab+' li a'] = 'onTabChange'; events['click ' + this.ui.btnShowMore] = 'onShowMore'; events['click ' + this.ui.btnShowLess] = 'onShowLess'; + events['click ' + this.ui.btnSave] = 'onSave'; return events; }, @@ -77,13 +79,30 @@ define(function(require){ _.extend(this, _.pick(options, 'groupList','tab')); this.showUsers = this.tab == 'usertab' ? true : false; + + this.chgFlags = []; + this.showUsers = true; + + if(_.isUndefined(this.groupList)){ + this.groupList = new VXGroupList(); + } + this.bindEvents(); }, /** all events binding here */ bindEvents : function(){ + var that = this; + this.listenTo(this.collection,"backgrid:selected", this.onModelChange); + this.listenTo(this.groupList,"backgrid:selected", this.onModelChange); /*this.listenTo(this.model, "change:foo", this.modelChanged, this);*/ /*this.listenTo(communicator.vent,'someView:someEvent', this.someEventHandler, this)'*/ + this.collection.on('change', function(){ + that.preventNavigation(); + }); + this.groupList.on('change', function(){ + that.preventNavigation(); + }); }, /** on render callback */ @@ -95,18 +114,85 @@ define(function(require){ this.renderUserTab(); this.addVisualSearch(); }, + + preventNavigation : function(){ + XAUtil.preventNavigation(localization.tt('dialogMsg.preventNavUserList'),this.rTableList.$el); + this.rTableList.$el.find('table').addClass('dirtyField'); + //this.ui.btnSave.removeClass('disabled'); + }, + + allowNavigation : function(){ + XAUtil.allowNavigation(); + this.rTableList.$el.find('table').removeClass('dirtyField'); + //this.ui.btnSave.addClass('disabled'); + }, + + onModelChange : function(model, selected){ + /*var that = this; + if(! (model.id in that.chgFlags)){ + that.chgFlags[model.id] = true; + } else { + that.chgFlags[model.id] ^= true; + } + + if (_.some(that.chgFlags)){ + that.preventNavigation(); + } else { + that.allowNavigation(); + }*/ + }, onTabChange : function(e){ + var that = this; + this.chgFlags = []; this.showUsers = $(e.currentTarget).attr('href') == '#users' ? true : false; - if(this.showUsers){ + if(this.showUsers){ this.renderUserTab(); this.addVisualSearch(); } - else{ + else{ this.renderGroupTab(); this.addVisualSearch(); } $(this.rUserDetail.el).hide(); }, + onSave : function(e){ + var that = this; + var updateReq = {}; + var collection = this.showUsers ? this.collection : this.groupList; + + collection.changed_models().each(function(m){ + m.toServer(); + updateReq[m.get('id')] = m.get('isVisible'); + }); + + var clearCache = function(coll){ + _.each(Backbone.fetchCache._cache, function(url, val){ + var urlStr = coll.url; + if((val.indexOf(urlStr) != -1)){ + Backbone.fetchCache.clearItem(val); + } + }); + coll.fetch({reset: true, cache : false}); + } + if(this.showUsers){ + collection.setUsersVisibility(updateReq, { + success : function(){ + that.chgFlags = []; + that.allowNavigation(); + clearCache(collection); + } + }); + } else { + collection.setGroupsVisibility(updateReq, { + success : function(){ + that.chgFlags = []; + that.allowNavigation(); + clearCache(collection); + } + }); + } + + }, renderUserTab : function(){ var that = this; if(_.isUndefined(this.collection)){ @@ -141,10 +227,26 @@ define(function(require){ }, renderUserListTable : function(){ var that = this; - /*var tableRow = Backgrid.Row.extend({ + var tableRow = Backgrid.Row.extend({ + + render: function () { + tableRow.__super__.render.apply(this, arguments); + if (this.model.get("isVisible") == 0) { + this.el.classList.add("tr-inactive"); + } + return this; + }, events: { - 'click' : 'onClick' + 'change' : 'onClickCheckbox' + }, + onClickCheckbox: function(e) { + if (this.model.get("isVisible") == 0) { + this.el.classList.add("tr-inactive"); + } else { + this.el.classList.remove("tr-inactive"); + }; }, + /* initialize : function(){ var that = this; var args = Array.prototype.slice.apply(arguments); @@ -180,14 +282,14 @@ define(function(require){ console.log('error..'); } }); - } - });*/ + } */ + }); this.rTableList.show(new XATableLayout({ columns: this.getColumns(), collection: this.collection, includeFilter : false, gridOpts : { -// row: tableRow, + row: tableRow, header : XABackgrid, emptyText : 'No Users found!' } @@ -198,6 +300,16 @@ define(function(require){ getColumns : function(){ var cols = { + isVisible : { + label : localization.tt("lbl.isVisible"), + //cell : Backgrid.SelectCell.extend({className: 'cellWidth-1'}), + cell: "select-row", + headerCell: "select-all", + click : false, + drag : false, + editable : false, + sortable : false + }, name : { label : localization.tt("lbl.userName"), href: function(model){ @@ -205,8 +317,7 @@ define(function(require){ }, editable:false, sortable:false, - cell :'uri' - + cell :'uri' }, emailAddress : { label : localization.tt("lbl.emailAddress"), @@ -364,6 +475,16 @@ define(function(require){ getGroupColumns : function(){ var cols = { + isVisible : { + label : localization.tt("lbl.isVisible"), + //cell : Backgrid.SelectCell.extend({className: 'cellWidth-1'}), + cell: "select-row", + headerCell: "select-all", + click : false, + drag : false, + editable : false, + sortable : false + }, name : { label : localization.tt("lbl.groupName"), href: function(model){ @@ -392,7 +513,7 @@ define(function(require){ drag : false, editable:false, sortable:false, - } + }, /*status : { label : localization.tt("lbl.status"), cell : Backgrid.HtmlCell.extend({className: 'cellWidth-1'}), @@ -419,10 +540,12 @@ define(function(require){ if(this.showUsers){ placeholder = localization.tt('h.searchForYourUser'); coll = this.collection; - searchOpt = ['User Name','Email Address','Role','User Source'];//,'Start Date','End Date','Today']; + searchOpt = ['User Name','Email Address','Visibility', 'Role','User Source'];//,'Start Date','End Date','Today']; var userRoleList = _.map(XAEnums.UserRoles,function(obj,key){return {label:obj.label,value:key};}); - serverAttrName = [{text : "User Name", label :"name"},{text : "Email Address", label :"emailAddress"}, + serverAttrName = [ {text : "User Name", label :"name"}, + {text : "Email Address", label :"emailAddress"}, {text : "Role", label :"userRoleList", 'multiple' : true, 'optionsArr' : userRoleList}, + {text : "Visibility", label :"isVisible", 'multiple' : true, 'optionsArr' : XAUtil.enumToSelectLabelValuePairs(XAEnums.VisibilityStatus)}, {text : "User Source", label :"userSource", 'multiple' : true, 'optionsArr' : XAUtil.enumToSelectLabelValuePairs(XAEnums.UserTypes)}, ]; // {text : 'Start Date',label :'startDate'},{text : 'End Date',label :'endDate'}, @@ -430,18 +553,20 @@ define(function(require){ }else{ placeholder = localization.tt('h.searchForYourGroup'); coll = this.groupList; - searchOpt = ['Group Name','Group Source'];//,'Start Date','End Date','Today']; + searchOpt = ['Group Name','Group Source', 'Visibility'];//,'Start Date','End Date','Today']; serverAttrName = [{text : "Group Name", label :"name"}, + {text : "Visibility", label :"isVisible", 'multiple' : true, 'optionsArr' : XAUtil.enumToSelectLabelValuePairs(XAEnums.VisibilityStatus)}, {text : "Group Source", label :"groupSource", 'multiple' : true, 'optionsArr' : XAUtil.enumToSelectLabelValuePairs(XAEnums.GroupTypes)},]; //{text : 'Start Date',label :'startDate'},{text : 'End Date',label :'endDate'}, //{text : 'Today',label :'today'}]; } + var query = (!_.isUndefined(coll.VSQuery)) ? coll.VSQuery : ''; var pluginAttr = { placeholder :placeholder, container : this.ui.visualSearch, - query : '', + query : query, callbacks : { valueMatches :function(facet, searchTerm, callback) { switch (facet) { @@ -454,6 +579,9 @@ define(function(require){ case 'Group Source': callback(XAUtil.hackForVSLabelValuePairs(XAEnums.GroupTypes)); break; + case 'Visibility': + callback(XAUtil.hackForVSLabelValuePairs(XAEnums.VisibilityStatus)); + break; /*case 'Start Date' : setTimeout(function () { XAUtil.displayDatepicker(that.ui.visualSearch, callback); }, 0); break; @@ -489,6 +617,7 @@ define(function(require){ /** on close */ onClose: function(){ + XAUtil.allowNavigation(); } }); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/webapp/styles/xa.css ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/styles/xa.css b/security-admin/src/main/webapp/styles/xa.css index 57ce781..5f8e580 100644 --- a/security-admin/src/main/webapp/styles/xa.css +++ b/security-admin/src/main/webapp/styles/xa.css @@ -1763,4 +1763,19 @@ margin-top: -29px; } .margin-left-5{ margin-left:5px; +} +.tr-inactive { + background-color: #F5F5F5; +} +.tr-inactive a { + color: #CCC; +} +.tr-inactive td span.label{ + background-color: #BCBCBC; + color: #fff; + font-weight: normal; + text-shadow: none; +} +td.select-row-cell { + text-align: center; } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/main/webapp/templates/users/UserTableLayout_tmpl.html ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/templates/users/UserTableLayout_tmpl.html b/security-admin/src/main/webapp/templates/users/UserTableLayout_tmpl.html index 421ef53..21006b1 100644 --- a/security-admin/src/main/webapp/templates/users/UserTableLayout_tmpl.html +++ b/security-admin/src/main/webapp/templates/users/UserTableLayout_tmpl.html @@ -45,8 +45,10 @@ <div class="clearfix"> <a href="#!/user/create" class="btn btn-primary btn-right" type="button" data-id="addNewUser"> {{tt 'lbl.addNewUser'}} </a> <a href="#!/group/create" class="btn btn-primary btn-right" type="button" data-id="addNewGroup" style="display:none;"> {{tt 'lbl.addNewGroup'}} </a> + <a href="javascript:void(0)" class="_allowNav btn btn-primary btn-right" type="button" data-id="save" style="display:block;" > {{tt 'btn.setVisibility'}} </a> </div> <div data-id="r_tableList" class="clickable"> + <b class="_prevNav"></b> </div> </div> http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2a309b5c/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java ---------------------------------------------------------------------- diff --git a/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java b/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java index b05ebb4..4ae1d02 100644 --- a/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java +++ b/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java @@ -18,6 +18,7 @@ package org.apache.ranger.biz; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; import org.apache.ranger.common.ContextUtil; @@ -30,6 +31,7 @@ import org.apache.ranger.db.XXGroupDao; import org.apache.ranger.db.XXGroupUserDao; import org.apache.ranger.db.XXUserDao; import org.apache.ranger.entity.XXGroup; +import org.apache.ranger.entity.XXUser; import org.apache.ranger.security.context.RangerContextHolder; import org.apache.ranger.security.context.RangerSecurityContext; import org.apache.ranger.service.XGroupService; @@ -59,7 +61,9 @@ import org.mockito.runners.MockitoJUnitRunner; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestXUserMgr { - private static Long userId = 1L; + private static Long userId = 10L; + + private static Integer emptyValue; @InjectMocks XUserMgr xUserMgr = new XUserMgr(); @@ -166,7 +170,75 @@ public class TestXUserMgr { } @Test - public void test13CreateXGroup() { + public void test13ModifyUserVisibilitySetOne() { + XXUserDao xxUserDao = Mockito.mock(XXUserDao.class); + XXUser xxUser = Mockito.mock(XXUser.class); + VXUser vxUser = vxUser(); + + Mockito.when(xUserService.updateResource(vxUser)).thenReturn(vxUser); + HashMap<Long, Integer> visibilityMap = new HashMap<Long, Integer>(); + Integer value = 1; + visibilityMap.put(userId, value); + + Mockito.when(daoManager.getXXUser()).thenReturn(xxUserDao); + Mockito.when(xxUserDao.getById(userId)).thenReturn(xxUser); + Mockito.when(xUserService.populateViewBean(xxUser)).thenReturn(vxUser); + + xUserMgr.modifyUserVisibility(visibilityMap); + Assert.assertEquals(value, vxUser.getIsVisible()); + Assert.assertEquals(userId, vxUser.getId()); + Mockito.verify(xUserService).updateResource(vxUser); + Mockito.verify(daoManager).getXXUser(); + Mockito.verify(xUserService).populateViewBean(xxUser); + } + + @Test + public void test14ModifyUserVisibilitySetZero() { + XXUserDao xxUserDao = Mockito.mock(XXUserDao.class); + XXUser xxUser = Mockito.mock(XXUser.class); + VXUser vxUser = vxUser(); + + Mockito.when(xUserService.updateResource(vxUser)).thenReturn(vxUser); + HashMap<Long, Integer> visibilityMap = new HashMap<Long, Integer>(); + Integer value = 0; + visibilityMap.put(userId, value); + + Mockito.when(daoManager.getXXUser()).thenReturn(xxUserDao); + Mockito.when(xxUserDao.getById(userId)).thenReturn(xxUser); + Mockito.when(xUserService.populateViewBean(xxUser)).thenReturn(vxUser); + + xUserMgr.modifyUserVisibility(visibilityMap); + Assert.assertEquals(value, vxUser.getIsVisible()); + Assert.assertEquals(userId, vxUser.getId()); + Mockito.verify(xUserService).updateResource(vxUser); + Mockito.verify(daoManager).getXXUser(); + Mockito.verify(xUserService).populateViewBean(xxUser); + } + + @Test + public void test15ModifyUserVisibilitySetEmpty() { + XXUserDao xxUserDao = Mockito.mock(XXUserDao.class); + XXUser xxUser = Mockito.mock(XXUser.class); + VXUser vxUser = vxUser(); + + Mockito.when(xUserService.updateResource(vxUser)).thenReturn(vxUser); + HashMap<Long, Integer> visibilityMap = new HashMap<Long, Integer>(); + visibilityMap.put(userId, emptyValue); + + Mockito.when(daoManager.getXXUser()).thenReturn(xxUserDao); + Mockito.when(xxUserDao.getById(userId)).thenReturn(xxUser); + Mockito.when(xUserService.populateViewBean(xxUser)).thenReturn(vxUser); + + xUserMgr.modifyUserVisibility(visibilityMap); + Assert.assertEquals(emptyValue, vxUser.getIsVisible()); + Assert.assertEquals(userId, vxUser.getId()); + Mockito.verify(xUserService).updateResource(vxUser); + Mockito.verify(daoManager).getXXUser(); + Mockito.verify(xUserService).populateViewBean(xxUser); + } + + @Test + public void test16CreateXGroup() { setup(); VXGroup vXGroup = new VXGroup(); vXGroup.setId(userId); @@ -195,7 +267,7 @@ public class TestXUserMgr { } @Test - public void test14UpdateXGroup() { + public void test17UpdateXGroup() { XXGroupDao xxGroupDao = Mockito.mock(XXGroupDao.class); setup(); VXGroup vXGroup = new VXGroup(); @@ -220,7 +292,84 @@ public class TestXUserMgr { } @Test - public void test15createXGroupUser() { + public void test18ModifyGroupsVisibilitySetOne() { + XXGroupDao xxGroupDao = Mockito.mock(XXGroupDao.class); + VXGroup vXGroup = new VXGroup(); + vXGroup.setId(userId); + vXGroup.setDescription("group test"); + vXGroup.setName("grouptest"); + + XXGroup xxGroup = new XXGroup(); + HashMap<Long, Integer> groupVisibilityMap = new HashMap<Long, Integer>(); + Integer value = 1; + groupVisibilityMap.put(userId, value); + + Mockito.when(daoManager.getXXGroup()).thenReturn(xxGroupDao); + Mockito.when(xxGroupDao.getById(vXGroup.getId())).thenReturn(xxGroup); + Mockito.when(xGroupService.populateViewBean(xxGroup)).thenReturn(vXGroup); + Mockito.when(xGroupService.updateResource(vXGroup)).thenReturn(vXGroup); + + xUserMgr.modifyGroupsVisibility(groupVisibilityMap); + Assert.assertEquals(value, vXGroup.getIsVisible()); + Assert.assertEquals(userId, vXGroup.getId()); + Mockito.verify(daoManager).getXXGroup(); + Mockito.verify(xGroupService).populateViewBean(xxGroup); + Mockito.verify(xGroupService).updateResource(vXGroup); + } + + @Test + public void test19ModifyGroupsVisibilitySetZero() { + XXGroupDao xxGroupDao = Mockito.mock(XXGroupDao.class); + VXGroup vXGroup = new VXGroup(); + vXGroup.setId(userId); + vXGroup.setDescription("group test"); + vXGroup.setName("grouptest"); + + XXGroup xxGroup = new XXGroup(); + HashMap<Long, Integer> groupVisibilityMap = new HashMap<Long, Integer>(); + Integer value = 0; + groupVisibilityMap.put(userId, value); + + Mockito.when(daoManager.getXXGroup()).thenReturn(xxGroupDao); + Mockito.when(xxGroupDao.getById(vXGroup.getId())).thenReturn(xxGroup); + Mockito.when(xGroupService.populateViewBean(xxGroup)).thenReturn(vXGroup); + Mockito.when(xGroupService.updateResource(vXGroup)).thenReturn(vXGroup); + + xUserMgr.modifyGroupsVisibility(groupVisibilityMap); + Assert.assertEquals(value, vXGroup.getIsVisible()); + Assert.assertEquals(userId, vXGroup.getId()); + Mockito.verify(daoManager).getXXGroup(); + Mockito.verify(xGroupService).populateViewBean(xxGroup); + Mockito.verify(xGroupService).updateResource(vXGroup); + } + + @Test + public void test20ModifyGroupsVisibilitySetEmpty() { + XXGroupDao xxGroupDao = Mockito.mock(XXGroupDao.class); + VXGroup vXGroup = new VXGroup(); + vXGroup.setId(userId); + vXGroup.setDescription("group test"); + vXGroup.setName("grouptest"); + + XXGroup xxGroup = new XXGroup(); + HashMap<Long, Integer> groupVisibilityMap = new HashMap<Long, Integer>(); + groupVisibilityMap.put(userId, emptyValue); + + Mockito.when(daoManager.getXXGroup()).thenReturn(xxGroupDao); + Mockito.when(xxGroupDao.getById(vXGroup.getId())).thenReturn(xxGroup); + Mockito.when(xGroupService.populateViewBean(xxGroup)).thenReturn(vXGroup); + Mockito.when(xGroupService.updateResource(vXGroup)).thenReturn(vXGroup); + + xUserMgr.modifyGroupsVisibility(groupVisibilityMap); + Assert.assertEquals(emptyValue, vXGroup.getIsVisible()); + Assert.assertEquals(userId, vXGroup.getId()); + Mockito.verify(daoManager).getXXGroup(); + Mockito.verify(xGroupService).populateViewBean(xxGroup); + Mockito.verify(xGroupService).updateResource(vXGroup); + } + + @Test + public void test21createXGroupUser() { VXGroupUser vxGroupUser = new VXGroupUser(); vxGroupUser.setId(userId); vxGroupUser.setName("group user test"); @@ -263,13 +412,13 @@ public class TestXUserMgr { } @Test - public void test16GetXUserGroups() { + public void test22GetXUserGroups() { VXGroupList dbVXGroupList = xUserMgr.getXUserGroups(userId); Assert.assertNotNull(dbVXGroupList); } @Test - public void test17GetXGroupUsers() { + public void test23GetXGroupUsers() { VXUserList dbVXUserList = xUserMgr.getXGroupUsers(userId);VXGroup vXGroup = new VXGroup(); vXGroup.setId(userId); vXGroup.setDescription("group test"); @@ -278,7 +427,7 @@ public class TestXUserMgr { } @Test - public void test18GetXUserByUserName() { + public void test24GetXUserByUserName() { VXUser vxUser = vxUser(); String userName = "test"; @@ -295,7 +444,7 @@ public class TestXUserMgr { } @Test - public void test19CreateXUserWithOutLogin(){ + public void test25CreateXUserWithOutLogin(){ VXUser vxUser = vxUser(); Mockito.when(xUserService.createXUserWithOutLogin(vxUser)) @@ -314,7 +463,7 @@ public class TestXUserMgr { } @Test - public void test20CreateXGroupWithoutLogin(){ + public void test26CreateXGroupWithoutLogin(){ VXGroup vXGroup = new VXGroup(); vXGroup.setId(userId); @@ -334,7 +483,7 @@ public class TestXUserMgr { } @Test - public void test21DeleteXGroup() { + public void test27DeleteXGroup() { XXGroupDao xxGroupDao = Mockito.mock(XXGroupDao.class); VXGroupUserList vxGroupUserList = new VXGroupUserList(); @@ -352,7 +501,7 @@ public class TestXUserMgr { } @Test - public void test22DeleteXUser() { + public void test28DeleteXUser() { XXGroupUserDao xxGroupDao = Mockito.mock(XXGroupUserDao.class); XXUserDao xxUserDao = Mockito.mock(XXUserDao.class); VXGroupUserList vxGroupUserList = new VXGroupUserList(); @@ -373,7 +522,7 @@ public class TestXUserMgr { } @Test - public void test23deleteXGroupAndXUser() { + public void test29deleteXGroupAndXUser() { VXUser vxUser = vxUser(); VXGroup vxGroup = new VXGroup(); VXGroupUserList vxGroupUserList = new VXGroupUserList(); @@ -397,7 +546,7 @@ public class TestXUserMgr { } @Test - public void test24CreateVXUserGroupInfo(){ + public void test30CreateVXUserGroupInfo(){ VXUserGroupInfo vXUserGroupInfo = new VXUserGroupInfo(); VXUser vXUser = new VXUser();
