AMBARI-16177. Views: User should be able to assign permission of a view 
instance to cluster roles. (dipayanb)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/4342a6b7
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/4342a6b7
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/4342a6b7

Branch: refs/heads/trunk
Commit: 4342a6b7eb6eed781d879c46435acc9f0ea8c981
Parents: 7eeab53
Author: Dipayan Bhowmick <dipayan.bhowm...@gmail.com>
Authored: Tue Apr 26 12:21:18 2016 +0530
Committer: Dipayan Bhowmick <dipayan.bhowm...@gmail.com>
Committed: Tue May 3 23:12:27 2016 +0530

----------------------------------------------------------------------
 .../controllers/ambariViews/ViewsEditCtrl.js    | 728 ++++++++++---------
 .../ui/admin-web/app/scripts/i18n.config.js     |   9 +
 .../ui/admin-web/app/scripts/services/Group.js  |  12 +-
 .../app/scripts/services/PermissionLoader.js    |  10 +-
 .../app/scripts/services/PermissionsSaver.js    |  16 +-
 .../ui/admin-web/app/scripts/services/View.js   |   8 +
 .../resources/ui/admin-web/app/styles/main.css  |   6 +
 .../admin-web/app/views/ambariViews/edit.html   |  85 ++-
 .../ambari/server/controller/AmbariServer.java  |   2 +-
 .../server/controller/ControllerModule.java     |   2 +
 .../GroupPrivilegeResourceProvider.java         |  24 +-
 .../internal/PrivilegeResourceProvider.java     |   3 +
 .../internal/UserPrivilegeResourceProvider.java |  37 +-
 .../ambari/server/orm/dao/PrincipalDAO.java     |   8 +
 .../server/orm/entities/PrincipalEntity.java    |   3 +-
 .../orm/entities/PrincipalTypeEntity.java       |  10 +
 .../authorization/AuthorizationHelper.java      |  73 +-
 .../ClusterInheritedPermissionHelper.java       | 213 ++++++
 .../server/upgrade/AbstractUpgradeCatalog.java  |  36 +
 .../server/upgrade/UpgradeCatalog240.java       |  27 +
 .../apache/ambari/server/view/ViewRegistry.java |  57 +-
 .../view/configuration/AutoInstanceConfig.java  |  27 +
 .../main/resources/Ambari-DDL-Derby-CREATE.sql  |  28 +-
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |  28 +-
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |  28 +-
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |  28 +-
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |  28 +-
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql |  28 +-
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |  19 +-
 .../AlertDefinitionResourceProviderTest.java    |   2 +
 .../AlertGroupResourceProviderTest.java         |   2 +
 .../AlertHistoryResourceProviderTest.java       |   2 +
 .../AlertNoticeResourceProviderTest.java        |   2 +
 .../internal/AlertResourceProviderTest.java     |   2 +
 .../internal/ComponentResourceProviderTest.java |   2 +
 .../GroupPrivilegeResourceProviderTest.java     |  19 +-
 .../internal/HostResourceProviderTest.java      |   3 +
 .../internal/RequestResourceProviderTest.java   |   3 +
 .../UserPrivilegeResourceProviderTest.java      | 129 +++-
 .../metrics/JMXPropertyProviderTest.java        |   2 +
 .../ganglia/GangliaPropertyProviderTest.java    |   2 +
 .../AuthorizationHelperInitializer.java         |  47 ++
 .../authorization/AuthorizationHelperTest.java  | 109 ++-
 .../server/upgrade/UpgradeCatalog240Test.java   |  51 ++
 .../configuration/AutoInstanceConfigTest.java   |  10 +
 45 files changed, 1488 insertions(+), 482 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsEditCtrl.js
----------------------------------------------------------------------
diff --git 
a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsEditCtrl.js
 
b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsEditCtrl.js
index 877e230..243a8e4 100644
--- 
a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsEditCtrl.js
+++ 
b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsEditCtrl.js
@@ -18,402 +18,412 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('ViewsEditCtrl', ['$scope', '$routeParams' , 'Cluster', 'View', 
'Alert', 'PermissionLoader', 'PermissionSaver', 'ConfirmationModal', 
'$location', 'UnsavedDialog', '$translate', function($scope, $routeParams, 
Cluster, View, Alert, PermissionLoader, PermissionSaver, ConfirmationModal, 
$location, UnsavedDialog, $translate) {
-  var $t = $translate.instant;
-  $scope.identity = angular.identity;
-  $scope.isConfigurationEmpty = true;
-  $scope.isSettingsEmpty = true;
-  $scope.constants = {
-    instance: $t('views.instance'),
-    props: $t('views.properties'),
-    perms: $t('views.permissions').toLowerCase()
-  };
-
-  function reloadViewInfo(section){
-    // Load instance data, after View permissions meta loaded
-    View.getInstance($routeParams.viewId, $routeParams.version, 
$routeParams.instanceId)
-    .then(function(instance) {
-      $scope.instance = instance;
-      $scope.settings = {
-        'visible': $scope.instance.ViewInstanceInfo.visible,
-        'label': $scope.instance.ViewInstanceInfo.label,
-        'description': $scope.instance.ViewInstanceInfo.description,
-        'shortUrl': $scope.instance.ViewInstanceInfo.short_url
-      };
-      switch (section) {
-        case "details" :
-          initConfigurations();
-          initCtrlVariables(instance);
-          break;
-        case "settings" :
-          initConfigurations(true);
-          break;
-        case "cluster" :
-          initCtrlVariables(instance);
-          break;
-      }
-    })
-    .catch(function(data) {
-      Alert.error($t('views.alerts.cannotLoadInstanceInfo'), 
data.data.message);
-    });
-  }
-
-  function initCtrlVariables(instance) {
-    if(instance.ViewInstanceInfo.cluster_handle) {
-      $scope.isLocalCluster = true;
-      $scope.cluster = instance.ViewInstanceInfo.cluster_handle;
-    }else{
-      $scope.isLocalCluster = false;
-      $scope.cluster = $scope.clusters.length > 0 ? $scope.clusters[0] : 
$t('common.noClusters');
-    }
-    $scope.originalLocalCluster = $scope.isLocalCluster;
-    $scope.isConfigurationEmpty = !$scope.numberOfClusterConfigs;
-    $scope.isSettingsEmpty = !$scope.numberOfSettingsConfigs;
-  }
-
-  function isClusterConfig(name) {
-    var configurationMeta = $scope.configurationMeta;
-    var clusterConfigs = configurationMeta.filter(function(el) {
-      return el.clusterConfig;
-    }).map(function(el) {
-      return el.name;
-    });
-    return clusterConfigs.indexOf(name) !== -1;
-  }
-
-  function initConfigurations(initClusterConfig) {
-    var initAllConfigs = !initClusterConfig;
-    var configuration = 
angular.copy($scope.instance.ViewInstanceInfo.properties);
-    if (initAllConfigs) {
-      $scope.configuration = 
angular.copy($scope.instance.ViewInstanceInfo.properties);
+  .controller('ViewsEditCtrl', ['$scope', '$routeParams' , 'Cluster', 'View', 
'Alert', 'PermissionLoader', 'PermissionSaver', 'ConfirmationModal', 
'$location', 'UnsavedDialog', '$translate', function($scope, $routeParams, 
Cluster, View, Alert, PermissionLoader, PermissionSaver, ConfirmationModal, 
$location, UnsavedDialog, $translate) {
+    var $t = $translate.instant;
+    $scope.identity = angular.identity;
+    $scope.isConfigurationEmpty = true;
+    $scope.isSettingsEmpty = true;
+    $scope.clusterInheritedPermissionKeys = 
View.clusterInheritedPermissionKeys;
+    $scope.constants = {
+      instance: $t('views.instance'),
+      props: $t('views.properties'),
+      perms: $t('views.permissions').toLowerCase()
+    };
+
+    function reloadViewInfo(section){
+      // Load instance data, after View permissions meta loaded
+      View.getInstance($routeParams.viewId, $routeParams.version, 
$routeParams.instanceId)
+        .then(function(instance) {
+          $scope.instance = instance;
+          $scope.settings = {
+            'visible': $scope.instance.ViewInstanceInfo.visible,
+            'label': $scope.instance.ViewInstanceInfo.label,
+            'description': $scope.instance.ViewInstanceInfo.description,
+            'shortUrl': $scope.instance.ViewInstanceInfo.short_url
+          };
+          switch (section) {
+            case "details" :
+              initConfigurations();
+              initCtrlVariables(instance);
+              break;
+            case "settings" :
+              initConfigurations(true);
+              break;
+            case "cluster" :
+              initCtrlVariables(instance);
+              break;
+          }
+        })
+        .catch(function(data) {
+          Alert.error($t('views.alerts.cannotLoadInstanceInfo'), 
data.data.message);
+        });
     }
-    for (var confName in configuration) {
-      if (configuration.hasOwnProperty(confName)) {
-        if (!isClusterConfig(confName) || initAllConfigs) {
-          $scope.configuration[confName] = configuration[confName] === 'null' 
? '' : configuration[confName];
-        }
+
+    function initCtrlVariables(instance) {
+      if(instance.ViewInstanceInfo.cluster_handle) {
+        $scope.isLocalCluster = true;
+        $scope.cluster = instance.ViewInstanceInfo.cluster_handle;
+      }else{
+        $scope.isLocalCluster = false;
+        $scope.cluster = $scope.clusters.length > 0 ? $scope.clusters[0] : 
$t('common.noClusters');
       }
+      $scope.originalLocalCluster = $scope.isLocalCluster;
+      $scope.isConfigurationEmpty = !$scope.numberOfClusterConfigs;
+      $scope.isSettingsEmpty = !$scope.numberOfSettingsConfigs;
     }
-  }
 
-  function filterClusterConfigs() {
-    $scope.configurationMeta.forEach(function (element) {
-      if (element.masked && !$scope.editConfigurationDisabled && 
element.clusterConfig && !$scope.isLocalCluster) {
-        $scope.configuration[element.name] = '';
-      }
-      if(!element.clusterConfig) {
-        delete $scope.configurationBeforeEdit[element.name];
+    function isClusterConfig(name) {
+      var configurationMeta = $scope.configurationMeta;
+      var clusterConfigs = configurationMeta.filter(function(el) {
+        return el.clusterConfig;
+      }).map(function(el) {
+        return el.name;
+      });
+      return clusterConfigs.indexOf(name) !== -1;
+    }
+
+    function initConfigurations(initClusterConfig) {
+      var initAllConfigs = !initClusterConfig;
+      var configuration = 
angular.copy($scope.instance.ViewInstanceInfo.properties);
+      if (initAllConfigs) {
+        $scope.configuration = 
angular.copy($scope.instance.ViewInstanceInfo.properties);
       }
-    });
-  }
-
-  // Get META for properties
-  View.getMeta($routeParams.viewId, $routeParams.version).then(function(data) {
-    $scope.configurationMeta = data.data.ViewVersionInfo.parameters;
-    $scope.clusterConfigurable = 
data.data.ViewVersionInfo.cluster_configurable;
-    $scope.clusterConfigurableErrorMsg = $scope.clusterConfigurable ? "" : 
$t('views.alerts.cannotUseOption');
-    angular.forEach($scope.configurationMeta, function (item) {
-      item.displayName = item.name.replace(/\./g, '\.\u200B');
-      item.clusterConfig = !!item.clusterConfig;
-      if (!item.clusterConfig) {
-        $scope.numberOfSettingsConfigs++;
+      for (var confName in configuration) {
+        if (configuration.hasOwnProperty(confName)) {
+          if (!isClusterConfig(confName) || initAllConfigs) {
+            $scope.configuration[confName] = configuration[confName] === 
'null' ? '' : configuration[confName];
+          }
+        }
       }
-      $scope.numberOfClusterConfigs = $scope.numberOfClusterConfigs + 
!!item.clusterConfig;
-    });
-    reloadViewInfo("details");
-  });
-
-  function reloadViewPrivileges(){
-    PermissionLoader.getViewPermissions({
-      viewName: $routeParams.viewId,
-      version: $routeParams.version,
-      instanceId: $routeParams.instanceId
-    })
-    .then(function(permissions) {
-      // Refresh data for rendering
-      $scope.permissionsEdit = permissions;
-      $scope.permissions = angular.copy(permissions);
-      $scope.isPermissionsEmpty = angular.equals({}, $scope.permissions);
-    })
-    .catch(function(data) {
-      Alert.error($t('views.alerts.cannotLoadPermissions'), data.data.message);
-    });
-  }
+    }
 
-  $scope.permissions = [];
+    function filterClusterConfigs() {
+      $scope.configurationMeta.forEach(function (element) {
+        if (element.masked && !$scope.editConfigurationDisabled && 
element.clusterConfig && !$scope.isLocalCluster) {
+          $scope.configuration[element.name] = '';
+        }
+        if(!element.clusterConfig) {
+          delete $scope.configurationBeforeEdit[element.name];
+        }
+      });
+    }
 
-  reloadViewPrivileges();
+    // Get META for properties
+    View.getMeta($routeParams.viewId, 
$routeParams.version).then(function(data) {
+      $scope.configurationMeta = data.data.ViewVersionInfo.parameters;
+      $scope.clusterConfigurable = 
data.data.ViewVersionInfo.cluster_configurable;
+      $scope.clusterConfigurableErrorMsg = $scope.clusterConfigurable ? "" : 
$t('views.alerts.cannotUseOption');
+      angular.forEach($scope.configurationMeta, function (item) {
+        item.displayName = item.name.replace(/\./g, '\.\u200B');
+        item.clusterConfig = !!item.clusterConfig;
+        if (!item.clusterConfig) {
+          $scope.numberOfSettingsConfigs++;
+        }
+        $scope.numberOfClusterConfigs = $scope.numberOfClusterConfigs + 
!!item.clusterConfig;
+      });
+      reloadViewInfo("details");
+    });
 
-  $scope.clusterConfigurable = false;
-  $scope.clusterConfigurableErrorMsg = "";
-  $scope.clusters = [];
-  $scope.cluster = null;
-  $scope.noClusterAvailible = true;
+    function reloadViewPrivileges(){
+      PermissionLoader.getViewPermissions({
+          viewName: $routeParams.viewId,
+          version: $routeParams.version,
+          instanceId: $routeParams.instanceId
+        })
+        .then(function(permissions) {
+          // Refresh data for rendering
+          $scope.permissionsEdit = permissions;
+          $scope.permissions = angular.copy(permissions);
+          $scope.isPermissionsEmpty = angular.equals({}, $scope.permissions);
+        })
+        .catch(function(data) {
+          Alert.error($t('views.alerts.cannotLoadPermissions'), 
data.data.message);
+        });
+    }
 
+    $scope.permissions = [];
 
-  $scope.editSettingsDisabled = true;
-  $scope.editDetailsSettingsDisabled = true;
-  $scope.numberOfClusterConfigs = 0;
-  $scope.numberOfSettingsConfigs = 0;
+    reloadViewPrivileges();
 
-  $scope.enableLocalCluster = function() {
-    angular.extend($scope.configuration, $scope.configurationBeforeEdit);
-    $scope.propertiesForm.$setPristine();
-  };
+    $scope.clusterConfigurable = false;
+    $scope.clusterConfigurableErrorMsg = "";
+    $scope.clusters = [];
+    $scope.cluster = null;
+    $scope.noClusterAvailible = true;
 
-  $scope.disableLocalCluster = function() {
-    filterClusterConfigs();
-  };
 
-  $scope.toggleSettingsEdit = function() {
-    $scope.editSettingsDisabled = !$scope.editSettingsDisabled;
-    $scope.settingsBeforeEdit = angular.copy($scope.configuration);
-    $scope.configurationMeta.forEach(function (element) {
-      if (element.masked && !$scope.editSettingsDisabled && 
!element.clusterConfig) {
-        $scope.configuration[element.name] = '';
-      }
-      if(element.clusterConfig) {
-        delete $scope.settingsBeforeEdit[element.name];
-      }
-    });
-  };
-
-  $scope.toggleDetailsSettingsEdit = function() {
-    $scope.editDetailsSettingsDisabled = !$scope.editDetailsSettingsDisabled;
-    $scope.settingsBeforeEdit = angular.copy($scope.configuration);
-    $scope.configurationMeta.forEach(function (element) {
-      if (element.masked && !$scope.editDetailsSettingsDisabled && 
!element.clusterConfig) {
-        $scope.configuration[element.name] = '';
-      }
-      if(element.clusterConfig) {
-        delete $scope.settingsBeforeEdit[element.name];
-      }
-    });
-  };
+    $scope.editSettingsDisabled = true;
+    $scope.editDetailsSettingsDisabled = true;
+    $scope.numberOfClusterConfigs = 0;
+    $scope.numberOfSettingsConfigs = 0;
 
-  Cluster.getAllClusters().then(function (clusters) {
-    if(clusters.length >0){
-      clusters.forEach(function(cluster) {
-        $scope.clusters.push(cluster.Clusters.cluster_name)
-      });
-      $scope.noClusterAvailible = false;
-    }else{
-      $scope.clusters.push($t('common.noClusters'));
-    }
-    $scope.cluster = $scope.clusters[0];
-  });
+    $scope.enableLocalCluster = function() {
+      angular.extend($scope.configuration, $scope.configurationBeforeEdit);
+      $scope.propertiesForm.$setPristine();
+    };
 
+    $scope.disableLocalCluster = function() {
+      filterClusterConfigs();
+    };
 
-  $scope.saveSettings = function(callback) {
-    if( $scope.settingsForm.$valid ){
-      var data = {
-        'ViewInstanceInfo':{
-          'properties':{}
-        }
-      };
+    $scope.toggleSettingsEdit = function() {
+      $scope.editSettingsDisabled = !$scope.editSettingsDisabled;
+      $scope.settingsBeforeEdit = angular.copy($scope.configuration);
       $scope.configurationMeta.forEach(function (element) {
-        if(!element.clusterConfig) {
-          data.ViewInstanceInfo.properties[element.name] = 
$scope.configuration[element.name];
+        if (element.masked && !$scope.editSettingsDisabled && 
!element.clusterConfig) {
+          $scope.configuration[element.name] = '';
         }
-      });
-      return View.updateInstance($routeParams.viewId, $routeParams.version, 
$routeParams.instanceId, data)
-      .success(function() {
-        if( callback ){
-          callback();
-        } else {
-          reloadViewInfo("settings");
-          $scope.editSettingsDisabled = true;
-          $scope.settingsForm.$setPristine();
+        if(element.clusterConfig) {
+          delete $scope.settingsBeforeEdit[element.name];
         }
-      })
-      .catch(function(data) {
-        Alert.error($t('views.alerts.cannotSaveSettings'), data.data.message);
       });
-    }
-  };
-  $scope.cancelSettings = function() {
-    angular.extend($scope.configuration, $scope.settingsBeforeEdit);
+    };
 
-    $scope.editSettingsDisabled = true;
-    $scope.settingsForm.$setPristine();
-  };
-
-  $scope.saveDetails = function(callback) {
-    if( $scope.detailsForm.$valid ){
-      var data = {
-        'ViewInstanceInfo':{
-          'visible': $scope.settings.visible,
-          'label': $scope.settings.label,
-          'description': $scope.settings.description
+    $scope.toggleDetailsSettingsEdit = function() {
+      $scope.editDetailsSettingsDisabled = !$scope.editDetailsSettingsDisabled;
+      $scope.settingsBeforeEdit = angular.copy($scope.configuration);
+      $scope.configurationMeta.forEach(function (element) {
+        if (element.masked && !$scope.editDetailsSettingsDisabled && 
!element.clusterConfig) {
+          $scope.configuration[element.name] = '';
         }
-      };
-      return View.updateInstance($routeParams.viewId, $routeParams.version, 
$routeParams.instanceId, data)
-      .success(function() {
-        $scope.$root.$emit('instancesUpdate');
-        if( callback ){
-          callback();
-        } else {
-          reloadViewInfo("cluster");
-          $scope.editDetailsSettingsDisabled = true;
-          $scope.settingsForm.$setPristine();
+        if(element.clusterConfig) {
+          delete $scope.settingsBeforeEdit[element.name];
         }
-      })
-      .catch(function(data) {
-        Alert.error($t('views.alerts.cannotSaveSettings'), data.data.message);
       });
-    }
-  };
-  $scope.cancelDetails = function() {
-    $scope.settings = {
-      'visible': $scope.instance.ViewInstanceInfo.visible,
-      'label': $scope.instance.ViewInstanceInfo.label,
-      'description': $scope.instance.ViewInstanceInfo.description,
-      'shortUrl': $scope.instance.ViewInstanceInfo.short_url
     };
-    $scope.editDetailsSettingsDisabled = true;
-    $scope.settingsForm.$setPristine();
-  };
-
-
-  $scope.editConfigurationDisabled = true;
-  $scope.togglePropertiesEditing = function () {
-    $scope.editConfigurationDisabled = !$scope.editConfigurationDisabled;
-    $scope.configurationBeforeEdit = angular.copy($scope.configuration);
-    filterClusterConfigs();
-  };
-  $scope.saveConfiguration = function() {
-    if( $scope.propertiesForm.$valid ){
-      var data = {
-        'ViewInstanceInfo':{
-          'properties':{}
-        }
-      };
-      if($scope.isLocalCluster) {
-        data.ViewInstanceInfo.cluster_handle = $scope.cluster;
-      } else {
-        data.ViewInstanceInfo.cluster_handle = null;
+
+    Cluster.getAllClusters().then(function (clusters) {
+      if(clusters.length >0){
+        clusters.forEach(function(cluster) {
+          $scope.clusters.push(cluster.Clusters.cluster_name)
+        });
+        $scope.noClusterAvailible = false;
+      }else{
+        $scope.clusters.push($t('common.noClusters'));
+      }
+      $scope.cluster = $scope.clusters[0];
+    });
+
+
+    $scope.saveSettings = function(callback) {
+      if( $scope.settingsForm.$valid ){
+        var data = {
+          'ViewInstanceInfo':{
+            'properties':{}
+          }
+        };
         $scope.configurationMeta.forEach(function (element) {
-          if(element.clusterConfig) {
+          if(!element.clusterConfig) {
             data.ViewInstanceInfo.properties[element.name] = 
$scope.configuration[element.name];
           }
         });
+        return View.updateInstance($routeParams.viewId, $routeParams.version, 
$routeParams.instanceId, data)
+          .success(function() {
+            if( callback ){
+              callback();
+            } else {
+              reloadViewInfo("settings");
+              $scope.editSettingsDisabled = true;
+              $scope.settingsForm.$setPristine();
+            }
+          })
+          .catch(function(data) {
+            Alert.error($t('views.alerts.cannotSaveSettings'), 
data.data.message);
+          });
       }
-      $scope.originalLocalCluster = $scope.isLocalCluster;
-      return View.updateInstance($routeParams.viewId, $routeParams.version, 
$routeParams.instanceId, data)
-      .success(function() {
-        $scope.editConfigurationDisabled = true;
-        $scope.propertiesForm.$setPristine();
-      })
-      .catch(function(data) {
-        var errorMessage = data.data.message;
-
-        //TODO: maybe the BackEnd should sanitize the string beforehand?
-        errorMessage = errorMessage.substr(errorMessage.indexOf("\{"));
-
-        if (data.status >= 400 && !$scope.isLocalCluster) {
-          try {
-            var errorObject = JSON.parse(errorMessage);
-            errorMessage = errorObject.detail;
-            angular.forEach(errorObject.propertyResults, function (item, key) {
-              $scope.propertiesForm[key].validationError = !item.valid;
-              if (!item.valid) {
-                $scope.propertiesForm[key].validationMessage = item.detail;
-              }
-            });
-          } catch (e) {
-            console.error($t('views.alerts.unableToParseError', {message: 
data.message}));
+    };
+    $scope.cancelSettings = function() {
+      angular.extend($scope.configuration, $scope.settingsBeforeEdit);
+
+      $scope.editSettingsDisabled = true;
+      $scope.settingsForm.$setPristine();
+    };
+
+    $scope.saveDetails = function(callback) {
+      if( $scope.detailsForm.$valid ){
+        var data = {
+          'ViewInstanceInfo':{
+            'visible': $scope.settings.visible,
+            'label': $scope.settings.label,
+            'description': $scope.settings.description
           }
-        }
-        Alert.error($t('views.alerts.cannotSaveProperties'), errorMessage);
-      });
-    }
-  };
-  $scope.cancelConfiguration = function() {
-    angular.extend($scope.configuration, $scope.configurationBeforeEdit);
-    $scope.isLocalCluster = $scope.originalLocalCluster;
+        };
+        return View.updateInstance($routeParams.viewId, $routeParams.version, 
$routeParams.instanceId, data)
+          .success(function() {
+            $scope.$root.$emit('instancesUpdate');
+            if( callback ){
+              callback();
+            } else {
+              reloadViewInfo("cluster");
+              $scope.editDetailsSettingsDisabled = true;
+              $scope.settingsForm.$setPristine();
+            }
+          })
+          .catch(function(data) {
+            Alert.error($t('views.alerts.cannotSaveSettings'), 
data.data.message);
+          });
+      }
+    };
+    $scope.cancelDetails = function() {
+      $scope.settings = {
+        'visible': $scope.instance.ViewInstanceInfo.visible,
+        'label': $scope.instance.ViewInstanceInfo.label,
+        'description': $scope.instance.ViewInstanceInfo.description,
+        'shortUrl': $scope.instance.ViewInstanceInfo.short_url
+      };
+      $scope.editDetailsSettingsDisabled = true;
+      $scope.settingsForm.$setPristine();
+    };
+
+
     $scope.editConfigurationDisabled = true;
-    $scope.propertiesForm.$setPristine();
-  };
+    $scope.togglePropertiesEditing = function () {
+      $scope.editConfigurationDisabled = !$scope.editConfigurationDisabled;
+      $scope.configurationBeforeEdit = angular.copy($scope.configuration);
+      filterClusterConfigs();
+    };
+    $scope.saveConfiguration = function() {
+      if( $scope.propertiesForm.$valid ){
+        var data = {
+          'ViewInstanceInfo':{
+            'properties':{}
+          }
+        };
+        if($scope.isLocalCluster) {
+          data.ViewInstanceInfo.cluster_handle = $scope.cluster;
+        } else {
+          data.ViewInstanceInfo.cluster_handle = null;
+          $scope.configurationMeta.forEach(function (element) {
+            if(element.clusterConfig) {
+              data.ViewInstanceInfo.properties[element.name] = 
$scope.configuration[element.name];
+            }
+          });
+          $scope.clearClusterInheritedPermissions();
+        }
+        $scope.originalLocalCluster = $scope.isLocalCluster;
+        return View.updateInstance($routeParams.viewId, $routeParams.version, 
$routeParams.instanceId, data)
+          .success(function() {
+            $scope.editConfigurationDisabled = true;
+            $scope.propertiesForm.$setPristine();
+          })
+          .catch(function(data) {
+            var errorMessage = data.data.message;
 
-  // Permissions edit
-  $scope.editPermissionDisabled = true;
-  $scope.cancelPermissions = function() {
-    $scope.permissionsEdit = angular.copy($scope.permissions); // Reset 
textedit areaes
-    $scope.editPermissionDisabled = true;
-  };
+            //TODO: maybe the BackEnd should sanitize the string beforehand?
+            errorMessage = errorMessage.substr(errorMessage.indexOf("\{"));
 
-  $scope.savePermissions = function() {
-    $scope.editPermissionDisabled = true;
-    return PermissionSaver.saveViewPermissions(
-      $scope.permissionsEdit,
-      {
-        view_name: $routeParams.viewId,
-        version: $routeParams.version,
-        instance_name: $routeParams.instanceId
+            if (data.status >= 400 && !$scope.isLocalCluster) {
+              try {
+                var errorObject = JSON.parse(errorMessage);
+                errorMessage = errorObject.detail;
+                angular.forEach(errorObject.propertyResults, function (item, 
key) {
+                  $scope.propertiesForm[key].validationError = !item.valid;
+                  if (!item.valid) {
+                    $scope.propertiesForm[key].validationMessage = item.detail;
+                  }
+                });
+              } catch (e) {
+                console.error($t('views.alerts.unableToParseError', {message: 
data.message}));
+              }
+            }
+            Alert.error($t('views.alerts.cannotSaveProperties'), errorMessage);
+          });
       }
-    )
-    .then(reloadViewPrivileges)
-    .catch(function(data) {
-      reloadViewPrivileges();
-      Alert.error($t('common.alerts.cannotSavePermissions'), 
data.data.message);
-    });
-  };
+    };
+    $scope.cancelConfiguration = function() {
+      angular.extend($scope.configuration, $scope.configurationBeforeEdit);
+      $scope.isLocalCluster = $scope.originalLocalCluster;
+      $scope.editConfigurationDisabled = true;
+      $scope.propertiesForm.$setPristine();
+    };
 
-  $scope.$watch(function() {
-    return $scope.permissionsEdit;
-  }, function(newValue) {
-    if(newValue){
-      $scope.savePermissions();
-    }
-  }, true);
-
-  $scope.deleteInstance = function(instance) {
-    ConfirmationModal.show(
-      $t('common.delete', {
-        term: $t('views.viewInstance')
-      }),
-      $t('common.deleteConfirmation', {
-        instanceType: $t('views.viewInstance'),
-        instanceName: instance.ViewInstanceInfo.label
-      })
-    ).then(function() {
-      View.deleteInstance(instance.ViewInstanceInfo.view_name, 
instance.ViewInstanceInfo.version, instance.ViewInstanceInfo.instance_name)
-      .then(function() {
-        $location.path('/views');
+    // Permissions edit
+    $scope.editPermissionDisabled = true;
+    $scope.cancelPermissions = function() {
+      $scope.permissionsEdit = angular.copy($scope.permissions); // Reset 
textedit areaes
+      $scope.editPermissionDisabled = true;
+    };
+
+    $scope.savePermissions = function() {
+      $scope.editPermissionDisabled = true;
+      return PermissionSaver.saveViewPermissions(
+        $scope.permissionsEdit,
+        {
+          view_name: $routeParams.viewId,
+          version: $routeParams.version,
+          instance_name: $routeParams.instanceId
+        }
+        )
+        .then(reloadViewPrivileges)
+        .catch(function(data) {
+          reloadViewPrivileges();
+          Alert.error($t('common.alerts.cannotSavePermissions'), 
data.data.message);
+        });
+    };
+
+    $scope.clearClusterInheritedPermissions = function() {
+      angular.forEach(View.clusterInheritedPermissionKeys, function(key) {
+        $scope.permissionsEdit["VIEW.USER"][key] = false;
       })
-      .catch(function(data) {
-        Alert.error($t('views.alerts.cannotDeleteInstance'), 
data.data.message);
+    };
+
+    $scope.$watch(function() {
+      return $scope.permissionsEdit;
+    }, function(newValue, oldValue) {
+      if(newValue && oldValue != undefined) {
+        $scope.savePermissions();
+      }
+    }, true);
+    
+    
+
+    $scope.deleteInstance = function(instance) {
+      ConfirmationModal.show(
+        $t('common.delete', {
+          term: $t('views.viewInstance')
+        }),
+        $t('common.deleteConfirmation', {
+          instanceType: $t('views.viewInstance'),
+          instanceName: instance.ViewInstanceInfo.label
+        })
+      ).then(function() {
+        View.deleteInstance(instance.ViewInstanceInfo.view_name, 
instance.ViewInstanceInfo.version, instance.ViewInstanceInfo.instance_name)
+          .then(function() {
+            $location.path('/views');
+          })
+          .catch(function(data) {
+            Alert.error($t('views.alerts.cannotDeleteInstance'), 
data.data.message);
+          });
       });
-    });
-  };
-
-  $scope.$on('$locationChangeStart', function(event, targetUrl) {
-    if( $scope.settingsForm.$dirty || $scope.propertiesForm.$dirty){
-      UnsavedDialog().then(function(action) {
-        targetUrl = targetUrl.split('#').pop();
-        switch(action){
-          case 'save':
-            if($scope.settingsForm.$valid &&  $scope.propertiesForm.$valid ){
-              $scope.saveSettings(function() {
-                $scope.saveConfiguration().then(function() {
-                  $scope.propertiesForm.$setPristine();
-                  $scope.settingsForm.$setPristine();
-                  $location.path(targetUrl);
+    };
+
+    $scope.$on('$locationChangeStart', function(event, targetUrl) {
+      if( $scope.settingsForm.$dirty || $scope.propertiesForm.$dirty){
+        UnsavedDialog().then(function(action) {
+          targetUrl = targetUrl.split('#').pop();
+          switch(action){
+            case 'save':
+              if($scope.settingsForm.$valid &&  $scope.propertiesForm.$valid ){
+                $scope.saveSettings(function() {
+                  $scope.saveConfiguration().then(function() {
+                    $scope.propertiesForm.$setPristine();
+                    $scope.settingsForm.$setPristine();
+                    $location.path(targetUrl);
+                  });
                 });
-              });
-            }
-            break;
-          case 'discard':
-            $scope.propertiesForm.$setPristine();
-            $scope.settingsForm.$setPristine();
-            $location.path(targetUrl);
-            break;
-          case 'cancel':
-            targetUrl = '';
-            break;
-        }
-      });
-      event.preventDefault();
-    }
-  });
-}]);
+              }
+              break;
+            case 'discard':
+              $scope.propertiesForm.$setPristine();
+              $scope.settingsForm.$setPristine();
+              $location.path(targetUrl);
+              break;
+            case 'cancel':
+              targetUrl = '';
+              break;
+          }
+        });
+        event.preventDefault();
+      }
+    });
+  }]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
----------------------------------------------------------------------
diff --git 
a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js 
b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
index 6af7d4c..175792c 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
@@ -209,6 +209,15 @@ angular.module('ambariAdminConsole')
       'urlCreate':'Create new URL',
       'urlDelete':'Delete URL',
 
+      'clusterPermissions': {
+        'label': 'Inherit Cluster Permission',
+        'allclusteradministrator': 'All Cluster Administrator',
+        'allclusteroperator': 'All Cluster Operator',
+        'allclusteruser': 'All Cluster User',
+        'allserviceadministrator': 'All Service Administrator',
+        'allserviceoperator': 'All Service Operator'
+      },
+
       'alerts': {
         'noSpecialChars': 'Must not contain any special characters.',
         'noSpecialCharsOrSpaces': 'Must not contain any special characters or 
spaces.',

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Group.js
----------------------------------------------------------------------
diff --git 
a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Group.js 
b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Group.js
index ce892ec..660306c 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Group.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Group.js
@@ -181,13 +181,11 @@ angular.module('ambariAdminConsole')
   };
 
   Group.getPrivileges = function(groupId) {
-    return $http.get(Settings.baseUrl + '/privileges', {
-        params:{
-          'PrivilegeInfo/principal_type': 'GROUP',
-          'PrivilegeInfo/principal_name': groupId,
-          'fields': '*'
-        }
-      });
+    return $http.get(Settings.baseUrl + '/groups/' + groupId + '/privileges', {
+      params:{
+        'fields': '*'
+      }
+    });
   };
 
   return Group;

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionLoader.js
----------------------------------------------------------------------
diff --git 
a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionLoader.js
 
b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionLoader.js
index cc56191..13db1e6 100644
--- 
a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionLoader.js
+++ 
b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionLoader.js
@@ -22,18 +22,26 @@ angular.module('ambariAdminConsole')
   
   function getPermissionsFor(resource, params){
     var deferred = $q.defer();
+
     resource.getPermissions(params).then(function(permissions) {
       var permissionsInner = {}; // Save object into closure, until it 
completely fills to prevent blinkong
       angular.forEach(permissions, function(permission) {
         permission.GROUP = [];
         permission.USER = [];
+        angular.forEach(View.clusterInheritedPermissionKeys, function(key) {
+          permission[key] = false;
+        });
         permissionsInner[permission.PermissionInfo.permission_name] = 
permission;
       });
 
       // Now we can get privileges
       resource.getPrivileges(params).then(function(privileges) {
         angular.forEach(privileges, function(privilege) {
-          
permissionsInner[privilege.PrivilegeInfo.permission_name][privilege.PrivilegeInfo.principal_type].push(privilege.PrivilegeInfo.principal_name);
+          if(!privilege.PrivilegeInfo.principal_type.startsWith("ALL.")) {
+            
permissionsInner[privilege.PrivilegeInfo.permission_name][privilege.PrivilegeInfo.principal_type].push(privilege.PrivilegeInfo.principal_name);
+          } else {
+            
permissionsInner[privilege.PrivilegeInfo.permission_name][privilege.PrivilegeInfo.principal_type]
 = true;
+          }
         });
 
         // After all builded - return object

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionsSaver.js
----------------------------------------------------------------------
diff --git 
a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionsSaver.js
 
b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionsSaver.js
index fd19e1f..bebd668 100644
--- 
a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionsSaver.js
+++ 
b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionsSaver.js
@@ -23,7 +23,6 @@ angular.module('ambariAdminConsole')
 
   function savePermissionsFor(resource, permissions, params){
     var arr = [];
-
     angular.forEach(permissions, function(permission) {
       // Sanitaize input
       var users = permission.USER.toString().split(',').filter(function(item) 
{return item.trim();}).map(function(item) {return item.trim()});
@@ -48,6 +47,19 @@ angular.module('ambariAdminConsole')
           }
         }
       }));
+
+      angular.forEach(View.clusterInheritedPermissionKeys, function(key) {
+        if(permission[key] === true) {
+          arr.push({
+            'PrivilegeInfo': {
+              'permission_name': 'VIEW.USER',
+              'principal_name': '*',
+              'principal_type': key
+            }
+          });
+        }
+      });
+
     });
     if (!passOneRoleCheck(arr)) {
       console.log("CHECK FAILED");
@@ -143,7 +155,7 @@ angular.module('ambariAdminConsole')
     var hash = {};
     for(var i = 0; i < arr.length; i++) {
       var obj = arr[i];
-      if (hash[obj.PrivilegeInfo.principal_name]) {
+      if (hash[obj.PrivilegeInfo.principal_name] && 
obj.PrivilegeInfo.principal_name !== "*") {
         return false;
       } else {
         hash[obj.PrivilegeInfo.principal_name] = true;

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/View.js
----------------------------------------------------------------------
diff --git 
a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/View.js 
b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/View.js
index edc47e4..d352508 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/View.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/View.js
@@ -190,6 +190,14 @@ angular.module('ambariAdminConsole')
     self.versionsList = item.versions;
   }
 
+  View.clusterInheritedPermissionKeys = [
+    "ALL.CLUSTER.ADMINISTRATOR",
+    "ALL.CLUSTER.OPERATOR",
+    "ALL.CLUSTER.USER",
+    "ALL.SERVICE.OPERATOR",
+    "ALL.SERVICE.ADMINISTRATOR"
+  ];
+
   View.getInstance = function(viewName, version, instanceName) {
     return ViewInstance.find(viewName, version, instanceName);
   };

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css 
b/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
index 7309cfb..3e0bd30 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
@@ -1652,4 +1652,10 @@ thead.view-permission-header > tr > th {
 
 .role-details-modal .table-head .table-cell:last-of-type {
   visibility: hidden;
+}
+
+.cluster-inherited-permission {
+    border-bottom: 2px solid #ddd;
+    padding-bottom: 10px;
+    margin-top: 5px;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/edit.html
----------------------------------------------------------------------
diff --git 
a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/edit.html 
b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/edit.html
index 8eff030..fb37571 100644
--- 
a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/edit.html
+++ 
b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/edit.html
@@ -107,41 +107,6 @@
   </div>
 </div>
 
-<div class="panel panel-default views-permissions-panel" style="">
-  <div class="panel-heading clearfix">
-    <h3 class="panel-title pull-left">{{'views.permissions' | translate}}</h3>
-  </div>
-  <div class="panel-body">
-
-
-    <table class="table" ng-show="!isPermissionsEmpty">
-      <thead>
-        <tr>
-          <th class="col-sm-2"><label>{{'views.permission' | 
translate}}</label></th>
-          <th><label>{{'views.grantUsers' | translate}}</label></th>
-          <th><label>{{'views.grantGroups' | translate}}</label></th>
-        </tr>
-      </thead>
-      <tbody>
-        <tr ng-repeat="permission in permissions">
-          <td>
-            <label class="" 
tooltip="{{permission.PermissionInfo.permission_name}}">{{permission.PermissionInfo.permission_name
 | translate}}</label>
-          </td>
-          <td>
-            <editable-list 
items-source="permissionsEdit[permission.PermissionInfo.permission_name].USER" 
editable="true" resource-type="User"></editable-list>
-          </td>
-          <td>
-            <editable-list 
items-source="permissionsEdit[permission.PermissionInfo.permission_name].GROUP" 
editable="true" resource-type="Group" ></editable-list>
-          </td>
-        </tr>
-      </tbody>
-    </table>
-    <div ng-show="isPermissionsEmpty">
-      <div class="alert alert-info">{{'views.alerts.notDefined' | translate: 
'{term: constants.perms}'}}</div>
-    </div>
-  </div>
-</div>
-
 <div class="panel panel-default" ng-cloak ng-hide="isSettingsEmpty && 
instance">
   <div class="panel-heading clearfix">
     <h3 class="panel-title pull-left">{{'views.settings' | translate}}</h3>
@@ -251,3 +216,53 @@
     </div>
   </div>
 </div>
+
+<div class="panel panel-default views-permissions-panel" style="">
+  <div class="panel-heading clearfix">
+    <h3 class="panel-title pull-left">{{'views.permissions' | translate}}</h3>
+  </div>
+  <div class="panel-body">
+
+
+    <table class="table" ng-show="!isPermissionsEmpty">
+      <thead>
+      <tr>
+        <th class="col-sm-2"><label>{{'views.permission' | 
translate}}</label></th>
+        <th><label>{{'views.grantUsers' | translate}}</label></th>
+        <th><label>{{'views.grantGroups' | translate}}</label></th>
+      </tr>
+      </thead>
+      <tbody>
+      <tr ng-repeat="permission in permissions">
+        <td>
+          <label class="" 
tooltip="{{permission.PermissionInfo.permission_name}}">{{permission.PermissionInfo.permission_name
 | translate}}</label>
+        </td>
+        <td>
+          <editable-list 
items-source="permissionsEdit[permission.PermissionInfo.permission_name].USER" 
editable="true" resource-type="User"></editable-list>
+        </td>
+        <td>
+          <editable-list 
items-source="permissionsEdit[permission.PermissionInfo.permission_name].GROUP" 
editable="true" resource-type="Group" ></editable-list>
+        </td>
+      </tr>
+      </tbody>
+    </table>
+    <div ng-show="!isPermissionsEmpty && isLocalCluster && 
editConfigurationDisabled">
+      <div class="col-sm-12 cluster-inherited-permission">
+        <strong>{{'views.clusterPermissions.label' | translate}}</strong>
+      </div>
+      <div class="col-sm-offset-3 col-sm-9">
+        <div class="checkbox col-sm-4" ng-repeat="key in 
clusterInheritedPermissionKeys">
+          <div ng-init="i18nKey = 'views.clusterPermissions.' + 
key.split('.').join('').toLowerCase()">
+            <label>
+              <input type="checkbox" 
ng-model="permissionsEdit['VIEW.USER'][key]"> {{i18nKey | translate}}
+            </label>
+          </div>
+        </div>
+      </div>
+
+    </div>
+    <div ng-show="isPermissionsEmpty">
+      <div class="alert alert-info">{{'views.alerts.notDefined' | translate: 
'{term: constants.perms}'}}</div>
+    </div>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index 5c9004b..8476ec6 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -902,7 +902,7 @@ public class AmbariServer {
         injector.getInstance(GroupDAO.class), 
injector.getInstance(PrincipalDAO.class),
         injector.getInstance(PermissionDAO.class), 
injector.getInstance(ResourceDAO.class));
     UserPrivilegeResourceProvider.init(injector.getInstance(UserDAO.class), 
injector.getInstance(ClusterDAO.class),
-        injector.getInstance(GroupDAO.class), 
injector.getInstance(ViewInstanceDAO.class));
+        injector.getInstance(GroupDAO.class), 
injector.getInstance(ViewInstanceDAO.class), 
injector.getInstance(PrivilegeDAO.class));
     
ClusterPrivilegeResourceProvider.init(injector.getInstance(ClusterDAO.class));
     
AmbariPrivilegeResourceProvider.init(injector.getInstance(ClusterDAO.class));
     
ActionManager.setTopologyManager(injector.getInstance(TopologyManager.class));

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index bb2a374..992f2d2 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -86,6 +86,7 @@ import 
org.apache.ambari.server.scheduler.ExecutionSchedulerImpl;
 import org.apache.ambari.server.security.AmbariEntryPoint;
 import org.apache.ambari.server.security.SecurityHelper;
 import org.apache.ambari.server.security.SecurityHelperImpl;
+import org.apache.ambari.server.security.authorization.AuthorizationHelper;
 import org.apache.ambari.server.security.encryption.CredentialStoreService;
 import org.apache.ambari.server.security.encryption.CredentialStoreServiceImpl;
 import 
org.apache.ambari.server.serveraction.kerberos.KerberosOperationHandlerFactory;
@@ -368,6 +369,7 @@ public class ControllerModule extends AbstractModule {
 
     requestStaticInjection(DatabaseChecker.class);
     requestStaticInjection(KerberosChecker.class);
+    requestStaticInjection(AuthorizationHelper.class);
 
     bindByAnnotation(null);
     bindNotificationDispatchers();

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProvider.java
index c853514..94d1cad 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProvider.java
@@ -28,6 +28,7 @@ import 
org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.dao.GroupDAO;
+import org.apache.ambari.server.orm.dao.PrivilegeDAO;
 import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.GroupEntity;
@@ -35,10 +36,7 @@ import 
org.apache.ambari.server.orm.entities.PrincipalTypeEntity;
 import org.apache.ambari.server.orm.entities.PrivilegeEntity;
 import org.apache.ambari.server.orm.entities.ViewEntity;
 import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
-import org.apache.ambari.server.security.authorization.AuthorizationException;
-import org.apache.ambari.server.security.authorization.AuthorizationHelper;
-import org.apache.ambari.server.security.authorization.ResourceType;
-import org.apache.ambari.server.security.authorization.RoleAuthorization;
+import org.apache.ambari.server.security.authorization.*;
 
 import java.util.EnumSet;
 import java.util.HashMap;
@@ -83,6 +81,12 @@ public class GroupPrivilegeResourceProvider extends 
ReadOnlyResourceProvider {
   protected static ViewInstanceDAO viewInstanceDAO;
 
   /**
+   * Data access object used to obtain privilege entities.
+   */
+  @Inject
+  protected static PrivilegeDAO privilegeDAO;
+
+  /**
    * The property ids for a privilege resource.
    */
   private static Set<String> propertyIds = new HashSet<String>();
@@ -103,16 +107,17 @@ public class GroupPrivilegeResourceProvider extends 
ReadOnlyResourceProvider {
 
   /**
    * Static initialization.
-   *
-   * @param clusterDAO      the cluster data access object
+   *  @param clusterDAO      the cluster data access object
    * @param groupDAO        the group data access object
    * @param viewInstanceDAO the view instance data access object
+   * @param privilegeDAO
    */
   public static void init(ClusterDAO clusterDAO, GroupDAO groupDAO,
-                          ViewInstanceDAO viewInstanceDAO) {
+                          ViewInstanceDAO viewInstanceDAO, PrivilegeDAO 
privilegeDAO) {
     GroupPrivilegeResourceProvider.clusterDAO = clusterDAO;
     GroupPrivilegeResourceProvider.groupDAO = groupDAO;
     GroupPrivilegeResourceProvider.viewInstanceDAO = viewInstanceDAO;
+    GroupPrivilegeResourceProvider.privilegeDAO = privilegeDAO;
   }
 
   @SuppressWarnings("serial")
@@ -176,6 +181,11 @@ public class GroupPrivilegeResourceProvider extends 
ReadOnlyResourceProvider {
         }
 
         final Set<PrivilegeEntity> privileges = 
groupEntity.getPrincipal().getPrivileges();
+
+        Set<PrivilegeEntity> allViewPrivilegesWithClusterPermission =
+          
ClusterInheritedPermissionHelper.getViewPrivilegesWithClusterPermission(viewInstanceDAO,
 privilegeDAO, privileges);
+        privileges.addAll(allViewPrivilegesWithClusterPermission);
+
         for (PrivilegeEntity privilegeEntity : privileges) {
           resources.add(toResource(privilegeEntity, groupName, requestedIds));
         }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PrivilegeResourceProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PrivilegeResourceProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PrivilegeResourceProvider.java
index c825dc9..34111df 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PrivilegeResourceProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PrivilegeResourceProvider.java
@@ -51,6 +51,7 @@ import 
org.apache.ambari.server.orm.entities.PrincipalTypeEntity;
 import org.apache.ambari.server.orm.entities.PrivilegeEntity;
 import org.apache.ambari.server.orm.entities.ResourceEntity;
 import org.apache.ambari.server.orm.entities.UserEntity;
+import 
org.apache.ambari.server.security.authorization.ClusterInheritedPermissionHelper;
 
 /**
  * Abstract resource provider for privilege resources.
@@ -348,6 +349,8 @@ public abstract class PrivilegeResourceProvider<T> extends 
AbstractAuthorizedRes
       if (userEntity != null) {
         
entity.setPrincipal(principalDAO.findById(userEntity.getPrincipal().getId()));
       }
+    } else if 
(ClusterInheritedPermissionHelper.isValidPrincipalType(principalType)) {
+      
entity.setPrincipal(principalDAO.findByPrincipalType(principalType).get(0)); // 
There will be only one principal for that type
     } else {
       throw new AmbariException("Unknown principal type " + principalType);
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java
index cef8a11..bdd73a6 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java
@@ -17,12 +17,8 @@
  */
 package org.apache.ambari.server.controller.internal;
 
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchResourceException;
 import org.apache.ambari.server.controller.spi.Predicate;
@@ -32,6 +28,7 @@ import 
org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.dao.GroupDAO;
+import org.apache.ambari.server.orm.dao.PrivilegeDAO;
 import org.apache.ambari.server.orm.dao.UserDAO;
 import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
@@ -39,15 +36,24 @@ import org.apache.ambari.server.orm.entities.GroupEntity;
 import org.apache.ambari.server.orm.entities.MemberEntity;
 import org.apache.ambari.server.orm.entities.PrincipalTypeEntity;
 import org.apache.ambari.server.orm.entities.PrivilegeEntity;
+import org.apache.ambari.server.orm.entities.ResourceEntity;
 import org.apache.ambari.server.orm.entities.UserEntity;
 import org.apache.ambari.server.orm.entities.ViewEntity;
 import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import 
org.apache.ambari.server.security.authorization.ClusterInheritedPermissionHelper;
 import org.apache.ambari.server.security.authorization.ResourceType;
 import org.apache.ambari.server.security.authorization.RoleAuthorization;
 import org.apache.ambari.server.security.authorization.UserType;
 
+import javax.annotation.Nullable;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * Resource provider for user privilege resources.
  */
@@ -86,6 +92,11 @@ public class UserPrivilegeResourceProvider extends 
ReadOnlyResourceProvider {
   protected static ViewInstanceDAO viewInstanceDAO;
 
   /**
+   * DAO used to obtain privilege entities.
+   */
+  protected static PrivilegeDAO privilegeDAO;
+
+  /**
    * The property ids for a privilege resource.
    */
   private static Set<String> propertyIds = new HashSet<String>();
@@ -105,18 +116,19 @@ public class UserPrivilegeResourceProvider extends 
ReadOnlyResourceProvider {
 
   /**
    * Static initialization.
-   *
-   * @param userDAO         the user data access object
+   *  @param userDAO         the user data access object
    * @param clusterDAO      the cluster data access object
    * @param groupDAO        the group data access object
    * @param viewInstanceDAO the view instance data access object
+   * @param privilegeDAO
    */
   public static void init(UserDAO userDAO, ClusterDAO clusterDAO, GroupDAO 
groupDAO,
-                          ViewInstanceDAO viewInstanceDAO) {
+                          ViewInstanceDAO viewInstanceDAO, PrivilegeDAO 
privilegeDAO) {
     UserPrivilegeResourceProvider.userDAO         = userDAO;
     UserPrivilegeResourceProvider.clusterDAO      = clusterDAO;
     UserPrivilegeResourceProvider.groupDAO        = groupDAO;
     UserPrivilegeResourceProvider.viewInstanceDAO = viewInstanceDAO;
+    UserPrivilegeResourceProvider.privilegeDAO    = privilegeDAO;
   }
 
   @SuppressWarnings("serial")
@@ -163,6 +175,7 @@ public class UserPrivilegeResourceProvider extends 
ReadOnlyResourceProvider {
     final Set<Resource> resources = new HashSet<Resource>();
     final Set<String> requestedIds = getRequestPropertyIds(request, predicate);
 
+
     boolean isUserAdministrator = 
AuthorizationHelper.isAuthorized(ResourceType.AMBARI, null,
         RoleAuthorization.AMBARI_MANAGE_USERS);
 
@@ -187,10 +200,15 @@ public class UserPrivilegeResourceProvider extends 
ReadOnlyResourceProvider {
         }
 
         final Set<PrivilegeEntity> privileges = 
userEntity.getPrincipal().getPrivileges();
+
         for (MemberEntity membership : userEntity.getMemberEntities()) {
           
privileges.addAll(membership.getGroup().getPrincipal().getPrivileges());
         }
 
+        Set<PrivilegeEntity> allViewPrivilegesWithClusterPermission =
+          
ClusterInheritedPermissionHelper.getViewPrivilegesWithClusterPermission(viewInstanceDAO,
 privilegeDAO, privileges);
+        privileges.addAll(allViewPrivilegesWithClusterPermission);
+
         for (PrivilegeEntity privilegeEntity : privileges) {
           resources.add(toResource(privilegeEntity, userName, requestedIds));
         }
@@ -199,6 +217,7 @@ public class UserPrivilegeResourceProvider extends 
ReadOnlyResourceProvider {
     return resources;
   }
 
+
   /**
    * Translate the found data into a Resource
    *

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/PrincipalDAO.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/PrincipalDAO.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/PrincipalDAO.java
index 3d09227..efbdfab 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/PrincipalDAO.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/PrincipalDAO.java
@@ -80,6 +80,14 @@ public class PrincipalDAO {
     return daoUtils.selectList(query);
   }
 
+
+  @RequiresSession
+  public List<PrincipalEntity> findByPrincipalType(String name) {
+    TypedQuery<PrincipalEntity> query = 
entityManagerProvider.get().createNamedQuery("principalByPrincipalType", 
PrincipalEntity.class);
+    query.setParameter("principal_type", name);
+    return  daoUtils.selectList(query);
+  }
+
   /**
    * Make an instance managed and persistent.
    *

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PrincipalEntity.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PrincipalEntity.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PrincipalEntity.java
index 601a7d1..25d8d14 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PrincipalEntity.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PrincipalEntity.java
@@ -47,7 +47,8 @@ import javax.persistence.TableGenerator;
     , allocationSize = 500
 )
 @NamedQueries({
-  @NamedQuery(name = "principalByPrivilegeId", query = "SELECT principal FROM 
PrincipalEntity principal JOIN principal.privileges privilege WHERE 
privilege.permission.id=:permission_id")
+  @NamedQuery(name = "principalByPrivilegeId", query = "SELECT principal FROM 
PrincipalEntity principal JOIN principal.privileges privilege WHERE 
privilege.permission.id=:permission_id"),
+  @NamedQuery(name = "principalByPrincipalType", query = "SELECT principal 
FROM PrincipalEntity principal WHERE principal.principalType.name = 
:principal_type")
 })
 public class PrincipalEntity {
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PrincipalTypeEntity.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PrincipalTypeEntity.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PrincipalTypeEntity.java
index f05a643..b94f1ff 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PrincipalTypeEntity.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PrincipalTypeEntity.java
@@ -37,9 +37,19 @@ public class PrincipalTypeEntity {
    */
   public static final int USER_PRINCIPAL_TYPE  = 1;
   public static final int GROUP_PRINCIPAL_TYPE = 2;
+  public static final int CLUSTER_ADMINISTRATOR_PRINCIPAL_TYPE = 3;
+  public static final int CLUSTER_OPERATOR_PRINCIPAL_TYPE = 4;
+  public static final int CLUSTER_USER_PRINCIPAL_TYPE = 5;
+  public static final int SERVICE_ADMINISTRATOR_PRINCIPAL_TYPE = 6;
+  public static final int SERVICE_OPERATOR_PRINCIPAL_TYPE = 7;
 
   public static final String USER_PRINCIPAL_TYPE_NAME  = "USER";
   public static final String GROUP_PRINCIPAL_TYPE_NAME = "GROUP";
+  public static final String CLUSTER_ADMINISTRATOR_PRINCIPAL_TYPE_NAME = 
"ALL.CLUSTER.ADMINISTRATOR";
+  public static final String CLUSTER_OPERATOR_PRINCIPAL_TYPE_NAME = 
"ALL.CLUSTER.OPERATOR";
+  public static final String CLUSTER_USER_PRINCIPAL_TYPE_NAME = 
"ALL.CLUSTER.USER";
+  public static final String SERVICE_ADMINISTRATOR_PRINCIPAL_TYPE_NAME = 
"ALL.SERVICE.ADMINISTRATOR";
+  public static final String SERVICE_OPERATOR_PRINCIPAL_TYPE_NAME = 
"ALL.SERVICE.OPERATOR";
 
   /**
    * The type id.

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
index 4007c76..f9f0611 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
@@ -17,17 +17,20 @@
  */
 package org.apache.ambari.server.security.authorization;
 
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Lists;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
 import com.google.inject.Singleton;
-
-import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.orm.dao.ClusterDAO;
+import org.apache.ambari.server.orm.dao.PrivilegeDAO;
 import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
 import org.apache.ambari.server.orm.entities.PermissionEntity;
 import org.apache.ambari.server.orm.entities.PrivilegeEntity;
 import org.apache.ambari.server.orm.entities.ResourceEntity;
 import org.apache.ambari.server.orm.entities.RoleAuthorizationEntity;
-import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.core.Authentication;
@@ -38,7 +41,11 @@ import 
org.springframework.web.context.request.RequestAttributes;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
-import java.util.*;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 
 @Singleton
 /**
@@ -47,6 +54,12 @@ import java.util.*;
 public class AuthorizationHelper {
   private final static Logger LOG = 
LoggerFactory.getLogger(AuthorizationHelper.class);
 
+  @Inject
+  static Provider<PrivilegeDAO> privilegeDAOProvider;
+
+  @Inject
+  static Provider<ViewInstanceDAO> viewInstanceDAOProvider;
+
   /**
    * Converts collection of RoleEntities to collection of GrantedAuthorities
    */
@@ -197,8 +210,56 @@ public class AuthorizationHelper {
         }
       }
 
-      return false;
+      // Check if the resourceId is a view.
+      // Get all privileges for the resourceId and the principal associated 
for them should be of all cluster/service
+      // type.
+      // Now from the authorities check if the user privileges with 
CLUSTER/SERVICE type permission and has access to
+      // cluster resource with the permission.
+      // Then if the permission type matches the cluster/service type 
principal(names) then the user should have access
+      // to those views.
+
+      if(resourceId == null) {
+        return false;
+      }
+
+      ViewInstanceDAO viewInstanceDAO = viewInstanceDAOProvider.get();
+
+      ViewInstanceEntity instanceEntity = 
viewInstanceDAO.findByResourceId(resourceId);
+      if(instanceEntity == null || instanceEntity.getClusterHandle() == null) {
+        return false;
+      }
+
+      PrivilegeDAO privilegeDAO = privilegeDAOProvider.get();
+
+      final Set<String> privilegeNames = 
FluentIterable.from(privilegeDAO.findByResourceId(resourceId))
+        
.filter(ClusterInheritedPermissionHelper.privilegeWithClusterInheritedPermissionTypePredicate)
+        
.transform(ClusterInheritedPermissionHelper.permissionNameFromClusterInheritedPrivilege)
+        .toSet();
+
+      return FluentIterable.from(authentication.getAuthorities())
+        .filter(new Predicate<GrantedAuthority>() {
+          @Override
+          public boolean apply(GrantedAuthority grantedAuthority) {
+            AmbariGrantedAuthority authority = (AmbariGrantedAuthority) 
grantedAuthority;
+            PrivilegeEntity privilege = authority.getPrivilegeEntity();
+            String resourceTypeName = 
privilege.getResource().getResourceType().getName();
+            return ResourceType.translate(resourceTypeName) == 
ResourceType.CLUSTER;
+          }
+        }).transform(new Function<GrantedAuthority, PermissionEntity>() {
+          @Override
+          public PermissionEntity apply(GrantedAuthority grantedAuthority) {
+            AmbariGrantedAuthority authority = (AmbariGrantedAuthority) 
grantedAuthority;
+            PrivilegeEntity privilege = authority.getPrivilegeEntity();
+            return privilege.getPermission();
+          }
+        }).anyMatch(new Predicate<PermissionEntity>() {
+          @Override
+          public boolean apply(PermissionEntity input) {
+            return privilegeNames.contains(input.getPermissionName());
+          }
+        });
     }
+
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/ClusterInheritedPermissionHelper.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/ClusterInheritedPermissionHelper.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/ClusterInheritedPermissionHelper.java
new file mode 100644
index 0000000..9922bb2
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/ClusterInheritedPermissionHelper.java
@@ -0,0 +1,213 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.server.security.authorization;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import org.apache.ambari.server.orm.dao.PrivilegeDAO;
+import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
+import org.apache.ambari.server.orm.entities.PrincipalTypeEntity;
+import org.apache.ambari.server.orm.entities.PrivilegeEntity;
+import org.apache.ambari.server.orm.entities.ResourceEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+
+import javax.annotation.Nullable;
+import java.util.Collection;
+import java.util.Set;
+
+
+/**
+ * Helper class to take care of the cluster inherited permission for any view.
+ */
+public class ClusterInheritedPermissionHelper {
+
+  /**
+   * Predicate which validates if the principalType passed is valid or not.
+   */
+  public static final Predicate<String> validPrincipalTypePredicate = new 
Predicate<String>() {
+    @Override
+    public boolean apply(String principalType) {
+      return isValidPrincipalType(principalType);
+    }
+  };
+
+  /**
+   * Predicate which validates if the privilegeEntity has resourceEntity of 
type {@see ResourceType.CLUSTER}
+   */
+  public static final Predicate<PrivilegeEntity> clusterPrivilegesPredicate = 
new Predicate<PrivilegeEntity>() {
+    @Override
+    public boolean apply(PrivilegeEntity privilegeEntity) {
+      String resourceTypeName = 
privilegeEntity.getResource().getResourceType().getName();
+      return ResourceType.translate(resourceTypeName) == ResourceType.CLUSTER;
+    }
+  };
+
+  /**
+   * Predicate which validates if view instance entity is cluster associated
+   */
+  public static final Predicate<ViewInstanceEntity> 
clusterAssociatedViewInstancePredicate = new Predicate<ViewInstanceEntity>() {
+    @Override
+    public boolean apply(ViewInstanceEntity viewInstanceEntity) {
+      return viewInstanceEntity.getClusterHandle() != null;
+    }
+  };
+
+  /**
+   * Predicate to validate if the privilege entity has a principal which has a 
cluster inherited principal type
+   */
+  public static final Predicate<PrivilegeEntity> 
privilegeWithClusterInheritedPermissionTypePredicate = new 
Predicate<PrivilegeEntity>() {
+    @Override
+    public boolean apply(PrivilegeEntity privilegeEntity) {
+      String principalTypeName = 
privilegeEntity.getPrincipal().getPrincipalType().getName();
+      return principalTypeName.startsWith("ALL.");
+    }
+  };
+
+  /**
+   * Mapper to return the Permission Name from the cluster inherited privilege 
name. Example: "ALL.CLUSTER.USER" becomes "CLUSTER.USER"
+   */
+  public static final Function<PrivilegeEntity, String> 
permissionNameFromClusterInheritedPrivilege = new Function<PrivilegeEntity, 
String>() {
+    @Override
+    public String apply(PrivilegeEntity input) {
+      return input.getPrincipal().getPrincipalType().getName().substring(4);
+    }
+  };
+
+  /**
+   * Mapper to return resources from view instance entity.
+   */
+  public static final Function<ViewInstanceEntity, ResourceEntity> 
resourceFromViewInstanceMapper = new Function<ViewInstanceEntity, 
ResourceEntity>() {
+    @Override
+    public ResourceEntity apply(ViewInstanceEntity viewInstanceEntity) {
+      return viewInstanceEntity.getResource();
+    }
+  };
+
+  /**
+   * Mapper to return all privileges from resource entity
+   */
+  public static final Function<ResourceEntity, Iterable<PrivilegeEntity>> 
allPrivilegesFromResoucesMapper = new Function<ResourceEntity, 
Iterable<PrivilegeEntity>>() {
+    @Override
+    public Iterable<PrivilegeEntity> apply(ResourceEntity resourceEntity) {
+      return resourceEntity.getPrivileges();
+    }
+  };
+
+  /**
+   * Mapper to return permission name from privilege
+   */
+  public static final Function<PrivilegeEntity, String> 
permissionNameFromPrivilegeMapper = new Function<PrivilegeEntity, String>() {
+    @Override
+    public String apply(PrivilegeEntity privilegeEntity) {
+      return privilegeEntity.getPermission().getPermissionName();
+    }
+  };
+
+  /**
+   * Predicate to validate if the cluster inherited principal type for 
privilege entity is present in the valid permission type set passed
+   * @param validSet - valid set of permission types
+   * @return Predicate to check the condition
+   */
+  public static final Predicate<PrivilegeEntity> principalTypeInSetFrom(final 
Collection<String> validSet) {
+    return new Predicate<PrivilegeEntity>() {
+      @Override
+      public boolean apply(PrivilegeEntity privilegeEntity) {
+        String permissionName = 
privilegeEntity.getPrincipal().getPrincipalType().getName().substring(4);
+        return validSet.contains(permissionName);
+      }
+    };
+  }
+
+  /**
+   * Predicate to filter out privileges which are already existing in the 
passed privileges set.
+   * @param existingPrivileges - Privileges set to which the comparison will 
be made
+   * @return Predicate to check the validation
+   */
+  public static Predicate<PrivilegeEntity> 
removeIfExistingPrivilegePredicate(final Set<PrivilegeEntity> 
existingPrivileges) {
+    return new Predicate<PrivilegeEntity>() {
+      @Override
+      public boolean apply(final PrivilegeEntity privilegeEntity) {
+        return !FluentIterable.from(existingPrivileges).anyMatch(new 
com.google.common.base.Predicate<PrivilegeEntity>() {
+          @Override
+          public boolean apply(PrivilegeEntity directPrivilegeEntity) {
+            return 
directPrivilegeEntity.getResource().getId().equals(privilegeEntity.getResource().getId())
+              && 
directPrivilegeEntity.getPermission().getId().equals(privilegeEntity.getPermission().getId());
+          }
+        });
+      }
+    };
+  }
+
+  /**
+   * Validates if the principal type is valid for cluster inherited 
permissions.
+   * @param principalType - Principal type
+   * @return true if the principalType is in ("ALL.CLUSTER.ADMINISTRATOR", 
"ALL.CLUSTER.OPERATOR",
+   * "ALL.CLUSTER.USER", "ALL.SERVICE.OPERATOR", "ALL.SERVICE.USER")
+   */
+  public static boolean isValidPrincipalType(String principalType) {
+    return 
PrincipalTypeEntity.CLUSTER_ADMINISTRATOR_PRINCIPAL_TYPE_NAME.equalsIgnoreCase(principalType)
+      || 
PrincipalTypeEntity.CLUSTER_OPERATOR_PRINCIPAL_TYPE_NAME.equalsIgnoreCase(principalType)
+      || 
PrincipalTypeEntity.CLUSTER_USER_PRINCIPAL_TYPE_NAME.equalsIgnoreCase(principalType)
+      || 
PrincipalTypeEntity.SERVICE_ADMINISTRATOR_PRINCIPAL_TYPE_NAME.equalsIgnoreCase(principalType)
+      || 
PrincipalTypeEntity.SERVICE_OPERATOR_PRINCIPAL_TYPE_NAME.equalsIgnoreCase(principalType);
+  }
+
+  /**
+   * Returns the view privileges for which cluster permissions has been 
specified. This filters out all the privileges
+   * which are related to view resources attached to a cluster and are 
configured to have cluster level permissions. Then
+   * It checks if the user has cluster level permissions and further filters 
down the privilege list to the ones for which
+   * the user should have privilege.
+   * @param userDirectPrivileges - direct privileges for the user.
+   * @return - Filtered list of privileges for view resource for which the 
user should have access.
+   */
+  public static Set<PrivilegeEntity> 
getViewPrivilegesWithClusterPermission(final ViewInstanceDAO viewInstanceDAO, 
final PrivilegeDAO privilegeDAO,
+                                                                            
final Set<PrivilegeEntity> userDirectPrivileges) {
+
+    final Set<String> clusterPrivileges = 
FluentIterable.from(userDirectPrivileges)
+      .filter(ClusterInheritedPermissionHelper.clusterPrivilegesPredicate)
+      
.transform(ClusterInheritedPermissionHelper.permissionNameFromPrivilegeMapper)
+      .toSet();
+
+    Set<Long> resourceIds = FluentIterable.from(viewInstanceDAO.findAll())
+      
.filter(ClusterInheritedPermissionHelper.clusterAssociatedViewInstancePredicate)
+      
.transform(ClusterInheritedPermissionHelper.resourceFromViewInstanceMapper)
+      .transform(new Function<ResourceEntity, Long>() {
+        @Nullable
+        @Override
+        public Long apply(@Nullable ResourceEntity input) {
+          return input.getId();
+        }
+      }).toSet();
+
+    Set<PrivilegeEntity> allPrivileges = FluentIterable.from(resourceIds)
+      .transformAndConcat(new Function<Long, Iterable<PrivilegeEntity>>() {
+        @Nullable
+        @Override
+        public Iterable<PrivilegeEntity> apply(@Nullable Long input) {
+          return privilegeDAO.findByResourceId(input);
+        }
+      }).toSet();
+
+    return FluentIterable.from(allPrivileges)
+      
.filter(ClusterInheritedPermissionHelper.privilegeWithClusterInheritedPermissionTypePredicate)
+      
.filter(ClusterInheritedPermissionHelper.principalTypeInSetFrom(clusterPrivileges))
+      
.filter(ClusterInheritedPermissionHelper.removeIfExistingPrivilegePredicate(userDirectPrivileges))
+      .toSet();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
index 2e857ed..1212d6e 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
@@ -155,6 +155,42 @@ public abstract class AbstractUpgradeCatalog implements 
UpgradeCatalog {
   }
 
   /**
+   * Get a sequence value and increment it in 
<code>ambariSequencesTable</code>.
+   * @param seqName name of sequence to be fetched and incremented
+   * @throws SQLException, IllegalArgumentException
+   */
+  @Transactional
+  public int getAndIncrementSequence(String seqName) throws SQLException{
+    Statement statement = null;
+    ResultSet rs = null;
+    int value = -1;
+    try {
+      statement = dbAccessor.getConnection().createStatement();
+      if (statement != null) {
+        rs = statement.executeQuery(String.format("SELECT COUNT(*) from %s 
where sequence_name='%s'", ambariSequencesTable, seqName));
+
+        if(rs != null) {
+          value = rs.getInt(1);
+          dbAccessor.executeUpdate(String.format("UPDATE %s SET sequence_value 
= sequence_value + 1 where sequence_name='%s'", ambariSequencesTable, seqName));
+        } else {
+          LOG.error("Sequence {} not found.", seqName);
+          throw new IllegalArgumentException("Sequence " + seqName + " not 
found.");
+        }
+
+      }
+    } finally {
+      if (rs != null) {
+        rs.close();
+      }
+      if (statement != null) {
+        statement.close();
+      }
+    }
+
+    return value;
+  }
+
+  /**
    * Add several new sequences to <code>ambariSequencesTable</code>.
    * @param seqNames list of sequences to be inserted
    * @param seqDefaultValue initial value for the sequence

http://git-wip-us.apache.org/repos/asf/ambari/blob/4342a6b7/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
index b9b14be..dc8d9b7 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
@@ -110,6 +110,8 @@ public class UpgradeCatalog240 extends 
AbstractUpgradeCatalog {
   public static final String TIMELINE_METRICS_SINK_COLLECTION_PERIOD = 
"timeline.metrics.sink.collection.period";
   public static final String VIEWURL_TABLE = "viewurl";
   public static final String URL_ID_COLUMN = "url_id";
+  private static final String PRINCIPAL_TYPE_TABLE = "adminprincipaltype";
+  private static final String PRINCIPAL_TABLE = "adminprincipal";
 
 
   @Inject
@@ -228,6 +230,31 @@ public class UpgradeCatalog240 extends 
AbstractUpgradeCatalog {
     removeHiveOozieDBConnectionConfigs();
     updateClustersAndHostsVersionStateTableDML();
     removeStandardDeviationAlerts();
+    updateClusterInheritedPermissionsConfig();
+  }
+
+  protected void updateClusterInheritedPermissionsConfig() throws SQLException 
{
+    dbAccessor.insertRow(PRINCIPAL_TYPE_TABLE, new 
String[]{"principal_type_id", "principal_type_name"}, new String[]{"3", 
"'ALL.CLUSTER.ADMINISTRATOR'"}, true);
+    dbAccessor.insertRow(PRINCIPAL_TYPE_TABLE, new 
String[]{"principal_type_id", "principal_type_name"}, new String[]{"4", 
"'ALL.CLUSTER.OPERATOR'"}, true);
+    dbAccessor.insertRow(PRINCIPAL_TYPE_TABLE, new 
String[]{"principal_type_id", "principal_type_name"}, new String[]{"5", 
"'ALL.CLUSTER.USER'"}, true);
+    dbAccessor.insertRow(PRINCIPAL_TYPE_TABLE, new 
String[]{"principal_type_id", "principal_type_name"}, new String[]{"6", 
"'ALL.SERVICE.ADMINISTRATOR'"}, true);
+    dbAccessor.insertRow(PRINCIPAL_TYPE_TABLE, new 
String[]{"principal_type_id", "principal_type_name"}, new String[]{"7", 
"'ALL.SERVICE.OPERATOR'"}, true);
+    getAndIncrementSequence("principal_type_id_seq");
+    getAndIncrementSequence("principal_type_id_seq");
+    getAndIncrementSequence("principal_type_id_seq");
+    getAndIncrementSequence("principal_type_id_seq");
+    getAndIncrementSequence("principal_type_id_seq");
+
+    int nextPrincipalSeqId = getAndIncrementSequence("principal_id_seq");
+    dbAccessor.insertRow(PRINCIPAL_TABLE, new String[]{"principal_id", 
"principal_type_id"}, new String[]{Integer.toString(nextPrincipalSeqId), "3"}, 
true);
+    nextPrincipalSeqId = getAndIncrementSequence("principal_id_seq");
+    dbAccessor.insertRow(PRINCIPAL_TABLE, new String[]{"principal_id", 
"principal_type_id"}, new String[]{Integer.toString(nextPrincipalSeqId), "4"}, 
true);
+    nextPrincipalSeqId = getAndIncrementSequence("principal_id_seq");
+    dbAccessor.insertRow(PRINCIPAL_TABLE, new String[]{"principal_id", 
"principal_type_id"}, new String[]{Integer.toString(nextPrincipalSeqId), "5"}, 
true);
+    nextPrincipalSeqId = getAndIncrementSequence("principal_id_seq");
+    dbAccessor.insertRow(PRINCIPAL_TABLE, new String[]{"principal_id", 
"principal_type_id"}, new String[]{Integer.toString(nextPrincipalSeqId), "6"}, 
true);
+    nextPrincipalSeqId = getAndIncrementSequence("principal_id_seq");
+    dbAccessor.insertRow(PRINCIPAL_TABLE, new String[]{"principal_id", 
"principal_type_id"}, new String[]{Integer.toString(nextPrincipalSeqId), "7"}, 
true);
   }
 
   private void createSettingTable() throws SQLException {

Reply via email to