Fix LDAP service update error

When a service is enabled, it must be disabled prior
to changing the service type, e.g change from OpenLDAP
to ActiveDirectory.

- Add check to determine if a service is already enabled
- Make two calls if service is already enabled. First to
  disable existing service. Second to enable updated
  service
- Remove toast message for ssl check and replace with
  error message which also keeps submit button disabled
  if the regex pattern is not met

Tested:
- Edge
- Safari
- Firefox
- Chrome
- IE 11

Signed-off-by: Derick Montague <derick.montague@ibm.com>
Change-Id: I195eeb7d1cd3621681c18f4dd9aa4414eb079c09
diff --git a/app/access-control/controllers/ldap-controller.html b/app/access-control/controllers/ldap-controller.html
index cfa929f..21d7e9e 100644
--- a/app/access-control/controllers/ldap-controller.html
+++ b/app/access-control/controllers/ldap-controller.html
@@ -29,34 +29,36 @@
       <fieldset ng-disabled="!ldapProperties.ServiceEnabled">
         <legend class="screen-reader-offscreen">LDAP Settings</legend>
         <div class="ldap__configure-settings row column">
-          <div class="large-3 column ldap__ssl-column">
-            <label class="control-check" ng-class="{'disabled' : certificates.length < 1}">
+          <div class="large-3 column ldap__ssl-column" ng-class="{'disabled' : !ldapProperties.ServiceEnabled}">
+            <label class="control-check" ng-class="{'disabled' : (!ldapCertificate || !caCertificate) || !ldapProperties.ServiceEnabled}">
               <input id="secure-ldap-ssl" aria-labelledby="use-ssl" type="checkbox"
+                ng-change="ldap__configuration.ldap__uri.$touched = true"
                 ng-model="ldapProperties.useSSL" ng-checked="ldapProperties.useSSL"
-                ng-disabled="certificates.length < 1" />
+                ng-disabled="!ldapCertificate || !caCertificate" />
               <span class="control__indicator"></span>
               <span class="control__label" id="use-ssl">Secure LDAP using SSL</span>
             </label>
-            <div>
-              <div class="ldap__certificate-info" ng-if="ldapProperties.ServiceEnabled">
-                <p>Client certificate valid until:</p>
-                <small>
-                  {{clientCertificateExpires ? (clientCertificateExpires | localeDate) : 'none available'}}</small>
-              </div>
-            </div>
-            <div class="ldap__certificate-info" ng-if="data.ValidNotAfter='' || !ldapProperties.ServiceEnabled">
-              <span>SSL certificates must be uploaded to secure LDAP using SSL.</span>
-            </div>
-            <div class="ldap__certificate-info">
-              <a href="#/access-control/ssl-certificates">Go to SSL certificates</a>
-            </div>
+            <dl class="ldap__certificate-info" ng-if="caCertificate && ldapCertificate">
+              <dt>CA certificate valid until</dt>
+              <dd>{{caCertificate.ValidNotAfter | localeDate }}</dd>
+            </dl>
+            <dl class="ldap__certificate-info" ng-if="caCertificate && ldapCertificate">
+              <dt>LDAP certificate valid until</dt>
+              <dd>{{ldapCertificate.ValidNotAfter | localeDate }}</dd>
+            </dl>
+            <p class="ldap__certificate-info" ng-if="!ldapCertificate || !caCertificate">
+              <span>A CA certificate and LDAP certificate are required. One or more are missing.</span>
+            </p>
+            <p ng-if="!ldapCertificate || !caCertificate" class="ldap__certificate-info">
+              <a ng-class="{'disabled': !ldapProperties.ServiceEnabled}" ng-href="{{ldapProperties.ServiceEnabled ? '#/access-control/ssl-certificates' : ''}}">Go to SSL certificates</a>
+            </p>
           </div>
           <div class="large-9 columns ldap__server-info">
             <div class="column service-type-column">
               <fieldset class="ldap__server-info-service-type">
                 <legend class="content-label">Service Type</legend>
                 <label class="control-radio control__radio__label">Open LDAP
-                  <input type="radio" name="service_enabled_type" id="open-ldap" value="ldap"
+                  <input type="radio" name="service_enabled_type" id="open-ldap" value="LDAP"
                     ng-checked="ldapProperties.LDAPServiceEnabled"
                     ng-change="ldapProperties.EnabledServiceUpdated = true" ng-model="ldapProperties.EnabledServiceType"
                     required />
@@ -64,7 +66,7 @@
                 </label>
                 <label class="control-radio control__radio__label">Active directory
                   <input type="radio" name="service_enabled_type" id="active-directory"
-                    ng-change="ldapProperties.EnabledServiceUpdated = true" value="ad"
+                    ng-change="ldapProperties.EnabledServiceUpdated = true" value="ActiveDirectory"
                     ng-checked="ldapProperties.ADServiceEnabled" ng-model="ldapProperties.EnabledServiceType"
                     required />
                   <span class="control__indicator control__indicator-on control__indicator-service-type"></span>
@@ -74,11 +76,14 @@
             <div class="medium-6 large-4 columns">
               <label for="ldap__uri">Server uri</label>
               <input id="ldap__uri" name="ldap__uri" type="text"
-                ng-change="ldapProperties.ServiceAddressesUpdated = true" ng-model="ldapProperties.ServiceAddresses[0]"
+                ng-change="ldapProperties.ServiceAddressesUpdated = true"
+                ng-model="ldapProperties.ServiceAddresses[0]"
+                ng-pattern="ldapProperties.useSSL ? '^ldaps://.*' : '^ldap://.*'"
                 required />
               <div ng-messages="ldap__configuration.ldap__uri.$error" class="form-error"
-                ng-class="{'visible' : ldap__configuration.ldap__uri.$touched || submitted}">
+                ng-class="{'visible' : ldap__configuration.ldap__uri.$touched || submitted}" role="alert">
                 <p ng-message="required">Field is required</p>
+                <p ng-message="pattern">Must start with {{ldapProperties.useSSL ? 'ldaps://' : 'ldap://'}}</p>
               </div>
             </div>
             <div class="medium-6 large-4 columns">
@@ -86,7 +91,7 @@
               <input id="ldap__bind__dn" name="ldap__bind__dn" type="text"
                 ng-change="ldapProperties.UsernameUpdated = true" ng-model="ldapProperties.Username" required />
               <div ng-messages="ldap__configuration.ldap__bind__dn.$error" class="form-error"
-                ng-class="{'visible' : ldap__configuration.ldap__bind__dn.$touched || submitted}">
+                ng-class="{'visible' : ldap__configuration.ldap__bind__dn.$touched || submitted}" role="alert">
                 <p ng-message="required">Field is required</p>
               </div>
             </div>
@@ -101,7 +106,7 @@
                 <span ng-show="togglePassword">Hide</span>
               </button>
               <div ng-messages="ldap__configuration.ldap__bind_pw.$error" class="form-error"
-                ng-class="{'visible' : ldap__configuration.ldap__bind_pw.$touched || submitted}">
+                ng-class="{'visible' : ldap__configuration.ldap__bind_pw.$touched || submitted}" role="alert">
                 <p ng-message="required">Field is required</p>
               </div>
             </div>
@@ -111,7 +116,7 @@
                 ng-change="ldapProperties.BaseDistinguishedNamesUpdated = true"
                 ng-model="ldapProperties.BaseDistinguishedNames[0]" required />
               <div ng-messages="ldap__configuration.ldap__base__dn.$error" class="form-error"
-                ng-class="{'visible' : ldap__configuration.ldap__base__dn.$touched || submitted}">
+                ng-class="{'visible' : ldap__configuration.ldap__base__dn.$touched || submitted}" role="alert">
                 <p ng-message="required">Field is required</p>
               </div>
             </div>
diff --git a/app/access-control/controllers/ldap-controller.js b/app/access-control/controllers/ldap-controller.js
index cfdab50..c812056 100644
--- a/app/access-control/controllers/ldap-controller.js
+++ b/app/access-control/controllers/ldap-controller.js
@@ -15,11 +15,12 @@
       $scope.loading = false;
       $scope.isSecure = false;
       $scope.ldapProperties = {};
-      $scope.originalProperties = {};
+      $scope.originalLdapProperties = {};
       $scope.submitted = false;
       $scope.roleGroups = [];
       $scope.roleGroupType = '';
-      $scope.clientCertificateExpires = '';
+      $scope.ldapCertExpiration = '';
+      $scope.caCertExpiration = '';
 
       $scope.$on('$viewContentLoaded', function() {
         $scope.loadLdap();
@@ -28,196 +29,338 @@
       $scope.loadLdap = function() {
         $scope.loading = true;
         $scope.submitted = false;
-        var getLdapProperties =
-            APIUtils.getAllUserAccountProperties()
-                .then(function(data) {
-                  $scope.ldapProperties = {
-                    'ServiceEnabled': data.LDAP.ServiceEnabled ?
-                        data.LDAP.ServiceEnabled :
-                        data.ActiveDirectory.ServiceEnabled ?
-                        data.ActiveDirectory.ServiceEnabled :
-                        false,
-                    'LDAPServiceEnabled': data.LDAP.ServiceEnabled,
-                    'ADServiceEnabled': data.ActiveDirectory.ServiceEnabled,
-                    'EnabledServiceType': data.LDAP.ServiceEnabled ?
-                        'ldap' :
-                        data.ActiveDirectory.ServiceEnabled ? 'ad' : '',
-                    'ServiceAddresses': data.LDAP.ServiceEnabled ?
-                        data.LDAP.ServiceAddresses :
-                        data.ActiveDirectory.ServiceEnabled ?
-                        data.ActiveDirectory.ServiceAddresses :
-                        [],
-                    'useSSL': $scope.isSSL(
-                        data.LDAP.ServiceEnabled ?
-                            data.LDAP.ServiceAddresses[0] :
-                            data.ActiveDirectory.ServiceAddresses[0]),
-                    'Username': data.LDAP.ServiceEnabled ?
-                        data.LDAP.Authentication.Username :
-                        data.ActiveDirectory.ServiceEnabled ?
-                        data.ActiveDirectory.Authentication.Username :
-                        '',
-                    'BaseDistinguishedNames': data.LDAP.ServiceEnabled ?
-                        data.LDAP.LDAPService.SearchSettings
-                            .BaseDistinguishedNames :
-                        data.ActiveDirectory.ServiceEnabled ?
-                        data.ActiveDirectory.LDAPService.SearchSettings
-                                .BaseDistinguishedNames :
-                        [],
-                    'GroupsAttribute': data.LDAP.ServiceEnabled ?
-                        data.LDAP.LDAPService.SearchSettings.GroupsAttribute :
-                        data.ActiveDirectory.ServiceEnabled ?
-                        data.ActiveDirectory.LDAPService.SearchSettings
-                                .GroupsAttribute :
-                        '',
-                    'UsernameAttribute': data.LDAP.ServiceEnabled ?
-                        data.LDAP.LDAPService.SearchSettings.UsernameAttribute :
-                        data.ActiveDirectory.ServiceEnabled ?
-                        data.ActiveDirectory.LDAPService.SearchSettings
-                                .UsernameAttribute :
-                        '',
-                    'AuthenticationType': data.LDAP.ServiceEnabled ?
-                        data.LDAP.Authentication.AuthenticationType :
-                        data.ActiveDirectory.Authentication.AuthenticationType,
+        const ldapAccountProperties =
+            APIUtils.getAllUserAccountProperties().then(
+                function(data) {
+                  const serviceEnabled = data.LDAP.ServiceEnabled ||
+                      data.ActiveDirectory.ServiceEnabled;
+                  const ldapServiceEnabled = data.LDAP.ServiceEnabled;
+                  const adServiceEnabled = data.ActiveDirectory.ServiceEnabled;
+                  const enabledServiceType = getEnabledServiceType(data);
+                  const serviceAddresses = getServiceAddresses(data);
+                  const useSSL = getUseSsl(data);
+                  const userName = getUsername(data);
+                  const baseDistinguishedNames =
+                      getBaseDistinguishedNames(data);
+                  const groupsAttribute = getGroupsAttribute(data);
+                  const usernameAttribute = getUsernameAttribute(data);
+                  const authenticationType = getAuthenticationType(data);
+                  const roleGroups = getRoleGroups(data);
+
+
+                  return {
+                    'ServiceEnabled': serviceEnabled,
+                    'LDAPServiceEnabled': ldapServiceEnabled,
+                    'ADServiceEnabled': adServiceEnabled,
+                    'EnabledServiceType': enabledServiceType,
+                    'ServiceAddresses': serviceAddresses,
+                    'useSSL': useSSL,
+                    'Username': userName,
+                    'BaseDistinguishedNames': baseDistinguishedNames,
+                    'GroupsAttribute': groupsAttribute,
+                    'UsernameAttribute': usernameAttribute,
+                    'AuthenticationType': authenticationType,
+                    'RoleGroups': roleGroups
                   };
-
-                  $scope.roleGroupType =
-                      $scope.ldapProperties.EnabledServiceType;
-
-                  if ($scope.ldapProperties.ServiceEnabled) {
-                    if ($scope.ldapProperties.LDAPServiceEnabled) {
-                      $scope.roleGroups = data.LDAP.RemoteRoleMapping;
-                    } else if ($scope.ldapProperties.ADServiceEnabled) {
-                      $scope.roleGroups =
-                          data.ActiveDirectory.RemoteRoleMapping;
-                    }
-                  }
-                })
-                .catch(function(error) {
-                  console.log(JSON.stringify(error));
-                });
-        var getClientCertificate =
-            APIUtils
-                .getCertificate('/redfish/v1/AccountService/LDAP/Certificates')
-                .then(function(data) {
-                  if (data.Members) {
-                    var certificate = data.Members[0];
-                    APIUtils.getCertificate(certificate['@odata.id'])
-                        .then(
-                            function(data) {
-                              $scope.clientCertificateExpires =
-                                  data.ValidNotAfter;
-                            },
-                            function(error) {
-                              console.log(JSON.stringify(error));
-                            })
-                  }
-                })
-                .catch(function(error) {
+                },
+                function(error) {
                   console.log(JSON.stringify(error));
                 });
 
-        var promises = [getLdapProperties, getClientCertificate];
-        $q.all(promises).finally(function() {
+        const ldapCertificate =
+            getCertificate('/redfish/v1/AccountService/LDAP/Certificates');
+
+        const caCertificate =
+            getCertificate('/redfish/v1/Managers/bmc/Truststore/Certificates/');
+
+        const promises =
+            [ldapAccountProperties, ldapCertificate, caCertificate];
+        $q.all(promises).then(function(results) {
+          $scope.ldapProperties = results[0];
+          $scope.originalLdapProperties = angular.copy(results[0]);
+          $scope.roleGroupType = results[0].EnabledServiceType;
+          $scope.roleGroups = results[0].RoleGroups;
+          $scope.ldapCertificate = results[1];
+          $scope.caCertificate = results[2];
           $scope.loading = false;
         });
       };
 
+      /**
+       * Save LDAP settings
+       * Will be making two calls every time to accomodate the backend design
+       * LDAP and ActiveDirectory changes can not be sent together when changing
+       * from ActiveDirectory to LDAP
+       */
       $scope.saveLdapSettings = function() {
-        for (var i in $scope.ldapProperties.ServiceAddresses) {
-          if ($scope.ldapProperties.useSSL !==
-              $scope.isSSL($scope.ldapProperties.ServiceAddresses[i])) {
-            toastService.error(
-                'Server URI ' + $scope.ldapProperties.ServiceAddresses[i] +
-                ' must begin with ' +
-                ($scope.ldapProperties.useSSL ? 'ldaps:// ' : 'ldap:// ') +
-                'when SSL is ' +
-                ($scope.ldapProperties.useSSL ? 'configured. ' :
-                                                'not configured.'));
-          }
-        }
+        const enabledServiceType = $scope.ldapProperties.EnabledServiceType;
+        const enabledServicePayload =
+            createLdapEnableRequest(enabledServiceType, $scope.ldapProperties);
+        const disabledServiceType =
+            enabledServiceType == 'LDAP' ? 'ActiveDirectory' : 'LDAP';
+        const disabledServicePayload =
+            createLdapDisableRequest(disabledServiceType);
 
-        // Default LDAP and AD Attributes
-        let LDAP = {};
-
-        let ActiveDirectory = {};
-
-        // Data to pass to request
-        let data = {};
-        data.LDAP = LDAP;
-        data.ActiveDirectory = ActiveDirectory;
-
-        // Values to update the service type object
-        let Authentication = {};
-        Authentication.Username = $scope.ldapProperties.Username;
-        Authentication.Password = $scope.ldapProperties.Password;
-        Authentication.AuthenticationType =
-            $scope.ldapProperties.AuthenticationType;
-
-        let LDAPService = {};
-        LDAPService.SearchSettings = {};
-        LDAPService.SearchSettings.BaseDistinguishedNames =
-            $scope.ldapProperties.BaseDistinguishedNames;
-        LDAPService.SearchSettings.GroupsAttribute =
-            $scope.ldapProperties.GroupsAttribute;
-        LDAPService.SearchSettings.UsernameAttribute =
-            $scope.ldapProperties.UsernameAttribute;
-
-        let ServiceAddresses = $scope.ldapProperties.ServiceAddresses;
-        if ($scope.ldapProperties.EnabledServiceType == 'ldap') {
-          ActiveDirectory.ServiceEnabled = false;
-          LDAP.ServiceEnabled = true;
-          LDAP.Authentication = Authentication;
-          LDAP.LDAPService = LDAPService;
-          LDAP.ServiceAddresses = ServiceAddresses;
-        } else if ($scope.ldapProperties.EnabledServiceType == 'ad') {
-          ActiveDirectory.ServiceEnabled = true;
-          LDAP.ServiceEnabled = false;
-          ActiveDirectory.Authentication = Authentication;
-          ActiveDirectory.LDAPService = LDAPService;
-          ActiveDirectory.ServiceAddresses = ServiceAddresses;
-        }
-
-        APIUtils.saveLdapProperties(data).then(
-            function(response) {
-              if (!response.data.hasOwnProperty('error')) {
-                toastService.success('Successfully updated LDAP settings.');
-                $scope.loadLdap();
-              } else {
-                toastService.error('Unable to update LDAP settings.');
-                console.log(JSON.stringify(response.data.error.message));
-              }
-            },
-            function(error) {
-              toastService.error('Unable to update LDAP settings.');
-              console.log(JSON.stringify(error));
-            });
+        APIUtils.saveLdapProperties(disabledServicePayload)
+            .then(function(response) {
+              return APIUtils.saveLdapProperties(enabledServicePayload);
+            })
+            .then(
+                function(response) {
+                  if (!response.data.hasOwnProperty('error')) {
+                    toastService.success('Successfully updated LDAP settings.');
+                    $scope.loadLdap();
+                  } else {
+                    // The response returned a 200 but there was an error
+                    // property sent in the response. It is unclear what
+                    // settings were saved. Reloading LDAP to make it clear
+                    // to the user.
+                    toastService.error('Unable to update all LDAP settings.');
+                    $scope.loadLdap();
+                    console.log(response.data.error.message);
+                  }
+                },
+                function(error) {
+                  toastService.error('Unable to update LDAP settings.');
+                  console.log(JSON.stringify(error));
+                });
       };
 
-      $scope.isSSL = function(uri) {
-        return uri.startsWith('ldaps://');
-      };
-      $scope.updateServiceEnabled = function() {
-        if (!$scope.ldapProperties.ServiceEnabled) {
+      /**
+       * Sends a request to disable the LDAP Service if the user
+       * toggled the service enabled checkbox in the UI and if
+       * there was a previously saved service type. This prevents
+       * unnecessary calls to the backend if the user toggled
+       * the service enabled, but never actually had saved settings.
+       */
+      $scope.updateServiceEnabled = () => {
+        const originalEnabledServiceType =
+            $scope.originalLdapProperties.EnabledServiceType;
+
+        if (!$scope.ldapProperties.ServiceEnabled &&
+            originalEnabledServiceType) {
           $scope.ldapProperties.EnabledServiceType = '';
-          let data = {};
-          let LDAP = {};
-          data.LDAP = LDAP;
-          LDAP.ServiceEnabled = false;
-          let ActiveDirectory = {};
-          data.ActiveDirectory = ActiveDirectory;
-          ActiveDirectory.ServiceEnabled = false;
 
-          APIUtils.saveLdapProperties(data).then(
-              function(response) {
-                toastService.success('Successfully disabled LDAP.');
-                $scope.roleGroups = [];
-                $scope.loadLdap();
-              },
-              function(error) {
-                toastService.error('Unable to disable LDAP.');
-                console.log(JSON.stringify(error));
-              });
+          const disabledServicePayload =
+              createLdapDisableRequest(originalEnabledServiceType);
+          APIUtils.saveLdapProperties(disabledServicePayload)
+              .then(
+                  function(response) {
+                    toastService.success('Successfully disabled LDAP.');
+                    $scope.roleGroups = [];
+                    $scope.loadLdap();
+                  },
+                  function(error) {
+                    toastService.error('Unable to update LDAP settings.');
+                    console.log(JSON.stringify(error));
+                  });
         }
+      };
+
+      /**
+       *
+       * @param {string} uri for certificate
+       * @returns {null | Object}
+       */
+      function getCertificate(location) {
+        return APIUtils.getCertificate(location).then(function(data) {
+          if (data.Members && data.Members.length) {
+            return APIUtils.getCertificate(data.Members[0]['@odata.id'])
+                .then(
+                    function(response) {
+                      return response;
+                    },
+                    function(error) {
+                      console.log(json.stringify(error));
+                    })
+          } else {
+            return null;
+          }
+        });
+      }
+
+      /**
+       *
+       * @param {Object} ldapProperties
+       * @returns {string}
+       */
+      function getEnabledServiceType(ldapProperties) {
+        let enabledServiceType = '';
+        if (ldapProperties.LDAP.ServiceEnabled) {
+          enabledServiceType = 'LDAP';
+        } else if (ldapProperties.ActiveDirectory.ServiceEnabled) {
+          enabledServiceType = 'ActiveDirectory';
+        }
+        return enabledServiceType;
+      }
+
+      /**
+       *
+       * @param {Object} ldapProperties
+       * @returns {Array}
+       */
+      function getServiceAddresses(ldapProperties) {
+        let serviceAddresses = [];
+        let serviceType = getEnabledServiceType(ldapProperties);
+        if (serviceType) {
+          serviceAddresses = ldapProperties[serviceType]['ServiceAddresses'];
+        }
+        return serviceAddresses;
+      }
+
+      /**
+       *
+       * @param {Object} ldapProperties
+       * @returns {boolean}
+       */
+      function getUseSsl(ldapProperties) {
+        let useSsl = false;
+        let serviceType = getEnabledServiceType(ldapProperties);
+        if (serviceType) {
+          const uri = ldapProperties[serviceType]['ServiceAddresses'][0];
+          useSsl = uri.startsWith('ldaps://');
+        }
+        return useSsl;
+      }
+
+      /**
+       *
+       * @param {Object} ldapProperties
+       * @returns {string}
+       */
+      function getUsername(ldapProperties) {
+        let username = '';
+        let serviceType = getEnabledServiceType(ldapProperties);
+        if (serviceType) {
+          username = ldapProperties[serviceType]['Authentication']['Username'];
+        }
+        return username;
+      }
+
+      /**
+       *
+       * @param {Object} ldapProperties
+       * @returns {Array}
+       */
+      function getBaseDistinguishedNames(ldapProperties) {
+        let basedDisguishedNames = [];
+        let serviceType = getEnabledServiceType(ldapProperties);
+        if (serviceType) {
+          basedDisguishedNames =
+              ldapProperties[serviceType]['LDAPService']['SearchSettings']['BaseDistinguishedNames'];
+        }
+        return basedDisguishedNames;
+      }
+
+      /**
+       *
+       * @param {Object} ldapProperties
+       * @returns {string}
+       */
+      function getGroupsAttribute(ldapProperties) {
+        let groupsAttribute = '';
+        let serviceType = getEnabledServiceType(ldapProperties);
+        if (serviceType) {
+          groupsAttribute =
+              ldapProperties[serviceType]['LDAPService']['SearchSettings']['GroupsAttribute'];
+        }
+        return groupsAttribute;
+      }
+
+
+      /**
+       *
+       * @param {Object} ldapProperties
+       * @returns {string}
+       */
+      function getUsernameAttribute(ldapProperties) {
+        let userNameAttribute = '';
+        let serviceType = getEnabledServiceType(ldapProperties);
+        if (serviceType) {
+          userNameAttribute =
+              ldapProperties[serviceType]['LDAPService']['SearchSettings']['UsernameAttribute'];
+        }
+        return userNameAttribute;
+      }
+
+      /**
+       *
+       * @param {Object} ldapProperties
+       * @returns {null | string}
+       */
+      function getAuthenticationType(ldapProperties) {
+        let authenticationType = null;
+        let serviceType = getEnabledServiceType(ldapProperties);
+        if (serviceType) {
+          authenticationType =
+              ldapProperties[serviceType]['Authentication']['AuthenticationType'];
+        }
+        return authenticationType;
+      }
+
+      /**
+       *
+       * @param {Object} ldapProperties
+       * @returns {Array} A list of role groups
+       */
+      function getRoleGroups(ldapProperties) {
+        let roleGroups = [];
+        let serviceType = getEnabledServiceType(ldapProperties);
+        if (serviceType) {
+          roleGroups = ldapProperties[serviceType]['RemoteRoleMapping'];
+        }
+
+        return roleGroups;
+      }
+
+      /**
+       * Returns the payload needed to enable an LDAP Service
+       * @param {string} serviceType - 'LDAP' or 'ActiveDirectory'
+       */
+      function createLdapEnableRequest(serviceType, ldapProperties) {
+        let ldapRequest = {};
+        const ServiceEnabled = true;
+        const Authentication = {
+          Username: ldapProperties.Username,
+          AuthenticationType: ldapProperties.AuthenticationType
+        };
+        const LDAPService = {
+          SearchSettings: {
+            BaseDistinguishedNames: ldapProperties.BaseDistinguishedNames,
+            GroupsAttribute: ldapProperties.GroupsAttribute,
+            UsernameAttribute: ldapProperties.UsernameAttribute
+          }
+        };
+        const ServiceAddresses = ldapProperties.ServiceAddresses;
+
+        if (serviceType == 'LDAP') {
+          ldapRequest = {
+            LDAP:
+                {ServiceEnabled, Authentication, LDAPService, ServiceAddresses}
+          };
+        } else {
+          ldapRequest = {
+            ActiveDirectory:
+                {ServiceEnabled, Authentication, LDAPService, ServiceAddresses}
+          };
+        }
+        return ldapRequest;
+      };
+
+      /**
+       * Returns the payload needed to disable an LDAP Service
+       * @param {string} serviceType - 'LDAP' or 'ActiveDirectory'
+       */
+      function createLdapDisableRequest(serviceType) {
+        let ldapRequest = {};
+        const ServiceEnabled = false;
+
+        if (serviceType == 'LDAP') {
+          ldapRequest = {LDAP: {ServiceEnabled}};
+        } else {
+          ldapRequest = {ActiveDirectory: {ServiceEnabled}};
+        }
+        return ldapRequest;
       }
     }
   ]);
diff --git a/app/access-control/styles/ldap.scss b/app/access-control/styles/ldap.scss
index 3a5d930..a2698e7 100644
--- a/app/access-control/styles/ldap.scss
+++ b/app/access-control/styles/ldap.scss
@@ -29,15 +29,23 @@
 
 .ldap__ssl-column {
   padding-left: 1.5em;
+
   .control__label {
     text-transform: none;
     font-weight: 400;
     font-size: 16px;
     color: $primary-dark;
   }
+
   .control__indicator {
     top: 5px;
   }
+
+  // using !important due to being a state and need to have higer specificity
+  &.disabled *,
+  .disabled {
+    color: $base-02--02 !important;
+  }
 }
 
 .ldap__configuration-buttons {
@@ -70,16 +78,22 @@
 }
 
 .ldap__certificate-info {
-  padding-top: 0.5em;
-  small {
-    font-size: 14px;
-  }
-  p {
-    color: $base-02--02;
+  margin-top: 0.5em;
+
+  dt {
     text-transform: uppercase;
+    color: $base-02--02;
     font-weight: 700;
-    font-size: 0.75em;
-    margin-bottom: 0;
+    font-size: 12px;
+  }
+
+  dd {
+    font-size: 14px;
+    margin-top: 0.25em;
+  }
+
+  .disabled {
+    color: $base-02--02;
   }
 }
 
diff --git a/app/common/directives/ldap-user-roles.html b/app/common/directives/ldap-user-roles.html
index e250772..22a9ffb 100644
--- a/app/common/directives/ldap-user-roles.html
+++ b/app/common/directives/ldap-user-roles.html
@@ -84,7 +84,7 @@
   <!-- LDAP Disabled Role Groups Table Row -->
   <div class="empty__logs" ng-if="roleGroups.length < 1 || !enabled">
     <p
-      ng-if="roleGroups.length < 1 && roleGroupType === 'ad' ||  roleGroupType === 'ldap'"
+      ng-if="!roleGroups.length && roleGroupType"
     >
       No role groups have been created yet.
     </p>
diff --git a/app/common/directives/ldap-user-roles.js b/app/common/directives/ldap-user-roles.js
index afe30c5..0074170 100644
--- a/app/common/directives/ldap-user-roles.js
+++ b/app/common/directives/ldap-user-roles.js
@@ -41,22 +41,19 @@
             };
 
             $scope.addRoleGroup = () => {
+              $scope.loading = true;
+
               const newGroup = {};
               newGroup.RemoteGroup = $scope.newGroup.RemoteGroup;
               newGroup.LocalRole = $scope.newGroup.LocalRole;
 
-              $scope.loading = true;
               const data = {};
-
-              if ($scope.roleGroupType == 'ldap') {
-                data.LDAP = {};
-                data.LDAP.RemoteRoleMapping = $scope.roleGroups;
-                data.LDAP.RemoteRoleMapping.push(newGroup);
-              } else {
-                data.ActiveDirectory = {};
-                data.ActiveDirectory.RemoteRoleMapping = $scope.roleGroups;
-                data.ActiveDirectory.RemoteRoleMapping.push(newGroup);
-              }
+              const roleGroups = $scope.roleGroups;
+              const roleGroupType = $scope.roleGroupType;
+              data[roleGroupType] = {};
+              data[roleGroupType]['RemoteRoleMapping'] = roleGroups;
+              data[roleGroupType]['RemoteRoleMapping'][roleGroups.length] =
+                  newGroup;
 
               APIUtils.saveLdapProperties(data)
                   .then(
@@ -82,19 +79,14 @@
             $scope.editRoleGroup = () => {
               $scope.loading = true;
               const data = {};
-
-              if ($scope.roleGroupType == 'ldap') {
-                data.LDAP = {};
-                data.LDAP.RemoteRoleMapping = $scope.roleGroups;
-                data.LDAP.RemoteRoleMapping[$scope.selectedGroupIndex]
-                    .LocalRole = $scope.newGroup.LocalRole;
-              } else {
-                data.ActiveDirectory = {};
-                data.ActiveDirectory.RemoteRoleMapping = $scope.roleGroups;
-                data.ActiveDirectory
-                    .RemoteRoleMapping[$scope.selectedGroupIndex]
-                    .LocalRole = $scope.newGroup.LocalRole;
-              }
+              const roleGroupType = $scope.roleGroupType;
+              const roleGroups = $scope.roleGroups;
+              const localRole = $scope.newGroup.LocalRole;
+              const selectedIndex = $scope.selectedGroupIndex;
+              data[roleGroupType] = {};
+              data[roleGroupType]['RemoteRoleMapping'] = roleGroups;
+              data[roleGroupType]['RemoteRoleMapping'][selectedIndex]['LocalRole'] =
+                  localRole;
 
               APIUtils.saveLdapProperties(data)
                   .then(
@@ -111,29 +103,21 @@
               $scope.editGroup = false;
             };
 
-            $scope.removeGroupFn = (index) => {
+            $scope.removeGroupFn = index => {
               $scope.removeGroup = true;
               $scope.selectedGroupIndex = index;
             };
 
             $scope.removeRoleGroup = () => {
               $scope.loading = true;
+              const roleGroupType = $scope.roleGroupType;
+              const roleGroups = $scope.roleGroups;
+              const selectedGroupIndex = $scope.selectedGroupIndex;
               const data = {};
-
-              if ($scope.roleGroupType == 'ldap') {
-                data.LDAP = {};
-                data.LDAP.RemoteRoleMapping = $scope.roleGroups;
-                data.LDAP.RemoteRoleMapping[$scope.selectedGroupIndex] =
-                    $scope.newGroup;
-              } else {
-                data.ActiveDirectory = {};
-                data.ActiveDirectory.RemoteRoleMapping = $scope.roleGroups;
-                data.ActiveDirectory
-                    .RemoteRoleMapping[$scope.selectedGroupIndex] =
-                    $scope.newGroup;
-              }
-
-              $scope.roleGroups[$scope.selectedGroupIndex] = null;
+              data[roleGroupType] = {};
+              data[roleGroupType]['RemoteRoleMapping'] = roleGroups;
+              data[roleGroupType]['RemoteRoleMapping'][selectedGroupIndex] =
+                  null;
 
               APIUtils.saveLdapProperties(data)
                   .then(
@@ -158,7 +142,7 @@
             $scope.roleGroupIsSelectedChanged = () => {
               let groupSelected = false;
               $scope.roleGroups.forEach(group => {
-                if (group['isSelected']) {
+                if (group && group['isSelected']) {
                   groupSelected = true;
                 }
               });
@@ -167,28 +151,18 @@
 
             $scope.removeMultipleRoleGroups = () => {
               $scope.loading = true;
+              const roleGroupType = $scope.roleGroupType;
+              const roleGroups = $scope.roleGroups;
               const data = {};
-
-              if ($scope.roleGroupType == 'ldap') {
-                data.LDAP = {};
-                data.LDAP.RemoteRoleMapping = $scope.roleGroups.map((group) => {
-                  if (group['isSelected']) {
-                    return null;
-                  } else {
-                    return group;
-                  }
-                });
-              } else {
-                data.ActiveDirectory = {};
-                data.ActiveDirectory.RemoteRoleMapping =
-                    $scope.roleGroups.map((group) => {
-                      if (group['isSelected']) {
-                        return null;
-                      } else {
-                        return group;
-                      }
-                    });
-              }
+              data[roleGroupType] = {};
+              data[roleGroupType]['RemoteRoleMapping'] =
+                  roleGroups.map((group) => {
+                    if (group['isSelected']) {
+                      return null;
+                    } else {
+                      return group;
+                    }
+                  });
 
               APIUtils.saveLdapProperties(data)
                   .then(