Skip to content

Commit

Permalink
RANGER-888 : Provide support to delete Users and Groups from Ranger A…
Browse files Browse the repository at this point in the history
…dmin UI
  • Loading branch information
pradeepagrawal8184 authored and gautamborad committed Mar 23, 2016
1 parent 66c3034 commit 2836dea
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 8 deletions.
20 changes: 19 additions & 1 deletion security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java
Original file line number Diff line number Diff line change
Expand Up @@ -1601,7 +1601,7 @@ public void deleteXUser(Long id, boolean force) {
if (logger.isDebugEnabled()) {
logger.debug("Force delete status="+force+" for user="+vXUser.getName());
}

restrictSelfAccountDeletion(vXUser.getName().trim());
SearchCriteria searchCriteria = new SearchCriteria();
searchCriteria.addParam("xUserId", id);
VXGroupUserList vxGroupUserList = searchXGroupUsers(searchCriteria);
Expand Down Expand Up @@ -1781,4 +1781,22 @@ private void removeUserGroupReferences(List<RangerPolicyItem> policyItems, Strin
policyItems.removeAll(itemsToRemove);
}
}

public void restrictSelfAccountDeletion(String loginID) {
UserSessionBase session = ContextUtil.getCurrentUserSession();
if (session != null) {
if (!session.isUserAdmin()) {
throw restErrorUtil.create403RESTException("Operation denied. LoggedInUser= "+session.getXXPortalUser().getLoginId() + " isn't permitted to perform the action.");
}else{
if(!StringUtil.isEmpty(loginID) && loginID.equals(session.getLoginId())){
throw restErrorUtil.create403RESTException("Operation denied. LoggedInUser= "+session.getXXPortalUser().getLoginId() + " isn't permitted to delete his own profile.");
}
}
} else {
VXResponse vXResponse = new VXResponse();
vXResponse.setStatusCode(HttpServletResponse.SC_UNAUTHORIZED);
vXResponse.setMsgDesc("Bad Credentials");
throw restErrorUtil.generateRESTException(vXResponse);
}
}
}
42 changes: 42 additions & 0 deletions security-admin/src/main/java/org/apache/ranger/rest/XUserREST.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
import org.apache.ranger.view.VXModuleDefList;
import org.apache.ranger.view.VXPermMap;
import org.apache.ranger.view.VXPermMapList;
import org.apache.ranger.view.VXString;
import org.apache.ranger.view.VXStringList;
import org.apache.ranger.view.VXUser;
import org.apache.ranger.view.VXUserGroupInfo;
Expand Down Expand Up @@ -1002,4 +1003,45 @@ public VXStringList getUserRolesByName(@PathParam("userName") String userName) {
vXStringList=xUserMgr.getUserRolesByName(userName);
return vXStringList;
}

@DELETE
@Path("/secure/users/delete")
@Produces({ "application/xml", "application/json" })
@PreAuthorize("hasRole('ROLE_SYS_ADMIN')")
public void deleteUsersByUserName(@Context HttpServletRequest request,VXStringList userList){
String forceDeleteStr = request.getParameter("forceDelete");
boolean forceDelete = false;
if(StringUtils.isNotEmpty(forceDeleteStr) && "true".equalsIgnoreCase(forceDeleteStr)) {
forceDelete = true;
}
if(userList!=null && userList.getList()!=null){
for(VXString userName:userList.getList()){
if(StringUtils.isNotEmpty(userName.getValue())){
VXUser vxUser = xUserService.getXUserByUserName(userName.getValue());
xUserMgr.deleteXUser(vxUser.getId(), forceDelete);
}
}
}
}

@DELETE
@Path("/secure/groups/delete")
@Produces({ "application/xml", "application/json" })
@PreAuthorize("hasRole('ROLE_SYS_ADMIN')")
public void deleteGroupsByGroupName(
@Context HttpServletRequest request,VXStringList groupList) {
String forceDeleteStr = request.getParameter("forceDelete");
boolean forceDelete = false;
if(StringUtils.isNotEmpty(forceDeleteStr) && "true".equalsIgnoreCase(forceDeleteStr)) {
forceDelete = true;
}
if(groupList!=null && groupList.getList()!=null){
for(VXString groupName:groupList.getList()){
if(StringUtils.isNotEmpty(groupName.getValue())){
VXGroup vxGroup = xGroupService.getGroupByGroupName(groupName.getValue());
xUserMgr.deleteXGroup(vxGroup.getId(), forceDelete);
}
}
}
}
}
15 changes: 13 additions & 2 deletions security-admin/src/main/webapp/scripts/model_bases/VXGroupBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,20 @@ define(function(require){
*/
initialize: function() {
this.modelName = 'VXGroupBase';
}
},
deleteGroups : function(groupNameValues, options){
var url = this.urlRoot + '/delete?forceDelete=true';

options = _.extend({
data : JSON.stringify(groupNameValues),
contentType : 'application/json',
dataType : 'json',

}, options);

}, {
return this.constructor.nonCrudOperation.call(this, url, 'DELETE', options);
},
},{
// static class members
});

Expand Down
14 changes: 12 additions & 2 deletions security-admin/src/main/webapp/scripts/model_bases/VXUserBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ define(function(require){
var XABaseModel = require('models/XABaseModel');
var XAGlobals = require('utils/XAGlobals');


var VXUserBase = XABaseModel.extend(
/** @lends VXUserBase.prototype */
{
Expand All @@ -41,7 +40,18 @@ define(function(require){
*/
initialize: function() {
this.modelName = 'VXUserBase';
}
},

deleteUsers : function(userNameValues,options){
var url = this.urlRoot + '/delete?forceDelete=true';
options = _.extend({
data : JSON.stringify(userNameValues),
contentType : 'application/json',
dataType : 'json',
}, options);

return this.constructor.nonCrudOperation.call(this, url, 'DELETE', options);
},

}, {
// static class members
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ define(function(require){
var XATableLayout = require('views/common/XATableLayout');
var vUserInfo = require('views/users/UserInfo');

var VXUser = require('models/VXUser');

var UsertablelayoutTmpl = require('hbs!tmpl/users/UserTableLayout_tmpl');

var UserTableLayout = Backbone.Marionette.Layout.extend(
Expand Down Expand Up @@ -63,7 +65,8 @@ define(function(require){
visibilityDropdown : '[data-id="visibilityDropdown"]',
activeStatusDropdown : '[data-id="activeStatusDropdown"]',
activeStatusDiv :'[data-id="activeStatusDiv"]',
addNewBtnDiv : '[data-id="addNewBtnDiv"]'
addNewBtnDiv : '[data-id="addNewBtnDiv"]',
deleteUser: '[data-id="deleteUserGroup"]'
},

/** ui events hash */
Expand All @@ -75,6 +78,7 @@ define(function(require){
events['click ' + this.ui.btnSave] = 'onSave';
events['click ' + this.ui.visibilityDropdown +' li a'] = 'onVisibilityChange';
events['click ' + this.ui.activeStatusDropdown +' li a'] = 'onStatusChange';
events['click ' + this.ui.deleteUser] = 'onDeleteUser';
return events;
},

Expand Down Expand Up @@ -205,7 +209,9 @@ define(function(require){
this.renderUserListTable();
_.extend(this.collection.queryParams, XAUtil.getUserDataParams())
this.collection.fetch({
cache:true,
//cache:true,
reset: true,
cache: false
// data : XAUtil.getUserDataParams(),
}).done(function(){
if(!_.isString(that.ui.addNewGroup)){
Expand All @@ -225,7 +231,9 @@ define(function(require){
this.groupList.selectNone();
this.renderGroupListTable();
this.groupList.fetch({
cache:true
//cache:true,
reset:true,
cache: false
}).done(function(){
that.ui.addNewUser.hide();
that.ui.addNewGroup.show();
Expand Down Expand Up @@ -469,6 +477,83 @@ define(function(require){
};
return this.groupList.constructor.getTableCols(cols, this.groupList);
},

onUserGroupDeleteSuccess: function(jsonUsers,collection){
_.each(jsonUsers.vXStrings,function(ob){
var model = _.find(collection.models, function(mo){
if(mo.get('name') === ob.value)
return mo;
});
collection.remove(model.get('id'));
});
},

onDeleteUser: function(e){

var that = this;
var collection = that.showUsers ? that.collection : that.groupList;
var selArr = [];
var message = '';
_.each(collection.selected,function(obj){
selArr.push(obj.get('name'));
});
var vXStrings = [];
var jsonUsers = {};
for(var i in selArr) {
var item = selArr[i];
vXStrings.push({
"value" : item,
});
}
jsonUsers.vXStrings = vXStrings;

var total_selected = jsonUsers.vXStrings.length;

if(total_selected == 1) {
message = 'Are you sure you want to delete '+(that.showUsers ? 'user':'group')+' \''+jsonUsers.vXStrings[0].value+'\'?';
}
else {
message = 'Are you sure you want to delete '+total_selected+' '+(that.showUsers ? 'users':'groups')+'?';
}
if(total_selected > 0){
XAUtil.confirmPopup({
msg: message,
callback: function(){
XAUtil.blockUI();
if(that.showUsers){
var model = new VXUser();
model.deleteUsers(jsonUsers,{
success: function(response,options){
XAUtil.blockUI('unblock');
that.onUserGroupDeleteSuccess(jsonUsers,collection);
XAUtil.notifySuccess('Success','User deleted successfully!');
that.collection.selected = {};
},
error:function(response,options){
XAUtil.blockUI('unblock');
XAUtil.notifyError('Error', 'Error deleting User!');
}
});
}
else {
var model = new VXGroup();
model.deleteGroups(jsonUsers,{
success: function(response){
XAUtil.blockUI('unblock');
that.onUserGroupDeleteSuccess(jsonUsers,collection);
XAUtil.notifySuccess('Success','Group deleted successfully!');
that.groupList.selected = {};
},
error:function(response,options){
XAUtil.blockUI('unblock');
XAUtil.notifyError('Error', 'Error deleting Group!');
}
});
}
}
});
}
},
addVisualSearch : function(){
var that = this;
var coll,placeholder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ <h3 class="wrap-header bold"> {{tt 'lbl.userListing'}} </h3>
<div class="visual_search"></div>
</div>
<div class="clearfix" data-id="addNewBtnDiv">
{{#isSystemAdmin .}}
<a href="javascript:void(0);" data-id="deleteUserGroup" title="Permanently delete selected users/groups" class="btn btn-primary btn-right btn-danger"><i class="icon-trash icon-large" /></a>
{{/isSystemAdmin}}
<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>
<div class="btn-group btn-right">
Expand Down

0 comments on commit 2836dea

Please sign in to comment.