You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ma...@apache.org on 2015/04/02 06:26:31 UTC

incubator-ranger git commit: RANGER-358 : Show previous/next version of policy in Policy View popup

Repository: incubator-ranger
Updated Branches:
  refs/heads/master 62fa3616a -> 5df9aa645


RANGER-358 : Show previous/next version of policy in Policy View popup

Signed-off-by: Madhan Neethiraj <ma...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/5df9aa64
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/5df9aa64
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/5df9aa64

Branch: refs/heads/master
Commit: 5df9aa6457776e411525fe83d269455be7861ab6
Parents: 62fa361
Author: Gautam Borad <gb...@gmail.com>
Authored: Wed Apr 1 23:33:11 2015 +0530
Committer: Madhan Neethiraj <ma...@apache.org>
Committed: Wed Apr 1 21:21:48 2015 -0700

----------------------------------------------------------------------
 .../org/apache/ranger/biz/ServiceDBStore.java   | 67 +++++++++++++-------
 .../org/apache/ranger/db/XXDataHistDao.java     | 31 ++++++++-
 .../org/apache/ranger/rest/ServiceREST.java     | 21 ++++--
 .../ranger/service/RangerBaseModelService.java  | 10 ++-
 .../ranger/service/RangerDataHistService.java   |  2 -
 .../resources/META-INF/jpa_named_queries.xml    | 10 +++
 .../main/webapp/scripts/models/RangerPolicy.js  | 24 ++++++-
 .../scripts/modules/globalize/message/en.js     |  4 ++
 .../scripts/views/policies/RangerPolicyRO.js    | 57 +++++++++++++++--
 .../webapp/scripts/views/reports/AuditLayout.js | 12 +++-
 security-admin/src/main/webapp/styles/xa.css    | 32 ++++++++++
 .../templates/policies/RangerPolicyRO_tmpl.html | 40 ++++++++++--
 .../service/ConfigurationItem_tmpl.html         |  4 +-
 13 files changed, 265 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5df9aa64/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 e6513b3..9fa9160 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
@@ -107,6 +107,7 @@ import org.apache.ranger.service.XUserService;
 import org.apache.ranger.view.RangerPolicyList;
 import org.apache.ranger.view.RangerServiceDefList;
 import org.apache.ranger.view.RangerServiceList;
+import org.apache.ranger.view.VXString;
 import org.apache.ranger.view.VXUser;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
@@ -538,9 +539,17 @@ public class ServiceDBStore implements ServiceStore {
 		} else {
 			version = new Long(version.longValue() + 1);
 		}
-		
+
 		service.setVersion(version);
-		service = svcService.update(service);
+
+		if(populateExistingBaseFields) {
+			svcService.setPopulateExistingBaseFields(true);
+			service = svcService.update(service);
+			svcService.setPopulateExistingBaseFields(false);
+		} else {
+			service = svcService.update(service);
+		}
+
 		XXService xUpdService = daoMgr.getXXService().getById(service.getId());
 		
 		List<XXServiceConfigMap> dbConfigMaps = daoMgr.getXXServiceConfigMap().findByServiceId(service.getId());
@@ -677,7 +686,7 @@ public class ServiceDBStore implements ServiceStore {
 		if(xServiceDef == null) {
 			throw new Exception("service-def does not exist - name=" + service.getType());
 		}
-		
+
 		XXPolicy existing = daoMgr.getXXPolicy().findByNameAndServiceId(policy.getName(), service.getId());
 
 		if(existing != null) {
@@ -688,7 +697,7 @@ public class ServiceDBStore implements ServiceStore {
 		List<RangerPolicyItem> policyItems = policy.getPolicyItems();
 
 		policy.setVersion(new Long(1));
-		
+
 		if(populateExistingBaseFields) {
 			policyService.setPopulateExistingBaseFields(true);
 			policy = policyService.create(policy);
@@ -701,14 +710,13 @@ public class ServiceDBStore implements ServiceStore {
 
 		createNewResourcesForPolicy(policy, xCreatedPolicy, resources);
 		createNewPolicyItemsForPolicy(policy, xCreatedPolicy, policyItems, xServiceDef);
-
 		handlePolicyUpdate(service);
 		RangerPolicy createdPolicy = policyService.getPopulatedViewObject(xCreatedPolicy);
 		dataHistService.createObjectDataHistory(createdPolicy, RangerDataHistService.ACTION_CREATE);
 
-		 List<XXTrxLog> trxLogList = policyService.getTransactionLog(createdPolicy, RangerPolicyService.OPERATION_CREATE_CONTEXT);
-		 bizUtil.createTrxLog(trxLogList);
-		
+		List<XXTrxLog> trxLogList = policyService.getTransactionLog(createdPolicy, RangerPolicyService.OPERATION_CREATE_CONTEXT);
+		bizUtil.createTrxLog(trxLogList);
+
 		return createdPolicy;
 	}
 
@@ -1069,22 +1077,9 @@ public class ServiceDBStore implements ServiceStore {
 		}
 		Map<String, String> validConfigs = new HashMap<String, String>();
 		for(Entry<String, String> config : configs.entrySet()) {
-			validConfigs.put(config.getKey(), config.getValue());
-			/*String confKey = ;
-			String confValue = ;
-
-			boolean found = false;
-			for(XXServiceConfigDef xConfDef : svcConfDefList) {
-				if((xConfDef.getName()).equalsIgnoreCase(confKey)) {
-					found = true;
-					break;
-				}
+			if(!stringUtil.isEmpty(config.getValue())) {
+				validConfigs.put(config.getKey(), config.getValue());
 			}
-			if(found) {
-			} else {
-				LOG.info("Ignoring this config parameter:" + confKey
-						+ ", as its not valid conf param for service");
-			}*/
 		}
 		return validConfigs;
 	}
@@ -1294,7 +1289,7 @@ public class ServiceDBStore implements ServiceStore {
 		this.populateExistingBaseFields = populateExistingBaseFields;
 	}
 
-	public RangerPolicy getPolicyFromEventTime(Date eventTime, Long policyId) {
+	public RangerPolicy getPolicyFromEventTime(String eventTime, Long policyId) {
 
 		XXDataHist xDataHist = daoMgr.getXXDataHist().findObjByEventTimeClassTypeAndId(eventTime,
 				AppConstants.CLASS_TYPE_RANGER_POLICY, policyId);
@@ -1311,4 +1306,28 @@ public class ServiceDBStore implements ServiceStore {
 		return policy;
 	}
 
+	public VXString getPolicyVersionList(Long policyId) {
+		List<Integer> versionList = daoMgr.getXXDataHist().getVersionListOfObject(policyId,
+				AppConstants.CLASS_TYPE_RANGER_POLICY);
+
+		VXString vXString = new VXString();
+		vXString.setValue(StringUtils.join(versionList, ","));
+
+		return vXString;
+	}
+
+	public RangerPolicy getPolicyForVersionNumber(Long policyId, int versionNo) {
+		XXDataHist xDataHist = daoMgr.getXXDataHist().findObjectByVersionNumber(policyId,
+				AppConstants.CLASS_TYPE_RANGER_POLICY, versionNo);
+
+		if (xDataHist == null) {
+			throw restErrorUtil.createRESTException("No Policy found for given version.", MessageEnums.DATA_NOT_FOUND);
+		}
+
+		String content = xDataHist.getContent();
+		RangerPolicy policy = (RangerPolicy) dataHistService.writeJsonToJavaObject(content, RangerPolicy.class);
+
+		return policy;
+	}
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5df9aa64/security-admin/src/main/java/org/apache/ranger/db/XXDataHistDao.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXDataHistDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXDataHistDao.java
index 4479145..f22e198 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXDataHistDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXDataHistDao.java
@@ -1,6 +1,7 @@
 package org.apache.ranger.db;
 
-import java.util.Date;
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.persistence.NoResultException;
 import javax.persistence.Query;
@@ -29,7 +30,7 @@ public class XXDataHistDao extends BaseDao<XXDataHist> {
 		}
 	}
 	
-	public XXDataHist findObjByEventTimeClassTypeAndId(Date eventTime, int classType, Long objId) {
+	public XXDataHist findObjByEventTimeClassTypeAndId(String eventTime, int classType, Long objId) {
 		if (eventTime == null || objId == null) {
 			return null;
 		}
@@ -44,4 +45,30 @@ public class XXDataHistDao extends BaseDao<XXDataHist> {
 		}
 	}
 
+	@SuppressWarnings("unchecked")
+	public List<Integer> getVersionListOfObject(Long objId, int classType) {
+		if (objId == null) {
+			return new ArrayList<Integer>();
+		}
+		try {
+			return getEntityManager().createNamedQuery("XXDataHist.getVersionListOfObject")
+					.setParameter("objId", objId).setParameter("classType", classType).getResultList();
+		} catch (NoResultException e) {
+			return new ArrayList<Integer>();
+		}
+	}
+
+	public XXDataHist findObjectByVersionNumber(Long objId, int classType, int versionNo) {
+		if (objId == null) {
+			return null;
+		}
+		try {
+			return getEntityManager().createNamedQuery("XXDataHist.findObjectByVersionNumber", tClass)
+					.setParameter("objId", objId).setParameter("classType", classType)
+					.setParameter("version", versionNo).getSingleResult();
+		} catch (NoResultException e) {
+			return null;
+		}
+	}
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5df9aa64/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 a0a358b..9d8d277 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
@@ -21,7 +21,6 @@ package org.apache.ranger.rest;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -81,6 +80,7 @@ import org.apache.ranger.view.RangerPolicyList;
 import org.apache.ranger.view.RangerServiceDefList;
 import org.apache.ranger.view.RangerServiceList;
 import org.apache.ranger.view.VXResponse;
+import org.apache.ranger.view.VXString;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Scope;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -1497,10 +1497,7 @@ public class ServiceREST {
 
 		Long policyId = Long.parseLong(policyIdStr);
 
-		Date eventTime = restErrorUtil.parseDate(eventTimeStr, "Invalid value for" + "Event Time",
-				MessageEnums.INVALID_INPUT_DATA, null, "eventTime", "MM/dd/yyyy hh:mm:ss");
-
-		RangerPolicy policy = svcStore.getPolicyFromEventTime(eventTime, policyId);
+		RangerPolicy policy = svcStore.getPolicyFromEventTime(eventTimeStr, policyId);
 
 		if (LOG.isDebugEnabled()) {
 			LOG.debug("<== ServiceREST.getPolicyFromEventTime()");
@@ -1509,4 +1506,18 @@ public class ServiceREST {
 		return policy;
 	}
 
+	@GET
+	@Path("/policy/{policyId}/versionList")
+	public VXString getPolicyVersionList(@PathParam("policyId") Long policyId) {
+		return svcStore.getPolicyVersionList(policyId);
+	}
+
+	@GET
+	@Path("/policy/{policyId}/version/{versionNo}")
+	@Produces({ "application/json", "application/xml" })
+	public RangerPolicy getPolicyForVersionNumber(@PathParam("policyId") Long policyId,
+			@PathParam("versionNo") int versionNo) {
+		return svcStore.getPolicyForVersionNumber(policyId, versionNo);
+	}
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5df9aa64/security-admin/src/main/java/org/apache/ranger/service/RangerBaseModelService.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerBaseModelService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerBaseModelService.java
index 78b846c..2193666 100644
--- a/security-admin/src/main/java/org/apache/ranger/service/RangerBaseModelService.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/RangerBaseModelService.java
@@ -228,13 +228,19 @@ public abstract class RangerBaseModelService<T extends XXDBBase, V extends Range
 			if (createTime == null) {
 				createTime = DateUtil.getUTCDate();
 			}
-			updTime = DateUtil.getUTCDate();
 
 			createdById = entityObj.getAddedByUserId();
 			if (createdById == null) {
 				createdById = ContextUtil.getCurrentUserId();
 			}
-			updById = ContextUtil.getCurrentUserId();
+			
+			if(populateExistingBaseFields) {
+				updTime = entityObj.getUpdateTime();
+				updById = entityObj.getUpdatedByUserId();
+			} else {				
+				updTime = DateUtil.getUTCDate();
+				updById = ContextUtil.getCurrentUserId();
+			}
 		} else {
 			throw restErrorUtil.createRESTException(
 					"Error while populating EntityBean",

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5df9aa64/security-admin/src/main/java/org/apache/ranger/service/RangerDataHistService.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerDataHistService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerDataHistService.java
index b75b514..dc73d83 100644
--- a/security-admin/src/main/java/org/apache/ranger/service/RangerDataHistService.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/RangerDataHistService.java
@@ -49,7 +49,6 @@ public class RangerDataHistService {
 		
 		Long objectId = baseModelObj.getId();
 		String objectGuid = baseModelObj.getGuid();
-		Long version = baseModelObj.getVersion();
 		Date currentDate = DateUtil.getUTCDate();
 		
 		XXDataHist xDataHist = new XXDataHist();;
@@ -93,7 +92,6 @@ public class RangerDataHistService {
 								+ objectName, MessageEnums.DATA_NOT_UPDATABLE);
 			}
 			
-			prevHist.setVersion(version);
 			prevHist.setUpdateTime(currentDate);
 			prevHist.setToTime(currentDate);
 			prevHist.setObjectName(objectName);

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5df9aa64/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
----------------------------------------------------------------------
diff --git a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
index 7a0fe30..b806dff 100644
--- a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
+++ b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
@@ -362,6 +362,16 @@
                                and obj.objectClassType = :classType ORDER BY obj.id</query>
 	</named-query>
 	
+	<named-query name="XXDataHist.getVersionListOfObject">
+		<query>select obj.version from XXDataHist obj where obj.objectId = :objId
+			and obj.objectClassType = :classType GROUP BY obj.version </query>
+	</named-query>
+	
+	<named-query name="XXDataHist.findObjectByVersionNumber">
+		<query>select obj from XXDataHist obj where obj.objectClassType = :classType and 
+		obj.objectId = :objId and obj.version = :version</query>
+	</named-query>
+	
 	<!-- XXTrxLog -->
 	<named-query name="XXTrxLog.findLogForMaxIdOfClassType">
 		<query>select MAX(obj.objectId) from XXTrxLog obj where obj.objectClassType = :classType</query>

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5df9aa64/security-admin/src/main/webapp/scripts/models/RangerPolicy.js
----------------------------------------------------------------------
diff --git a/security-admin/src/main/webapp/scripts/models/RangerPolicy.js b/security-admin/src/main/webapp/scripts/models/RangerPolicy.js
index 2228f23..46e498b 100644
--- a/security-admin/src/main/webapp/scripts/models/RangerPolicy.js
+++ b/security-admin/src/main/webapp/scripts/models/RangerPolicy.js
@@ -89,14 +89,34 @@ define(function(require){
 			queryParams.policyId = this.get('id');
 			if(_.isUndefined(queryParams.eventTime)){
 				throw('eventTime can not be undefined');
-			}else{
-				queryParams.eventTime = Globalize.format(new Date(queryParams.eventTime),  "MM/dd/yyyy hh:mm:ss")
 			}
 
 			opt.url = 'service/plugins/policies/eventTime';
 			return this.fetch(opt);
 		},
 
+		fetchByVersion : function(versionNo, opt){
+			if(_.isUndefined(versionNo)){
+				throw('versionNo can not be undefined');
+			}
+			opt.url = 'service/plugins/policy/'+this.get('id')+'/version/'+versionNo;
+			return this.fetch(opt);
+		},
+
+		fetchVersions : function(){
+			var versionList;
+			var url = 'service/plugins/policy/'+this.get('id')+'/versionList';
+			$.ajax({
+				url : url,
+				async : false,
+				dataType : 'JSON',
+				success : function(data){
+					versionList = data.value.split(',');
+				},
+			});
+			return versionList;
+		},
+
 		/** This models toString() */
 		toString : function(){
 			return this.get('name');

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5df9aa64/security-admin/src/main/webapp/scripts/modules/globalize/message/en.js
----------------------------------------------------------------------
diff --git a/security-admin/src/main/webapp/scripts/modules/globalize/message/en.js b/security-admin/src/main/webapp/scripts/modules/globalize/message/en.js
index 2231037..9b5b5e8 100644
--- a/security-admin/src/main/webapp/scripts/modules/globalize/message/en.js
+++ b/security-admin/src/main/webapp/scripts/modules/globalize/message/en.js
@@ -207,6 +207,7 @@ define(function(require) {
 				selectServiceName				: 'Select Service Name',
 				topologyName					: 'Topology Name',
 				serivceName						: 'Service Name',
+				serivceType						: 'Service Type',
 				ipAddress						: 'IP Address',
 				isVisible                       : 'Visible',
 				delegatedAdmin					: 'Delegate Admin',
@@ -253,6 +254,8 @@ define(function(require) {
 				agents						: 'Plugins',
 				repository					: 'Repository',
 				policy						: 'Policy',
+				policyDetails				: 'Policy Details',
+				userGroupPermissions		: 'User and Group Permissions',
 				groups						: 'Groups',
 				admin						: 'Admin',
 				bigData						: 'Big Data',
@@ -294,6 +297,7 @@ define(function(require) {
 				userDoesNotExistAnymore   : 'User does not exist anymore..',
 				repoDoesNotExistAnymore   : 'Repository does not exist anymore..',
 				policyDisabledMsg		  : 'This policy is currently in disabled state.',
+				noRecordsFound			  : 'No Records Found',
 				
 				
 				

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5df9aa64/security-admin/src/main/webapp/scripts/views/policies/RangerPolicyRO.js
----------------------------------------------------------------------
diff --git a/security-admin/src/main/webapp/scripts/views/policies/RangerPolicyRO.js b/security-admin/src/main/webapp/scripts/views/policies/RangerPolicyRO.js
index 16f489a..a9ee1b5 100644
--- a/security-admin/src/main/webapp/scripts/views/policies/RangerPolicyRO.js
+++ b/security-admin/src/main/webapp/scripts/views/policies/RangerPolicyRO.js
@@ -36,7 +36,7 @@ define(function(require) {
 		template: RangerPolicyROTmpl,
 		templateHelpers: function() {
 			return {
-				PolicyDetails: this.PolicyDetails,
+				PolicyDetails: this.policyDetails,
 			};
 		},
 		breadCrumbs: [],
@@ -58,7 +58,7 @@ define(function(require) {
 		},
 
 		/**
-		 * intialize a new AuditLayout Layout
+		 * intialize a new RangerPolicyRO Layout
 		 * @constructs
 		 */
 		initialize: function(options) {
@@ -80,13 +80,15 @@ define(function(require) {
 
 		initializePolicyDetailsObj : function(){
 			var self = this;
-			var details = this.PolicyDetails = {};
+			var details = this.policyDetails = {};
 			details.id = this.policy.get('id');
 			details.name = this.policy.get('name');
 			details.isEnabled = this.policy.get('isEnabled') ? localization.tt('lbl.ActiveStatus_STATUS_ENABLED') : localization.tt('lbl.ActiveStatus_STATUS_DISABLED');
 			details.description = this.policy.get('description');
 			details.isAuditEnabled = this.policy.get('isAuditEnabled') ? XAEnums.AuditStatus.AUDIT_ENABLED.label : XAEnums.AuditStatus.AUDIT_DISABLED.label;
 			details.resources = [];
+			details.service = this.policy.get('service');
+			details.serviceType = this.serviceDef.get('name');
 			_.each(this.serviceDef.get('resources'), function(def, i){
 				if(!_.isUndefined(this.policy.get('resources')[def.name])){
 					var resource = {},
@@ -103,6 +105,10 @@ define(function(require) {
 			}, this);
 			var perm = details.permissions = this.getPermHeaders();
 			perm.policyItems = this.policy.get('policyItems');
+			details.createdBy = this.policy.get('createdBy');
+			details.createTime = Globalize.format(new Date(this.policy.get('createTime')),  "MM/dd/yyyy hh:mm tt");
+			details.updatedBy = this.policy.get('updatedBy');
+			details.updateTime = Globalize.format(new Date(this.policy.get('updateTime')),  "MM/dd/yyyy hh:mm tt");
 		},
 
 		/** all events binding here */
@@ -110,7 +116,10 @@ define(function(require) {
 
 		/** on render callback */
 		onRender: function() {
-			this.$el.find('#permissionsDetails table tr td:empty').html('-')
+			this.$el.find('#permissionsDetails table tr td:empty').html('-');
+			if(this.$el.find('#permissionsDetails table tbody tr').length == 0){
+				this.$el.find('#permissionsDetails table tbody').append('<tr><td colspan="5">'+ localization.tt("msg.noRecordsFound") +'</td></tr>');
+			}
 		},
 
 		getPermHeaders : function(){
@@ -130,6 +139,46 @@ define(function(require) {
 			};
 		},
 
+		nextVer : function(e){
+			var $el = $(e.currentTarget);
+			if($el.hasClass('active')){
+				var curr = this.policy.get('version');
+				this.getPolicyByVersion(++curr, e);
+			}
+		},
+
+		previousVer : function(e){
+			var $el = $(e.currentTarget);
+			if($el.hasClass('active')){
+				var curr = this.policy.get('version');
+				this.getPolicyByVersion(--curr, e);
+			}
+		},
+
+		getPolicyByVersion : function(ver, e){
+			this.policy.fetchByVersion(ver, {
+				cache : false,
+				async : false
+			});
+			this.initializePolicyDetailsObj();
+			this.render();
+			var verEl = $(e.currentTarget).parent();
+			verEl.find('text').text('Version '+this.policy.get('version'));
+			var prevEl = verEl.find('#preVer'),
+				nextEl = verEl.find('#nextVer');
+			if(this.policy.get('version')>1){
+				prevEl.addClass('active');
+			}else{
+				prevEl.removeClass('active');
+			}
+			var policyVerIndexAt = this.policyVersionList.indexOf(this.policy.get('version').toString());
+			if(!_.isUndefined(this.policyVersionList[++policyVerIndexAt])){
+				nextEl.addClass('active');
+			}else{
+				nextEl.removeClass('active');
+			}
+		},
+
 		/** on close */
 		onClose: function() {}
 	});

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5df9aa64/security-admin/src/main/webapp/scripts/views/reports/AuditLayout.js
----------------------------------------------------------------------
diff --git a/security-admin/src/main/webapp/scripts/views/reports/AuditLayout.js b/security-admin/src/main/webapp/scripts/views/reports/AuditLayout.js
index 26375d8..9a3cbde 100644
--- a/security-admin/src/main/webapp/scripts/views/reports/AuditLayout.js
+++ b/security-admin/src/main/webapp/scripts/views/reports/AuditLayout.js
@@ -735,19 +735,29 @@ define(function(require) {
 					var policy = new RangerPolicy({
 						id: policyId
 					});
+					var policyVersionList = policy.fetchVersions();
 					var view = new RangerPolicyRO({
 						policy: policy,
+						policyVersionList : policyVersionList,
 						serviceDef: serviceDef,
 						eventTime : eventTime
 					});
 					var modal = new Backbone.BootstrapModal({
 						animate : true, 
 						content		: view,
-						title: localization.tt("h.policy")+': '+policy.get('name'),
+						title: localization.tt("h.policyDetails"),
 						okText :localization.tt("lbl.ok"),
 						allowCancel : false,
 						escape : true
 					}).open();
+					var policyVerEl = modal.$el.find('.modal-footer').prepend('<div class="policyVer pull-left"></div>').find('.policyVer');
+					policyVerEl.append('<i id="preVer" class="icon-chevron-left '+ ((policy.get('version')>1) ? 'active' : '') +'"></i><text>Version '+ policy.get('version') +'</text>').find('#preVer').click(function(e){
+						view.previousVer(e);
+					});
+					var policyVerIndexAt = policyVersionList.indexOf(policy.get('version').toString());
+					policyVerEl.append('<i id="nextVer" class="icon-chevron-right '+ (!_.isUndefined(policyVersionList[++policyVerIndexAt])? 'active' : '')+'"></i>').find('#nextVer').click(function(e){
+						view.nextVer(e);
+					});
 				}
 			});
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5df9aa64/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 c4f2f71..31e2a46 100644
--- a/security-admin/src/main/webapp/styles/xa.css
+++ b/security-admin/src/main/webapp/styles/xa.css
@@ -645,6 +645,38 @@ table.backgrid thead tr:hover {
   color: #4F4F4F !important;
   background-color: inherit !important;
 }
+.serviceInfo{
+  margin-top: -5px;
+}
+.updateInfo{
+  margin-top: 10px;
+}
+.updateInfo p {
+  margin-bottom: 0px;
+  margin-top: 0px;
+  font-size: 11px;
+}
+.policyVer{
+  font-size: 23px;
+  padding: 5px 0 0 3px;
+}
+.policyVer i{
+  color : #3C9C11 !important;
+  opacity: 0.4;
+  -webkit-user-select: none;
+}
+.policyVer i.active{
+  color : #3C9C11 !important;
+  cursor : pointer;
+  opacity: 1;
+}
+.policyVer text{
+  padding : 0 10px;
+  color : black;
+  font-size: 14px;
+  position: relative;
+  top: -3px;
+}
 
 .r-path {
   word-break: break-all;

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5df9aa64/security-admin/src/main/webapp/templates/policies/RangerPolicyRO_tmpl.html
----------------------------------------------------------------------
diff --git a/security-admin/src/main/webapp/templates/policies/RangerPolicyRO_tmpl.html b/security-admin/src/main/webapp/templates/policies/RangerPolicyRO_tmpl.html
index b2cec3a..77f7605 100644
--- a/security-admin/src/main/webapp/templates/policies/RangerPolicyRO_tmpl.html
+++ b/security-admin/src/main/webapp/templates/policies/RangerPolicyRO_tmpl.html
@@ -14,9 +14,21 @@
   See the License for the specific language governing permissions and
   limitations under the License.
 --}}
-<div id="policyDetails">
+<div class="serviceInfo row-fluid">
+  <div class="pull-left">
+    <p>
+      <strong>{{tt 'lbl.serivceName'}} :</strong> {{PolicyDetails.service}}
+    </p>
+  </div>
+  <div class="pull-right">
+    <p>
+      <strong>{{tt 'lbl.serivceType'}} :</strong> {{PolicyDetails.serviceType}}
+    </p>
+  </div>
+</div>
+<div id="policyDetails" class="row-fluid">
   <p class="formHeader">
-    Policy Details : 
+    {{tt 'h.policyDetails'}} : 
   </p>
   <table class="table table-bordered table-condensed">
     <tbody>
@@ -25,7 +37,7 @@
           {{tt 'lbl.policyId'}}
         </td>
         <td>
-          <div class="controls"><label class="label label-ranger">{{PolicyDetails.id}}</label></div>
+          <div class="controls"><label class="label label-ranger" style="cursor: auto;">{{PolicyDetails.id}}</label></div>
         </td>
       </tr>
       <tr>
@@ -69,9 +81,9 @@
     </tbody>
   </table>
 </div>
-<div id="permissionsDetails">
+<div id="permissionsDetails" class="row-fluid">
   <p class="formHeader">
-    User and Group Permissions :
+    {{tt 'h.userGroupPermissions'}} :
   </p>
   <table class="table-permission table-condensed table-read-only" style="width:100%">
     <thead>
@@ -110,4 +122,22 @@
       {{/each}}
     </tbody>
   </table>
+</div>
+<div class="updateInfo row-fluid">
+  <div class="pull-left">
+    <p>
+      <strong>{{tt 'lbl.updatedBy'}} :</strong> {{PolicyDetails.updatedBy}}
+    </p>
+    <p>
+      <strong>{{tt 'lbl.updatedOn'}} :</strong> {{PolicyDetails.updateTime}}
+    </p>
+  </div>
+  <div class="pull-right">
+    <p>
+      <strong>{{tt 'lbl.createdBy'}} :</strong> {{PolicyDetails.createdBy}}
+    </p>
+    <p>
+      <strong>{{tt 'lbl.createdOn'}} :</strong> {{PolicyDetails.createTime}}
+    </p>
+  </div>
 </div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5df9aa64/security-admin/src/main/webapp/templates/service/ConfigurationItem_tmpl.html
----------------------------------------------------------------------
diff --git a/security-admin/src/main/webapp/templates/service/ConfigurationItem_tmpl.html b/security-admin/src/main/webapp/templates/service/ConfigurationItem_tmpl.html
index a225b1b..6d330c4 100644
--- a/security-admin/src/main/webapp/templates/service/ConfigurationItem_tmpl.html
+++ b/security-admin/src/main/webapp/templates/service/ConfigurationItem_tmpl.html
@@ -14,8 +14,8 @@
   See the License for the specific language governing permissions and
   limitations under the License.
 --}}
-<td><input type="text" data-js="name" value={{this.name}}></td>
-<td><input type="text" data-js="value" value={{this.value}}></td>
+<td><input type="text" data-js="name" value="{{this.name}}"></td>
+<td><input type="text" data-js="value" value="{{this.value}}"></td>
 <td>
 	<button type="button" class="btn btn-small btn-danger" data-action="delete">
 		<i class="icon-remove"></i>