1/**
2 * Controller for LDAP
3 *
4 * @module app/access-control
5 * @exports ldapController
6 * @name ldapController
7 */
8
9window.angular && (function(angular) {
10  'use strict';
11
12  angular.module('app.accessControl').controller('ldapController', [
13    '$scope', 'APIUtils', '$q', 'toastService',
14    function($scope, APIUtils, $q, toastService) {
15      $scope.loading = false;
16      $scope.isSecure = false;
17      $scope.ldapProperties = {};
18      $scope.originalLdapProperties = {};
19      $scope.submitted = false;
20      $scope.roleGroups = [];
21      $scope.roleGroupType = '';
22      $scope.ldapCertExpiration = '';
23      $scope.caCertExpiration = '';
24
25      $scope.$on('$viewContentLoaded', function() {
26        $scope.loadLdap();
27      });
28
29      $scope.loadLdap = function() {
30        $scope.loading = true;
31        $scope.submitted = false;
32        const ldapAccountProperties =
33            APIUtils.getAllUserAccountProperties().then(
34                function(data) {
35                  const serviceEnabled = data.LDAP.ServiceEnabled ||
36                      data.ActiveDirectory.ServiceEnabled;
37                  const ldapServiceEnabled = data.LDAP.ServiceEnabled;
38                  const adServiceEnabled = data.ActiveDirectory.ServiceEnabled;
39                  const enabledServiceType = getEnabledServiceType(data);
40                  const serviceAddresses = getServiceAddresses(data);
41                  const useSSL = getUseSsl(data);
42                  const userName = getUsername(data);
43                  const baseDistinguishedNames =
44                      getBaseDistinguishedNames(data);
45                  const groupsAttribute = getGroupsAttribute(data);
46                  const usernameAttribute = getUsernameAttribute(data);
47                  const roleGroups = getRoleGroups(data);
48
49
50                  return {
51                    'ServiceEnabled': serviceEnabled,
52                    'LDAPServiceEnabled': ldapServiceEnabled,
53                    'ADServiceEnabled': adServiceEnabled,
54                    'EnabledServiceType': enabledServiceType,
55                    'ServiceAddresses': serviceAddresses,
56                    'useSSL': useSSL,
57                    'Username': userName,
58                    'Password': null,
59                    'BaseDistinguishedNames': baseDistinguishedNames,
60                    'GroupsAttribute': groupsAttribute,
61                    'UsernameAttribute': usernameAttribute,
62                    'RoleGroups': roleGroups
63                  };
64                },
65                function(error) {
66                  console.log(JSON.stringify(error));
67                });
68
69        const ldapCertificate =
70            getCertificate('/redfish/v1/AccountService/LDAP/Certificates');
71
72        const caCertificate =
73            getCertificate('/redfish/v1/Managers/bmc/Truststore/Certificates/');
74
75        const promises =
76            [ldapAccountProperties, ldapCertificate, caCertificate];
77        $q.all(promises).then(function(results) {
78          $scope.ldapProperties = results[0];
79          $scope.originalLdapProperties = angular.copy(results[0]);
80          $scope.roleGroupType = results[0].EnabledServiceType;
81          $scope.roleGroups = results[0].RoleGroups;
82          $scope.ldapCertificate = results[1];
83          $scope.caCertificate = results[2];
84          $scope.loading = false;
85        });
86      };
87
88      /**
89       * Save LDAP settings
90       * Will be making two calls every time to accomodate the backend design
91       * LDAP and ActiveDirectory changes can not be sent together when changing
92       * from ActiveDirectory to LDAP
93       */
94      $scope.saveLdapSettings = function() {
95        const enabledServiceType = $scope.ldapProperties.EnabledServiceType;
96        const enabledServicePayload =
97            createLdapEnableRequest(enabledServiceType, $scope.ldapProperties);
98        const disabledServiceType =
99            enabledServiceType == 'LDAP' ? 'ActiveDirectory' : 'LDAP';
100        const disabledServicePayload =
101            createLdapDisableRequest(disabledServiceType);
102
103        APIUtils.saveLdapProperties(disabledServicePayload)
104            .then(function(response) {
105              return APIUtils.saveLdapProperties(enabledServicePayload);
106            })
107            .then(
108                function(response) {
109                  if (!response.data.hasOwnProperty('error')) {
110                    toastService.success('Successfully updated LDAP settings.');
111                    $scope.loadLdap();
112                  } else {
113                    // The response returned a 200 but there was an error
114                    // property sent in the response. It is unclear what
115                    // settings were saved. Reloading LDAP to make it clear
116                    // to the user.
117                    toastService.error('Unable to update all LDAP settings.');
118                    $scope.loadLdap();
119                    console.log(response.data.error.message);
120                  }
121                },
122                function(error) {
123                  toastService.error('Unable to update LDAP settings.');
124                  console.log(JSON.stringify(error));
125                });
126      };
127
128      /**
129       * Sends a request to disable the LDAP Service if the user
130       * toggled the service enabled checkbox in the UI and if
131       * there was a previously saved service type. This prevents
132       * unnecessary calls to the backend if the user toggled
133       * the service enabled, but never actually had saved settings.
134       */
135      $scope.updateServiceEnabled = () => {
136        const originalEnabledServiceType =
137            $scope.originalLdapProperties.EnabledServiceType;
138
139        if (!$scope.ldapProperties.ServiceEnabled &&
140            originalEnabledServiceType) {
141          $scope.ldapProperties.EnabledServiceType = '';
142
143          const disabledServicePayload =
144              createLdapDisableRequest(originalEnabledServiceType);
145          APIUtils.saveLdapProperties(disabledServicePayload)
146              .then(
147                  function(response) {
148                    toastService.success('Successfully disabled LDAP.');
149                    $scope.roleGroups = [];
150                    $scope.loadLdap();
151                  },
152                  function(error) {
153                    toastService.error('Unable to update LDAP settings.');
154                    console.log(JSON.stringify(error));
155                  });
156        }
157      };
158
159      /**
160       *
161       * @param {string} uri for certificate
162       * @returns {null | Object}
163       */
164      function getCertificate(location) {
165        return APIUtils.getCertificate(location).then(function(data) {
166          if (data.Members && data.Members.length) {
167            return APIUtils.getCertificate(data.Members[0]['@odata.id'])
168                .then(
169                    function(response) {
170                      return response;
171                    },
172                    function(error) {
173                      console.log(json.stringify(error));
174                    })
175          } else {
176            return null;
177          }
178        });
179      }
180
181      /**
182       *
183       * @param {Object} ldapProperties
184       * @returns {string}
185       */
186      function getEnabledServiceType(ldapProperties) {
187        let enabledServiceType = '';
188        if (ldapProperties.LDAP.ServiceEnabled) {
189          enabledServiceType = 'LDAP';
190        } else if (ldapProperties.ActiveDirectory.ServiceEnabled) {
191          enabledServiceType = 'ActiveDirectory';
192        }
193        return enabledServiceType;
194      }
195
196      /**
197       *
198       * @param {Object} ldapProperties
199       * @returns {Array}
200       */
201      function getServiceAddresses(ldapProperties) {
202        let serviceAddresses = [];
203        let serviceType = getEnabledServiceType(ldapProperties);
204        if (serviceType) {
205          serviceAddresses = ldapProperties[serviceType]['ServiceAddresses'];
206        }
207        return serviceAddresses;
208      }
209
210      /**
211       *
212       * @param {Object} ldapProperties
213       * @returns {boolean}
214       */
215      function getUseSsl(ldapProperties) {
216        let useSsl = false;
217        let serviceType = getEnabledServiceType(ldapProperties);
218        if (serviceType) {
219          const uri = ldapProperties[serviceType]['ServiceAddresses'][0];
220          useSsl = uri.startsWith('ldaps://');
221        }
222        return useSsl;
223      }
224
225      /**
226       *
227       * @param {Object} ldapProperties
228       * @returns {string}
229       */
230      function getUsername(ldapProperties) {
231        let username = '';
232        let serviceType = getEnabledServiceType(ldapProperties);
233        if (serviceType) {
234          username = ldapProperties[serviceType]['Authentication']['Username'];
235        }
236        return username;
237      }
238
239      /**
240       *
241       * @param {Object} ldapProperties
242       * @returns {Array}
243       */
244      function getBaseDistinguishedNames(ldapProperties) {
245        let basedDisguishedNames = [];
246        let serviceType = getEnabledServiceType(ldapProperties);
247        if (serviceType) {
248          basedDisguishedNames =
249              ldapProperties[serviceType]['LDAPService']['SearchSettings']['BaseDistinguishedNames'];
250        }
251        return basedDisguishedNames;
252      }
253
254      /**
255       *
256       * @param {Object} ldapProperties
257       * @returns {string}
258       */
259      function getGroupsAttribute(ldapProperties) {
260        let groupsAttribute = '';
261        let serviceType = getEnabledServiceType(ldapProperties);
262        if (serviceType) {
263          groupsAttribute =
264              ldapProperties[serviceType]['LDAPService']['SearchSettings']['GroupsAttribute'];
265        }
266        return groupsAttribute;
267      }
268
269      /**
270       *
271       * @param {Object} ldapProperties
272       * @returns {string}
273       */
274      function getUsernameAttribute(ldapProperties) {
275        let userNameAttribute = '';
276        let serviceType = getEnabledServiceType(ldapProperties);
277        if (serviceType) {
278          userNameAttribute =
279              ldapProperties[serviceType]['LDAPService']['SearchSettings']['UsernameAttribute'];
280        }
281        return userNameAttribute;
282      }
283
284      /**
285       *
286       * @param {Object} ldapProperties
287       * @returns {Array} A list of role groups
288       */
289      function getRoleGroups(ldapProperties) {
290        let roleGroups = [];
291        let serviceType = getEnabledServiceType(ldapProperties);
292        if (serviceType) {
293          roleGroups = ldapProperties[serviceType]['RemoteRoleMapping'];
294        }
295
296        return roleGroups;
297      }
298
299      /**
300       * Returns the payload needed to enable an LDAP Service
301       * @param {string} serviceType - 'LDAP' or 'ActiveDirectory'
302       */
303      function createLdapEnableRequest(serviceType, ldapProperties) {
304        let ldapRequest = {};
305        const ServiceEnabled = true;
306        const Authentication = {
307          Username: ldapProperties.Username,
308          Password: ldapProperties.Password
309        };
310        const LDAPService = {
311          SearchSettings: {
312            BaseDistinguishedNames: ldapProperties.BaseDistinguishedNames,
313            GroupsAttribute: ldapProperties.GroupsAttribute,
314            UsernameAttribute: ldapProperties.UsernameAttribute
315          }
316        };
317        const ServiceAddresses = ldapProperties.ServiceAddresses;
318
319        if (serviceType == 'LDAP') {
320          ldapRequest = {
321            LDAP:
322                {ServiceEnabled, Authentication, LDAPService, ServiceAddresses}
323          };
324        } else {
325          ldapRequest = {
326            ActiveDirectory:
327                {ServiceEnabled, Authentication, LDAPService, ServiceAddresses}
328          };
329        }
330        return ldapRequest;
331      };
332
333      /**
334       * Returns the payload needed to disable an LDAP Service
335       * @param {string} serviceType - 'LDAP' or 'ActiveDirectory'
336       */
337      function createLdapDisableRequest(serviceType) {
338        let ldapRequest = {};
339        const ServiceEnabled = false;
340
341        if (serviceType == 'LDAP') {
342          ldapRequest = {LDAP: {ServiceEnabled}};
343        } else {
344          ldapRequest = {ActiveDirectory: {ServiceEnabled}};
345        }
346        return ldapRequest;
347      }
348    }
349  ]);
350})(angular);
351