Repository: incubator-ranger Updated Branches: refs/heads/master bc1cf982e -> dbd0bba9e
RANGER-913 : Improvements on Reports page in Ranger Admin Signed-off-by: Gautam Borad <[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/dbd0bba9 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/dbd0bba9 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/dbd0bba9 Branch: refs/heads/master Commit: dbd0bba9e4450c0e2022826f922879907f8495df Parents: bc1cf98 Author: Mehul Parikh <[email protected]> Authored: Thu Apr 14 12:55:46 2016 +0530 Committer: Gautam Borad <[email protected]> Committed: Fri Apr 15 11:31:36 2016 +0530 ---------------------------------------------------------------------- .../apache/ranger/plugin/util/SearchFilter.java | 4 + pom.xml | 1 + security-admin/pom.xml | 10 + .../org/apache/ranger/biz/ServiceDBStore.java | 235 ++++++++++++- .../org/apache/ranger/rest/ServiceREST.java | 38 +++ .../ranger/service/RangerPolicyServiceBase.java | 41 ++- .../src/main/webapp/scripts/utils/XAUtils.js | 8 + .../scripts/views/reports/UserAccessLayout.js | 327 +++++++++++++++---- security-admin/src/main/webapp/styles/xa.css | 4 + .../reports/UserAccessLayout_tmpl.html | 37 ++- 10 files changed, 624 insertions(+), 81 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dbd0bba9/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java index 61e8b09..cba3275 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java @@ -118,6 +118,10 @@ public class SearchFilter { params.put(name, value); } + public void removeParam(String name) { + + params.remove(name); + } public Map<String, String> getParamsWithPrefix(String prefix, boolean stripPrefix) { Map<String, String> ret = null; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dbd0bba9/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index c6f8ed7..ff16abd 100644 --- a/pom.xml +++ b/pom.xml @@ -213,6 +213,7 @@ <jackson.version>1.9.13</jackson.version> <sun-jersey-bundle.version>1.19</sun-jersey-bundle.version> <atlas.version>0.6-incubating-SNAPSHOT</atlas.version> + <poi.version>3.12</poi.version> <distMgmtStagingId>apache.staging.https</distMgmtStagingId> <distMgmtStagingName>Apache Release Distribution Repository</distMgmtStagingName> <distMgmtStagingUrl>https://repository.apache.org/service/local/staging/deploy/maven2</distMgmtStagingUrl> http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dbd0bba9/security-admin/pom.xml ---------------------------------------------------------------------- diff --git a/security-admin/pom.xml b/security-admin/pom.xml index 5e03564..2af0cf4 100644 --- a/security-admin/pom.xml +++ b/security-admin/pom.xml @@ -68,6 +68,16 @@ <version>${commons.cli.version}</version> </dependency> <dependency> + <groupId>org.apache.poi</groupId> + <artifactId>poi</artifactId> + <version>${poi.version}</version> + </dependency> + <dependency> + <groupId>org.apache.poi</groupId> + <artifactId>poi-ooxml</artifactId> + <version>${poi.version}</version> + </dependency> + <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>${commons.codec.version}</version> http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dbd0bba9/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java index 9d2e4c6..21ed686 100644 --- a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java @@ -21,9 +21,13 @@ package org.apache.ranger.biz; import java.util.*; import java.util.Map.Entry; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.text.SimpleDateFormat; import javax.annotation.PostConstruct; - +import javax.servlet.http.HttpServletResponse; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; @@ -80,7 +84,13 @@ import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; - +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; @Component public class ServiceDBStore extends AbstractServiceStore { @@ -1792,20 +1802,80 @@ public class ServiceDBStore extends AbstractServiceStore { if(LOG.isDebugEnabled()) { LOG.debug("==> ServiceDBStore.getPolicies()"); } - RangerPolicyList policyList = policyService.searchRangerPolicies(filter); - - predicateUtil.applyFilter(policyList.getPolicies(), filter); - List<RangerPolicy> ret = policyList.getPolicies(); - if(LOG.isDebugEnabled()) { LOG.debug("<== ServiceDBStore.getPolicies()"); } + return ret; + } + + public List<RangerPolicy> getPoliciesForReports(SearchFilter filter) throws Exception { + if (LOG.isDebugEnabled()) { + LOG.debug("==> ServiceDBStore.getPoliciesForReports()"); + } + List<RangerPolicy> ret = new ArrayList<RangerPolicy>(); + List<RangerPolicy> retTemp = new ArrayList<RangerPolicy>(); + Map<Long, RangerPolicy> orderedPolicies = new TreeMap<Long, RangerPolicy>(); + String serviceTypeNames = filter.getParam("serviceType"); + if (serviceTypeNames != null) { + List<String> serviceTypeList = new ArrayList<String>(Arrays.asList(serviceTypeNames.split("_"))); + if (!CollectionUtils.isEmpty(serviceTypeList)) { + for (String serviceType : serviceTypeList) { + filter.setParam("serviceType", serviceType); + RangerPolicyList policyList = policyService.searchRangerPolicies(filter); + if (policyList!=null){ + retTemp = policyList.getPolicies(); + if(!CollectionUtils.isEmpty(retTemp)) { + ret.addAll(retTemp); + } + } + } + if (!CollectionUtils.isEmpty(ret)){ + for (RangerPolicy policy : ret) { + if(policy!=null){ + orderedPolicies.put(policy.getId(), policy); + } + } + if (orderedPolicies.size()>0) { + ret.clear(); + ret.addAll(orderedPolicies.values()); + } + } + } + } else { + RangerPolicyList policyList = policyService.searchRangerPolicies(filter); + ret = policyList.getPolicies(); + if (!CollectionUtils.isEmpty(ret)) { + for (RangerPolicy policy : ret) { + if (policy != null) { + orderedPolicies.put(policy.getId(), policy); + } + } + if (orderedPolicies.size() > 0) { + ret.clear(); + ret.addAll(orderedPolicies.values()); + } + } + if (policyList != null) { + ret = policyList.getPolicies(); + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== ServiceDBStore.getPoliciesForReports()"); + } return ret; } + public void getPoliciesInExcel(List<RangerPolicy> policies, HttpServletResponse response) throws Exception { + if (LOG.isDebugEnabled()) { + LOG.debug("==> ServiceDBStore.getPoliciesInExcel()"); + } + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); + String excelFileName = "Ranger_Policies_"+timeStamp+".xls"; + writeExcel(policies, excelFileName, response); + } public PList<RangerPolicy> getPaginatedPolicies(SearchFilter filter) throws Exception { if (LOG.isDebugEnabled()) { @@ -2707,4 +2777,155 @@ public class ServiceDBStore extends AbstractServiceStore { return false; } + private void writeExcel(List<RangerPolicy> policies, String excelFileName, HttpServletResponse response) + throws IOException { + Workbook workbook=null; + OutputStream outStream =null; + try{ + workbook = new HSSFWorkbook(); + Sheet sheet = workbook.createSheet(); + createHeaderRow(sheet); + int rowCount = 0; + if (!CollectionUtils.isEmpty(policies)){ + for (RangerPolicy policy : policies) { + Row row = sheet.createRow(++rowCount); + writeBook(policy, row); + } + } + ByteArrayOutputStream outByteStream = new ByteArrayOutputStream(); + workbook.write(outByteStream); + byte[] outArray = outByteStream.toByteArray(); + response.setContentType("application/ms-excel"); + response.setContentLength(outArray.length); + response.setHeader("Expires:", "0"); + response.setHeader("Content-Disposition", "attachment; filename=" + excelFileName); + outStream=response.getOutputStream(); + outStream.write(outArray); + outStream.flush(); + }catch(IOException ex){ + LOG.error("Failed to create report file " + excelFileName, ex); + }catch(Exception ex){ + LOG.error("Error while generating report file " + excelFileName, ex); + }finally{ + if(outStream!=null){ + outStream.close(); + } + if(workbook!=null){ + workbook.close(); + } + } + } + + private void writeBook(RangerPolicy policy, Row row) { + String policyStatus = ""; + Cell cell = row.createCell(0); + cell.setCellValue(policy.getId()); + cell = row.createCell(1); + cell.setCellValue(policy.getName()); + cell = row.createCell(2); + if (policy.getIsEnabled()) { + policyStatus = "Enabled"; + } else { + policyStatus = "Disabled"; + } + cell.setCellValue(policyStatus); + cell = row.createCell(3); + List<RangerPolicyItem> policyItems = policy.getPolicyItems(); + List<String> groups = new ArrayList<String>(); + List<String> users = new ArrayList<String>(); + String groupNames = ""; + String userNames = ""; + String accessType = ""; + if (!CollectionUtils.isEmpty(policyItems)) { + for (RangerPolicyItem policyItem : policyItems) { + groups = policyItem.getGroups(); + List<RangerPolicyItemAccess> accesses = policyItem.getAccesses(); + accessType = accessType + "["; + for (RangerPolicyItemAccess access : accesses) { + accessType = accessType + access.getType() + " "; + } + accessType = accessType + "] "; + if (!groups.isEmpty()) { + groupNames = groupNames + groups.toString(); + } + users = policyItem.getUsers(); + if (!users.isEmpty()) { + userNames = userNames + users.toString(); + } + } + } + cell.setCellValue(groupNames); + cell = row.createCell(4); + cell.setCellValue(userNames); + cell = row.createCell(5); + XXService xxservice = daoMgr.getXXService().findByName(policy.getService()); + String ServiceType = ""; + if (xxservice != null) { + Long ServiceId = xxservice.getType(); + XXServiceDef xxservDef = daoMgr.getXXServiceDef().getById(ServiceId); + if (xxservDef != null) { + ServiceType = xxservDef.getName(); + } + } + cell.setCellValue(ServiceType); + cell = row.createCell(6); + cell.setCellValue(accessType.trim()); + cell = row.createCell(7); + String resValue = ""; + String resourceKeyVal = ""; + String resKey = ""; + Map<String, RangerPolicyResource> resources = policy.getResources(); + if (resources!=null) { + for (Entry<String, RangerPolicyResource> resource : resources.entrySet()) { + resKey = resource.getKey(); + RangerPolicyResource policyResource = resource.getValue(); + List<String> resvalueList = policyResource.getValues(); + resValue = resvalueList.toString(); + resourceKeyVal = resourceKeyVal + " " + resKey + "=" + resValue; + } + } + cell.setCellValue(resourceKeyVal); + } + + private void createHeaderRow(Sheet sheet) { + CellStyle cellStyle = sheet.getWorkbook().createCellStyle(); + Font font = sheet.getWorkbook().createFont(); + font.setBold(true); + font.setFontHeightInPoints((short) 12); + cellStyle.setFont(font); + + Row row = sheet.createRow(0); + + Cell cellID = row.createCell(0); + cellID.setCellStyle(cellStyle); + cellID.setCellValue("ID"); + + Cell cellNAME = row.createCell(1); + cellNAME.setCellStyle(cellStyle); + cellNAME.setCellValue("Name"); + + Cell cellStatus = row.createCell(2); + cellStatus.setCellStyle(cellStyle); + cellStatus.setCellValue("Status"); + + Cell cellGroups = row.createCell(3); + cellGroups.setCellStyle(cellStyle); + cellGroups.setCellValue("Groups"); + + Cell cellUsers = row.createCell(4); + cellUsers.setCellStyle(cellStyle); + cellUsers.setCellValue("Users"); + + Cell cellServiceType = row.createCell(5); + cellServiceType.setCellStyle(cellStyle); + cellServiceType.setCellValue("Service Type"); + + Cell cellAccesses = row.createCell(6); + cellAccesses.setCellStyle(cellStyle); + cellAccesses.setCellValue("Accesses"); + + Cell cellResources = row.createCell(7); + cellResources.setCellStyle(cellStyle); + cellResources.setCellValue("Resources"); + } } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dbd0bba9/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java index 8f01bfc..ad25817 100644 --- a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java +++ b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java @@ -1290,6 +1290,44 @@ public class ServiceREST { return ret; } + @GET + @Path("/policies/downloadExcel") + @Produces("application/ms-excel") + public void getPoliciesInExcel(@Context HttpServletRequest request, + @Context HttpServletResponse response) { + + if (LOG.isDebugEnabled()) { + LOG.debug("==> ServiceREST.getPoliciesInExcel()"); + } + RangerPerfTracer perf = null; + + SearchFilter filter = searchUtil.getSearchFilter(request, policyService.sortFields); + + try { + if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "ServiceREST.getPoliciesInExcel()"); + } + List<RangerPolicy> policies=new ArrayList<RangerPolicy>(); + if (filter != null) { + filter.setStartIndex(0); + filter.setMaxRows(Integer.MAX_VALUE); + policies = svcStore.getPoliciesForReports(filter); + } + svcStore.getPoliciesInExcel(policies, response); + + } catch (WebApplicationException excp) { + throw excp; + } catch (Throwable excp) { + LOG.error("Error while downloading policy report", excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + } + + public List<RangerPolicy> getPolicies(SearchFilter filter) { if(LOG.isDebugEnabled()) { LOG.debug("==> ServiceREST.getPolicies(filter)"); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dbd0bba9/security-admin/src/main/java/org/apache/ranger/service/RangerPolicyServiceBase.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerPolicyServiceBase.java b/security-admin/src/main/java/org/apache/ranger/service/RangerPolicyServiceBase.java index 4929cf6..87f3463 100644 --- a/security-admin/src/main/java/org/apache/ranger/service/RangerPolicyServiceBase.java +++ b/security-admin/src/main/java/org/apache/ranger/service/RangerPolicyServiceBase.java @@ -18,9 +18,13 @@ package org.apache.ranger.service; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; +import java.util.Set; import org.apache.commons.lang.StringUtils; +import org.apache.ranger.authorization.utils.StringUtil; import org.apache.ranger.common.GUIDUtil; import org.apache.ranger.common.MessageEnums; import org.apache.ranger.common.SearchField; @@ -28,13 +32,16 @@ import org.apache.ranger.common.SortField; import org.apache.ranger.common.SearchField.DATA_TYPE; import org.apache.ranger.common.SearchField.SEARCH_TYPE; import org.apache.ranger.common.SortField.SORT_ORDER; +import org.apache.ranger.entity.XXGroup; import org.apache.ranger.entity.XXPolicy; import org.apache.ranger.entity.XXPolicyBase; import org.apache.ranger.entity.XXService; +import org.apache.ranger.entity.XXUser; import org.apache.ranger.plugin.model.RangerPolicy; import org.apache.ranger.plugin.util.SearchFilter; import org.apache.ranger.view.RangerPolicyList; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; public abstract class RangerPolicyServiceBase<T extends XXPolicyBase, V extends RangerPolicy> extends RangerBaseModelService<T, V> { @@ -121,12 +128,40 @@ public abstract class RangerPolicyServiceBase<T extends XXPolicyBase, V extends List<RangerPolicy> policyList = new ArrayList<RangerPolicy>(); RangerPolicyList retList = new RangerPolicyList(); + Comparator<RangerPolicy> comparator = new Comparator<RangerPolicy>() { + public int compare(RangerPolicy c1, RangerPolicy c2) { + return (int) ((c1.getId()).compareTo(c2.getId())); + } + }; + List<XXPolicy> xPolList = (List<XXPolicy>) searchResources(searchFilter, searchFields, sortFields, retList); - for (XXPolicy xPol : xPolList) { - policyList.add(populateViewBean((T) xPol)); + String userName = searchFilter.getParam("user"); + if (!StringUtil.isEmpty(userName)) { + searchFilter.removeParam("user"); + Set<String> groupNames = daoMgr.getXXGroupUser().findGroupNamesByUserName(userName); + if (!CollectionUtils.isEmpty(groupNames)) { + List<XXPolicy> xPolList2 = null; + for (String groupName : groupNames) { + xPolList2 = new ArrayList<XXPolicy>(); + searchFilter.setParam("group", groupName); + xPolList2 = (List<XXPolicy>) searchResources(searchFilter, searchFields, sortFields, retList); + if (!CollectionUtils.isEmpty(xPolList2)) { + for (XXPolicy xPol2 : xPolList2) { + if(xPol2!=null){ + policyList.add(populateViewBean((T) xPol2)); + } + } + } + } + } + } + if (!CollectionUtils.isEmpty(xPolList)) { + for (XXPolicy xPol : xPolList) { + policyList.add(populateViewBean((T) xPol)); + } + Collections.sort(policyList, comparator); } retList.setPolicies(policyList); - return retList; } } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dbd0bba9/security-admin/src/main/webapp/scripts/utils/XAUtils.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/utils/XAUtils.js b/security-admin/src/main/webapp/scripts/utils/XAUtils.js index 6611fa6..f258a95 100644 --- a/security-admin/src/main/webapp/scripts/utils/XAUtils.js +++ b/security-admin/src/main/webapp/scripts/utils/XAUtils.js @@ -1177,6 +1177,14 @@ define(function(require) { } return singleValue; }; + XAUtils.getBaseUrl = function (){ + if(!window.location.origin){ + window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: ''); + } + return window.location.origin + + window.location.pathname.substring(window.location.pathname + .indexOf('/', 2) + 1, 0); + }; XAUtils.isMaskingPolicy = function(type){ return type == XAEnums.RangerPolicyType.RANGER_MASKING_POLICY_TYPE.value ? true : false; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dbd0bba9/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 47177f4..ff835fd 100644 --- a/security-admin/src/main/webapp/scripts/views/reports/UserAccessLayout.js +++ b/security-admin/src/main/webapp/scripts/views/reports/UserAccessLayout.js @@ -27,6 +27,7 @@ define(function(require) {'use strict'; var XABackgrid = require('views/common/XABackgrid'); var XATableLayout = require('views/common/XATableLayout'); var localization = require('utils/XALangSupport'); + var XAGlobals = require('utils/XAGlobals'); var RangerService = require('models/RangerService'); var RangerServiceDefList= require('collections/RangerServiceDefList'); @@ -72,7 +73,9 @@ define(function(require) {'use strict'; btnShowMore : '[data-id="showMore"]', btnShowLess : '[data-id="showLess"]', btnShowMoreUsers : '[data-id="showMoreUsers"]', - btnShowLessUsers : '[data-id="showLessUsers"]' + btnShowLessUsers : '[data-id="showLessUsers"]', + componentType : '[data-id="component"]', + downloadReport : '[data-id="downloadReport"]' }, /** ui events hash */ @@ -85,6 +88,7 @@ define(function(require) {'use strict'; events['click ' + this.ui.btnShowLess] = 'onShowLess'; events['click ' + this.ui.btnShowMoreUsers] = 'onShowMoreUsers'; events['click ' + this.ui.btnShowLessUsers] = 'onShowLessUsers'; + events['click ' + this.ui.downloadReport] = 'onDownload'; return events; }, @@ -96,6 +100,9 @@ define(function(require) {'use strict'; console.log("initialized a UserAccessLayout Layout"); _.extend(this, _.pick(options, 'groupList','userList')); this.bindEvents(); + this.previousSearchUrl = ''; + this.searchedFlag = true; + this.allowDownload = false; }, initializeRequiredData : function() { this.policyCollList = []; @@ -126,16 +133,25 @@ define(function(require) {'use strict'; onRender : function() { this.initializePlugins(); this.setupGroupAutoComplete(); + this.onComponentSelect(); //Show policies listing for each service and GET policies for each service _.each(this.policyCollList, function(obj,i){ this.renderTable(obj.collName, obj.serviceDefName); this.getResourceLists(obj.collName,obj.serviceDefName); },this); + this.modifyTableForSubcolumns(); this.$el.find('[data-js="policyName"]').focus() + var url_string = XAUtil.getBaseUrl(); + if(url_string.slice(-1) == "/") { + url_string = url_string.slice(0,-1); + } + this.previousSearchUrl = url_string+"/service/plugins/policies/downloadExcel?"; }, getResourceLists: function(collName, serviceDefName){ + var that = this, coll = this[collName]; + that.allowDownload = false; coll.queryParams.serviceType = serviceDefName; coll.fetch({ cache : false, @@ -144,13 +160,15 @@ define(function(require) {'use strict'; }).done(function(){ coll.trigger('sync') XAUtil.blockUI('unblock'); + if(coll.length >= 1 && !that.allowDownload) + that.allowDownload = true; }); }, - renderTable : function(collName){ + renderTable : function(collName,serviceDefName){ var that = this, tableRegion = this[collName+'Table']; tableRegion.show(new XATableLayout({ - columns: this.getColumns(this[collName]), + columns: this.getColumns(this[collName],collName,serviceDefName), collection: this[collName], includeFilter : false, scrollToTop : false, @@ -162,7 +180,7 @@ define(function(require) {'use strict'; })); }, - getColumns : function(coll){ + getColumns : function(coll,collName,serviceDefName){ var that = this; var cols = { id : { @@ -199,53 +217,186 @@ define(function(require) {'use strict'; drag : false, sortable : false }, - isAuditEnabled:{ - label:localization.tt('lbl.auditLogging'), - cell :"html", - editable:false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function (rawValue) { - return rawValue ? '<label class="label label-success">Enabled</label>' : '<label class="label label-important">Disabled</label>'; + permissions: { + label: 'Permissions', + cell : Backgrid.HtmlCell.extend({className: 'cellWidth-1', className: 'html-cell' }), + formatter: _.extend({}, Backgrid.CellFormatter.prototype,{ + fromRaw: function(rawValue,model){ + if(model.get("policyItems").length != 0) { + var htmlStr = ''; + var accessStr = ''; + var grpStr = ''; + var userStr = ''; + _.each(model.get("policyItems"),function(policyItem){ + if(_.isEmpty(policyItem.groups)){ + grpStr = '--'; + _.map(policyItem.users,function(el){ + userStr+='<span class="label label-info cellWidth-1 float-left-margin-2" style="">'+el+'</span>'; + }); + accessStr = ''; + _.each(policyItem.accesses,function(obj2){ + accessStr+='<span class="label label-info cellWidth-1 float-left-margin-2" style="">'+obj2.type+'</span>'; + }); + } + else if(_.isEmpty(policyItem.users)) { + userStr = '--'; + _.map(policyItem.groups,function(el){ + grpStr+='<span class="label label-info cellWidth-1 float-left-margin-2" style="">'+el+'</span>'; + }); + accessStr = ''; + _.each(policyItem.accesses,function(obj2){ + accessStr+='<span class="label label-info cellWidth-1 float-left-margin-2" style="">'+obj2.type+'</span>'; + }); + } + else{ + _.map(policyItem.users,function(el){ + userStr+='<span class="label label-info cellWidth-1 float-left-margin-2" style="">'+el+'</span>'; + }); + _.map(policyItem.groups,function(el){ + grpStr+='<span class="label label-info cellWidth-1 float-left-margin-2" style="">'+el+'</span>'; + }); + accessStr = ''; + _.each(policyItem.accesses,function(obj2){ + accessStr+='<span class="label label-info cellWidth-1 float-left-margin-2" style="">'+obj2.type+'</span>'; + }); + } + htmlStr+='<tr style="height:60px"><td style ="width:80px">'+grpStr+'</td>\ + <td style="width:80px">'+(userStr)+'</td>\ + <td style="width:150px">'+accessStr+'</td></tr>'; + accessStr = ''; + grpStr = ''; + userStr = ''; + }); + return htmlStr; + } + else { + return '---'; + } } }), - click : false, - drag : false, - sortable : false + editable: false, + sortable: false, + click: false }, - policyItems : { - reName : 'groupName', - cell : Backgrid.HtmlCell.extend({className: 'cellWidth-1'}), - label : localization.tt("lbl.group"), + resources: + { + label: 'Resources', + cell: 'Html', formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function (rawValue, model) { - if(!_.isUndefined(rawValue)) - return XAUtil.showGroupsOrUsersForPolicy(rawValue, model); - else - return '--'; - } + fromRaw: function (rawValue,model) { + var strVal = ''; + var res = model.get('resources'); + _.each(res,function(res_obj,key){ + strVal += "<b>"+key+":</b>"; + _.map(res_obj.values,function(ob){ + strVal +="<span title='"+ob+"'>"+ ob+"</span>" + ","; + }); + strVal = strVal.slice(0,-1); + strVal = strVal+ "<br />"; + }); + return strVal; + } }), - editable : false, - sortable : false - }, - //Hack for backgrid plugin doesn't allow to have same column name - guid : { - reName : 'userName', - cell : Backgrid.HtmlCell.extend({className: 'cellWidth-1'}), - label : localization.tt("lbl.users"), - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function (rawValue, model) { - if(!_.isUndefined(rawValue)) - return XAUtil.showGroupsOrUsersForPolicy(model.get('policyItems'), model, false); - else - return '--'; - } - }), - editable : false, - sortable : false - }, + editable: false, + sortable: false, + click: false + } }; + return coll.constructor.getTableCols(cols, coll); }, + /* components */ + onComponentSelect: function(){ + var that = this; + var options = this.serviceDefList.map(function(m){ return { 'id' : m.get('name'), 'text' : m.get('name')}; }); + this.ui.componentType.select2({ + multiple: true, + closeOnSelect: true, + placeholder: 'Select Component', + //maximumSelectionSize : 1, + width: '220px', + allowClear: true, + data: options + }); + }, + modifyTableForSubcolumns : function(){ + this.$el.find(".permissions").html('<tr><th colspan="3">Permissions</th></tr>\ + <tr><th style="width:80px">Groups</th><th style="width:80px">Users</th>\ + <th style="width:150px">Accesses</th></tr>'); + }, + onDownload: function(e){ + if(!this.allowDownload){ + XAUtil.alertPopup({ + msg :"No policies found to download!", + }); + return; + } + var rangerPolicyList = new RangerPolicyList(); + var that = this; + var url = ''; + var groups = (this.ui.userGroup.is(':visible')) ? this.ui.userGroup.select2('val'):undefined; + if(groups == "") { + groups = undefined; + } + var users = (this.ui.userName.is(':visible')) ? this.ui.userName.select2('val'):undefined; + var rxName = this.ui.resourceName.val() || undefined; + var policyName = this.ui.policyName.val() || undefined; + var params = {group : groups, user : users, polResource : rxName, policyNamePartial : policyName}; + var component = (this.ui.componentType.val() != "") ? this.ui.componentType.select2('val'):undefined; + _.each(that.policyCollList, function(obj,i){ + var coll = that[obj.collName]; + },this); + var btn = $(e.currentTarget); + if(!this.searchedFlag) { + var url_string = XAUtil.getBaseUrl(); + if(url_string.slice(-1) == "/") { + url_string = url_string.slice(0,-1); + } + url = url_string + that.getDownloadExcelUrl(this,component,params); + this.previousSearchUrl = url; + } + else { + url = this.previousSearchUrl; + } + $('<a href="'+url+'" download hidden>').appendTo('body').get(0).click(); + + }, + getDownloadExcelUrl: function(that,component,params){ + var queryParams = {}; + var data = {}; + var comp_str = ''; + if(!_.isUndefined(component)) { + _.each(component,function(comp){ + comp_str = comp_str + comp + '_'; + }); + } + if (comp_str != '') { + comp_str = comp_str.slice(0,-1); + } + queryParams = that['hdfsPolicyList'].queryParams; + _.map(params, function(value, key) { + if (!_.isUndefined(value)) { + data[key] = value; + } + }); + if(!_.isUndefined(queryParams.group)) { + data.group = queryParams.group; + } + if(!_.isUndefined(queryParams.user)) { + data.user = queryParams.user; + } + if(!_.isUndefined(queryParams.polResource)) { + data.polResource = queryParams.polResource; + } + if(!_.isUndefined(queryParams.policyNamePartial)) { + data.policyNamePartial = queryParams.policyNamePartial; + } + var policyList; + var url = '/service/plugins/policies/downloadExcel?'; + var str = jQuery.param( data ); + url = url + str + "&serviceType="+comp_str; + return url; + }, /** on render callback */ setupGroupAutoComplete : function(){ this.groupArr = this.groupList.map(function(m){ @@ -360,7 +511,7 @@ define(function(require) {'use strict'; var wrap = $(this).next(); // If next element is a wrap and hasn't .non-collapsible class if (wrap.hasClass('wrap') && ! wrap.hasClass('non-collapsible')) - $(this).append('<a href="#" class="wrap-collapse pull-right">hide <i class="icon-caret-up"></i></a>').append('<a href="#" class="wrap-expand pull-right" style="display: none">show <i class="icon-caret-down"></i></a>'); + $(this).prepend('<a href="#" class="wrap-collapse btn-right">hide <i class="icon-caret-up"></i></a>').prepend('<a href="#" class="wrap-expand btn-right" style="display: none">show <i class="icon-caret-down"></i></a>'); }); // Collapse wrap @@ -395,20 +546,80 @@ define(function(require) {'use strict'; var rxName = this.ui.resourceName.val() || undefined; var policyName = this.ui.policyName.val() || undefined; var params = {group : groups, user : users, polResource : rxName, policyNamePartial : policyName}; - - _.each(this.policyCollList, function(obj,i){ - var coll = this[obj.collName]; - //clear previous query params - _.each(params, function(val, attr){ - delete coll.queryParams[attr]; - }); - //Set default page state - coll.state = this.defaultPageState; - coll.queryParams = $.extend(coll.queryParams, params) - this.getResourceLists(obj.collName, obj.serviceDefName); - },this); - - }, + var component = (this.ui.componentType.val() != "") ? this.ui.componentType.select2('val'):undefined; + var compFlag = false; + var showTabs = false; + if(_.isUndefined(users) && _.isUndefined(rxName) && _.isUndefined(policyName) && (groups=="")) { + showTabs = false; + } + else { + showTabs = true; + } + if(!_.isUndefined(component)) { + compFlag = true; + } + else { + compFlag = false; + } + that.$el.find('[data-compHeader]').show(); + that.$el.find('[data-comp]').show(); + if(compFlag) { //if components selected + that.$el.find('[data-compHeader]').hide(); + that.$el.find('[data-comp]').hide(); + _.each(that.policyCollList, function(obj,i){ + _.each(component,function(comp){ + if(comp === obj.serviceDefName) { + var coll = that[obj.collName]; + //clear previous query params + _.each(params, function(val, attr){ + delete coll.queryParams[attr]; + }); + //Set default page state + coll.state = that.defaultPageState; + coll.queryParams = $.extend(coll.queryParams, params); + that.getResourceLists(obj.collName, obj.serviceDefName); + that.$el.find('[data-compHeader="'+comp+'"]').show(); + that.$el.find('[data-comp="'+comp+'"]').show(); + } + }); + },this); + } + else { // show all tables if no search component values selected + that.$el.find('[data-compHeader]').show(); + that.$el.find('[data-comp]').show(); + _.each(this.policyCollList, function(obj,i){ + var coll = this[obj.collName]; + //clear previous query params + _.each(params, function(val, attr){ + delete coll.queryParams[attr]; + }); + //Set default page state + coll.state = this.defaultPageState; + coll.queryParams = $.extend(coll.queryParams, params); + this.getResourceLists(obj.collName, obj.serviceDefName); + },this); + } + var rangerPolicyList = new RangerPolicyList(); + var url = ''; + if (groups == "") { + groups = undefined; + } + params = { + group : groups, + user : users, + polResource : rxName, + policyNamePartial : policyName + }; + var url_string = XAUtil.getBaseUrl(); + if(url_string.slice(-1) == "/") { + url_string = url_string.slice(0,-1); + } + url = url_string + + this.getDownloadExcelUrl(this, component, + params); + this.previousSearchUrl = url; + this.searchedFlag = true; + }, autocompleteFilter : function(e){ var $el = $(e.currentTarget); var $button = $(e.currentTarget).parents('.btn-group').find('button').find('span').first(); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dbd0bba9/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 331cda1..df683b9 100644 --- a/security-admin/src/main/webapp/styles/xa.css +++ b/security-admin/src/main/webapp/styles/xa.css @@ -1908,3 +1908,7 @@ input[type="radio"], input[type="checkbox"] {margin-top: 0;} margin-top: -2px; font-size: 11px; } +.backgrid > tbody > tr > td:nth-child(5) { + text-align: left !important; + width: 200px +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dbd0bba9/security-admin/src/main/webapp/templates/reports/UserAccessLayout_tmpl.html ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/templates/reports/UserAccessLayout_tmpl.html b/security-admin/src/main/webapp/templates/reports/UserAccessLayout_tmpl.html index 1352882..8f201dd 100644 --- a/security-admin/src/main/webapp/templates/reports/UserAccessLayout_tmpl.html +++ b/security-admin/src/main/webapp/templates/reports/UserAccessLayout_tmpl.html @@ -32,12 +32,19 @@ </div> </div> <div class="control-group"> - <label class="control-label">Resource</label> - <div class="controls"> - <input type="text" name="resourceName" data-js="resourceName" class="input-xxlarge"> + <div class="span4"> + <label class="control-label" for="component">Component</label> + <div class="controls"> + <input type=text data-id="component" name="componentType"> + </div> + </div> + <div class="span4"> + <label class="control-label" style="width:80px;">Resource</label> + <div class="controls" style="margin-left:90px;"> + <input type="text" name="resourceName" data-js="resourceName"> </div> </div> - + </div> <div class="control-group search-by"> <label class="control-label">Search By</label> <div class="controls" data-js="searchBy"> @@ -73,25 +80,29 @@ </button> </div> </div> - </div> - </div> </div> </div> </div> - + <div class="row-fluid"> + <a href="javascript:void(0)" data-id="downloadReport"> + <span> + <button type="button" class="btn btn-primary btn-small btn-right" data-js="downloadBtn" title="Download all below policies" name="downloadPolicy"> + <i class="icon-download-alt"></i> + Download + </button> + </span></a> + </div> <div class="row-fluid"> {{#each policyHeaderList}} - <h3 class="wrap-header bold reportSearchHeader" data-js="hdfsHeader"> {{capitaliseLetter this.serviceDefName}} - <span class="label label-yellow pull-right" data-js="hdfsSearchResult" ></span> + <h3 class="wrap-header bold reportSearchHeader" data-js="hdfsHeader" data-compHeader="{{this.serviceDefName}}"> {{capitaliseLetter this.serviceDefName}} + <span class="label label-yellow btn-right" data-js="hdfsSearchResult" ></span> </h3> - <div class="wrap well position-relative"> + <div class="wrap well position-relative" data-comp="{{this.serviceDefName}}"> <div data-id="{{this.collName}}" class="hdfs-table showMoreLess"></div> </div> - {{/each}} - + {{/each}} </div> - </div>
