You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ga...@apache.org on 2016/12/21 13:36:08 UTC
incubator-ranger git commit: RANGER-1237 : Ranger permissions do not
load when there are bulk users
Repository: incubator-ranger
Updated Branches:
refs/heads/ranger-0.6 f2990fe78 -> d6308e68a
RANGER-1237 : Ranger permissions do not load when there are bulk users
Signed-off-by: Gautam Borad <ga...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/d6308e68
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/d6308e68
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/d6308e68
Branch: refs/heads/ranger-0.6
Commit: d6308e68ad66211731f7d3949f5b219d7ba015cc
Parents: f2990fe
Author: pradeep agrawal <pr...@freestoneinfotech.com>
Authored: Tue Dec 20 19:31:01 2016 +0530
Committer: Gautam Borad <ga...@apache.org>
Committed: Wed Dec 21 19:05:46 2016 +0530
----------------------------------------------------------------------
.../java/org/apache/ranger/biz/XUserMgr.java | 24 +-
.../ranger/service/XGroupPermissionService.java | 26 ++
.../apache/ranger/service/XGroupService.java | 17 +-
.../ranger/service/XModuleDefService.java | 43 +--
.../ranger/service/XUserPermissionService.java | 27 ++
.../org/apache/ranger/service/XUserService.java | 24 ++
.../webapp/scripts/controllers/Controller.js | 2 +-
.../scripts/modules/globalize/message/en.js | 9 +-
.../src/main/webapp/scripts/utils/XAUtils.js | 34 +--
.../views/permissions/ModulePermissionCreate.js | 22 +-
.../views/permissions/ModulePermissionForm.js | 259 +++++++++++--------
.../views/permissions/ModulePermsTableLayout.js | 20 +-
.../scripts/views/policies/PermissionList.js | 5 +-
security-admin/src/main/webapp/styles/xa.css | 23 ++
.../permissions/ModulePermissionForm_tmpl.html | 41 ++-
15 files changed, 394 insertions(+), 182 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d6308e68/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 6dc1e2f..e62fc87 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
@@ -842,18 +842,26 @@ public class XUserMgr extends XUserMgrBase {
VXModuleDef vModuleDefPopulateOld = xModuleDefService.populateViewBean(xModuleDef);
List<XXGroupPermission> xgroupPermissionList = daoManager.getXXGroupPermission().findByModuleId(vXModuleDef.getId(), true);
-
- for (XXGroupPermission xGrpPerm : xgroupPermissionList) {
- VXGroupPermission vXGrpPerm = xGroupPermissionService.populateViewBean(xGrpPerm);
- groupPermListOld.add(vXGrpPerm);
+ Map<Long, XXGroup> xXGroupMap=xGroupService.getXXGroupIdXXGroupMap();
+ if(xXGroupMap==null || xXGroupMap.isEmpty()){
+ for (XXGroupPermission xGrpPerm : xgroupPermissionList) {
+ VXGroupPermission vXGrpPerm = xGroupPermissionService.populateViewBean(xGrpPerm);
+ groupPermListOld.add(vXGrpPerm);
+ }
+ }else{
+ groupPermListOld=xGroupPermissionService.getPopulatedVXGroupPermissionList(xgroupPermissionList,xXGroupMap,vModuleDefPopulateOld);
}
vModuleDefPopulateOld.setGroupPermList(groupPermListOld);
List<XXUserPermission> xuserPermissionList = daoManager.getXXUserPermission().findByModuleId(vXModuleDef.getId(), true);
-
- for (XXUserPermission xUserPerm : xuserPermissionList) {
- VXUserPermission vUserPerm = xUserPermissionService.populateViewBean(xUserPerm);
- userPermListOld.add(vUserPerm);
+ Map<Long, XXUser> xXPortalUserIdXXUserMap=xUserService.getXXPortalUserIdXXUserMap();
+ if(xXPortalUserIdXXUserMap==null || xXPortalUserIdXXUserMap.isEmpty()){
+ for (XXUserPermission xUserPerm : xuserPermissionList) {
+ VXUserPermission vUserPerm = xUserPermissionService.populateViewBean(xUserPerm);
+ userPermListOld.add(vUserPerm);
+ }
+ }else{
+ userPermListOld=xUserPermissionService.getPopulatedVXUserPermissionList(xuserPermissionList,xXPortalUserIdXXUserMap,vModuleDefPopulateOld);
}
vModuleDefPopulateOld.setUserPermList(userPermListOld);
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d6308e68/security-admin/src/main/java/org/apache/ranger/service/XGroupPermissionService.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/service/XGroupPermissionService.java b/security-admin/src/main/java/org/apache/ranger/service/XGroupPermissionService.java
index 20c3b67..3df5233 100644
--- a/security-admin/src/main/java/org/apache/ranger/service/XGroupPermissionService.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/XGroupPermissionService.java
@@ -17,12 +17,17 @@
package org.apache.ranger.service;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
import org.apache.ranger.common.MessageEnums;
import org.apache.ranger.common.SearchField;
import org.apache.ranger.db.RangerDaoManager;
import org.apache.ranger.entity.XXGroup;
import org.apache.ranger.entity.XXGroupPermission;
import org.apache.ranger.view.VXGroupPermission;
+import org.apache.ranger.view.VXModuleDef;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
@@ -77,4 +82,25 @@ public class XGroupPermissionService extends XGroupPermissionServiceBase<XXGroup
vObj.setGroupName(xGroup.getName());
return vObj;
}
+
+ public List<VXGroupPermission> getPopulatedVXGroupPermissionList(List<XXGroupPermission> xgroupPermissionList,Map<Long, XXGroup> xXGroupMap,VXModuleDef vModuleDef){
+ List<VXGroupPermission> vXGroupPermissionList = new ArrayList<VXGroupPermission>();
+ XXGroup xXGroup=null;
+ for(XXGroupPermission xgroupPermission:xgroupPermissionList){
+ if(xXGroupMap.containsKey(xgroupPermission.getGroupId())){
+ xXGroup =xXGroupMap.get(xgroupPermission.getGroupId());
+ VXGroupPermission vXGrpPerm=new VXGroupPermission();
+ vXGrpPerm.setId(xgroupPermission.getId());
+ vXGrpPerm.setGroupId(xgroupPermission.getGroupId());
+ vXGrpPerm.setModuleId(xgroupPermission.getModuleId());
+ vXGrpPerm.setIsAllowed(xgroupPermission.getIsAllowed());
+ vXGrpPerm.setCreateDate(xgroupPermission.getCreateTime());
+ vXGrpPerm.setUpdateDate(xgroupPermission.getUpdateTime());
+ vXGrpPerm.setGroupName(xXGroup.getName());
+ vXGrpPerm.setModuleName(vModuleDef.getModule());
+ vXGroupPermissionList.add(vXGrpPerm);
+ }
+ }
+ return vXGroupPermissionList;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d6308e68/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 19c3d19..5c5d59a 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
@@ -23,6 +23,7 @@ import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import org.apache.ranger.common.AppConstants;
import org.apache.ranger.common.MessageEnums;
@@ -41,6 +42,7 @@ import org.apache.ranger.view.VXGroup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
@Service
@Scope("singleton")
@@ -253,5 +255,18 @@ public class XGroupService extends XGroupServiceBase<XXGroup, VXGroup> {
protected VXGroup mapEntityToViewBean(VXGroup vObj, XXGroup mObj) {
super.mapEntityToViewBean(vObj, mObj);
return vObj;
- }
+ }
+
+ public Map<Long, XXGroup> getXXGroupIdXXGroupMap(){
+ Map<Long, XXGroup> xXGroupMap=new HashMap<Long, XXGroup>();
+ try{
+ List<XXGroup> xXGroupList=rangerDaoManager.getXXGroup().getAll();
+ if(!CollectionUtils.isEmpty(xXGroupList)){
+ for(XXGroup xXGroup:xXGroupList){
+ xXGroupMap.put(xXGroup.getId(), xXGroup);
+ }
+ }
+ }catch(Exception ex){}
+ return xXGroupMap;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d6308e68/security-admin/src/main/java/org/apache/ranger/service/XModuleDefService.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/service/XModuleDefService.java b/security-admin/src/main/java/org/apache/ranger/service/XModuleDefService.java
index 2e00643..b8403e8 100644
--- a/security-admin/src/main/java/org/apache/ranger/service/XModuleDefService.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/XModuleDefService.java
@@ -19,12 +19,14 @@ package org.apache.ranger.service;
import java.util.ArrayList;
import java.util.List;
-
+import java.util.Map;
import org.apache.ranger.common.RangerConstants;
import org.apache.ranger.common.SearchField;
import org.apache.ranger.db.RangerDaoManager;
+import org.apache.ranger.entity.XXGroup;
import org.apache.ranger.entity.XXGroupPermission;
import org.apache.ranger.entity.XXModuleDef;
+import org.apache.ranger.entity.XXUser;
import org.apache.ranger.entity.XXUserPermission;
import org.apache.ranger.view.VXGroupPermission;
import org.apache.ranger.view.VXModuleDef;
@@ -32,6 +34,7 @@ import org.apache.ranger.view.VXUserPermission;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
@Service
@Scope("singleton")
@@ -49,6 +52,11 @@ public class XModuleDefService extends
@Autowired
XGroupPermissionService xGrpPermService;
+ @Autowired
+ XUserService xUserService;
+
+ @Autowired
+ XGroupService xGroupService;
public XModuleDefService() {
searchFields.add(new SearchField("module", "obj.module",
SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.PARTIAL));
@@ -84,34 +92,33 @@ public class XModuleDefService extends
@Override
public VXModuleDef populateViewBean(XXModuleDef xObj) {
-
VXModuleDef vModuleDef = super.populateViewBean(xObj);
+ Map<Long, XXUser> xXPortalUserIdXXUserMap=xUserService.getXXPortalUserIdXXUserMap();
+ Map<Long, XXGroup> xXGroupMap=xGroupService.getXXGroupIdXXGroupMap();
List<VXUserPermission> vXUserPermissionList = new ArrayList<VXUserPermission>();
List<VXGroupPermission> vXGroupPermissionList = new ArrayList<VXGroupPermission>();
-
List<XXUserPermission> xuserPermissionList = rangerDaoManager
.getXXUserPermission().findByModuleId(xObj.getId(), false);
List<XXGroupPermission> xgroupPermissionList = rangerDaoManager
.getXXGroupPermission().findByModuleId(xObj.getId(), false);
- for (XXUserPermission xUserPerm : xuserPermissionList) {
-
- VXUserPermission vXUserPerm = xUserPermService
- .populateViewBean(xUserPerm);
- vXUserPermissionList.add(vXUserPerm);
-
+ if(CollectionUtils.isEmpty(xXPortalUserIdXXUserMap)){
+ for (XXUserPermission xUserPerm : xuserPermissionList) {
+ VXUserPermission vXUserPerm = xUserPermService.populateViewBean(xUserPerm);
+ vXUserPermissionList.add(vXUserPerm);
+ }
+ }else{
+ vXUserPermissionList=xUserPermService.getPopulatedVXUserPermissionList(xuserPermissionList,xXPortalUserIdXXUserMap,vModuleDef);
}
-
- for (XXGroupPermission xGrpPerm : xgroupPermissionList) {
-
- VXGroupPermission vXGrpPerm = xGrpPermService
- .populateViewBean(xGrpPerm);
- vXGroupPermissionList.add(vXGrpPerm);
-
+ if(CollectionUtils.isEmpty(xXGroupMap)){
+ for (XXGroupPermission xGrpPerm : xgroupPermissionList) {
+ VXGroupPermission vXGrpPerm = xGrpPermService.populateViewBean(xGrpPerm);
+ vXGroupPermissionList.add(vXGrpPerm);
+ }
+ }else{
+ vXGroupPermissionList=xGrpPermService.getPopulatedVXGroupPermissionList(xgroupPermissionList,xXGroupMap,vModuleDef);
}
-
vModuleDef.setUserPermList(vXUserPermissionList);
vModuleDef.setGroupPermList(vXGroupPermissionList);
return vModuleDef;
}
-
}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d6308e68/security-admin/src/main/java/org/apache/ranger/service/XUserPermissionService.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/service/XUserPermissionService.java b/security-admin/src/main/java/org/apache/ranger/service/XUserPermissionService.java
index bd3a50d..3a97ef8 100644
--- a/security-admin/src/main/java/org/apache/ranger/service/XUserPermissionService.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/XUserPermissionService.java
@@ -17,11 +17,17 @@
package org.apache.ranger.service;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
import org.apache.ranger.common.SearchField;
import org.apache.ranger.db.RangerDaoManager;
import org.apache.ranger.entity.XXModuleDef;
import org.apache.ranger.entity.XXPortalUser;
+import org.apache.ranger.entity.XXUser;
import org.apache.ranger.entity.XXUserPermission;
+import org.apache.ranger.view.VXModuleDef;
import org.apache.ranger.view.VXUserPermission;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
@@ -71,4 +77,25 @@ public class XUserPermissionService extends XUserPermissionServiceBase<XXUserPer
return vObj;
}
+ public List<VXUserPermission> getPopulatedVXUserPermissionList(List<XXUserPermission> xuserPermissionList,Map<Long, XXUser> xXPortalUserIdXXUserMap,VXModuleDef vModuleDef){
+ List<VXUserPermission> vXUserPermissionList = new ArrayList<VXUserPermission>();
+ XXUser xXUser=null;
+ for(XXUserPermission xuserPermission:xuserPermissionList){
+ if(xXPortalUserIdXXUserMap.containsKey(xuserPermission.getUserId())){
+ xXUser =xXPortalUserIdXXUserMap.get(xuserPermission.getUserId());
+ VXUserPermission vXUserPerm=new VXUserPermission();
+ vXUserPerm.setId(xuserPermission.getId());
+ vXUserPerm.setUserId(xXUser.getId());
+ vXUserPerm.setModuleId(xuserPermission.getModuleId());
+ vXUserPerm.setIsAllowed(xuserPermission.getIsAllowed());
+ vXUserPerm.setCreateDate(xuserPermission.getCreateTime());
+ vXUserPerm.setUpdateDate(xuserPermission.getUpdateTime());
+ vXUserPerm.setModuleName(vModuleDef.getModule());
+ vXUserPerm.setLoginId(xXUser.getName());
+ vXUserPerm.setUserName(xXUser.getName());
+ vXUserPermissionList.add(vXUserPerm);
+ }
+ }
+ return vXUserPermissionList;
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d6308e68/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 8210650..813079f 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
@@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.apache.ranger.biz.RangerBizUtil;
@@ -47,6 +48,7 @@ import org.apache.ranger.view.VXUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
@Service
@Scope("singleton")
@@ -383,5 +385,27 @@ public class XUserService extends XUserServiceBase<XXUser, VXUser> {
return trxLogList;
}
+ public Map<Long, XXUser> getXXPortalUserIdXXUserMap(){
+ Map<Long, XXUser> xXPortalUserIdXXUserMap=new HashMap<Long, XXUser>();
+ try{
+ Map<String, XXUser> xXUserMap=new HashMap<String, XXUser>();
+ List<XXUser> xXUserList=daoManager.getXXUser().getAll();
+ if(!CollectionUtils.isEmpty(xXUserList)){
+ for(XXUser xxUser:xXUserList){
+ xXUserMap.put(xxUser.getName(), xxUser);
+ }
+ }
+ xXUserList=null;
+ List<XXPortalUser> xXPortalUserList=daoManager.getXXPortalUser().getAll();
+ if(!CollectionUtils.isEmpty(xXPortalUserList)){
+ for(XXPortalUser xXPortalUser:xXPortalUserList){
+ if(xXUserMap.containsKey(xXPortalUser.getLoginId())){
+ xXPortalUserIdXXUserMap.put(xXPortalUser.getId(),xXUserMap.get(xXPortalUser.getLoginId()));
+ }
+ }
+ }
+ }catch(Exception ex){}
+ return xXPortalUserIdXXUserMap;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d6308e68/security-admin/src/main/webapp/scripts/controllers/Controller.js
----------------------------------------------------------------------
diff --git a/security-admin/src/main/webapp/scripts/controllers/Controller.js b/security-admin/src/main/webapp/scripts/controllers/Controller.js
index fc56496..041c6b7 100755
--- a/security-admin/src/main/webapp/scripts/controllers/Controller.js
+++ b/security-admin/src/main/webapp/scripts/controllers/Controller.js
@@ -346,7 +346,7 @@ define(function(require) {
var modulePermission = new ModulePermission({id : moduleId});
var that = this
modulePermission.collection = new ModulePermissionList();
- modulePermission.fetch({cache : true}).done(function(){
+ modulePermission.fetch({cache : false}).done(function(){
App.rContent.show(new view({
model : modulePermission,
groupList : that.groupList,
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d6308e68/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 de12935..fb7a326 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
@@ -233,7 +233,9 @@ define(function(require) {
componentPermissions : 'Component Permissions',
selectDataMaskTypes : 'Select Data Mask Types',
accessTypes : 'Access Types',
- rowLevelFilter : 'Row Level Filter'
+ rowLevelFilter : 'Row Level Filter',
+ selectAndAddUser : 'Select and Add User',
+ selectAndAddGroup : 'Select and Add Group',
},
btn : {
add : 'Add',
@@ -338,7 +340,10 @@ define(function(require) {
grpUpdatedSucc : 'Group updated successfully',
grpCreatedSucc : 'Group created successfully',
errorLoadingAuditLogs : 'Unable to connect to Audit store !!',
- enterCustomMask : 'Please enter custom masked value or expression !!'
+ enterCustomMask : 'Please enter custom masked value or expression !!',
+ pleaseSelectUser : 'Please select user.',
+ pleaseSelectGroup : 'Please select group.',
+ addSelectedUserGroup : 'Please add selected user/group to permissions else user/group will not be added.'
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d6308e68/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 05733f8..b776e8d 100644
--- a/security-admin/src/main/webapp/scripts/utils/XAUtils.js
+++ b/security-admin/src/main/webapp/scripts/utils/XAUtils.js
@@ -521,24 +521,29 @@ define(function(require) {
};
XAUtils.showGroupsOrUsers = function(rawValue, model, userOrGroups) {
- var showMoreLess = false, objArr = [];
+ var showMoreLess = false, objArr, lastShowMoreCnt = 1, j = 1, listShownCnt = 5000;
if (!_.isArray(rawValue) && rawValue.length == 0)
return '--';
- if (userOrGroups == 'groups') {
- _.each(rawValue, function(perm) {
- objArr = _.union(objArr, _.escape(perm.groupName))
- });
- } else if (userOrGroups == 'users') {
- _.each(rawValue, function(perm) {
- objArr = _.union(objArr, _.escape(perm.userName))
- });
- }
-
+ objArr = (userOrGroups == 'groups') ? _.pluck(rawValue, 'groupName') : _.pluck(rawValue, 'userName');
var newObjArr = _.map(objArr, function(name, i) {
if (i >= 4) {
- return '<span class="label label-info float-left-margin-2" policy-' + userOrGroups
- + '-id="' + model.id + '" style="display:none;">'
- + name + '</span>';
+ var eleStr = '', span = '<span class="label label-info float-left-margin-2" policy-' + userOrGroups
+ + '-id="' + model.id +'">'
+ + _.escape(name) + '</span>';
+ if( (i + listShownCnt ) === (listShownCnt*j) + 4){
+ eleStr = '<div data-id="moreSpans" style="display:none;">'+span;
+ if(i == objArr.length - 1){
+ eleStr += '</div>';
+ }
+ lastShowMoreCnt = ( listShownCnt*j ) + 4;
+ j++;
+ }else if(i === lastShowMoreCnt - 1 || i == objArr.length - 1){
+ eleStr = span + '</div>';
+
+ }else{
+ eleStr = span;
+ }
+ return eleStr;
} else if (i == 3 && objArr.length > 4) {
showMoreLess = true;
return '<span class="label label-info float-left-margin-2" policy-' + userOrGroups
@@ -563,7 +568,6 @@ define(function(require) {
newObjArr.unshift('<div data-id="groupsDiv">');
newObjArr.push('</div>');
return newObjArr.length ? newObjArr.join(' ') : '--';
-
};
XAUtils.defaultErrorHandler = function(model, error) {
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d6308e68/security-admin/src/main/webapp/scripts/views/permissions/ModulePermissionCreate.js
----------------------------------------------------------------------
diff --git a/security-admin/src/main/webapp/scripts/views/permissions/ModulePermissionCreate.js b/security-admin/src/main/webapp/scripts/views/permissions/ModulePermissionCreate.js
index 02b879d..0d1c92f 100644
--- a/security-admin/src/main/webapp/scripts/views/permissions/ModulePermissionCreate.js
+++ b/security-admin/src/main/webapp/scripts/views/permissions/ModulePermissionCreate.js
@@ -92,29 +92,9 @@ define(function(require){
initializePlugins: function(){
},
renderForm : function(){
- var VXGroupList = require('collections/VXGroupList');
- var VXUserList = require('collections/VXUserList');
- var params = {sortBy : 'name'};
- this.userList = new VXUserList();
- this.userList.setPageSize(100,{fetch:true});
- this.userList.fetch({
- cache :false,
- data: params,
- async : false
- });
- this.groupList = new VXGroupList();
- this.groupList.setPageSize(100,{fetch:true});
- this.groupList.fetch({
- cache :false,
- data : params,
- async : false
- });
- var that = this;
this.form = new ModulePermissionForm({
template : require('hbs!tmpl/permissions/ModulePermissionForm_tmpl'),
- model : that.model,
- groupList : that.groupList,
- userList : that.userList
+ model : this.model,
});
this.rForm.show(this.form);
},
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d6308e68/security-admin/src/main/webapp/scripts/views/permissions/ModulePermissionForm.js
----------------------------------------------------------------------
diff --git a/security-admin/src/main/webapp/scripts/views/permissions/ModulePermissionForm.js b/security-admin/src/main/webapp/scripts/views/permissions/ModulePermissionForm.js
index 1756955..76154a9 100644
--- a/security-admin/src/main/webapp/scripts/views/permissions/ModulePermissionForm.js
+++ b/security-admin/src/main/webapp/scripts/views/permissions/ModulePermissionForm.js
@@ -48,20 +48,34 @@ define(function(require) {
templateHelpers :function(){
},
templateData : function(){
- return { 'id' : this.model.id, 'permHeaders' : this.getPermHeaders() };
+ return {
+ 'id' : this.model.id,
+ 'permHeaders' : this.getPermHeaders(),
+ 'userList' : this.model.get('userPermList'),
+ 'groupList' : this.model.get('groupPermList')
+ };
},
initialize : function(options) {
- _.extend(this, _.pick(options, 'groupList','userList'));
+ _.extend(this, _.pick(options));
if (!this.model.isNew()){
this.setupFieldsforEditModule();
}
Backbone.Form.prototype.initialize.call(this, options);
},
ui : {
- /*selectGroups : 'div[data-fields="selectGroups"]',
- selectUsers : 'div[data-fields="selectUsers"]',*/
+ selectGroups : 'div[data-editors="selectGroups"]',
+ selectUsers : 'div[data-editors="selectUsers"]',
+ addGroupBtn : '[data-id="addGroupBtn"]',
+ addUserBtn : '[data-id="addUserBtn"]',
+
},
- events : {
+ events : function(){
+ var events = {};
+ events['click ' + this.ui.addGroupBtn ] = 'onAddGroup';
+ events['click ' + this.ui.addUserBtn ] = 'onAddUser';
+ events['click ' + '[data-js="addUser"]'] = 'onAddUserClick';
+ events['click ' + '[data-js="selectedGroupSpan"]'] = 'onRemovedGroupClick';
+ return events;
},
/** fields for the form
*/
@@ -81,13 +95,13 @@ define(function(require) {
selectGroups : {
type : 'Select2Remote',
editorAttrs : {'placeholder' :'Select Group','tokenSeparators': [",", " "],multiple:true},
- pluginAttr: this.getPlugginAttr(true,{'lookupURL':"service/xusers/groups",'permList':that.model.get('groupPermList'),'idKey':'groupId','textKey':'groupName'}),
+ pluginAttr: this.getPlugginAttr(true,{'lookupURL':"service/xusers/groups",'idKey':'groupId','textKey':'groupName'}),
title : localization.tt('lbl.selectGroup')+' *'
},
selectUsers : {
type : 'Select2Remote',
editorAttrs : {'placeholder' :'Select User','tokenSeparators': [",", " "],multiple:true},
- pluginAttr: this.getPlugginAttr(true,{'lookupURL':"service/xusers/users",'permList':that.model.get('userPermList'),'idKey':'userId','textKey':'userName'}),
+ pluginAttr: this.getPlugginAttr(true,{'lookupURL':"service/xusers/users",'idKey':'userId','textKey':'userName'}),
title : localization.tt('lbl.selectUser')+' *',
},
isAllowed : {
@@ -98,29 +112,28 @@ define(function(require) {
}
},
render: function(options) {
- var that = this;
Backbone.Form.prototype.render.call(this, options);
-
+ this.$el.find('[data-js="selectedGroupList"] span i').on('click', this.removeGroup.bind(this));
+ this.$el.find('[data-js="selectedUserList"] span i').on('click', this.removeUser.bind(this));
+ if(this.model.get('groupPermList').length <= 0){
+ this.$el.find('.emptySelectedGroups').show();
+ }else{
+ this.$el.find('.emptySelectedGroups').hide();
+ }
+ if(this.model.get('userPermList').length <= 0){
+ this.$el.find('.emptySelectedUsers').show();
+ }else{
+ this.$el.find('.emptySelectedUsers').hide();
+ }
},
setupFieldsforEditModule : function(){
- var groupsNVList=[],usersNVList =[];
- groupsNVList = _.map(this.model.get('groupPermList'),function(gPerm){
- return {'id': Number(gPerm.groupId), 'text':_.escape(gPerm.groupName)};
- });
- this.model.set('selectGroups', groupsNVList);
-
- usersNVList = _.map(this.model.get('userPermList'),function(uPerm){
- return {'id': Number(uPerm.userId), 'text':_.escape(uPerm.userName)};
- });
- this.model.set('selectUsers', usersNVList);
-
+ this.addedGroups = _.map(this.model.get('groupPermList'), function(g){ return { 'id' : g.groupId, 'text' : g.groupName} });
+ this.addedUsers = _.map(this.model.get('userPermList'), function(u){ return { 'id' : u.userId, 'text' : u.userName} });
},
getPermHeaders : function(){
var permList = [];
- permList.unshift(localization.tt('lbl.allowAccess'));
- permList.unshift(localization.tt('lbl.selectUser'));
- permList.unshift(localization.tt('lbl.selectGroup'));
-// permList.push("");
+ permList.unshift(localization.tt('lbl.selectAndAddUser'));
+ permList.unshift(localization.tt('lbl.selectAndAddGroup'));
return permList;
},
getPlugginAttr :function(autocomplete, options){
@@ -131,25 +144,7 @@ define(function(require) {
return {
closeOnSelect : true,
multiple: true,
- minimumInputLength: 0,
tokenSeparators: [",", " "],
- initSelection : function (element, callback) {
- var data = [];
- _.each(options.permList,function (elem) {
- data.push({id: elem[options.idKey], text: _.escape(elem[options.textKey])});
- });
- callback(data);
- },
- createSearchChoice: function(term, data) {
- if ($(data).filter(function() {
- return this.text.localeCompare(term) === 0;
- }).length === 0) {
- return {
- id : term,
- text: term
- };
- }
- },
ajax: {
url: options.lookupURL,
type : 'GET',
@@ -169,13 +164,15 @@ define(function(require) {
selectedVals = that.getSelectedValues(options);
if(data.resultSize != "0"){
if(!_.isUndefined(data.vXGroups)){
- results = data.vXGroups.map(function(m, i){ return {id : m.id+"", text: _.escape(m.name) }; });
- } else if(!_.isUndefined(data.vXUsers)){
- results = data.vXUsers.map(function(m, i){ return {id : m.id+"", text: _.escape(m.name) }; });
- if(!_.isEmpty(selectedVals)){
- results = XAUtil.filterResultByText(results, selectedVals);
- }
+ results = data.vXGroups.map(function(m, i){ return {id : m.id, text: _.escape(m.name)}; });
+ }
+ else if(!_.isUndefined(data.vXUsers)){
+ results = data.vXUsers.map(function(m, i){ return {id : m.id, text: _.escape(m.name)}; });
}
+ if(!_.isEmpty(selectedVals)){
+ results = XAUtil.filterResultByText(results, selectedVals);
+ }
+
}
return { results : results};
},
@@ -195,80 +192,136 @@ define(function(require) {
return result.text;
},
formatNoMatches : function(term){
- return options.textKey == 'groupName' ? 'No group found.' : 'No user found.';
+ switch (term){
+ default : return "No Matches found";
+ }
}
};
}
},
getSelectedValues : function(options){
var vals = [],selectedVals = [];
- var type = options.textKey == 'groupName' ? 'selectGroups' : 'selectUsers';
- var $select = this.$('[name="'+type+'"]');
- if(!_.isEmpty($select.select2('data'))){
- selectedVals = _.map($select.select2('data'),function(obj){ return obj.text; });
+ var added = options.textKey == 'groupName' ? this.addedGroups : this.addedUsers;
+ if(!_.isEmpty(added)){
+ selectedVals = _.map(added, function(obj){ return obj.text; });
}
vals.push.apply(vals , selectedVals);
- vals = $.unique(vals);
return vals;
},
beforeSaveModulePermissions : function(){
- if(this.model.get('module') != ''){
- var groupValStr = this.fields.selectGroups.getValue();
- var userValStr = this.fields.selectUsers.getValue();
- this.compareAndUpdateObj(groupValStr,{'mode':'groups','permList':this.model.get('groupPermList'),'idKey':'groupId','textKey':'groupName'});
- this.compareAndUpdateObj(userValStr,{'mode':'users','permList':this.model.get('userPermList'),'idKey':'userId','textKey':'userName'});
+ if(!_.isEmpty(this.fields.selectGroups.editor.$el.select2('data'))
+ || !_.isEmpty(this.fields.selectUsers.editor.$el.select2('data'))){
+ XAUtil.alertPopup({
+ msg :localization.tt('msg.addSelectedUserGroup'),
+ });
+ return false;
}
+ this.model.unset('selectUsers');
+ this.model.unset('selectGroups');
+
return true;
},
- compareAndUpdateObj: function(objValsStr,options){
+ onAddGroup : function(e){
+ var that = this, newPerms = [];
+ var selectedGroups = this.fields.selectGroups.editor.$el.select2('data');
+ _.each(selectedGroups, function(obj){
+ var self = that;
+ this.$el.find('[data-js="selectedGroupList"]').append('<span class="selected-widget" ><i class="icon remove icon-remove" data-js="selectedGroupIcon" data-id="'+obj.id+'"></i> '+obj.text+'</span>')
+ this.addedGroups.push(obj)
+ this.$el.find('[data-js="selectedGroupList"] :last').on('click',this.removeGroup.bind(this));
+ this.fields.selectGroups.editor.$el.select2('data',[]);
+ var addedGroupPerm =_.findWhere(this.model.get('groupPermList'), {'groupId': parseInt(obj.id) });
+ if(!_.isUndefined(addedGroupPerm)){
+ addedGroupPerm.isAllowed = XAEnums.AccessResult.ACCESS_RESULT_ALLOWED.value;
+ }else{
+ var perm = {};
+ perm['moduleId'] = that.model.get('id');
+ perm['groupId'] = obj['id'];
+ perm.isAllowed = XAEnums.AccessResult.ACCESS_RESULT_ALLOWED.value;
+ newPerms.push(perm);
+ }
+ }, this);
+ if(!_.isEmpty(newPerms)){
+ var permissions = this.model.get('groupPermList');
+ this.model.set('groupPermList', permissions.concat(newPerms));
+ }
+
+ this.emptyCheck();
+ if(_.isEmpty(selectedGroups)) alert(localization.tt("msg.pleaseSelectGroup"));
+ return false;
+
+ },
- var selectedVals = (!_.isNull(objValsStr)) ? objValsStr.toString().split(',') : [];
- var selectedIdList=[];
- selectedVals = _.each(selectedVals, function(eachVal){
- //Ignoring any non existing Group Name
- if(_.isNumber(parseInt(eachVal)) && !_.isNaN(parseInt(eachVal))){
- selectedIdList.push(Number(eachVal));
+ removeGroup : function(e){
+ var ele = $(e.currentTarget);
+ var id = ele.attr('data-id');
+ ele.parent().remove();
+ this.addedGroups = _.reject(this.addedGroups, function(d){ return d.id == id; });
+ var removedGroupPerm =_.findWhere(this.model.get('groupPermList'), {'groupId': parseInt(id) });
+ if(!_.isUndefined(removedGroupPerm)){
+ if(!_.has(removedGroupPerm, 'id')){
+ this.model.set('groupPermList', _.reject(this.model.get('groupPermList'), function(perm){ return perm.groupId == removedGroupPerm.groupId }));
+ }else{
+ removedGroupPerm.isAllowed = XAEnums.AccessResult.ACCESS_RESULT_DENIED.value;
}
- });
- var modelPermList = options.permList;
- var modelPerms = _.unique(_.pluck(options.permList, options.idKey));
- if(!_.isEmpty(selectedIdList)){
- //Look for equals
- if(_.isEqual(selectedIdList,modelPerms)) {
- //No changes in Selected Users
- } else {
- //look for new values -
- //loop through each new element and check if it has any non matching ids
- var diff = _.filter(selectedIdList, function(value){ return !_.contains(modelPerms, value); });
- var that = this;
- if(!_.isEmpty(diff)){
- //push new elements to model groupPermList
- _.each(diff, function(newEl){
- var newObj = {};
- newObj[options.idKey] = newEl;
- newObj['moduleId'] = that.model.get('id');
- newObj['isAllowed'] = 1;
- options.permList.push(newObj);
- });
- }
- //Look for removed users/groups
- //loop through each model element and check new selected groups is missing from any original list of group ids
- var updDiff = _.filter(modelPerms, function(value){ return !_.contains(selectedIdList, value); });
- if(!_.isEmpty(updDiff)){
- _.each(options.permList, function(origElem){
- if(_.contains(updDiff, origElem[options.idKey]))
- origElem.isAllowed = 0;
- });
- }
+ }
+ this.emptyCheck();
+ },
+ onAddUser : function(e){
+ var that = this, newPerms = [];
+ var selectedUsers = this.fields.selectUsers.editor.$el.select2('data');
+ _.each(selectedUsers, function(obj){
+ var self = that;
+ this.$el.find('[data-js="selectedUserList"]').append('<span class="selected-widget" ><i class="icon remove icon-remove" data-js="selectedUserIcon" data-id="'+obj.id+'"></i> '+obj.text+'</span>')
+ this.addedUsers.push(obj)
+ this.$el.find('[data-js="selectedUserList"] :last').on('click',this.removeUser.bind(this));
+ this.fields.selectUsers.editor.$el.select2('data', []);
+ var addedUserPerm =_.findWhere(this.model.get('userPermList'), {'userId': parseInt(obj.id) });
+ if(!_.isUndefined(addedUserPerm)){
+ addedUserPerm.isAllowed = XAEnums.AccessResult.ACCESS_RESULT_ALLOWED.value;
+ }else{
+ var perm = {};
+ perm['moduleId'] = that.model.get('id');
+ perm['userId'] = obj['id'];
+ perm.isAllowed = XAEnums.AccessResult.ACCESS_RESULT_ALLOWED.value;
+ newPerms.push(perm);
}
+ }, this);
+ if(!_.isEmpty(newPerms)){
+ var permissions = this.model.get('userPermList');
+ this.model.set('userPermList', permissions.concat(newPerms));
+ }
+ this.emptyCheck();
+ if(_.isEmpty(selectedUsers)) alert(localization.tt("msg.pleaseSelectUser"));
+ return false;
+ },
+ removeUser : function(e){
+ var ele = $(e.currentTarget);
+ var id = ele.attr('data-id');
+ ele.parent().remove();
+ this.addedUsers = _.reject(this.addedUsers, function(d){ return d.id == id; });
+ var removedUserPerm =_.findWhere(this.model.get('userPermList'), {'userId': parseInt(id) });
+ if(!_.isUndefined(removedUserPerm)){
+ if(!_.has(removedUserPerm, 'id')){
+ this.model.set('userPermList', _.reject(this.model.get('userPermList'), function(perm){ return perm.userId == removedUserPerm.userId }));
+ }else{
+ removedUserPerm.isAllowed = XAEnums.AccessResult.ACCESS_RESULT_DENIED.value;
+ }
+ }
+ this.emptyCheck();
+ },
+ emptyCheck : function(type){
+ if(this.$el.find('[data-js="selectedGroupList"] span').length > 0){
+ this.$el.find('.emptySelectedGroups').hide();
+ }else{
+ this.$el.find('.emptySelectedGroups').show();
+ }
- } else {
- //Remove permissions from all objects which earlier had permission
- _.each(options.permList, function(perm){
- perm.isAllowed = 0;
- });
+ if(this.$el.find('[data-js="selectedUserList"] span').length > 0){
+ this.$el.find('.emptySelectedUsers').hide();
+ }else{
+ this.$el.find('.emptySelectedUsers').show();
}
-
}
});
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d6308e68/security-admin/src/main/webapp/scripts/views/permissions/ModulePermsTableLayout.js
----------------------------------------------------------------------
diff --git a/security-admin/src/main/webapp/scripts/views/permissions/ModulePermsTableLayout.js b/security-admin/src/main/webapp/scripts/views/permissions/ModulePermsTableLayout.js
index 76dc027..92c07c7 100644
--- a/security-admin/src/main/webapp/scripts/views/permissions/ModulePermsTableLayout.js
+++ b/security-admin/src/main/webapp/scripts/views/permissions/ModulePermsTableLayout.js
@@ -184,9 +184,21 @@ define(function(require){
attrName = 'policy-users-id';
}
var $td = $(e.currentTarget).parents('td');
- $td.find('['+attrName+'="'+id+'"]').show();
- $td.find('[data-id="showLess"]['+attrName+'="'+id+'"]').show();
- $td.find('[data-id="showMore"]['+attrName+'="'+id+'"]').hide();
+ var show = false, shownCnt = 1;
+ $.each($td.find('[data-id="moreSpans"]'), function(i, div){
+ if($(div).is(':hidden') && !show){
+ $(div).show();
+ show = true;
+ return false;
+ }
+ if(!$(div).is(':hidden')){
+ shownCnt++;
+ }
+ })
+ if($td.find('[data-id="moreSpans"]').length == shownCnt){
+ $td.find('[data-id="showLess"]['+attrName+'="'+id+'"]').show();
+ $td.find('[data-id="showMore"]['+attrName+'="'+id+'"]').hide();
+ }
$td.find('[data-id="showMore"]['+attrName+'="'+id+'"]').parents('div[data-id="groupsDiv"]').addClass('set-height-groups');
},
onShowLess : function(e){
@@ -197,7 +209,7 @@ define(function(require){
attrName = 'policy-users-id';
}
var $td = $(e.currentTarget).parents('td');
- $td.find('['+attrName+'="'+id+'"]').slice(4).hide();
+ $td.find('[data-id="moreSpans"]').hide();
$td.find('[data-id="showLess"]['+attrName+'="'+id+'"]').hide();
$td.find('[data-id="showMore"]['+attrName+'="'+id+'"]').show();
$td.find('[data-id="showMore"]['+attrName+'="'+id+'"]').parents('div[data-id="groupsDiv"]').removeClass('set-height-groups');
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d6308e68/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 d5631e0..6a61f55 100644
--- a/security-admin/src/main/webapp/scripts/views/policies/PermissionList.js
+++ b/security-admin/src/main/webapp/scripts/views/policies/PermissionList.js
@@ -472,10 +472,11 @@ define(function(require) {
val = pcond['evaluatorOptions']['engineName'] + ' Condition'
}
i++;
- return '<span class="'+label+' white-space-normal" >'+name+' : '+ val + '</span>';
+ return '<span class="'+label+' white-space-normal" >'+name+' : '+ _.escape(val) + '</span>';
});
var cond = _.map(value, function(val, name) {
- return {'type' : name, 'values' : !_.isArray(val) ? val.split(', ') : val};
+ val = _.escape(val);
+ return {'type' : name, 'values' : !_.isArray(val) ? val.split(',') : val};
});
that.model.set('conditions', cond);
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d6308e68/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 9dbed64..13b1839 100644
--- a/security-admin/src/main/webapp/styles/xa.css
+++ b/security-admin/src/main/webapp/styles/xa.css
@@ -2026,4 +2026,27 @@ td.subgrid-custom-cell{
}
.customMask{
width: 95px;
+}
+.selected-widget {
+ padding: 3px 5px 3px 4px;
+ border-radius: 3px;
+ border: 1px solid #aaaaaa;
+ background-color: #e4e4e4;
+ margin: 3px 3px;
+ float: left;
+}
+.selected-list {
+ margin: 5px;
+ max-height: 270px;
+ overflow: auto;
+}
+.inline {
+ display: inline;
+}
+.vertAlignInitial{
+ vertical-align: initial !important;
+ text-align: left;
+}
+.selected-widget .remove{
+ cursor:pointer;
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d6308e68/security-admin/src/main/webapp/templates/permissions/ModulePermissionForm_tmpl.html
----------------------------------------------------------------------
diff --git a/security-admin/src/main/webapp/templates/permissions/ModulePermissionForm_tmpl.html b/security-admin/src/main/webapp/templates/permissions/ModulePermissionForm_tmpl.html
index 1bf096b..34cb017 100644
--- a/security-admin/src/main/webapp/templates/permissions/ModulePermissionForm_tmpl.html
+++ b/security-admin/src/main/webapp/templates/permissions/ModulePermissionForm_tmpl.html
@@ -16,7 +16,7 @@
--}}
<form class="form-horizontal">
<fieldset>
- <p class="formHeader"> Policy Details : </p>
+ <p class="formHeader"> Module Details : </p>
<div class="clearfix"></div>
<b class="policy-form">
<fieldset>
@@ -35,21 +35,48 @@
<thead>
<tr>
{{#each permHeaders}}
- <th>{{./this}}</th>
+ <th width="49%">{{./this}}</th>
{{/each}}
</tr>
</thead>
<tbody class="js-formInput">
<tr>
<td>
- <div data-editors="selectGroups"></div>
+ <div data-editors="selectGroups" class="inline"></div>
+ <button data-id="addGroupBtn" class="icon icon-plus icon-2x btn btn-default" title="Add Group"></button>
</td>
<td>
- <div data-editors="selectUsers"></div>
- </td>
- <td>
- <div data-editors="isAllowed"></div>
+ <div data-editors="selectUsers" class="inline"></div>
+ <button data-id="addUserBtn" class="icon icon-plus icon-2x btn btn-default" title="Add User"></button>
+
</td>
+ <!--<td>
+ <div data-editors="isAllowed"></div>
+ </td>-->
+ </tr>
+ <tr>
+ <td class="vertAlignInitial">
+ <div class="selected-list clearfix" data-js="selectedGroupList">
+ <label class="editable-empty emptySelectedGroups">No Selected Groups</label>
+ {{#each groupList}}
+ <span class="selected-widget">
+ <i class="icon remove icon-remove" data-id="{{./this.groupId}}"></i>
+ {{./this.groupName}}
+ </span>
+ {{/each}}
+
+ </div></td>
+ <td class="vertAlignInitial" width="100%">
+ <div class="selected-list clearfix" data-js="selectedUserList">
+ <label class="editable-empty emptySelectedUsers" style="text-align: center;">No Selected Users</label>
+
+ {{#each userList}}
+ <span class="selected-widget">
+ <i class="icon remove icon-remove" data-id="{{./this.userId}}"></i>
+ {{./this.userName}}
+ </span>
+ {{/each}}
+ </div></td>
</tr>
</tbody>
</table>