RANGER-1014 : Show allow/deny policy items info on Reports page

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/759f52e3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/759f52e3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/759f52e3

Branch: refs/heads/master
Commit: 759f52e3ea0fec9b1c6374714e46a8724f378968
Parents: 9a9f7cd
Author: Mehul Parikh <[email protected]>
Authored: Wed Jun 1 17:00:32 2016 +0530
Committer: Velmurugan Periasamy <[email protected]>
Committed: Tue Jun 7 15:56:21 2016 -0400

----------------------------------------------------------------------
 .../scripts/views/common/CustomSubgrid.js       | 195 +++++++++
 .../scripts/views/reports/UserAccessLayout.js   | 408 ++++++++++++-------
 security-admin/src/main/webapp/styles/xa.css    |  58 ++-
 3 files changed, 512 insertions(+), 149 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/759f52e3/security-admin/src/main/webapp/scripts/views/common/CustomSubgrid.js
----------------------------------------------------------------------
diff --git 
a/security-admin/src/main/webapp/scripts/views/common/CustomSubgrid.js 
b/security-admin/src/main/webapp/scripts/views/common/CustomSubgrid.js
new file mode 100644
index 0000000..0c7e52a
--- /dev/null
+++ b/security-admin/src/main/webapp/scripts/views/common/CustomSubgrid.js
@@ -0,0 +1,195 @@
+/*
+ * 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.
+ */
+
+define(function(require){
+       require('backgrid');
+/*
+                       SubgridCustomRow is a simple container view that takes 
a grid instance and renders a
+                       grid within the specific column.
+                       @extends Backbone.View
+                  */
+                 var SubgridCustomRow = Backgrid.SubgridCustomRow = 
Backbone.View.extend({
+
+                         tagName: "tr",
+
+                         className: "backgrid-subgrid-custom-row",
+
+                         submodel: Backbone.Model.extend({}),
+
+                         /**
+                          * Initializes a row view instance.
+                          * @param {Object} options
+                          * @param 
{Backbone.Collection.<Backgrid.Column>|Array.<Backgrid.Column>|Array.<Object>} 
options.columns Column metadata.
+                          * @param {Backbone.Model} options.model The model 
instance to render.
+                          * @throws {TypeError} If options.columns or 
options.model is undefined.
+                          */
+                         //params: options.columnName, options.labelName , 
options.columnCollectionName
+                         //define model.attributes.<columnName>Collection eg. 
model.attributes.colnameCollection
+                         initialize: function (options) {
+                                 var thisView = this;
+                                 var GridColumnView = Backbone.View.extend({ 
tagName: "td" });
+                                 var SubCollection  = 
Backbone.Collection.extend({ model: this.submodel });
+                                 this.gridColumnView = new GridColumnView({});
+                                 this.sideColumnView = new GridColumnView({});
+                                 this.el.id = this.model.get("id");
+                                 // requireOptions(options, ["columns", 
"model"]);
+                                 this.columns = options.columns;
+                                 var subcolumns = this.subcolumns = 
options.model.get("subcolumns");
+                                 if (!(subcolumns instanceof 
Backgrid.Columns)) {
+                                         subcolumns = this.subcolumns = 
this.model.subcolumns = new Backgrid.Columns(subcolumns);
+                                 }
+
+                                 var customCollection = 
this[options.columnCollectionName] = 
options.model.get(options.columnCollectionName);
+                                 if(!(customCollection instanceof 
Backbone.Collection)) {
+                                         customCollection = 
this[options.columnCollectionName] = 
this.model.attributes[options.columnCollectionName] = new 
SubCollection(customCollection);
+                                 }
+                                 this.label = options.labelName;
+                                 this.subgrid = new Backgrid.Grid({
+                                         columns: this.subcolumns,
+                                         collection: 
this[options.columnCollectionName],
+                                         emptyText: "No records found"
+                                 });
+
+                                 this.listenTo(Backbone, 
"SubgridCustomCell:remove", this.render);
+                         },
+                         /**
+                          * Renders a row containing a subgrid for this row's 
model.
+                          * */
+                         render: function () {
+                                 this.$el.empty();
+                                 this.$el.addClass("warning");// add class 
warning to subgrid row
+                                 this.gridColumnView.el.colSpan = 
(this.columns.length - 1);
+                                 // Appends the first  empty column
+                                 
$(this.el).append(this.sideColumnView.render().$el);
+                                 // Appends the subgrid column that spans the 
rest of the table
+                                 
$(this.el).append(this.gridColumnView.render().$el);
+                                 // Appends the Subgrid
+                                 
this.gridColumnView.$el.append(this.subgrid.render().$el);
+                                 
$(this.$el.children()[0]).html('<b>'+this.label+'</b>');
+                                 
this.gridColumnView.$el.find('[class="backgrid"]').addClass("table-bordered");
+                                 return this;
+                         }
+                 });
+                 /*
+                 SubgridCustomCell is a cell class to expand and collaspe 
another grid within
+                 the grid specific to each row.
+
+                 @extends Backgrid.Cell
+                  */
+
+                 var SubgridCustomCell = Backgrid.SubgridCustomCell = 
Backgrid.Cell.extend({
+
+                         className: "subgrid-custom-cell",
+                         // define the icon within the cell
+                         icon: function () {
+                                 var iconOptions = '<a 
href="javascript:void(0);" style="color:black;"><i class="icon-plus"></i></a>';
+                                 if(this.state == "expanded")
+                                         iconOptions = '<a 
href="javascript:void(0);" style="color:black;"><i class="icon-minus"></i></a>';
+                                 return (iconOptions);
+                         },
+                         optionValues: undefined,
+
+                         /**
+                          * Initializer.
+                          * @param {Object} options
+                          * @param {Backbone.Model} options.model
+                          * @param {Backgrid.Column} options.column
+                          * @param {Backgrid.Columns} options.column.attributes
+                          * @throws {ReferenceError} If formatter is a string 
but a formatter class of
+                          * said name cannot be found in the Backgrid module.
+                          * */
+                         initialize: function (options) {
+                                 this.state = "collasped";
+                                 //requireOptions(options, ["model", 
"column"]);
+                                 //requireOptions(options.column.attributes, 
["optionValues"]);
+                                 this.model.set("subcolumns", 
options.column.get("optionValues"));
+                                 //requireTypeOrder(options.column, "subgrid", 
0 );
+                                 this.column = options.column;
+                                 if (!(this.column instanceof 
Backgrid.Column)) {
+                                         this.column = new 
Backgrid.Column(this.column);
+                                 }
+                                 this.listenTo(Backbone, "backgrid:sort", 
this.clearSubgrid);
+                                 this.model.bind("remove", this.clearSubgrid, 
this);
+                         },
+                         /**
+                          * Renders a collasped view.
+                          */
+                         render: function () {
+                                 
//this.$el.empty().text(this.formatter.fromRaw(this.model.get(this.column.get("name"))));
+                                 $(this.el).append(this.icon());
+                                 return this;
+                         },
+
+                         events: {
+                                 "click": "stateConverter"
+                         },
+                         /**
+                          * Checks the current state of the cell, either:
+                          * appends another row for the subgrid and appends 
the grid to the row
+                          * or removes the row from the parent grid,
+                          * and saves the current data the model.
+                          * */
+                         stateConverter: function () {
+
+                                 var columnName = this.column.get('name');
+                                 var columnCollectionName = 
columnName+"Collection";
+                                 var labelName = this.column.attributes.label;
+                                 $(this.el).html("");
+                                 if (this.state == "collasped"){
+                                         
$(this.el).parent().addClass("warning");
+                                         this.state = "expanded";
+                                         this.subrow = new SubgridCustomRow({
+                                                 columns: 
this.column.collection,
+                                                 model: this.model,
+                                                 columnName: columnName,
+                                                 columnCollectionName: 
columnCollectionName,
+                                                 labelName: labelName
+                                         });
+                                         
$(this.el).parent("tr").after(this.subrow.render().$el);
+                                 } else {
+                                         if( 
$(this.el).parent().siblings('.warning').length <= 1 ){
+                                                 
$(this.el).parent().removeClass("warning")
+                                         }
+                                         this.state = "collasped";
+                                         this.subrow.remove();
+                                 }
+                                 //this.model.set("subgrid", 
this.subrow.subgrid);
+                                 this.model.set(columnCollectionName, 
this.subrow[columnCollectionName]);
+
+                                 $(this.el).append(this.icon());
+                         },
+                         /**
+                          * Binds the remove function with the row when a 
model is removed.
+                          */
+                         clearSubgrid: function () {
+                                 var thisView = this;
+                                 // TO DO : Clean up code
+                                 
$(".backgrid-subgrid-custom-row").filter(function() {
+                                         return ($(this).attr("id") == 
thisView.model.get('id'));
+                                 }).remove()
+                         },
+                         remove: function () {
+                                 if (this.subrow) {
+                                         this.subrow.remove.apply(this, 
arguments);
+                                         delete this.subrow;
+                                 }
+                                 return 
Backbone.View.prototype.remove.apply(this, arguments);
+                         }
+                 });
+});

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/759f52e3/security-admin/src/main/webapp/scripts/views/reports/UserAccessLayout.js
----------------------------------------------------------------------
diff --git 
a/security-admin/src/main/webapp/scripts/views/reports/UserAccessLayout.js 
b/security-admin/src/main/webapp/scripts/views/reports/UserAccessLayout.js
index 4c02504..159d18a 100644
--- a/security-admin/src/main/webapp/scripts/views/reports/UserAccessLayout.js
+++ b/security-admin/src/main/webapp/scripts/views/reports/UserAccessLayout.js
@@ -28,6 +28,7 @@ define(function(require) {'use strict';
        var XATableLayout               = require('views/common/XATableLayout');
        var localization                = require('utils/XALangSupport');
        var XAGlobals                   = require('utils/XAGlobals');
+       var CustomSubgrid               = require('views/common/CustomSubgrid');
        
        var RangerService               = require('models/RangerService');
        var RangerServiceDefList= require('collections/RangerServiceDefList');
@@ -76,7 +77,9 @@ define(function(require) {'use strict';
                        btnShowLessUsers        : '[data-id="showLessUsers"]',
                        componentType       : '[data-id="component"]',
                        downloadReport      : '[data-id="downloadReport"]',
-                       policyType          : '[data-id="policyType"]'
+                       policyType          : '[data-id="policyType"]',
+                       btnShowMoreAccess       : '[data-id="showMoreAccess"]',
+                       btnShowLessAccess       : '[data-id="showLessAccess"]'
                },
 
                /** ui events hash */
@@ -90,6 +93,8 @@ define(function(require) {'use strict';
                        events['click ' + this.ui.btnShowMoreUsers]  = 
'onShowMoreUsers';
                        events['click ' + this.ui.btnShowLessUsers]  = 
'onShowLessUsers';
                        events['click .downloadFormat'] = 
'setDownloadFormatFilter';
+                       events['click ' + this.ui.btnShowMoreAccess] = 
'onShowMorePermissions';
+                       events['click ' + this.ui.btnShowLessAccess] = 
'onShowLessPermissions';
                        return events;
                },
 
@@ -140,7 +145,6 @@ define(function(require) {'use strict';
                                this.renderTable(obj.collName, 
obj.serviceDefName);
                                
this.getResourceLists(obj.collName,obj.serviceDefName);
                        },this);
-                       this.modifyTableForSubcolumns();
                        this.$el.find('[data-js="policyName"]').focus()
                        var urlString = XAUtil.getBaseUrl();
                        if(urlString.slice(-1) == "/") {
@@ -163,13 +167,26 @@ define(function(require) {'use strict';
                                XAUtil.blockUI('unblock');
                                if(coll.length >= 1 && !that.allowDownload)
                                        that.allowDownload = true;
-                               
+                               
_.each(that[collName].models,function(model,ind){
+                                       if 
(XAUtil.isMaskingPolicy(model.get('policyType'))) {
+                                               //'<name>Collection' must be 
same as subgrid custom column name
+                                               
model.attributes.allowCollection = model.get('dataMaskPolicyItems');
+                                       } else if 
(XAUtil.isRowFilterPolicy(model.get('policyType'))) {
+                                               
model.attributes.allowCollection = model.get('rowFilterPolicyItems');
+                                       } else {
+                                               
model.attributes.allowCollection = model.get('policyItems');
+                                       }
+                                       model.attributes.denyCollection  = 
model.get('denyPolicyItems');
+                                       model.attributes.denyExcludeCollection  
  = model.get('denyExceptions');
+                                       model.attributes.allowExcludeCollection 
= model.get('allowExceptions');
+                               });
+
                        });
                },
                renderTable : function(collName,serviceDefName){
                        var that = this, tableRegion  = this[collName+'Table'];
                        tableRegion.show(new XATableLayout({
-                               columns: 
this.getColumns(this[collName],collName,serviceDefName),
+                               columns: 
this.getSubgridColumns(this[collName],collName,serviceDefName),
                                collection: this[collName],
                                includeFilter : false,
                                scrollToTop : false,
@@ -181,17 +198,110 @@ define(function(require) {'use strict';
                        }));
                
                },
-               getColumns : function(coll,collName,serviceDefName){
+               getSubgridColumns:function(coll,collName,serviceDefName){
                        var that = this;
-                       var cols = {
+
+                       var subcolumns = [{
+                                       name: 'groups',
+                                       cell: 'html',
+                                       label: 'Groups',
+                                       formatter: _.extend({}, 
Backgrid.CellFormatter.prototype, {
+                                               fromRaw: function 
(rawValue,model, coll) {
+                                                       var startSpanEle = 
'<span class="label label-info cellWidth-1 float-left-margin-2" 
style="">',endSpanEle = '</span>';
+                                                       var group_str = '';
+                                                       
if(_.isEmpty(model.get('groups'))){
+                                                               return 
'<center>--</center>';
+                                                       } else {
+                                                               
_.each(model.get('groups'),function(group,index){
+                                                                       
if(index < 4) {
+                                                                               
group_str += '<span class="label label-info cellWidth-1 float-left-margin-2" 
group-policy-id="'+model.cid+'" style="">' + group + endSpanEle  + " ";
+                                                                       } else {
+                                                                               
group_str += '<span class="label label-info cellWidth-1 float-left-margin-2" 
group-policy-id="'+model.cid+'" style="display:none">' + group+ endSpanEle  + " 
";
+                                                                       }
+                                                               });
+                                                               
if(model.get('groups').length > 4) {
+                                                                       
group_str += '<span class="pull-left float-left-margin-2">\
+                                                                       <a 
href="javascript:void(0);" data-id="showMoreAccess" policy-id="'+
+                                                                       
model.cid+'"><code style=""> + More..</code></a></span>\
+                                                                       <span 
class="pull-left float-left-margin-2" ><a href="javascript:void(0);" 
data-id="showLessAccess" policy-id="'+
+                                                                       
model.cid+'" style="display:none;"><code style=""> - Less..</code></a></span>';}
+                                                                       return 
group_str;
+                                                               }
+                                               }
+                                       }),
+                                       editable: false,
+                                       click: false,
+                                       sortable: false
+                               },
+                               {
+                                       name: 'users',
+                                       cell: 'html',
+                                       label: 'Users',
+                                       formatter: _.extend({}, 
Backgrid.CellFormatter.prototype, {
+                                               fromRaw: function 
(rawValue,model) {
+                                                       var startSpanEle = 
'<span class="label label-info cellWidth-1 float-left-margin-2" 
style="">',endSpanEle = '</span>';
+                                                       var user_str = '';
+                                                       
if(_.isEmpty(model.get('users'))){
+                                                               return 
'<center>--</center>';
+                                                       } else {
+                                                               
_.each(model.get('users'),function(user,index){
+                                                                       
if(index < 4) {
+                                                                               
user_str += '<span class="label label-info cellWidth-1 float-left-margin-2" 
user-policy-id="'+model.cid+'" style="">' + user + endSpanEle  + " ";
+                                                                       } else {
+                                                                               
user_str += '<span class="label label-info cellWidth-1 float-left-margin-2" 
user-policy-id="'+model.cid+'" style="display:none">' + user+ endSpanEle  + " ";
+                                                                       }
+                                                               });
+                                                               
if(model.get('users').length > 4) {
+                                                                       
user_str += '<span class="pull-left float-left-margin-2">\
+                                                                       <a 
href="javascript:void(0);" data-id="showMoreAccess" policy-id="'+
+                                                                       
model.cid+'"><code style=""> + More..</code></a></span>\
+                                                                       <span 
class="pull-left float-left-margin-2" ><a href="javascript:void(0);" 
data-id="showLessAccess" policy-id="'+
+                                                                       
model.cid+'" style="display:none;"><code style=""> - Less..</code></a></span>';}
+                                                                       return 
user_str;}
+                                                               }
+                                       }),
+                                       editable: false,
+                                       click: false,
+                                       sortable: false
+                               },
+                               { 
+                                       name: 'accesses',
+                                       cell: 'html',
+                                       label: 'Accesses',
+                                       formatter: _.extend({}, 
Backgrid.CellFormatter.prototype, {
+                                               fromRaw: function 
(rawValue,model) {
+                                                       var startSpanEle = 
'<span class="label label-info cellWidth-1 float-left-margin-2" 
style="">',endSpanEle = '</span>';
+                                                       var access_str = '';
+                                                       
_.each(model.get('accesses'),function(access,index){
+                                                               if(index < 4){
+                                                                       
access_str += '<span class="label label-info cellWidth-1 float-left-margin-2" 
access-policy-id="'+model.cid+'" style="">' + access.type+ endSpanEle  + " ";
+                                                               } else {
+                                                                       
access_str += '<span class="label label-info cellWidth-1 float-left-margin-2" 
access-policy-id="'+model.cid+'" style="display:none">' + access.type+ 
endSpanEle  + " ";
+                                                               }
+                                                       });
+                                                       
if(model.get('accesses').length > 4) {
+                                                               access_str += 
'<span class="pull-left float-left-margin-2">\
+                                                               <a 
href="javascript:void(0);" data-id="showMoreAccess" policy-id="'+
+                                                               
model.cid+'"><code style=""> + More..</code></a></span>\
+                                                               <span 
class="pull-left float-left-margin-2" ><a href="javascript:void(0);" 
data-id="showLessAccess" policy-id="'+
+                                               model.cid+'" 
style="display:none;"><code style=""> - Less..</code></a></span>';}
+                                                               return 
access_str;
+                                               }
+                                       }),
+                                       editable: false,
+                                       click: false,
+                                       sortable: false
+                               }
+                       ];
+                       var columns = {
                                id : {
                                        cell : "uri",
                                        href: function(model){
                                                var rangerService = new 
RangerService();
-                                               rangerService.urlRoot += 
'/name/'+model.get('service'); 
+                                               rangerService.urlRoot += 
'/name/'+model.get('service');
                                                rangerService.fetch({
-                                                 cache : false,
-                                                 async : false
+                                                       cache : false,
+                                                       async : false
                                                });
                                                return 
'#!/service/'+rangerService.get('id')+'/policies/'+model.id+'/edit';
                                        },
@@ -205,8 +315,7 @@ define(function(require) {'use strict';
                                        editable: false,
                                        sortable : false
                                },
-                               resources:
-                               {
+                               resources: {
                                        label: 'Resources',
                                        cell: 'Html',
                                        formatter: _.extend({}, 
Backgrid.CellFormatter.prototype, {
@@ -225,12 +334,12 @@ define(function(require) {'use strict';
                                                                strVal = 
strVal+ "<br />";
                                                        });
                                                        return strVal;
-                                                       }
+                                               }
                                        }),
                                        editable: false,
                                        sortable: false,
                                        click: false
-                               },
+                                       },
                                policyType: {
                                        label: 'Policy Type',
                                        cell: 
Backgrid.HtmlCell.extend({className: 'cellWidth-1', className: 'html-cell'}),
@@ -251,56 +360,6 @@ define(function(require) {'use strict';
                                        sortable: false,
                                        click: false
                                },
-                               permissions: {
-                                       label: 'Permissions',
-                                       cell : 
Backgrid.HtmlCell.extend({className: 'cellWidth-1', className: 'html-cell' }),
-                                       formatter: _.extend({}, 
Backgrid.CellFormatter.prototype,{
-                                               fromRaw: 
function(rawValue,model){
-                                                       var itemList = [], 
policyType = model.get("policyType");
-                                                       if 
(XAUtil.isMaskingPolicy(policyType)) {
-                                                               itemList = 
model.get("dataMaskPolicyItems");
-                                                       } else if 
(XAUtil.isRowFilterPolicy(policyType)) {
-                                                               itemList = 
model.get("rowFilterPolicyItems");
-                                                       }else{// by default it 
is access
-                                                               itemList = 
model.get("policyItems");
-                                                       }
-                                                       if(itemList.length > 0) 
{
-                                                           var htmlStr = '', 
accessStr = '', grpStr = '', userStr = '';
-                                                           var startSpanEle = 
'<span class="label label-info cellWidth-1 float-left-margin-2" 
style="">',endSpanEle = '</span>';
-                                                               
_.each(itemList,function(policyItem){
-                                                                       
if(!_.isUndefined(policyItem.groups) || !_.isUndefined(policyItem.users) &&
-                                                                               
        !_.isUndefined(policyItem.accesses)){
-                                                                               
var maxItem = policyItem.groups.length > policyItem.users.length ? 
policyItem.groups :  policyItem.users;
-                                                                               
maxItem = policyItem.accesses.length > maxItem.length ? policyItem.accesses : 
maxItem; 
-                                                                               
-                                                                               
_.each(maxItem,function(item, i){
-                                                                               
        if(!_.isUndefined(policyItem.users[i])){
-                                                                               
                userStr += startSpanEle + policyItem.users[i] + endSpanEle;
-                                                                               
        }
-                                                                               
        if(!_.isUndefined(policyItem.groups[i])){
-                                                                               
                grpStr += startSpanEle + policyItem.groups[i] + endSpanEle;
-                                                                               
        }
-                                                                               
        if(!_.isUndefined(policyItem.accesses[i])){
-                                                                               
                accessStr += startSpanEle + policyItem.accesses[i].type + 
endSpanEle;
-                                                                               
        }
-                                                                               
});
-                                                                               
-                                                                       }
-                                                                       htmlStr 
+= '<tr style="height:60px"><td class="report-user-group">'+grpStr+'</td>\
-                                                                               
                <td class="report-user-group">'+(userStr)+'</td>\
-                                                                               
                <td class="report-access">'+accessStr+'</td></tr>';
-                                                                       
accessStr = '', grpStr = '', userStr = '';
-                                                               });
-                                                               return htmlStr;
-                                                       } else {
-                                                               return '---';
-                                                       }
-                                               }
-                                       }),
-                                       editable: false,
-                                       sortable: false,
-                                       click: false
-                               },
                                isEnabled:{
                                        label:localization.tt('lbl.status'),
                                        cell :"html",
@@ -314,91 +373,143 @@ define(function(require) {'use strict';
                                        drag : false,
                                        sortable : false
                                }
-
                        };
+                       var permissions = 
this.getPermissionColumns(this[collName],collName,serviceDefName,subcolumns);
+                       _.extend(columns,permissions);
+                       return coll.constructor.getTableCols(columns, coll);
+               },
+               getPermissionColumns: function 
(coll,collName,serviceDefName,subcolumns){
+
+                       var that = this,permissions,cols,serviceDefOptions;
+
+                       var serviceDefOptions = {};
+                       _.each(this.serviceDefList.models, function(model){
+                               if(model.get('name') === serviceDefName)
+                                       serviceDefOptions = 
model.get('options');
+                       });
+                       var enableDenyAndExceptionsInPolicies = false;
+                       
if(!_.isUndefined(serviceDefOptions.enableDenyAndExceptionsInPolicies))
+                                enableDenyAndExceptionsInPolicies = true;
+                       if(serviceDefName === 
XAEnums.ServiceType.SERVICE_TAG.label){
+                               enableDenyAndExceptionsInPolicies = true;
+                       }
 
-                       return coll.constructor.getTableCols(cols, coll);
+            permissions = {
+                       allow:{
+                                       label: 'Allow Conditions',
+                                       cell: "subgrid-custom",
+                                       optionValues : subcolumns,
+                                       editable: false,
+                                       sortable: false,
+                                       click : false
+                       }
+            };
+            if(enableDenyAndExceptionsInPolicies) {
+               cols = {
+                               allowExclude:{
+                                       label: 'Allow Exclude',
+                                       cell: "subgrid-custom",
+                                       optionValues : subcolumns,
+                                       editable: false,
+                                       sortable: false,
+                                       click : false
+                               },      
+                               deny:{
+                                       label: 'Deny Conditions',
+                                       cell: "subgrid-custom",
+                                       optionValues : subcolumns,
+                                       editable: false,
+                                       sortable: false,
+                                       click : false
+                               },
+                               denyExclude:{
+                                       label: 'Deny Exclude',
+                                       cell: "subgrid-custom",
+                                       optionValues : subcolumns,
+                                       editable: false,        
+                                       sortable: false,
+                                       click : false
+                               }
+               };
+            }
+                       return _.extend(permissions,cols);
                },
-               /* add 'component' and 'policy type' select */
-       renderComponentAndPolicyTypeSelect: function(){
-               var that = this;
-               var options = this.serviceDefList.map(function(m){ return { 
'id' : m.get('name'), 'text' : m.get('name')}; });
-               var policyTypes = _.map(XAEnums.RangerPolicyType,function(m){
-                       return {'id': m.value,'text': m.label};
-               });
-               this.ui.componentType.select2({
-                       multiple: true,
-                       closeOnSelect: true,
-                       placeholder: 'Select Component',
-                   //maximumSelectionSize : 1,
-                   width: '220px',
-                   allowClear: true,
-                   data: options
-               });
-               this.ui.policyType.select2({
-                       closeOnSelect: true,
-                       placeholder: 'Select policy type',
-                       maximumSelectionSize : 1,
-                       width: '220px',
-                       allowClear: true,
-                       data: policyTypes
 
-               });
-       },
-       modifyTableForSubcolumns : function(){
-               this.$el.find(".permissions").html('<tr><th 
colspan="3">Permissions</th></tr>\
-                                                       <tr><th 
style="width:80px;max-width:80px;">Groups</th><th 
style="width:80px;max-width:80px;">Users</th>\
-                                                       <th 
style="width:150px">Accesses</th></tr>');
-       },
-       onDownload: function(e){
-               var that = this, url = '';
-               if(!this.allowDownload){
-                       XAUtil.alertPopup({
-                               msg :"No policies found to download!",
+               /* add 'component' and 'policy type' select */
+               renderComponentAndPolicyTypeSelect: function(){
+                       var that = this;
+                       var options = this.serviceDefList.map(function(m){ 
return { 'id' : m.get('name'), 'text' : m.get('name')}; });
+                       var policyTypes = 
_.map(XAEnums.RangerPolicyType,function(m){
+                               return {'id': m.value,'text': m.label};
                        });
-                       return;
-               }
-               if(!this.searchedFlag) {
-                       url =  this.previousSearchUrl;
-               } else if (this.searchedFlag && this.updatedUrl) {
-                       var urlString = XAUtil.getBaseUrl();
-                       if(urlString.slice(-1) === "/") {
-                               urlString = urlString.slice(0,-1);
+                       this.ui.componentType.select2({
+                               multiple: true,
+                               closeOnSelect: true,
+                               placeholder: 'Select Component',
+                           //maximumSelectionSize : 1,
+                           width: '220px',
+                           allowClear: true,
+                           data: options
+                       });
+                       this.ui.policyType.select2({
+                               closeOnSelect: true,
+                               placeholder: 'Select policy type',
+                               maximumSelectionSize : 1,
+                               width: '220px',
+                               allowClear: true,
+                               data: policyTypes
+       
+                       });
+               },
+               onDownload: function(e){
+                       var that = this, url = '';
+                       if(!this.allowDownload){
+                               XAUtil.alertPopup({
+                                       msg :"No policies found to download!",
+                               });
+                               return;
                        }
-                       url = url + urlString;
-                       if (e === "xlsFormat") {
-                                       url = url + 
'/service/plugins/policies/downloadExcel?';
-                       } else {
-                                       url = url + 
'/service/plugins/policies/csv?';
+                       if(!this.searchedFlag) {
+                               url =  this.previousSearchUrl;
+                       } else if (this.searchedFlag && this.updatedUrl) {
+                               var urlString = XAUtil.getBaseUrl();
+                               if(urlString.slice(-1) === "/") {
+                                       urlString = urlString.slice(0,-1);
+                               }
+                               url = url + urlString;
+                               if (e === "xlsFormat") {
+                                               url = url + 
'/service/plugins/policies/downloadExcel?';
+                               } else {
+                                               url = url + 
'/service/plugins/policies/csv?';
+                               }
+                               url = url + this.searchedParamsString + 
this.searchedComponentString;
+                               this.previousSearchUrl = url;
+                               this.searchedFlag = true;
                        }
-                       url = url + this.searchedParamsString + 
this.searchedComponentString;
-                       this.previousSearchUrl = url;
-                       this.searchedFlag = true;
-               }
-               this.ui.downloadReport.attr("href",url)[0].click();
-       },
-       setDownloadReportUrl: function(that,component,params){
+                       this.ui.downloadReport.attr("href",url)[0].click();
+               },
+               setDownloadReportUrl: function(that,component,params){
 
-               var compString = '', url = '';
-               if(!_.isUndefined(component)) {
-                       _.each(component,function(comp){
-                               compString = compString + comp + '_';
-                               });
-               }
-               if (!_.isEmpty(compString)) {
-                       compString = compString.slice(0,-1);
-               }
-               _.each(params, function(val, paramName){
-                       if(_.isUndefined(val) || _.isEmpty(val)) {
-                               delete params[paramName];
+                       var compString = '', url = '';
+                       if(!_.isUndefined(component)) {
+                               _.each(component,function(comp){
+                                       compString = compString + comp + '_';
+                                       });
                        }
-               });
-               var str = jQuery.param( params );
-               this.searchedComponentString = "&serviceType=" + compString;
-               this.searchedParamsString = str;
-               this.updatedUrl = true;
+                       if (!_.isEmpty(compString)) {
+                               compString = compString.slice(0,-1);
+                       }
+                       _.each(params, function(val, paramName){
+                               if(_.isUndefined(val) || _.isEmpty(val)) {
+                                       delete params[paramName];
+                               }
+                       });
+                       var str = jQuery.param( params );
+                       this.searchedComponentString = "&serviceType=" + 
compString;
+                       this.searchedParamsString = str;
+                       this.updatedUrl = true;
 
-       },
+               },      
                /** on render callback */
                setupGroupAutoComplete : function(){
                        this.groupArr = this.groupList.map(function(m){
@@ -673,6 +784,27 @@ define(function(require) {'use strict';
                                }, 1100);
                        }
                },
+               onShowMorePermissions: function(e){
+                                               var policyId = 
$(e.currentTarget).attr('policy-id');
+                                               var $td = 
$(e.currentTarget).parents('td');
+                                               
$td.find('[access-policy-id="'+policyId+'"]').show();
+                                               
$td.find('[user-policy-id="'+policyId+'"]').show();
+                                               
$td.find('[group-policy-id="'+policyId+'"]').show();
+                                               
$td.find('[data-id="showLessAccess"][policy-id="'+policyId+'"]').show();
+                                               
$td.find('[data-id="showMoreAccess"][policy-id="'+policyId+'"]').hide();
+
+                                       },
+                                       onShowLessPermissions: function(e){
+                                               var policyId = 
$(e.currentTarget).attr('policy-id');
+                                               var $td = 
$(e.currentTarget).parents('td');
+                                               
$td.find('[access-policy-id="'+policyId+'"]').slice(4).hide();
+                                               
$td.find('[user-policy-id="'+policyId+'"]').slice(4).hide();
+                                               
$td.find('[group-policy-id="'+policyId+'"]').slice(4).hide();
+                                               
$td.find('[data-id="showMoreAccess"][policy-id="'+policyId+'"]').show();
+                                               
$td.find('[data-id="showLessAccess"][policy-id="'+policyId+'"]').hide();
+
+                                       },
+
                onShowMore : function(e){
                        var attrName = 'policy-groups-id';
                        var id = $(e.currentTarget).attr(attrName);

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/759f52e3/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 a451761..fb5d80e 100644
--- a/security-admin/src/main/webapp/styles/xa.css
+++ b/security-admin/src/main/webapp/styles/xa.css
@@ -1945,38 +1945,41 @@ input[type="radio"], input[type="checkbox"] 
{margin-top: 0;}
   max-width: 120px;
 }
 .hdfs-table table.backgrid thead th:nth-child(1){
-  width: 60px;
-  max-width: 60px
+  width: 8%;
+  
 }
 .hdfs-table table.backgrid thead th:nth-child(2) {
   /*width: 300px;*/
   width: 25%;
 }
 .hdfs-table table.backgrid thead th:nth-child(3){
-  width:200px;
+  width:30%;
 }
 .hdfs-table table.backgrid thead th:nth-child(4){
-  width:100px;
+  width:10%;
 }
 .hdfs-table table.backgrid tbody td:nth-child(4){
-  width:100px;
+  width:10%;
   text-align: center;
 }
 .hdfs-table table.backgrid tbody tr td:nth-child(3){
  text-align: left !important;
  max-width: 200px;
 }
-.hdfs-table table.backgrid tbody tr td:nth-child(6){
+.hdfs-table table.backgrid tbody tr td:nth-child(5){
   text-align: center;
   width: 100px
 }
-.hdfs-table table.backgrid thead th:nth-child(6){
+.hdfs-table table.backgrid thead th:nth-child(5){
   text-align: center;
-  width: 100px;
+  width: 10%;
 }
-.hdfs-table table.backgrid thead th:nth-child(5) tr{
-  border-left-style: hidden;
+.hdfs-table table.backgrid thead th:nth-child(6){
+  width: 10%;
 }
+/*.hdfs-table table.backgrid thead th:nth-child(5) tr{
+  border-left-style: hidden;
+}*/
 .report-access{
   width:100%;
   border-right:1px solid #DDD;
@@ -1984,4 +1987,37 @@ input[type="radio"], input[type="checkbox"] {margin-top: 
0;}
 .report-user-group{
   width:80px;
   min-width:80px;
-}
\ No newline at end of file
+}
+td.subgrid-custom-cell{
+  text-align: center;
+}
+.backgrid-subgrid-custom-row table.backgrid thead th:nth-child(1){
+  width: 300px;
+  max-width: 300px;
+}
+.backgrid-subgrid-custom-row table.backgrid thead th:nth-child(2){
+  width: 300px;
+  max-width: 300px;
+}
+.backgrid-subgrid-custom-row table.backgrid thead th:nth-child(3){
+  width: 300px;
+  max-width: 300px;
+}
+.backgrid-subgrid-custom-row table.backgrid tbody td:nth-child(1){
+  width: 300px;
+  max-width: 300px;
+}
+.backgrid-subgrid-custom-row table.backgrid tbody td:nth-child(2){
+  width: 300px;
+  max-width: 300px;
+}
+.backgrid-subgrid-custom-row table.backgrid tbody td:nth-child(3){
+  width: 300px;
+  max-width: 300px;
+}
+.hdfs-table table.backgrid tbody tr.backgrid-subgrid-custom-row{
+  background-color: #f9f9f9;
+}
+.backgrid-subgrid-custom-row table.backgrid thead th {
+  font-weight:inherit;
+}

Reply via email to