You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ni...@apache.org on 2021/03/16 05:23:54 UTC
[ranger] branch master updated: RANGER-3191 : Ranger UI for
configuring Audit filters.
This is an automated email from the ASF dual-hosted git repository.
ni3galave pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push:
new e1075ac RANGER-3191 : Ranger UI for configuring Audit filters.
e1075ac is described below
commit e1075ac0dbe50a466aba3a7a74014f69166e565c
Author: Nitin Galave <ni...@apache.org>
AuthorDate: Mon Mar 15 20:53:24 2021 +0530
RANGER-3191 : Ranger UI for configuring Audit filters.
---
.../webapp/scripts/models/BackboneFormDataType.js | 26 +-
.../src/main/webapp/scripts/utils/XAUtils.js | 25 +-
.../scripts/views/service/AuditFilterConfig.js | 438 ++++++++++++++++++
.../views/service/ServiceAuditFilterResources.js | 488 +++++++++++++++++++++
.../webapp/scripts/views/service/ServiceForm.js | 35 +-
.../scripts/views/users/AddUsersOrGroupsList.js | 2 +-
security-admin/src/main/webapp/styles/xa.css | 97 ++++
.../templates/service/AuditFilterItem_tmpl.html | 70 +++
.../templates/service/AuditFilterList_tmpl.html | 50 +++
.../ServiceAuditFilterResourcesForm_tmpl.html | 17 +
.../webapp/templates/service/ServiceForm_tmpl.html | 14 +
11 files changed, 1239 insertions(+), 23 deletions(-)
diff --git a/security-admin/src/main/webapp/scripts/models/BackboneFormDataType.js b/security-admin/src/main/webapp/scripts/models/BackboneFormDataType.js
index bf048e8..18c760b 100644
--- a/security-admin/src/main/webapp/scripts/models/BackboneFormDataType.js
+++ b/security-admin/src/main/webapp/scripts/models/BackboneFormDataType.js
@@ -124,7 +124,11 @@ define(function(require) {
}
opts['type'] = v.name;
if(v.lookupSupported){
- opts['lookupURL'] = "service/plugins/services/lookupResource/"+form.rangerService.get('name');
+ if (form.serviceName) {
+ opts['lookupURL'] = "service/plugins/services/lookupResource/"+form.serviceName;
+ } else {
+ opts['lookupURL'] = "service/plugins/services/lookupResource/"+form.rangerService.get('name');
+ }
resourceOpts['select2Opts'] = form.getPlugginAttr(true, opts);
}else{
resourceOpts['select2Opts'] = XAUtils.select2OptionForUserCreateChoice();
@@ -207,15 +211,19 @@ define(function(require) {
formObj['recursiveSupport'] = v.recursiveSupported;
formObj['name'] = v.name;
formObj['editorAttrs'] = {'data-placeholder': v.label };
- formObj.fieldAttrs = { 'data-name' : 'field-'+v.name, 'parent' : v.parent };
- formObj.fieldAttrs.fieldClass = "resorces-with-label-css"
- if(!_.isUndefined(v.lookupSupported)){
+ formObj.fieldAttrs = { 'data-name' : 'field-'+v.name, 'parent' : v.parent };
+ formObj.fieldAttrs.fieldClass = "resorces-with-label-css"
+ if(!_.isUndefined(v.lookupSupported)){
var options = {
- 'containerCssClass' : v.name,
- };
- if(v.lookupSupported){
- options['lookupURL'] = "service/plugins/services/lookupResource/"+form.rangerService.get('name');
- }
+ 'containerCssClass' : v.name,
+ };
+ if(v.lookupSupported){
+ if (form.serviceName) {
+ options['lookupURL'] = "service/plugins/services/lookupResource/"+form.serviceName;
+ } else {
+ options['lookupURL'] = "service/plugins/services/lookupResource/"+form.rangerService.get('name');
+ }
+ }
//to support regexp level validation
if(_.has(v, 'validationRegEx') && !_.isEmpty(v.validationRegEx)){
options['regExpValidation'] = {'type': 'regexp', 'regexp':new RegExp(v.validationRegEx), 'message' : v.validationMessage};
diff --git a/security-admin/src/main/webapp/scripts/utils/XAUtils.js b/security-admin/src/main/webapp/scripts/utils/XAUtils.js
index 600a0fe..b90f885 100644
--- a/security-admin/src/main/webapp/scripts/utils/XAUtils.js
+++ b/security-admin/src/main/webapp/scripts/utils/XAUtils.js
@@ -1640,27 +1640,26 @@ define(function(require) {
});
}
- XAUtils.getUsersGroupsList = function($select, domElement){
+ XAUtils.getUsersGroupsList = function($select, domElement, width, auditFilter){
var that = domElement,
tags = [],
placeholder = $select === 'users' ? "Select User" : $select === 'groups' ? "Select Group" : "Select Role",
searchUrl = $select === 'users' ? "service/xusers/lookup/users" : $select === 'groups' ? "service/xusers/lookup/groups"
: "service/roles/roles";
- // if(that.model && !_.isEmpty(that.model.get('name'))){
- // tags.push({
- // 'id': _.escape(that.model.get('name')),
- // 'text': _.escape(that.model.get('name'))
- // });
- // domElement.ui['selectUsersOrGroups'].val(tags.map(function(val) {
- // return val.text
- // }));
- // }
+ if(that.model && !_.isEmpty(that.model.get($select))){
+ _.map (that.model.get($select) , function(name){
+ tags.push({
+ 'id': _.escape(name),
+ 'text': _.escape(name)
+ });
+ })
+ }
return {
closeOnSelect : true,
placeholder : placeholder,
tags : true,
- width : '300px',
+ width : width,
initSelection: function(element, callback) {
callback(tags);
},
@@ -1686,7 +1685,9 @@ define(function(require) {
if (data.totalCount != "0") {
//remove users {USER} and {OWNER}
if ($select == 'users' || $select == 'groups') {
- data.vXStrings = _.reject(data.vXStrings, function(m){return (m.value == '{USER}' || m.value == '{OWNER}')})
+ if (_.isUndefined(auditFilter)) {
+ data.vXStrings = _.reject(data.vXStrings, function(m){return (m.value == '{USER}' || m.value == '{OWNER}')})
+ }
results = data.vXStrings.map(function(m) {
return {
id: _.escape(m.value),
diff --git a/security-admin/src/main/webapp/scripts/views/service/AuditFilterConfig.js b/security-admin/src/main/webapp/scripts/views/service/AuditFilterConfig.js
new file mode 100644
index 0000000..79dcd07
--- /dev/null
+++ b/security-admin/src/main/webapp/scripts/views/service/AuditFilterConfig.js
@@ -0,0 +1,438 @@
+/*
+ * 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) {
+ 'use strict';
+
+ var Backbone = require('backbone');
+ var App = require('App');
+ var XAEnums = require('utils/XAEnums');
+ var XAUtil = require('utils/XAUtils');
+ var localization = require('utils/XALangSupport');
+ var ServiceAuditFilterResourcesForm = require('views/service/ServiceAuditFilterResources');
+ var RangerPolicyResource = require('models/RangerPolicyResource');
+ require('bootstrap-editable');
+
+ var AuditConfigItem = Backbone.Marionette.ItemView.extend({
+ _msvName : 'FormInputItem',
+
+ template : require('hbs!tmpl/service/AuditFilterItem_tmpl'),
+
+ tagName : 'tr',
+
+ templateHelpers : function(){},
+
+ ui : {
+ selectUsers : '[data-js="selectUsers"]',
+ selectGroups : '[data-js="selectGroups"]',
+ selectRoles : '[data-js="selectRoles"]',
+ addPerms : 'a[data-js="permissions"]',
+ addPermissionsSpan : '.add-permissions',
+ addResources : '[data-js="serviceResource"]',
+ removeResources : '[data-action="deleteResources"]',
+ oparations : '[data-js="oparations"]',
+ accessResult : '[data-js="accessResult"]',
+ },
+ events : {
+ 'click [data-action="delete"]' : 'evDelete',
+ 'change [data-js="isAudited"]': 'evIsAudited',
+ 'change [data-js="accessResult"]': 'evAccessResult',
+ 'click [data-js="serviceResource"]' : 'eGetResources',
+ 'click [data-action="deleteResources"]' : 'eRemoveResources',
+ 'change [data-js="selectUsers"]': 'evSelectUsers',
+ 'change [data-js="selectGroups"]': 'evSelectGroup',
+ 'change [data-js="selectRoles"]': 'evSelectRoles',
+ 'change [data-js="oparations"]': 'evOparations',
+ },
+
+ initialize : function(options) {
+ _.extend(this, _.pick(options,'rangerServiceDefModel', 'accessTypes', 'serviceName'));
+ },
+
+ onRender : function() {
+ var accessResultVal = _.map(XAEnums.AccessResult, function(m){
+ return {'id' : m.label ,'text': m.label}
+ })
+ if (this.model && !_.isUndefined(this.model.get('accessResult'))) {
+ this.ui.accessResult.val(this.model.get('accessResult'));
+ }
+ this.ui.accessResult.select2({
+ placeholder: "Select Value",
+ allowClear: true,
+ maximumSelectionSize : 1,
+ data: accessResultVal,
+ theme: 'bootstrap4',
+ });
+ this.setupFormForEditMode();
+ this.evIsAudited();
+ this.renderPermissions();
+ this.ui.selectUsers.select2(XAUtil.getUsersGroupsList("users", this, '250px', "auditFilter"));
+ this.ui.selectGroups.select2(XAUtil.getUsersGroupsList("groups", this, '250px', "auditFilter"));
+ this.ui.selectRoles.select2(XAUtil.getUsersGroupsList("roles", this, '250px', "auditFilter"));
+ this.selectOparations();
+ },
+
+ setupFormForEditMode : function () {
+ var that = this;
+ if(!this.model.isEmpty()) {
+ if (this.model.get('isAudited')) {
+ this.$el.find('[data-js="isAudited"]').val(this.model.get('isAudited'));
+ }
+ if (this.model.get('users')) {
+ this.ui.selectUsers.val(_.map(this.model.get('users'), function(name){ return _.escape(name)}));
+ }
+ if (this.model.get('groups')) {
+ this.ui.selectGroups.val(_.map(this.model.get('groups'), function(name){ return _.escape(name); }));
+ }
+ if (this.model.get('roles')) {
+ this.ui.selectRoles.val(_.map(this.model.get('roles'), function(name){ return _.escape(name); }));
+ }
+ if (this.model.get('accessTypes')) {
+ _.each(this.model.get('accessTypes'), function(val) {
+ that.$el.find('input[data-name="' + val + '"]').prop('checked', true);
+ })
+ }
+ if (this.model.get('resources')) {
+ this.displayResources(this.model.get('resources'));
+ }
+ }
+ },
+
+ evIsAudited : function (e) {
+ if(_.isUndefined(e)) {
+ this.model.set('isAudited',this.$el.find('[data-js="isAudited"]').val());
+ }else {
+ this.model.set('isAudited', e.currentTarget.value);
+ }
+ },
+
+ evAccessResult : function (e){
+ if($(e.currentTarget).val() != "") {
+ this.model.set('accessResult', e.currentTarget.value);
+ } else {
+ this.model.unset('accessResult');
+ }
+ },
+
+ evSelectUsers : function (e) {
+ this.model.set('users', e.val)
+ },
+
+ evSelectGroup : function (e) {
+ this.model.set('groups', e.val)
+ },
+
+ evSelectRoles : function (e) {
+ this.model.set('roles', e.val)
+ },
+
+ evOparations : function (e) {
+ this.model.set('actions', e.val)
+ },
+
+ renderPermissions : function() {
+ this.permsIds = [];
+ var that = this;
+ this.perms = _.map(this.accessTypes , function(m){return {text : m.label, value : m.name};});
+ if(this.perms.length > 1){
+ this.perms.push({'value' : -1, 'text' : 'Select/Deselect All'});
+ }
+ if (this.model && this.model.get('accessTypes')) {
+ this.permsIds = this.model.get('accessTypes');
+ }
+ this.ui.addPerms.editable({
+ emptytext : 'Add Permissions',
+ source: this.perms,
+ value : this.permsIds,
+ display: function(values,srcData) {
+ if(_.isNull(values) || _.isEmpty(values) || (_.contains(values,"-1") && values.length == 1)){
+ $(this).empty();
+ that.model.unset('accessTypes');
+ that.ui.addPermissionsSpan.find('i').attr('class', 'fa-fw fa fa-plus');
+ that.ui.addPermissionsSpan.attr('title','add');
+ return;
+ }
+ if(_.contains(values,"-1")){
+ values = _.without(values,"-1")
+ }
+ //that.checkDirtyFieldForGroup(values);
+ var permTypeArr = [];
+ var valArr = _.map(values, function(id){
+ if(!_.isUndefined(id)){
+ var obj = _.findWhere(that.rangerServiceDefModel.attributes.accessTypes,{'name' : id});
+ permTypeArr.push({permType : obj.value});
+ return "<span class='badge badge-info'>" + obj.label + "</span>";
+ }
+ });
+ that.model.set('accessTypes', values);
+ $(this).html(valArr.join(" "));
+ that.ui.addPermissionsSpan.find('i').attr('class', 'fa-fw fa fa-pencil');
+ that.ui.addPermissionsSpan.attr('title','edit');
+ }}).on('shown', function(e, editable) {
+ that.clickOnPermissions(that);
+ });
+ that.ui.addPermissionsSpan.click(function(e) {
+ e.stopImmediatePropagation();
+ that.$('a[data-js="permissions"]').editable('toggle');
+ that.clickOnPermissions(that);
+ });
+
+ },
+
+ clickOnPermissions : function(that) {
+ var selectAll = true;
+ var checklist = $('.editable-checklist').find('input[type="checkbox"]')
+ _.each(checklist,function(checkbox){
+ if($(checkbox).val() != -1 && !$(checkbox).is(':checked'))
+ selectAll = false;
+ })
+ if(selectAll){
+ $('.editable-checklist').find('input[type="checkbox"][value="-1"]').prop('checked',true)
+ } else {
+ $('.editable-checklist').find('input[type="checkbox"][value="-1"]').prop('checked',false)
+ }
+ //for selectAll functionality
+ $('input[type="checkbox"][value="-1"]').click(function(e){
+ var checkboxlist =$(this).closest('.editable-checklist').find('input[type="checkbox"][value!=-1]')
+ $(this).is(':checked') ? checkboxlist.prop('checked',true) : checkboxlist.prop('checked',false);
+ });
+ $('.editable-checklist input[type="checkbox"]').click(function(e){
+ if(this.value!="-1"){
+ var selectAll = true;
+ $('.editable-checklist input[type="checkbox"]').each(function(index,item){
+ if(item.value!="-1" && !item.checked){
+ selectAll = false;
+ }
+ });
+ $('input[type="checkbox"][value="-1"]').prop('checked',selectAll);
+ }
+ });
+ },
+
+ eGetResources :function () {
+ var model = null;
+ if (!_.isUndefined(this.model.get('resources'))) {
+ this.model.set('policyType', 0);
+ this.model.set('id', 'resource' + this.model.collection.length);
+ model = $.extend(true, {}, this.model);
+ // model = _.clone(resourceModel)
+ // _.each(model.get('resources'), function(val, key, obj) {
+ // obj[key] = {
+ // 'values': val
+ // };
+ // });
+ }
+ // this.rangerServiceDefModel.get('resources')[0].lookupSupported = false
+ if (_.isEmpty(this.serviceName)) {
+ this.rangerServiceDefModel.get('resources').map( function(m){
+ m.lookupSupported = false;
+ m.validationRegEx = '';
+ m.validationMessage = '';
+ })
+ }
+ this.form = new ServiceAuditFilterResourcesForm({
+ template: require('hbs!tmpl/service/ServiceAuditFilterResourcesForm_tmpl'),
+ model: model ? model : new RangerPolicyResource({
+ policyType: 0
+ }),
+ rangerServiceDefModel: this.rangerServiceDefModel,
+ serviceName : this.serviceName,
+ });
+ this.modal = new Backbone.BootstrapModal({
+ animate: true,
+ content: this.form,
+ title: 'Add/Edit Resources',
+ okText: 'Save',
+ allowCancel: true,
+ escape: true
+ }).open();
+ this.modal.on("ok", this.onSave.bind(this, this.model));
+ },
+
+ onSave: function(resourceModel) {
+ var that = this,
+ tmpResource = {}, resource = {};
+ var errors = this.form.commit({
+ validate: false
+ });
+ if (!_.isEmpty(errors)) {
+ that.modal.preventClose();
+ return;
+ }
+ _.each(this.form.model.attributes, function(val, key) {
+ if (key.indexOf("sameLevel") >= 0 && !_.isNull(val)) {
+ this.form.model.set(val.resourceType, val);
+ this.form.model.unset(key);
+ }
+ }, this);
+ _.each(that.rangerServiceDefModel.get('resources'), function(obj) {
+ var tmpObj = that.form.model.get(obj.name);
+ if (!_.isUndefined(tmpObj) && _.isObject(tmpObj) && !_.isEmpty(tmpObj.resource)) {
+ tmpResource[obj.name] ={}, resource[obj.name] ={};
+ tmpResource[obj.name].values = tmpObj.resource.split(',');
+ resource[obj.name].values = tmpObj.resource.split(',');
+ if (obj.excludesSupported) {
+ resource[obj.name]['isExcludes'] = tmpObj.isExcludes;
+ }
+ if (obj.recursiveSupported) {
+ resource[obj.name]['isRecursive'] = tmpObj.isRecursive;
+ }
+ that.form.model.unset(obj.name);
+ }
+ });
+ this.displayResources(resource);
+ this.model.set('resources', resource) ;
+ },
+
+ displayResources : function(tmpResource) {
+ var $dataResources;
+ $dataResources = '<div class="resourceGrp"><div>'
+ _.filter(tmpResource, function(key, value) {
+ var $toggleBtn =''
+ if(!_.isUndefined(key.isExcludes)) {
+ var isExcludes = key.isExcludes ? XAEnums.ExcludeStatus.STATUS_EXCLUDE.label : XAEnums.ExcludeStatus.STATUS_INCLUDE.label;
+ $toggleBtn += '<span class="badge badge-dark pull-right">'+isExcludes+'</span>'
+ }
+ if (!_.isUndefined(key.isRecursive)) {
+ var isRecursive = key.isRecursive ? XAEnums.RecursiveStatus.STATUS_RECURSIVE.label : XAEnums.RecursiveStatus.STATUS_NONRECURSIVE.label;
+ $toggleBtn += '<span class="badge badge-dark pull-right">'+isRecursive+'</span>'
+ }
+ $dataResources += '<div class="resourcesFilter"><div><b>' + value + '</b>:' + key.values.join(', ') +'</div>' + $toggleBtn +'</div>'
+ })
+ $dataResources += '</div>'
+ this.$el.find('.js-formInput').html($dataResources);
+ this.ui.addResources.find('i').attr('class', 'fa-fw fa fa-pencil');
+ },
+
+ eRemoveResources : function (argument) {
+ var $dataResources = '<div class="resourceGrp text-center">--</div>'
+ this.$el.find('.js-formInput').html($dataResources);
+ if(this.model && !_.isUndefined(this.model.get('resources'))) {
+ this.model.unset('resources');
+ }
+ },
+
+ evSelectUserGroupRole : function (e) {
+ e.currentTarget.select2(XAUtil.getUsersGroupsList(e.currentTarget.dataset.type, this))
+ },
+ evDelete : function(){
+ var that = this;
+ this.collection.remove(this.model);
+ },
+ selectOparations : function() {
+ var that = this;
+ var tags = [];
+ this.ui.oparations.select2({
+ multiple: true,
+ closeOnSelect : true,
+ placeholder : 'Select Action',
+ allowClear: true,
+ width : '200px',
+ tokenSeparators: ["," , " "],
+ tags : [],
+ dropdownCssClass: 'select2-text-hidden',
+ initSelection : function (element, callback) {
+ callback(tags);
+ },
+ createSearchChoice : function(term, data) {
+ if ($(data).filter(function() {
+ return this.text.localeCompare(term)===0;
+ }).length===0)
+ {return {id:term, text:term};}
+ },
+ })
+ if (this.model.get('actions')) {
+ _.each(this.model.get('actions') , function(name){
+ tags.push( { 'id' : _.escape( name ), 'text' : _.escape( name ) } );
+ });
+ this.ui.oparations.select2('val',tags)
+ }
+ },
+
+ });
+
+ var AuditFilterList = Backbone.Marionette.CompositeView.extend({
+ _msvName : 'AuditFilterList',
+
+ template : require('hbs!tmpl/service/AuditFilterList_tmpl'),
+
+ templateHelpers :function(){
+ return {
+ emptyAuditFilterCol : this.collection.length == 0 ? true : false,
+ }
+ },
+
+ getItemView : function(item){
+ if(!item){
+ return;
+ }
+ return AuditConfigItem;
+ },
+ itemViewContainer : ".js-formInput",
+
+ itemViewOptions : function() {
+ return {
+ 'collection' : this.collection,
+ 'accessTypes' : this.rangerServiceDefModel.get('accessTypes').filter(function(val) { return val !== null; }),
+ 'rangerServiceDefModel' : this.rangerServiceDefModel,
+ 'serviceName' : this.serviceName,
+ };
+ },
+ events : {
+ 'click [data-action="addGroup"]' : 'addNew'
+ },
+ initialize : function(options) {
+ _.extend(this, _.pick(options, 'rangerServiceDefModel', 'serviceName'));
+ if(this.collection.length == 0){
+ this.collection.add();
+ }
+ },
+ onRender : function(){
+ this.makePolicyItemSortable();
+ },
+ addNew : function(){
+ var that =this;
+ this.$el.find('.emptySet').remove();
+ this.$('table').show();
+ this.collection.add(new Backbone.Model());
+ },
+ makePolicyItemSortable : function(){
+ var that = this, draggedModel;
+ this.$el.find(".js-formInput" ).sortable({
+ placeholder: "ui-state-highlight",
+ start : function(event, ui){
+ var row = ui.item[0].rowIndex - 1;
+ draggedModel = that.collection.at(row);
+ },
+ stop : function(event, ui){
+ var row = ui.item[0].rowIndex -1;
+ that.collection.remove(draggedModel, { silent : true});
+ that.collection.add(draggedModel ,{ at: row, silent : true });
+ that.$el.find(ui.item[0]).addClass("dirtyField");
+ },
+ });
+ }
+ });
+
+ return AuditFilterList;
+
+});
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/scripts/views/service/ServiceAuditFilterResources.js b/security-admin/src/main/webapp/scripts/views/service/ServiceAuditFilterResources.js
new file mode 100644
index 0000000..c08f745
--- /dev/null
+++ b/security-admin/src/main/webapp/scripts/views/service/ServiceAuditFilterResources.js
@@ -0,0 +1,488 @@
+/*
+ * 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) {
+ 'use strict';
+
+ var Backbone = require('backbone');
+ var XAEnums = require('utils/XAEnums');
+ var localization = require('utils/XALangSupport');
+ var XAUtil = require('utils/XAUtils');
+ var RangerPolicyResource = require('models/RangerPolicyResource');
+ var BackboneFormDataType = require('models/BackboneFormDataType');
+ require('backbone-forms.list');
+ require('backbone-forms.templates');
+ require('backbone-forms');
+ require('backbone-forms.XAOverrides');
+ require('jquery-ui');
+ require('tag-it');
+
+ var ServiceAuditFilterResources = Backbone.Form.extend(
+ /** @lends ServiceAuditFilterResources */
+ {
+ _viewName: 'ServiceAuditFilterResources',
+
+ /**
+ * intialize a new ServiceAuditFilterResources Form View
+ * @constructs
+ */
+
+ templateData: function() {
+ var policyType = XAUtil.enumElementByValue(XAEnums.RangerPolicyType, this.model.get('policyType'));
+ return {
+ 'id': this.model.id,
+ 'policyType': policyType.label
+ };
+ },
+
+ initialize: function(options) {
+ console.log("initialized a ServiceAuditFilterResources Form View");
+ _.extend(this, _.pick(options, 'rangerServiceDefModel', 'serviceName'));
+ this.setupForm();
+ Backbone.Form.prototype.initialize.call(this, options);
+ this.bindEvents();
+ this.defaultValidator = {}
+ },
+
+ /** all events binding here */
+ bindEvents: function() {
+ this.on('policyForm:parentChildHideShow', this.renderParentChildHideShow);
+ },
+
+ ui: {},
+
+ /** fields for the form
+ */
+ fields: [],
+
+ schema: function() {
+ return this.getSchema();
+ },
+
+ getSchema: function() {
+ var attrs = {},
+ that = this;
+ var formDataType = new BackboneFormDataType();
+ attrs = formDataType.getFormElements(this.rangerServiceDefModel.get('resources'), this.rangerServiceDefModel.get('enums'), attrs, this, true);
+ return attrs;
+ },
+
+ /** on render callback */
+ render: function(options) {
+ var that = this;
+ Backbone.Form.prototype.render.call(this, options);
+ //initialize path plugin for hdfs component : resourcePath
+ if (!_.isUndefined(this.initilializePathPlugin) && this.initilializePathPlugin) {
+ this.initializePathPlugins(this.pathPluginOpts);
+ }
+ //checkParent
+ this.renderParentChildHideShow();
+ },
+
+ setupForm: function() {
+ if (!this.model.isNew()) {
+ this.selectedResourceTypes = {};
+ var resourceDefList = this.rangerServiceDefModel.get('resources');
+ _.each(this.model.get('resources'), function(obj, key) {
+ var resourceDef = _.findWhere(resourceDefList, {
+ 'name': key
+ }),
+ sameLevelResourceDef = [],
+ parentResource;
+ sameLevelResourceDef = _.filter(resourceDefList, function(objRsc){
+ if (objRsc.level === resourceDef.level && objRsc.parent === resourceDef.parent) {
+ return objRsc
+ }
+ });
+ //for parent leftnode status
+ if (resourceDef.parent) {
+ parentResource = _.findWhere(resourceDefList, {
+ 'name': resourceDef.parent
+ });
+ }
+ if (sameLevelResourceDef.length == 1 && !_.isUndefined(sameLevelResourceDef[0].parent) &&
+ !_.isEmpty(sameLevelResourceDef[0].parent) &&
+ parentResource.isValidLeaf) {
+ sameLevelResourceDef.push({
+ 'level': sameLevelResourceDef[0].level,
+ name: 'none',
+ label: 'none'
+ });
+ }
+ if (sameLevelResourceDef.length > 1) {
+ obj['resourceType'] = key;
+ if (_.isUndefined(resourceDef.parent)) {
+ this.model.set('sameLevel' + resourceDef.level, obj);
+ //parentShowHide
+ this.selectedResourceTypes['sameLevel' + resourceDef.level] = key;
+ } else {
+ this.model.set('sameLevel' + resourceDef.level + resourceDef.parent, obj);
+ this.selectedResourceTypes['sameLevel' + resourceDef.level + resourceDef.parent] = key;
+ }
+
+ } else {
+ this.model.set(resourceDef.name, obj)
+ }
+ }, this);
+ }
+ },
+
+ /** all custom field rendering */
+ renderParentChildHideShow: function(onChangeOfSameLevelType, val, e) {
+ var formDiv = this.$el.find('.zoneResources-form');
+ if (!this.model.isNew() && !onChangeOfSameLevelType) {
+ _.each(this.selectedResourceTypes, function(val, sameLevelName) {
+ if (formDiv.find('.field-' + sameLevelName).length > 0) {
+ formDiv.find('.field-' + sameLevelName).attr('data-name', 'field-' + val)
+ }
+ });
+ }
+ //hide form fields if it's parent is hidden
+ var resources = formDiv.find('.form-group');
+ _.each(resources, function(rsrc, key) {
+ var parent = $(rsrc).attr('parent');
+ var label = $(rsrc).find('label').html();
+ $(rsrc).removeClass('error');
+ //remove validation and Required msg
+ $(rsrc).find('.help-inline').empty();
+ $(rsrc).find('.help-block').empty();
+ if (!_.isUndefined(parent) && !_.isEmpty(parent)) {
+ var selector = "div[data-name='field-" + parent + "']";
+ var kclass = formDiv.find(selector).attr('class');
+ var label = $(rsrc).find('label').html();
+ if (_.isUndefined(kclass) || (kclass.indexOf("field-sameLevel") >= 0 &&
+ formDiv.find(selector).find('select').val() != parent) ||
+ formDiv.find(selector).hasClass('hideResource')) {
+ $(rsrc).addClass('hideResource');
+ $(rsrc).removeClass('error');
+ //reset input field to "none" if it is hide
+ var resorceFieldName = _.pick(this.schema, this.selectedFields[key]);
+ if (resorceFieldName[this.selectedFields[key]].sameLevelOpts && _.contains(resorceFieldName[this.selectedFields[key]].sameLevelOpts, 'none') &&
+ formDiv.find(selector).find('select').val() != 'none' && onChangeOfSameLevelType) {
+ //change trigger and set value to none
+ $(rsrc).find('select').val("none").trigger('change', "onChangeResources");
+ }
+ } else {
+ if ($(rsrc).find('select').val() == 'none') {
+ $(rsrc).find('input[data-js="resource"]').select2('disable');
+ $(rsrc).removeClass('error');
+ $(rsrc).find('label').html(label.split('*').join(''));
+ } else {
+ $(rsrc).find('input[data-js="resource"]').select2('enable');
+ if (label.slice(-2) == '**') {
+ $(rsrc).find('label').html(label.slice(-1) == '*' ? label : label + "*");
+ }
+ }
+ $(rsrc).removeClass('hideResource');
+ }
+ }
+ }, this);
+ //remove validation of fields if it's hidden
+ //remove validation if fields is not empty
+ _.each(this.fields, function(field, key) {
+ if ((key.substring(0, key.length - 2) === "sameLevel") && field.$el.find('[data-js="resource"]').val() != "" && field.$el.hasClass('error')) {
+ field.$el.removeClass('error');
+ field.$el.find('.help-inline').empty();
+ }
+ if (field.$el.hasClass('hideResource')) {
+ if ($.inArray('required', field.editor.validators) >= 0) {
+ this.defaultValidator[key] = field.editor.validators;
+ field.editor.validators = [];
+ var label = field.$el.find('label').html();
+ field.$el.find('label').html(label.replace('*', ''));
+ field.$el.removeClass('error');
+ field.$el.find('.help-inline').empty();
+ }
+ } else {
+ if (field.$el.find('select').val() == 'none') {
+ field.editor.validators = [];
+ this.defaultValidator[key] = field.editor.validators;
+ field.$el.removeClass('error');
+ field.$el.find('.help-inline').empty();
+ } else {
+ if (!_.isUndefined(this.defaultValidator[key])) {
+ field.editor.validators.push('required');
+ if ($.inArray('required', field.editor.validators) >= 0) {
+ var label = field.$el.find('label').html();
+ field.$el.find('label').html(label.slice(-1) == '*' ? label : label + "*");
+ }
+ }
+ }
+ }
+ }, this);
+ },
+
+ /** all post render plugin initialization */
+ initializePathPlugins: function(options) {
+ var that = this,
+ defaultValue = [];
+ if (!this.model.isNew() && !_.isUndefined(this.model.get('path'))) {
+ defaultValue = this.model.get('path').values;
+ }
+
+ function split(val) {
+ return val.split(/,\s*/);
+ }
+
+ function extractLast(term) {
+ return split(term).pop();
+ }
+ var tagitOpts = {}
+ if (!_.isUndefined(options.lookupURL) && options.lookupURL) {
+ tagitOpts["autocomplete"] = {
+ cache: false,
+ source: function(request, response) {
+ var url = "service/plugins/services/lookupResource/" + that.serviceName;
+ var context = {
+ 'userInput': extractLast(request.term),
+ 'resourceName': that.pathFieldName,
+ 'resources': {}
+ };
+ var val = that.fields[that.pathFieldName].editor.getValue();
+ context.resources[that.pathFieldName] = _.isNull(val) || _.isEmpty(val) ? [] : val.resource.split(",");
+ var p = $.ajax({
+ url: url,
+ type: "POST",
+ data: JSON.stringify(context),
+ dataType: 'json',
+ contentType: "application/json; charset=utf-8",
+ }).done(function(data) {
+ if (data) {
+ response(data);
+ } else {
+ response();
+ }
+ }).fail(function() {
+ response();
+ });
+ setTimeout(function() {
+ p.abort();
+ console.log('connection timeout for resource path request...!!');
+ }, 10000);
+ },
+ open: function() {
+ $(this).removeClass('working');
+ },
+ search: function() {
+ $('.tagit-autocomplete').addClass('tagit-position');
+ if (!_.isUndefined(this.value) && (/[ ,]+/).test(this.value)) {
+ var values = this.value.trim().split(/[ ,]+/);
+ if (values.length > 1) {
+ for (var i = 0; i < values.length; i++) {
+ that.fields[that.pathFieldName].editor.$el.find('[data-js="resource"]').tagit("createTag", values[i]);
+ }
+ return ''
+ } else {
+ return val
+ }
+ }
+ var term = extractLast(_.escape(this.value));
+ $(this).addClass('working');
+ if (term.length < 1) {
+ return false;
+ }
+ },
+ }
+ }
+ tagitOpts['beforeTagAdded'] = function(event, ui) {
+ // do something special
+ that.fields[that.pathFieldName].$el.removeClass('error');
+ that.fields[that.pathFieldName].$el.find('.help-inline').html('');
+ var tags = [];
+ console.log(ui.tag);
+ if (!_.isUndefined(options.regExpValidation) && !options.regExpValidation.regexp.test(ui.tagLabel)) {
+ that.fields[that.pathFieldName].$el.addClass('error');
+ that.fields[that.pathFieldName].$el.find('.help-inline').html(options.regExpValidation.message);
+ return false;
+ }
+ }
+ this.fields[that.pathFieldName].editor.$el.find('[data-js="resource"]').tagit(tagitOpts).on('change', function(e) {
+ //check dirty field for tagit input type : `path`
+ XAUtil.checkDirtyField($(e.currentTarget).val(), defaultValue.toString(), $(e.currentTarget));
+ });
+ },
+
+ getPlugginAttr: function(autocomplete, options) {
+ var that = this,
+ type = options.containerCssClass,
+ validRegExpString = true,
+ select2Opts = [];
+ if (!autocomplete)
+ return {
+ tags: true,
+ width: '220px',
+ multiple: true,
+ minimumInputLength: 1,
+ 'containerCssClass': type
+ };
+ else {
+ select2Opts = {
+ containerCssClass: options.type,
+ closeOnSelect: true,
+ tags: true,
+ multiple: true,
+ minimumInputLength: 1,
+ width: '220px',
+ tokenSeparators: [",", " "],
+ initSelection: function(element, callback) {
+ var data = [];
+ //to set single select value
+ if (!_.isUndefined(options.singleValueInput) && options.singleValueInput) {
+ callback({
+ id: element.val(),
+ text: element.val()
+ });
+ return;
+ }
+ //this is form multi-select value
+ $(element.val().split(",")).each(function() {
+ data.push({
+ id: this,
+ text: this
+ });
+ });
+ callback(data);
+ },
+ createSearchChoice: function(term, data) {
+ term = _.escape(term);
+ if ($(data).filter(function() {
+ return this.text.localeCompare(term) === 0;
+ }).length === 0) {
+ if (!_.isUndefined(options.regExpValidation) && !options.regExpValidation.regexp.test(term)) {
+ validRegExpString = false;
+ } else if ($.inArray(term, this.val()) >= 0) {
+ return null;
+ } else {
+ return {
+ id: term,
+ text: term
+ };
+ }
+ }
+ },
+ ajax: {
+ url: options.lookupURL,
+ type: 'POST',
+ params: {
+ timeout: 10000,
+ contentType: "application/json; charset=utf-8",
+ },
+ cache: false,
+ data: function(term, page) {
+ return that.getDataParams(term, options);
+ },
+ results: function(data, page) {
+ var results = [];
+ if (!_.isUndefined(data)) {
+ if (_.isArray(data) && data.length > 0) {
+ results = data.map(function(m, i) {
+ return {
+ id: m,
+ text: m
+ };
+ });
+ }
+ if (!_.isUndefined(data.resultSize) && data.resultSize != "0") {
+ results = data.vXStrings.map(function(m, i) {
+ return {
+ id: m.value,
+ text: m.value
+ };
+ });
+ }
+ }
+ return {
+ results: results
+ };
+ },
+ transport: function(options) {
+ $.ajax(options).fail(function() {
+ console.log("ajax failed");
+ this.success({
+ resultSize: 0
+ });
+ });
+ }
+
+ },
+ formatResult: function(result) {
+ return result.text;
+ },
+ formatSelection: function(result) {
+ return result.text;
+ },
+ formatNoMatches: function(term) {
+ if (!validRegExpString && !_.isUndefined(options.regExpValidation)) {
+ return options.regExpValidation.message;
+ }
+ return "No Matches found";
+ }
+ };
+ //To support single value input
+ if (!_.isUndefined(options.singleValueInput) && options.singleValueInput) {
+ select2Opts['maximumSelectionSize'] = 1;
+ }
+ return select2Opts;
+ }
+ },
+
+ getDataParams: function(term, options) {
+ var resources = {},
+ resourceName = options.type;
+ var isParent = true,
+ name = options.type,
+ val = null,
+ isCurrentSameLevelField = true;
+ while (isParent) {
+ var currentResource = _.findWhere(this.rangerServiceDefModel.get('resources'), {
+ 'name': name
+ });
+ //same level type
+ if (_.isUndefined(this.fields[currentResource.name])) {
+ if (!_.isUndefined(currentResource.parent)) {
+ var sameLevelName = 'sameLevel' + currentResource.level + currentResource.parent;
+ } else {
+ var sameLevelName = 'sameLevel' + currentResource.level;
+ }
+
+ name = this.fields[sameLevelName].editor.$resourceType.val()
+ val = this.fields[sameLevelName].getValue();
+ if (isCurrentSameLevelField) {
+ resourceName = name;
+ }
+ } else {
+ val = this.fields[name].getValue();
+ }
+ resources[name] = _.isNull(val) ? [] : val.resource.split(',');
+ if (!_.isEmpty(currentResource.parent)) {
+ name = currentResource.parent;
+ } else {
+ isParent = false;
+ }
+ isCurrentSameLevelField = false;
+ }
+ var context = {
+ 'userInput': term,
+ 'resourceName': resourceName,
+ 'resources': resources
+ };
+ return JSON.stringify(context);
+ },
+ });
+ return ServiceAuditFilterResources;
+});
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/scripts/views/service/ServiceForm.js b/security-admin/src/main/webapp/scripts/views/service/ServiceForm.js
index 653d3d5..e7d5b79 100644
--- a/security-admin/src/main/webapp/scripts/views/service/ServiceForm.js
+++ b/security-admin/src/main/webapp/scripts/views/service/ServiceForm.js
@@ -27,7 +27,8 @@ define(function(require){
var localization = require('utils/XALangSupport');
var BackboneFormDataType = require('models/BackboneFormDataType');
- var ConfigurationList = require('views/service/ConfigurationList')
+ var ConfigurationList = require('views/service/ConfigurationList');
+ var AuditFilterConfig = require('views/service/AuditFilterConfig')
require('backbone-forms');
require('backbone-forms.list');
@@ -62,6 +63,7 @@ define(function(require){
console.log("initialized a ServiceForm Form View");
_.extend(this, _.pick(options, 'rangerServiceDefModel'));
this.extraConfigColl = new Backbone.Collection();
+ this.auditFilterColl = new Backbone.Collection();
this.setupFormForEditMode();
Backbone.Form.prototype.initialize.call(this, options);
@@ -98,9 +100,16 @@ define(function(require){
this.setupForm();
this.initializePlugins();
this.renderCustomFields();
+ this.renderAuditFilterFields();
},
setupFormForEditMode : function() {
+ var that = this;
if(!this.model.isNew()){
+
+ if(this.model.get('configs')['ranger.plugin.audit.filters']) {
+ var auditFilterCollValue = this.model.get('configs')['ranger.plugin.audit.filters'];
+ delete this.model.get('configs')['ranger.plugin.audit.filters']
+ }
_.each(this.model.get('configs'),function(value, name){
var configObj = _.findWhere(this.rangerServiceDefModel.get('configs'),{'name' : name });
if(!_.isUndefined(configObj) && configObj.type == 'bool'){
@@ -112,6 +121,14 @@ define(function(require){
}
}
},this);
+
+ if(auditFilterCollValue) {
+ auditFilterCollValue = JSON.parse(auditFilterCollValue);
+ console.log(auditFilterCollValue);
+ auditFilterCollValue.forEach(function(model) {
+ that.auditFilterColl.add(new Backbone.Model(model));
+ })
+ }
}
},
setupForm : function() {
@@ -138,6 +155,15 @@ define(function(require){
}).render().el);
},
+ /**Audit filters rendering**/
+ renderAuditFilterFields: function(){
+ this.$('[data-customfields="aduitFilterConfig"]').html(new AuditFilterConfig({
+ collection : this.auditFilterColl,
+ rangerServiceDefModel : this.rangerServiceDefModel,
+ serviceName : (!_.isUndefined(this.model) && !_.isEmpty(this.model.get('name')) ? this.model.get('name') : ''),
+ }).render().el);
+ },
+
/** all post render plugin initialization */
initializePlugins: function(){
},
@@ -185,6 +211,13 @@ define(function(require){
this.extraConfigColl.each(function(obj){
if(!_.isEmpty(obj.attributes)) config[obj.get('name')] = obj.get('value');
});
+ if (this.auditFilterColl.length > 0) {
+ var auditFiltter = [];
+ this.auditFilterColl.each(function (e) {
+ auditFiltter.push(e.attributes);
+ })
+ config['ranger.plugin.audit.filters'] = JSON.stringify(auditFiltter);
+ }
this.model.set('configs',config);
//Set service type
diff --git a/security-admin/src/main/webapp/scripts/views/users/AddUsersOrGroupsList.js b/security-admin/src/main/webapp/scripts/views/users/AddUsersOrGroupsList.js
index 3a24690..26a62e6 100644
--- a/security-admin/src/main/webapp/scripts/views/users/AddUsersOrGroupsList.js
+++ b/security-admin/src/main/webapp/scripts/views/users/AddUsersOrGroupsList.js
@@ -128,7 +128,7 @@ define(function(require) {
this.$el.find('[data-id="userGroupsTable"]').html('<tr data-name="'+this.fieldName+'"><td colspan="3"> No '
+this.fieldName+' found</td></tr>');
}
- this.ui.selectUsersOrGroups.select2(XAUtil.getUsersGroupsList(this.fieldName, this));
+ this.ui.selectUsersOrGroups.select2(XAUtil.getUsersGroupsList(this.fieldName, this, '300px'));
this.ui.selectUsersOrGroups.attr("data-name", this.fieldName+"Select");
this.ui.addUserGroupRoleBtn.attr("data-name", this.fieldName+"AddBtn")
},
diff --git a/security-admin/src/main/webapp/styles/xa.css b/security-admin/src/main/webapp/styles/xa.css
index 80ece70..5c11e14 100644
--- a/security-admin/src/main/webapp/styles/xa.css
+++ b/security-admin/src/main/webapp/styles/xa.css
@@ -4566,4 +4566,101 @@ input.textFiledInputPadding:disabled {
.report-table .backgrid-subgrid-custom-row th:not(.renderable), .report-table .backgrid-subgrid-custom-row td:not(.renderable){
display: table-cell!important;
+}
+
+.zoneResources-form .select2-container {
+ float: left;
+}
+
+.zoneResources-form .form-group.field-path[fieldclass="resorces-with-label-css"] .include-toggle {
+ left: -7vw;
+ top: 7vh;
+}
+
+.zoneResources-form .form-horizontal .form-group{
+ float:none;
+}
+
+.zoneResources-form .control-label{
+ padding-top: 1px;
+}
+
+.zoneResources-form .recursive-toggle-2 {
+ left: -7vw;
+ position: relative;
+}
+
+.width-75 {
+ width: 75px
+}
+
+.width-170 {
+ width: 170px
+}
+
+.min-width-150 {
+ min-width: 150px
+}
+
+.zoneResources-form .form-group.field-path[fieldclass="resorces-with-label-css"] .recursive-toggle-hdfs-1 {
+ margin-left: 14vw;
+ margin-top: 0px;
+}
+
+.zoneResources-form .include-toggle {
+ left: -7vw;
+}
+
+.zoneResources-form .form-group.field-path[fieldclass="resorces-with-label-css"] .include-toggle {
+ left: -7vw;
+ top: 2vw;
+}
+
+.select2-text-hidden {
+ display:none !important;
+}
+
+.resourcesFilter {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ margin-bottom: 8px;
+}
+
+.zoneResources-form [fieldclass="resorces-with-label-css"] > .control-label{
+ top:10px;
+}
+
+.zoneResources-form [fieldclass="resorces-with-label-css"] .include-toggle{
+ margin-top: 0px;
+}
+
+.zoneResources-form [fieldclass="resorces-css"] .include-toggle{
+ top: 0px;
+}
+
+.zoneResources-form [fieldclass="resorces-with-label-css"] .recursive-toggle-1{
+ margin-left: 16vw;
+}
+
+@media screen and (max-width: 1366px) {
+ .zoneResources-form [fieldclass="resorces-css"] .include-toggle{
+ margin-left: 28vw;
+ }
+
+ .zoneResources-form [fieldclass="resorces-with-label-css"] .include-toggle{
+ margin-left: 28vw;
+ }
+ .zoneResources-form .form-group.field-path[fieldclass="resorces-with-label-css"] .recursive-toggle-hdfs-1{
+ margin-left: 21vw;
+ }
+ .zoneResources-form [fieldclass="resorces-with-label-css"] .recursive-toggle-1 {
+ margin-left: 21vw;
+ }
+ .zoneResources-form [fieldclass="resorces-with-label-css"] .recursive-toggle-2 {
+ left:0px;
+ }
+ .zoneResources-form [fieldclass="resorces-css"] .recursive-toggle-2 {
+ left:0px;
+ }
}
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/templates/service/AuditFilterItem_tmpl.html b/security-admin/src/main/webapp/templates/service/AuditFilterItem_tmpl.html
new file mode 100644
index 0000000..0fc2ce7
--- /dev/null
+++ b/security-admin/src/main/webapp/templates/service/AuditFilterItem_tmpl.html
@@ -0,0 +1,70 @@
+{{!--
+ 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.
+--}}
+
+<!-- Is Audited -->
+<td class="">
+ <div class="width-75">
+ <select class="form-control custom-select-sm w-100" data-js="isAudited">
+ <option selected value="true">Yes</option>
+ <option value="false">No</option>
+ </select>
+ </div>
+</td>
+<!-- Access Result -->
+<td class="">
+ <div class="width-170">
+ <input type="text" class="form-control custom-select-sm" data-js="accessResult">
+ </div>
+</td>
+<!-- Resources -->
+<td>
+ <div class="resource-list min-width-150">
+ <div class="js-formInput"><div class="resourceGrp text-center">--</div></div>
+ <button type="button" class="btn btn-mini btn-primary" title="Add Resources" data-js="serviceResource" style="display: inline-block;">
+ <i class="fa-fw fa fa-plus"></i>
+ </button>
+ <a class="btn btn-danger btn-mini" data-action="deleteResources"><i class="fa-fw fa fa-remove"></i></a></div>
+ </div>
+</td>
+
+<!-- Oparations -->
+<td>
+ <input type="text" data-js="oparations" data-type="roles"/>
+</td>
+<!-- Actions -->
+<td>
+ <a href="javascript:;" data-js="permissions" data-type="checklist" data-title="Select permissions" title="add/edit permissions" ></a>
+ <button type="button" class="btn btn-sm add-permissions" title="Add" style="display: inline-block;">
+ <i class="fa-fw fa fa-plus"></i>
+ </button>
+</td>
+<!-- -->
+<td class="">
+ <input type="text" data-js="selectUsers" data-type="users" />
+</td>
+<td class="">
+ <input type="text" data-js="selectGroups" data-type="groups" />
+</td>
+<td class="">
+ <input type="text" data-js="selectRoles" data-type="roles"/>
+</td>
+<!-- Cross Button -->
+<td>
+ <button type="button" class="btn btn-sm btn-danger " data-action="delete">
+ <i class="fa-fw fa fa-remove"></i>
+ </button>
+</td>
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/templates/service/AuditFilterList_tmpl.html b/security-admin/src/main/webapp/templates/service/AuditFilterList_tmpl.html
new file mode 100644
index 0000000..268917a
--- /dev/null
+++ b/security-admin/src/main/webapp/templates/service/AuditFilterList_tmpl.html
@@ -0,0 +1,50 @@
+{{!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+--}}
+<div class="form-group">
+ <!--label class="control-label">{{headerTitle}}</label-->
+ <div class="col-md-12 m-t-sm">
+ <div class="table-responsive">
+ <table class="table-permission table-condensed">
+ <thead>
+ <tr>
+ <th>Is Audited</th>
+ <th>Access Result</th>
+ <th>Resources</th>
+ <th>Operations</th>
+ <th>Permissions</th>
+ <th>Users</th>
+ <th>Groups</th>
+ <th>Roles</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody class="js-formInput permissionItemSortable">
+ {{#if emptyAuditFilterCol}}
+ <td class="emptySet text-muted" colspan="9">No Audit Filter Data Found !!</td>
+ {{/if}}
+ </tbody>
+ </table>
+ </div>
+ </div>
+</div>
+<div class="form-group">
+ <div class="col-md-12 m-t-sm">
+ <button type="button" class="btn btn-sm" data-action="addGroup" title="Add">
+ <i class="fa-fw fa fa-plus"></i>
+ </button>
+ </div>
+</div>
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/templates/service/ServiceAuditFilterResourcesForm_tmpl.html b/security-admin/src/main/webapp/templates/service/ServiceAuditFilterResourcesForm_tmpl.html
new file mode 100644
index 0000000..d3ed5ab
--- /dev/null
+++ b/security-admin/src/main/webapp/templates/service/ServiceAuditFilterResourcesForm_tmpl.html
@@ -0,0 +1,17 @@
+{{!-- 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. --}}
+<form class="form-horizontal">
+ <fieldset>
+ <b data-fieldsets class="zoneResources-form"></b>
+ </fieldset>
+</form>
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/templates/service/ServiceForm_tmpl.html b/security-admin/src/main/webapp/templates/service/ServiceForm_tmpl.html
index 90ee2a5..2b2e9c0 100644
--- a/security-admin/src/main/webapp/templates/service/ServiceForm_tmpl.html
+++ b/security-admin/src/main/webapp/templates/service/ServiceForm_tmpl.html
@@ -30,6 +30,20 @@
{{/compare}}
<div class="extraServiceConfigs"></div>
</fieldset>
+ <fieldset class="configProp">
+ <p class="formHeader">
+ Audit Filter :
+ </p>
+ <div data-customfields="aduitFilterConfig">
+ <div class="form-group">
+ <div class="controls">
+ <img src="images/loading.gif"
+ style="margin-left: 4%; margin-top: 1%;">
+ </img>
+ </div>
+ </div>
+ </div>
+ </fieldset>
<div>
<div class="form-group field-username hdfs hive knox storm">
<label class="control-label" for="c12_username"></label>