ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From srima...@apache.org
Subject [2/2] ambari git commit: AMBARI-9626. Enabling ranger plugin config should modify dependent configs (srimanth)
Date Sat, 14 Feb 2015 01:14:03 GMT
AMBARI-9626. Enabling ranger plugin config should modify dependent configs (srimanth)


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

Branch: refs/heads/trunk
Commit: ec4bed3a9e4de72fd04f1dfc81f5788f005ce293
Parents: 7f752be
Author: Srimanth Gunturi <sgunturi@hortonworks.com>
Authored: Fri Feb 13 07:09:05 2015 -0800
Committer: Srimanth Gunturi <sgunturi@hortonworks.com>
Committed: Fri Feb 13 13:36:56 2015 -0800

----------------------------------------------------------------------
 .../app/controllers/wizard/step7_controller.js  |   2 +-
 ambari-web/app/data/HDP2.2/site_properties.js   |  15 +-
 ambari-web/app/messages.js                      |   2 +
 .../configs/propertyDependence_footer.hbs       |   4 +-
 .../configs/modification_handlers/hbase.js      | 126 ++++++++++++++
 .../utils/configs/modification_handlers/hdfs.js |  58 +++++++
 .../utils/configs/modification_handlers/hive.js | 127 ++++++++++++++
 .../utils/configs/modification_handlers/knox.js |  73 ++++++++
 .../utils/configs/modification_handlers/misc.js |  93 +++++++++++
 .../modification_handler.js                     |  63 +++++++
 .../configs/modification_handlers/storm.js      |  75 +++++++++
 .../configs/service_configs_by_category_view.js | 167 +++++++------------
 ambari-web/app/views/common/controls_view.js    |  13 +-
 13 files changed, 700 insertions(+), 118 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/ec4bed3a/ambari-web/app/controllers/wizard/step7_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step7_controller.js b/ambari-web/app/controllers/wizard/step7_controller.js
index 5f44e80..b0d8463 100644
--- a/ambari-web/app/controllers/wizard/step7_controller.js
+++ b/ambari-web/app/controllers/wizard/step7_controller.js
@@ -70,7 +70,7 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, {
     return App.router.get('mainAdminKerberosController.securityEnabled');
   }.property('App.router.mainAdminKerberosController.securityEnabled'),
   /**
-   * If miscConfigChange Modal is shown
+   * If configChangeObserver Modal is shown
    * @type {bool}
    */
   miscModalVisible: false,

http://git-wip-us.apache.org/repos/asf/ambari/blob/ec4bed3a/ambari-web/app/data/HDP2.2/site_properties.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/data/HDP2.2/site_properties.js b/ambari-web/app/data/HDP2.2/site_properties.js
index d84d531..8ce4c0d 100644
--- a/ambari-web/app/data/HDP2.2/site_properties.js
+++ b/ambari-web/app/data/HDP2.2/site_properties.js
@@ -133,7 +133,8 @@ hdp22properties.push(
     "isOverridable": false,
     "filename": "ranger-hdfs-plugin-properties.xml",
     "category": "Advanced ranger-hdfs-plugin-properties",
-    "serviceName": "HDFS"
+    "serviceName": "HDFS",
+    "index": 1
   },
   {
     "id": "site property",
@@ -189,7 +190,8 @@ hdp22properties.push(
     "isOverridable": false,
     "filename": "ranger-hive-plugin-properties.xml",
     "category": "Advanced ranger-hive-plugin-properties",
-    "serviceName": "HIVE"
+    "serviceName": "HIVE",
+    "index": 1
   },
   {
     "id": "site property",
@@ -255,7 +257,8 @@ hdp22properties.push(
     "isOverridable": false,
     "filename": "ranger-hbase-plugin-properties.xml",
     "category": "Advanced ranger-hbase-plugin-properties",
-    "serviceName": "HBASE"
+    "serviceName": "HBASE",
+    "index": 1
   },
   {
     "id": "site property",
@@ -321,7 +324,8 @@ hdp22properties.push(
     "isOverridable": false,
     "filename": "ranger-storm-plugin-properties.xml",
     "category": "Advanced ranger-storm-plugin-properties",
-    "serviceName": "STORM"
+    "serviceName": "STORM",
+    "index": 1
   },
   {
     "id": "site property",
@@ -377,7 +381,8 @@ hdp22properties.push(
     "isOverridable": false,
     "filename": "ranger-knox-plugin-properties.xml",
     "category": "Advanced ranger-knox-plugin-properties",
-    "serviceName": "KNOX"
+    "serviceName": "KNOX",
+    "index": 1
   },
   {
     "id": "site property",

http://git-wip-us.apache.org/repos/asf/ambari/blob/ec4bed3a/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index b5c0ee1..74ab371 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -379,6 +379,8 @@ Em.I18n.translations = {
   'services.storm.topology.metrics.total': 'Total topologies',
   'services.storm.tasks.metrics.title': 'Number of tasks',
   'services.storm.tasks.metrics.total': 'Total tasks',
+  'services.storm.configs.range-plugin-enable.dialog.title': 'Enable Ranger for STORM',
+  'services.storm.configs.range-plugin-enable.dialog.message': 'Enabling Ranger plugin for STORM is effective only on a secured cluster.',
 
 
   'services.alerts.head':'You have {0} critical alert notification(s).',

http://git-wip-us.apache.org/repos/asf/ambari/blob/ec4bed3a/ambari-web/app/templates/common/configs/propertyDependence_footer.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/configs/propertyDependence_footer.hbs b/ambari-web/app/templates/common/configs/propertyDependence_footer.hbs
index 7b7bab9..b09e2bb 100644
--- a/ambari-web/app/templates/common/configs/propertyDependence_footer.hbs
+++ b/ambari-web/app/templates/common/configs/propertyDependence_footer.hbs
@@ -18,6 +18,8 @@
 
 <div class="pull-right">
   <button class="btn" {{action onUndo target="view.parentView"}}>{{t common.cancel}}</button>
-  <button class="btn btn-warning" {{action onIgnore target="view.parentView"}}>{{t common.ignore}}</button>
+  {{#if view.canIgnore}}
+    <button class="btn btn-warning" {{action onIgnore target="view.parentView"}}>{{t common.ignore}}</button>
+  {{/if}}
   <button class="btn btn-success" {{action onApply target="view.parentView"}}>{{t common.apply}}</button>
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/ec4bed3a/ambari-web/app/utils/configs/modification_handlers/hbase.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/configs/modification_handlers/hbase.js b/ambari-web/app/utils/configs/modification_handlers/hbase.js
new file mode 100644
index 0000000..1fb6b29
--- /dev/null
+++ b/ambari-web/app/utils/configs/modification_handlers/hbase.js
@@ -0,0 +1,126 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+require('utils/configs/modification_handlers/modification_handler');
+
+module.exports = App.ServiceConfigModificationHandler.create({
+  serviceId : 'HBASE',
+
+  getConfig : function(allConfigs, configName, configFilename, configServiceName) {
+    return allConfigs.findProperty("serviceName", configServiceName).get("configs").find(function(config) {
+      return configName == config.get('name') && (configFilename == null || configFilename == config.get('filename'));
+    });
+  },
+
+  updateConfigClasses : function(configClasses, authEnabled, affectedProperties, addOldValue) {
+    if (configClasses != null) {
+      var xaAuthCoProcessorClass = "com.xasecure.authorization.hbase.XaSecureAuthorizationCoprocessor";
+      var nonXAClass = 'org.apache.hadoop.hbase.security.access.AccessController';
+      var currentClassesList = configClasses.get('value').trim().length > 0 ? configClasses.get('value').trim().split(',') : [];
+      var newClassesList = null, xaClassIndex, nonXaClassIndex;
+
+      if (authEnabled) {
+        var nonXaClassIndex = currentClassesList.indexOf(nonXAClass);
+        if (nonXaClassIndex > -1) {
+          currentClassesList = currentClassesList.splice(nonXaClassIndex, nonXaClassIndex);
+          newClassesList = currentClassesList;
+        }
+        var xaClassIndex = currentClassesList.indexOf(xaAuthCoProcessorClass);
+        if (xaClassIndex < 0) {
+          currentClassesList.push(xaAuthCoProcessorClass);
+          newClassesList = currentClassesList;
+        }
+      } else {
+        var xaClassIndex = currentClassesList.indexOf(xaAuthCoProcessorClass);
+        if (xaClassIndex > -1) {
+          currentClassesList = currentClassesList.splice(xaClassIndex, xaClassIndex);
+          newClassesList = currentClassesList;
+        }
+        if (addOldValue) {
+          var nonXaClassIndex = currentClassesList.indexOf(nonXAClass);
+          if (nonXaClassIndex < 0) {
+            currentClassesList.push(nonXAClass);
+            newClassesList = currentClassesList;
+          }
+        }
+      }
+
+      if (newClassesList != null) {
+        affectedProperties.push({
+          serviceName : "HBASE",
+          sourceServiceName : "HBASE",
+          propertyName : configClasses.get('name'),
+          propertyDisplayName : configClasses.get('name'),
+          newValue : newClassesList.join(','),
+          curValue : configClasses.get('value'),
+          changedPropertyName : 'ranger-hbase-plugin-enabled',
+          removed : false,
+          filename : 'hbase-site.xml'
+        });
+      }
+    }
+  },
+
+  getDependentConfigChanges : function(changedConfig, selectedServices, allConfigs, securityEnabled) {
+    var affectedProperties = [];
+    var newValue = changedConfig.get("value");
+    var hbaseAuthEnabledPropertyName = "ranger-hbase-plugin-enabled";
+    var affectedPropertyName = changedConfig.get("name");
+    if (affectedPropertyName == hbaseAuthEnabledPropertyName) {
+      var configAuthEnabled = this.getConfig(allConfigs, 'hbase.security.authorization', 'hbase-site.xml', 'HBASE');
+      var configMasterClasses = this.getConfig(allConfigs, 'hbase.coprocessor.master.classes', 'hbase-site.xml', 'HBASE');
+      var configRegionClasses = this.getConfig(allConfigs, 'hbase.coprocessor.region.classes', 'hbase-site.xml', 'HBASE');
+      var configRpcProtection = this.getConfig(allConfigs, 'hbase.rpc.protection', 'hbase-site.xml', 'HBASE');
+
+      var authEnabled = newValue == "Yes";
+      var newAuthEnabledValue = authEnabled ? "true" : "false";
+      var newRpcProtectionValue = authEnabled ? "privacy" : "authentication";
+
+      // Add Hive-Ranger configs
+      this.updateConfigClasses(configMasterClasses, authEnabled, affectedProperties, configAuthEnabled.get('value') != 'true');
+      this.updateConfigClasses(configRegionClasses, authEnabled, affectedProperties, configAuthEnabled.get('value') != 'true');
+      if (newRpcProtectionValue !== configRpcProtection.get('value')) {
+        affectedProperties.push({
+          serviceName : "HBASE",
+          sourceServiceName : "HBASE",
+          propertyName : 'hbase.rpc.protection',
+          propertyDisplayName : 'hbase.rpc.protection',
+          newValue : newRpcProtectionValue,
+          curValue : configRpcProtection.get('value'),
+          changedPropertyName : hbaseAuthEnabledPropertyName,
+          removed : false,
+          filename : 'hbase-site.xml'
+        });
+      }
+      if (authEnabled && newAuthEnabledValue !== configAuthEnabled.get('value')) {
+        affectedProperties.push({
+          serviceName : "HBASE",
+          sourceServiceName : "HBASE",
+          propertyName : 'hbase.security.authorization',
+          propertyDisplayName : 'hbase.security.authorization',
+          newValue : newAuthEnabledValue,
+          curValue : configAuthEnabled.get('value'),
+          changedPropertyName : hbaseAuthEnabledPropertyName,
+          removed : false,
+          filename : 'hbase-site.xml'
+        });
+      }
+    }
+    return affectedProperties;
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/ec4bed3a/ambari-web/app/utils/configs/modification_handlers/hdfs.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/configs/modification_handlers/hdfs.js b/ambari-web/app/utils/configs/modification_handlers/hdfs.js
new file mode 100644
index 0000000..128b62b
--- /dev/null
+++ b/ambari-web/app/utils/configs/modification_handlers/hdfs.js
@@ -0,0 +1,58 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+require('utils/configs/modification_handlers/modification_handler');
+
+module.exports = App.ServiceConfigModificationHandler.create({
+  serviceId : 'HDFS',
+
+  getConfig : function(allConfigs, configName, configFilename, configServiceName) {
+    return allConfigs.findProperty("serviceName", configServiceName).get("configs").find(function(config) {
+      return configName == config.get('name') && (configFilename == null || configFilename == config.get('filename'));
+    });
+  },
+
+  getDependentConfigChanges : function(changedConfig, selectedServices, allConfigs, securityEnabled) {
+    var affectedProperties = [];
+    var newValue = changedConfig.get("value");
+    var rangerPluginEnabledName = "ranger-hdfs-plugin-enabled";
+    var affectedPropertyName = changedConfig.get("name");
+    if (affectedPropertyName == rangerPluginEnabledName) {
+      var configDfsPermissionsEnabled = this.getConfig(allConfigs, 'dfs.permissions.enabled', 'hdfs-site.xml', 'HDFS');
+
+      var rangerPluginEnabled = newValue == "Yes";
+      var newDfsPermissionsEnabled = rangerPluginEnabled ? "true" : "true";
+
+      // Add Hive-Ranger configs
+      if (configDfsPermissionsEnabled != null && newDfsPermissionsEnabled !== configDfsPermissionsEnabled.get('value')) {
+        affectedProperties.push({
+          serviceName : "HDFS",
+          sourceServiceName : "HDFS",
+          propertyName : 'dfs.permissions.enabled',
+          propertyDisplayName : 'dfs.permissions.enabled',
+          newValue : newDfsPermissionsEnabled,
+          curValue : configDfsPermissionsEnabled.get('value'),
+          changedPropertyName : rangerPluginEnabledName,
+          removed : false,
+          filename : 'hdfs-site.xml'
+        });
+      }
+    }
+    return affectedProperties;
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/ec4bed3a/ambari-web/app/utils/configs/modification_handlers/hive.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/configs/modification_handlers/hive.js b/ambari-web/app/utils/configs/modification_handlers/hive.js
new file mode 100644
index 0000000..092ef40
--- /dev/null
+++ b/ambari-web/app/utils/configs/modification_handlers/hive.js
@@ -0,0 +1,127 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+require('utils/configs/modification_handlers/modification_handler');
+
+module.exports = App.ServiceConfigModificationHandler.create({
+  serviceId : 'HIVE',
+
+  getConfig : function(allConfigs, configName, configFilename, configServiceName) {
+    return allConfigs.findProperty("serviceName", configServiceName).get("configs").find(function(config) {
+      return configName == config.get('name') && (configFilename == null || configFilename == config.get('filename'));
+    });
+  },
+
+  getDependentConfigChanges : function(changedConfig, selectedServices, allConfigs, securityEnabled) {
+    var affectedProperties = [];
+    var newValue = changedConfig.get("value");
+    var rangerPluginEnabledName = "ranger-hive-plugin-enabled";
+    var affectedPropertyName = changedConfig.get("name");
+    if (affectedPropertyName == rangerPluginEnabledName) {
+      var configAuthorizationEnabled = this.getConfig(allConfigs, 'hive.security.authorization.enabled', 'hive-site.xml', 'HIVE');
+      var configAuthorizationManager = this.getConfig(allConfigs, 'hive.security.authorization.manager', 'hiveserver2-site.xml', 'HIVE');
+      var configAuthenticatorManager = this.getConfig(allConfigs, 'hive.security.authenticator.manager', 'hiveserver2-site.xml', 'HIVE');
+      var configRestrictedList = this.getConfig(allConfigs, 'hive.conf.restricted.list', 'hive-site.xml', 'HIVE');
+
+      var rangerPluginEnabled = newValue == "Yes";
+      var newConfigAuthorizationEnabledValue = rangerPluginEnabled ? "true" : "false";
+      var newAuthorizationManagerValue = rangerPluginEnabled ? "com.xasecure.authorization.hive.authorizer.XaSecureHiveAuthorizerFactory"
+          : "org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory";
+      var newAuthenticatorManagerValue = rangerPluginEnabled ? "org.apache.hadoop.hive.ql.security.SessionStateUserAuthenticator"
+          : "org.apache.hadoop.hive.ql.security.SessionStateUserAuthenticator";
+      var enabledRestrictedMap = {
+        "hive.security.authorization.enabled" : "hive.security.authorization.enabled",
+        "hive.security.authorization.manager" : "hive.security.authorization.manager",
+        "hive.security.authenticator.manager" : "hive.security.authenticator.manager"
+      }
+      var enabledRestrictedList = Object.keys(enabledRestrictedMap);
+      var newRestrictedListValue = rangerPluginEnabled ? enabledRestrictedList : [];
+
+      // Add Hive-Ranger configs
+      if (configAuthorizationEnabled != null && newConfigAuthorizationEnabledValue !== configAuthorizationEnabled.get('value')) {
+        affectedProperties.push({
+          serviceName : "HIVE",
+          sourceServiceName : "HIVE",
+          propertyName : 'hive.security.authorization.enabled',
+          propertyDisplayName : 'hive.security.authorization.enabled',
+          newValue : newConfigAuthorizationEnabledValue,
+          curValue : configAuthorizationEnabled.get('value'),
+          changedPropertyName : rangerPluginEnabledName,
+          removed : false,
+          filename : 'hive-site.xml'
+        });
+      }
+      if (configAuthorizationManager != null && newAuthorizationManagerValue !== configAuthorizationManager.get('value')) {
+        affectedProperties.push({
+          serviceName : "HIVE",
+          sourceServiceName : "HIVE",
+          propertyName : 'hive.security.authorization.manager',
+          propertyDisplayName : 'hive.security.authorization.manager',
+          newValue : newAuthorizationManagerValue,
+          curValue : configAuthorizationManager.get('value'),
+          changedPropertyName : rangerPluginEnabledName,
+          removed : false,
+          filename : 'hiveserver2-site.xml'
+        });
+      }
+      if (configAuthenticatorManager != null && newAuthenticatorManagerValue !== configAuthenticatorManager.get('value')) {
+        affectedProperties.push({
+          serviceName : "HIVE",
+          sourceServiceName : "HIVE",
+          propertyName : 'hive.security.authenticator.manager',
+          propertyDisplayName : 'hive.security.authenticator.manager',
+          newValue : newAuthenticatorManagerValue,
+          curValue : configAuthenticatorManager.get('value'),
+          changedPropertyName : rangerPluginEnabledName,
+          removed : false,
+          filename : 'hiveserver2-site.xml'
+        });
+      }
+      if (configRestrictedList != null) {
+        var currentValueList = configRestrictedList.get('value').split(',');
+        // 'newRestrictedListValue' elements should be found in existing list
+        var newValueList = [];
+        currentValueList.forEach(function(s) {
+          if (enabledRestrictedMap[s] == s) {
+            return;
+          }
+          newValueList.push(s);
+        });
+        if (newRestrictedListValue.length > 0)
+          newValueList = newValueList.concat(newRestrictedListValue);
+
+        if (newValueList.length != currentValueList.length) {
+          // One of the value was not found - set all of them in.
+          var newValueListString = newValueList.join(',');
+          affectedProperties.push({
+            serviceName : "HIVE",
+            sourceServiceName : "HIVE",
+            propertyName : 'hive.conf.restricted.list',
+            propertyDisplayName : 'hive.conf.restricted.list',
+            newValue : newValueListString,
+            curValue : configRestrictedList.get('value'),
+            changedPropertyName : rangerPluginEnabledName,
+            removed : false,
+            filename : 'hive-site.xml'
+          });
+        }
+      }
+    }
+    return affectedProperties;
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/ec4bed3a/ambari-web/app/utils/configs/modification_handlers/knox.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/configs/modification_handlers/knox.js b/ambari-web/app/utils/configs/modification_handlers/knox.js
new file mode 100644
index 0000000..3b0740c
--- /dev/null
+++ b/ambari-web/app/utils/configs/modification_handlers/knox.js
@@ -0,0 +1,73 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+require('utils/configs/modification_handlers/modification_handler');
+
+module.exports = App.ServiceConfigModificationHandler.create({
+  serviceId : 'KNOX',
+
+  getConfig : function(allConfigs, configName, configFilename, configServiceName) {
+    return allConfigs.findProperty("serviceName", configServiceName).get("configs").find(function(config) {
+      return configName == config.get('name') && (configFilename == null || configFilename == config.get('filename'));
+    });
+  },
+
+  getDependentConfigChanges : function(changedConfig, selectedServices, allConfigs, securityEnabled) {
+    var affectedProperties = [];
+    var newValue = changedConfig.get("value");
+    var rangerPluginEnablePropertyName = "ranger-knox-plugin-enabled";
+    var affectedPropertyName = changedConfig.get("name");
+    if (affectedPropertyName == rangerPluginEnablePropertyName) {
+      var topologyXmlContent = this.getConfig(allConfigs, 'content', 'topology.xml', 'KNOX');
+      if (topologyXmlContent != null) {
+        var topologyXmlContentString = topologyXmlContent.get('value');
+        var newTopologyXmlContentString = null;
+        var authEnabled = newValue == "Yes";
+        var authXml = /<provider>[\s]*<role>[\s]*authorization[\s]*<\/role>[\s\S]*?<\/provider>/.exec(topologyXmlContentString);
+        if (authXml != null && authXml.length > 0) {
+          var nameArray = /<name>\s*(.*?)\s*<\/name>/.exec(authXml[0]);
+          if (nameArray != null && nameArray.length > 1) {
+            if (authEnabled && 'AclsAuthz' == nameArray[1]) {
+              var newName = nameArray[0].replace('AclsAuthz', 'XASecurePDPKnox');
+              var newAuthXml = authXml[0].replace(nameArray[0], newName);
+              newTopologyXmlContentString = topologyXmlContentString.replace(authXml[0], newAuthXml);
+            } else if (!authEnabled && 'XASecurePDPKnox' == nameArray[1]) {
+              var newName = nameArray[0].replace('XASecurePDPKnox', 'AclsAuthz');
+              var newAuthXml = authXml[0].replace(nameArray[0], newName);
+              newTopologyXmlContentString = topologyXmlContentString.replace(authXml[0], newAuthXml);
+            }
+          }
+        }
+        if (newTopologyXmlContentString != null) {
+          affectedProperties.push({
+            serviceName : "KNOX",
+            sourceServiceName : "KNOX",
+            propertyName : 'content',
+            propertyDisplayName : 'content',
+            newValue : newTopologyXmlContentString,
+            curValue : topologyXmlContent.get('value'),
+            changedPropertyName : rangerPluginEnablePropertyName,
+            removed : false,
+            filename : 'topology.xml'
+          });
+        }
+      }
+    }
+    return affectedProperties;
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/ec4bed3a/ambari-web/app/utils/configs/modification_handlers/misc.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/configs/modification_handlers/misc.js b/ambari-web/app/utils/configs/modification_handlers/misc.js
new file mode 100644
index 0000000..42decb5
--- /dev/null
+++ b/ambari-web/app/utils/configs/modification_handlers/misc.js
@@ -0,0 +1,93 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+require('utils/configs/modification_handlers/modification_handler');
+
+module.exports = App.ServiceConfigModificationHandler.create({
+  serviceId : 'MISC',
+  getDependentConfigChanges : function(changedConfig, selectedServices, allConfigs, securityEnabled) {
+    var affectedProperties = [];
+    var newValue = changedConfig.get("value");
+    var curConfigs = "";
+    var affectedPropertyName = "dfs.permissions.superusergroup";
+    if (changedConfig.get("name") == "hdfs_user") {
+      curConfigs = allConfigs.findProperty("serviceName", "HDFS").get("configs");
+      if (newValue != curConfigs.findProperty("name", affectedPropertyName).get("value")) {
+        affectedProperties.push({
+          serviceName : "HDFS",
+          sourceServiceName : "MISC",
+          propertyName : affectedPropertyName,
+          propertyDisplayName : affectedPropertyName,
+          newValue : newValue,
+          curValue : curConfigs.findProperty("name", affectedPropertyName).get("value"),
+          changedPropertyName : "hdfs_user",
+          remove : false,
+          filename : 'hdfs-site.xml'
+        });
+      }
+      if ($.trim(newValue) != $.trim(curConfigs.findProperty("name", "dfs.cluster.administrators").get("value"))) {
+        affectedProperties.push({
+          serviceName : "HDFS",
+          sourceServiceName : "MISC",
+          propertyName : "dfs.cluster.administrators",
+          propertyDisplayName : "dfs.cluster.administrators",
+          newValue : " " + $.trim(newValue),
+          curValue : curConfigs.findProperty("name", "dfs.cluster.administrators").get("value"),
+          changedPropertyName : "hdfs_user",
+          remove : false,
+          filename : 'hdfs-site.xml'
+        });
+      }
+    } else if (changedConfig.get("name") == "user_group") {
+      if (!(selectedServices.indexOf("YARN") >= 0)) {
+        return;
+      }
+      if (selectedServices.indexOf("MAPREDUCE2") >= 0) {
+        curConfigs = allConfigs.findProperty("serviceName", "MAPREDUCE2").get("configs");
+        if ($.trim(newValue) != $.trim(curConfigs.findProperty("name", "mapreduce.cluster.administrators").get("value"))) {
+          affectedProperties.push({
+            serviceName : "MAPREDUCE2",
+            sourceServiceName : "MISC",
+            propertyName : "mapreduce.cluster.administrators",
+            propertyDisplayName : "mapreduce.cluster.administrators",
+            newValue : " " + $.trim(newValue),
+            curValue : curConfigs.findProperty("name", "mapreduce.cluster.administrators").get("value"),
+            changedPropertyName : "user_group",
+            filename : 'mapred-site.xml'
+          });
+        }
+      }
+      if (selectedServices.indexOf("YARN") >= 0) {
+        curConfigs = allConfigs.findProperty("serviceName", "YARN").get("configs");
+        if (newValue != curConfigs.findProperty("name", "yarn.nodemanager.linux-container-executor.group").get("value")) {
+          affectedProperties.push({
+            serviceName : "YARN",
+            sourceServiceName : "MISC",
+            propertyName : "yarn.nodemanager.linux-container-executor.group",
+            propertyDisplayName : "yarn.nodemanager.linux-container-executor.group",
+            newValue : newValue,
+            curValue : curConfigs.findProperty("name", "yarn.nodemanager.linux-container-executor.group").get("value"),
+            changedPropertyName : "user_group",
+            filename : 'yarn-site.xml'
+          })
+        }
+      }
+    }
+    return affectedProperties;
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/ec4bed3a/ambari-web/app/utils/configs/modification_handlers/modification_handler.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/configs/modification_handlers/modification_handler.js b/ambari-web/app/utils/configs/modification_handlers/modification_handler.js
new file mode 100644
index 0000000..5b32cde
--- /dev/null
+++ b/ambari-web/app/utils/configs/modification_handlers/modification_handler.js
@@ -0,0 +1,63 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+/**
+ * Config modification handler for a given service.
+ * 
+ * This handler should take care of scenarios that arise from modification of a
+ * config. Scenarios like updating dependency configs, or doing any special
+ * processing.
+ */
+App.ServiceConfigModificationHandler = Em.Object.extend({
+
+  /**
+   * Service whose configs this handler will react to.
+   */
+  serviceId : DS.attr('string'),
+
+  /**
+   * Given a changed config, provide an array of changes to dependent configs
+   * across all services. Dependent configs can be created, updated and deleted.
+   * 
+   *  Example: Here, setting 'hdfs_user' updates 'dfs.permissions.superusergroup'. 
+   *  [
+   *   {
+   *     serviceName: "HDFS",
+   *     sourceServiceName: "MISC",  // Cross service configs
+   *     propertyName: "dfs.permissions.superusergroup",
+   *     propertyDisplayName: "dfs.permissions.superusergroup",
+   *     filename: 'hdfs-site',
+   *     remove: false,
+   *     curValue: "hdfs",
+   *     newValue: "my_hdfs",
+   *     changedPropertyName: "hdfs_user"
+   *   }
+   *  ]
+   *  
+   * @param changedConfig
+   * @param selectedServices
+   * @param allConfigs
+   * @param securityEnabled
+   * @return Array of dependent config updates
+   */
+  getDependentConfigChanges : function(changedConfig, selectedServices, allConfigs, securityEnabled) {
+    return [];
+  }
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/ec4bed3a/ambari-web/app/utils/configs/modification_handlers/storm.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/configs/modification_handlers/storm.js b/ambari-web/app/utils/configs/modification_handlers/storm.js
new file mode 100644
index 0000000..3e27e3e
--- /dev/null
+++ b/ambari-web/app/utils/configs/modification_handlers/storm.js
@@ -0,0 +1,75 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+require('utils/configs/modification_handlers/modification_handler');
+
+module.exports = App.ServiceConfigModificationHandler.create({
+  serviceId : 'STORM',
+
+  getConfig : function(allConfigs, configName, configFilename, configServiceName) {
+    return allConfigs.findProperty("serviceName", configServiceName).get("configs").find(function(config) {
+      return configName == config.get('name') && (configFilename == null || configFilename == config.get('filename'));
+    });
+  },
+
+  getDependentConfigChanges : function(changedConfig, selectedServices, allConfigs, securityEnabled) {
+    var affectedProperties = [];
+    var newValue = changedConfig.get("value");
+    var rangerPluginEnablePropertyName = "ranger-storm-plugin-enabled";
+    var affectedPropertyName = changedConfig.get("name");
+    if (affectedPropertyName == rangerPluginEnablePropertyName) {
+      var authEnabled = newValue == "Yes";
+      var configNimbusAuthorizer = this.getConfig(allConfigs, 'nimbus.authorizer', 'storm-site.xml', 'STORM');
+      if (configNimbusAuthorizer != null) {
+        // Only when configuration is already present, do we act on it.
+        // Unsecured clusters do not have this config, and hence we skip any
+        // updates
+        var newNimbusAuthorizer = authEnabled ? "com.xasecure.authorization.storm.authorizer.XaSecureStormAuthorizer"
+            : "backtype.storm.security.auth.authorizer.SimpleACLAuthorizer";
+
+        // Add Hive-Ranger configs
+        if (newNimbusAuthorizer !== configNimbusAuthorizer.get('value')) {
+          affectedProperties.push({
+            serviceName : "STORM",
+            sourceServiceName : "STORM",
+            propertyName : 'nimbus.authorizer',
+            propertyDisplayName : 'nimbus.authorizer',
+            newValue : newNimbusAuthorizer,
+            curValue : configNimbusAuthorizer.get('value'),
+            changedPropertyName : rangerPluginEnablePropertyName,
+            removed : false,
+            filename : 'storm-site.xml'
+          });
+        }
+      }
+      if (authEnabled && affectedProperties.length < 1 && !securityEnabled) {
+        App.ModalPopup.show({
+          header : Em.I18n.t('services.storm.configs.range-plugin-enable.dialog.title'),
+          primary : Em.I18n.t('ok'),
+          secondary : false,
+          showCloseButton : false,
+          onPrimary : function() {
+            this.hide();
+          },
+          body : Em.I18n.t('services.storm.configs.range-plugin-enable.dialog.message')
+        });
+      }
+    }
+    return affectedProperties;
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/ec4bed3a/ambari-web/app/views/common/configs/service_configs_by_category_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/configs/service_configs_by_category_view.js b/ambari-web/app/views/common/configs/service_configs_by_category_view.js
index f4f61b2..5334c7c 100644
--- a/ambari-web/app/views/common/configs/service_configs_by_category_view.js
+++ b/ambari-web/app/views/common/configs/service_configs_by_category_view.js
@@ -20,6 +20,7 @@ var App = require('app');
 
 var validator = require('utils/validator');
 var stringUtils = require('utils/string_utils');
+require('utils/configs/modification_handlers/modification_handler');
 
 App.ServiceConfigsByCategoryView = Em.View.extend(App.UserPref, {
 
@@ -113,7 +114,7 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.UserPref, {
    * Warn/prompt user to adjust Service props when changing user/groups in Misc
    * Is triggered when user ended editing text field
    */
-  miscConfigChange: function (manuallyChangedProperty) {
+  configChangeObserver: function (manuallyChangedProperty) {
     var changedProperty;
     if (manuallyChangedProperty.get("id")) {
       changedProperty = [manuallyChangedProperty];
@@ -128,114 +129,62 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.UserPref, {
     else {
       return;
     }
-    if (this.get('controller.selectedService.serviceName') == 'MISC') {
-      var newValue = changedProperty.get("value");
-      var stepConfigs = this.get("controller.stepConfigs");
-      this.affectedProperties = [];
-      var curConfigs = "";
-      var affectedPropertyName = "dfs.permissions.superusergroup";
-      if (changedProperty.get("name") == "hdfs_user") {
-        curConfigs = stepConfigs.findProperty("serviceName", "HDFS").get("configs");
-        if (newValue != curConfigs.findProperty("name", affectedPropertyName).get("value")) {
-          this.affectedProperties.push(
-            {
-              serviceName: "HDFS",
-              propertyName: affectedPropertyName,
-              propertyDisplayName: affectedPropertyName,
-              newValue: newValue,
-              curValue: curConfigs.findProperty("name", affectedPropertyName).get("value"),
-              changedPropertyName: "hdfs_user"
-            }
-          );
-        }
-        if ($.trim(newValue) != $.trim(curConfigs.findProperty("name", "dfs.cluster.administrators").get("value"))) {
-          this.affectedProperties.push(
-            {
-              serviceName: "HDFS",
-              propertyName: "dfs.cluster.administrators",
-              propertyDisplayName: "dfs.cluster.administrators",
-              newValue: " " + $.trim(newValue),
-              curValue: curConfigs.findProperty("name", "dfs.cluster.administrators").get("value"),
-              changedPropertyName: "hdfs_user"
-            }
-          );
-        }
-      }
-      else if (changedProperty.get("name") == "user_group") {
-        if (!(this.get("controller.selectedServiceNames").indexOf("YARN") >= 0)) {
-          return;
-        }
-        if (this.get("controller.selectedServiceNames").indexOf("MAPREDUCE2") >= 0) {
-          curConfigs = stepConfigs.findProperty("serviceName", "MAPREDUCE2").get("configs");
-          if ($.trim(newValue) != $.trim(curConfigs.findProperty("name", "mapreduce.cluster.administrators").get("value"))) {
-            this.affectedProperties.push(
-              {
-                serviceName: "MAPREDUCE2",
-                propertyName: "mapreduce.cluster.administrators",
-                propertyDisplayName: "mapreduce.cluster.administrators",
-                newValue: " " + $.trim(newValue),
-                curValue: curConfigs.findProperty("name", "mapreduce.cluster.administrators").get("value"),
-                changedPropertyName: "user_group"
-              }
-            );
-          }
-        }
-        if (this.get("controller.selectedServiceNames").indexOf("YARN") >= 0) {
-          curConfigs = stepConfigs.findProperty("serviceName", "YARN").get("configs");
-          if (newValue != curConfigs.findProperty("name", "yarn.nodemanager.linux-container-executor.group").get("value")) {
-            this.affectedProperties.push(
-              {
-                serviceName: "YARN",
-                propertyName: "yarn.nodemanager.linux-container-executor.group",
-                propertyDisplayName: "yarn.nodemanager.linux-container-executor.group",
-                newValue: newValue,
-                curValue: curConfigs.findProperty("name", "yarn.nodemanager.linux-container-executor.group").get("value"),
-                changedPropertyName: "user_group"
-              }
-            )
+    this.affectedProperties = [];
+    var stepConfigs = this.get("controller.stepConfigs");
+    var serviceId = this.get('controller.selectedService.serviceName');
+    var serviceConfigModificationHandler = null;
+    try{
+      serviceConfigModificationHandler = require('utils/configs/modification_handlers/'+serviceId.toLowerCase());
+    }catch (e) {
+      console.log("Unable to load modification handler for ", serviceId);
+    }
+    if (serviceConfigModificationHandler != null) {
+      var securityEnabled = App.router.get('mainAdminSecurityController.securityEnabled');
+      this.affectedProperties = serviceConfigModificationHandler.getDependentConfigChanges(changedProperty, this.get("controller.selectedServiceNames"), stepConfigs, securityEnabled);
+    }
+    changedProperty.set("editDone", false); // Turn off flag
+    
+    if (this.affectedProperties.length > 0 && !this.get("controller.miscModalVisible")) {
+      this.newAffectedProperties = this.affectedProperties;
+      var self = this;
+      return App.ModalPopup.show({
+        classNames: ['modal-690px-width'],
+        showCloseButton: false,
+        header: "Warning: you must also change these Service properties",
+        onApply: function () {
+          self.get("newAffectedProperties").forEach(function(item) {
+            self.get("controller.stepConfigs").findProperty("serviceName", item.serviceName).get("configs").find(function(config) {
+              return item.propertyName == config.get('name') && (item.filename == null || item.filename == config.get('filename'));
+            }).set("value", item.newValue);
+          });
+          self.get("controller").set("miscModalVisible", false);
+          this.hide();
+        },
+        onIgnore: function () {
+          self.get("controller").set("miscModalVisible", false);
+          this.hide();
+        },
+        onUndo: function () {
+          var affected = self.get("newAffectedProperties").objectAt(0);
+          self.get("controller.stepConfigs").findProperty("serviceName", affected.sourceServiceName).get("configs")
+          .findProperty("name", affected.changedPropertyName).set("value", $.trim(affected.curValue));
+          self.get("controller").set("miscModalVisible", false);
+          this.hide();
+        },
+        footerClass: Ember.View.extend({
+          classNames: ['modal-footer'],
+          templateName: require('templates/common/configs/propertyDependence_footer'),
+          canIgnore: serviceId == 'MISC'
+        }),
+        bodyClass: Ember.View.extend({
+          templateName: require('templates/common/configs/propertyDependence'),
+          controller: this,
+          propertyChange: self.get("newAffectedProperties"),
+          didInsertElement: function () {
+            self.get("controller").set("miscModalVisible", true);
           }
-        }
-      }
-      if (this.affectedProperties.length > 0 && !this.get("controller.miscModalVisible")) {
-        this.newAffectedProperties = this.affectedProperties;
-        var self = this;
-        return App.ModalPopup.show({
-          classNames: ['modal-690px-width'],
-          showCloseButton: false,
-          header: "Warning: you must also change these Service properties",
-          onApply: function () {
-            self.get("newAffectedProperties").forEach(function (item) {
-              self.get("controller.stepConfigs").findProperty("serviceName", item.serviceName).get("configs")
-                .findProperty("name", item.propertyName).set("value", item.newValue);
-            });
-            self.get("controller").set("miscModalVisible", false);
-            this.hide();
-          },
-          onIgnore: function () {
-            self.get("controller").set("miscModalVisible", false);
-            this.hide();
-          },
-          onUndo: function () {
-            var affected = self.get("newAffectedProperties").objectAt(0);
-            self.get("controller.stepConfigs").findProperty("serviceName", "MISC").get("configs")
-              .findProperty("name", affected.changedPropertyName).set("value", $.trim(affected.curValue));
-            self.get("controller").set("miscModalVisible", false);
-            this.hide();
-          },
-          footerClass: Ember.View.extend({
-            classNames: ['modal-footer'],
-            templateName: require('templates/common/configs/propertyDependence_footer')
-          }),
-          bodyClass: Ember.View.extend({
-            templateName: require('templates/common/configs/propertyDependence'),
-            controller: this,
-            propertyChange: self.get("newAffectedProperties"),
-            didInsertElement: function () {
-              self.get("controller").set("miscModalVisible", true);
-            }
-          })
-        });
-      }
+        })
+      });
     }
   }.observes('categoryConfigs.@each.editDone'),
 
@@ -658,7 +607,7 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.UserPref, {
     if (supportsFinal) {
       serviceConfigProperty.set('isFinal', defaultIsFinal);
     }
-    this.miscConfigChange(serviceConfigProperty);
+    this.configChangeObserver(serviceConfigProperty);
     Em.$('body>.tooltip').remove(); //some tooltips get frozen when their owner's DOM element is removed
   },
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/ec4bed3a/ambari-web/app/views/common/controls_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/controls_view.js b/ambari-web/app/views/common/controls_view.js
index bd5e7e6..91441e3 100644
--- a/ambari-web/app/views/common/controls_view.js
+++ b/ambari-web/app/views/common/controls_view.js
@@ -248,8 +248,10 @@ App.ServiceConfigCheckbox = Ember.Checkbox.extend(App.ServiceConfigPopoverSuppor
    * change service config value if click on checkbox
    */
   toggleValue: function() {
-    if (this.isNotAppropriateValue())
+    if (this.isNotAppropriateValue()){
       this.set('serviceConfig.value', this.get(this.get('checked') + 'Value'));
+      this.get('serviceConfig').set("editDone", true);
+    }
   }.observes('checked'),
 
   /**
@@ -262,7 +264,14 @@ App.ServiceConfigCheckbox = Ember.Checkbox.extend(App.ServiceConfigPopoverSuppor
 
   disabled: function () {
     return !this.get('serviceConfig.isEditable');
-  }.property('serviceConfig.isEditable')
+  }.property('serviceConfig.isEditable'),
+
+  //Set editDone false for all current category config text field parameter
+  focusIn: function (event) {
+    if (!this.get('serviceConfig.isOverridden') && !this.get('serviceConfig.isComparison')) {
+      this.get("parentView.categoryConfigsAll").setEach("editDone", false);
+    }
+  }
 });
 
 /**


Mime
View raw message