1/**
2 * Controller for Certificate Management
3 *
4 * @module app/access-control
5 * @exports certificateController
6 * @name certificateController
7 */
8
9window.angular && (function(angular) {
10  'use strict';
11
12  angular.module('app.configuration').controller('certificateController', [
13    '$scope', 'APIUtils', '$q', 'Constants', 'toastService', '$timeout',
14    '$uibModal',
15    function(
16        $scope, APIUtils, $q, Constants, toastService, $timeout, $uibModal) {
17      $scope.loading = false;
18      $scope.certificates = [];
19      $scope.availableCertificateTypes = [];
20      $scope.allCertificateTypes = Constants.CERTIFICATE_TYPES;
21      $scope.newCertificate = {};
22      $scope.newCSR = {};
23      $scope.keyBitLength = Constants.CERTIFICATE.KEY_BIT_LENGTH;
24      $scope.keyPairAlgorithm = Constants.CERTIFICATE.KEY_PAIR_ALGORITHM;
25      $scope.keyCurveId = Constants.CERTIFICATE.KEY_CURVE_ID;
26      $scope.countryList = Constants.COUNTRIES;
27
28      $scope.$on('$viewContentLoaded', () => {
29        getBmcTime();
30      })
31
32      $scope.loadCertificates = function() {
33        $scope.certificates = [];
34        $scope.availableCertificateTypes = Constants.CERTIFICATE_TYPES;
35        $scope.loading = true;
36        // Use Certificate Service to get the locations of all the certificates,
37        // then add a promise for fetching each certificate
38        APIUtils.getCertificateLocations().then(
39            function(data) {
40              var promises = [];
41              var locations = data.Links.Certificates;
42              for (var i in locations) {
43                var location = locations[i];
44                promises.push(getCertificatePromise(location['@odata.id']));
45              }
46              $q.all(promises)
47                  .catch(function(error) {
48                    toastService.error('Failed to load certificates.');
49                    console.log(JSON.stringify(error));
50                  })
51                  .finally(function() {
52                    $scope.loading = false;
53                  });
54            },
55            function(error) {
56              $scope.loading = false;
57              $scope.availableCertificateTypes = [];
58              toastService.error('Failed to load certificates.');
59              console.log(JSON.stringify(error));
60            });
61      };
62
63      $scope.uploadCertificate = function() {
64        if ($scope.newCertificate.file.name.split('.').pop() !== 'pem') {
65          toastService.error('Certificate must be a .pem file.');
66          return;
67        }
68        APIUtils
69            .addNewCertificate(
70                $scope.newCertificate.file, $scope.newCertificate.selectedType)
71            .then(
72                function(data) {
73                  toastService.success(
74                      $scope.newCertificate.selectedType.name +
75                      ' was uploaded.');
76                  $scope.newCertificate = {};
77                  $scope.loadCertificates();
78                },
79                function(error) {
80                  toastService.error(
81                      $scope.newCertificate.selectedType.name +
82                      ' failed upload.');
83                  console.log(JSON.stringify(error));
84                });
85      };
86
87      var getCertificatePromise = function(url) {
88        var promise = APIUtils.getCertificate(url).then(function(data) {
89          var certificate = data;
90          isExpiring(certificate);
91          updateAvailableTypes(certificate);
92          $scope.certificates.push(certificate);
93        });
94        return promise;
95      };
96
97      var isExpiring = function(certificate) {
98        // convert certificate time to epoch time
99        // if ValidNotAfter is less than or equal to 30 days from bmc time
100        // (2592000000), isExpiring. If less than or equal to 0, is expired.
101        // dividing bmc time by 1000 converts epoch milliseconds to seconds
102        var difference = (new Date(certificate.ValidNotAfter).getTime()) -
103            ($scope.bmcTime) / 1000;
104        if (difference <= 0) {
105          certificate.isExpired = true;
106        } else if (difference <= 2592000000) {
107          certificate.isExpiring = true;
108        } else {
109          certificate.isExpired = false;
110          certificate.isExpiring = false;
111        }
112      };
113
114      // add optional name
115      $scope.names = [];
116      $scope.addOptionalRow = function() {
117        $scope.names.push({Value: ''})
118      };
119
120      // remove optional name row
121      $scope.deleteOptionalRow = function(index) {
122        $scope.names.splice(index, 1);
123        if ($scope.names.length == 0) {
124          $scope.names = [];
125        }
126      };
127
128      // create a CSR object to send to the backend
129      $scope.getCSRCode = function() {
130        var addCSR = {};
131        let alternativeNames = $scope.names.map(name => name.Value);
132
133        // if user provided a first alternative name then push to alternative
134        // names array
135        $scope.newCSR.firstAlternativeName ?
136            alternativeNames.push($scope.newCSR.firstAlternativeName) :
137            $scope.newCSR.firstAlternativeName = '';
138
139        addCSR.CertificateCollection = {
140          '@odata.id': $scope.newCSR.certificateCollection.location
141        };
142        addCSR.CommonName = $scope.newCSR.commonName;
143        addCSR.ContactPerson = $scope.newCSR.contactPerson || '';
144        addCSR.City = $scope.newCSR.city;
145        addCSR.AlternativeNames = alternativeNames || [];
146        addCSR.ChallengePassword = $scope.newCSR.challengePassword || '';
147        addCSR.Email = $scope.newCSR.emailAddress || '';
148        addCSR.Country = $scope.newCSR.countryCode.code;
149        addCSR.Organization = $scope.newCSR.organization;
150        addCSR.OrganizationalUnit = $scope.newCSR.companyUnit;
151        addCSR.KeyCurveId = $scope.newCSR.keyCurveId || '';
152        addCSR.KeyBitLength = $scope.newCSR.keyBitLength
153        addCSR.KeyPairAlgorithm = $scope.newCSR.keyPairAlgorithm || '';
154        addCSR.State = $scope.newCSR.state;
155
156        APIUtils.createCSRCertificate(addCSR).then(
157            function(data) {
158              $scope.csrCode = data;
159              openDownloadCsrModal();
160            },
161            function(error) {
162              toastService.error('Unable to generate CSR. Try again.');
163              console.log(JSON.stringify(error));
164            })
165      };
166
167      function openDownloadCsrModal() {
168        const modalTemplateCsrDownload =
169            require('./certificate-modal-csr-download.html');
170        $uibModal
171            .open({
172              template: modalTemplateCsrDownload,
173              windowTopClass: 'uib-modal',
174              scope: $scope,
175              ariaLabelledBy: 'modal_label',
176              size: 'lg',
177            })
178            .result.catch(function() {
179              resetCSRModal();
180            });
181      };
182
183      $scope.addCertModal = function() {
184        openAddCertModal();
185      };
186
187      function openAddCertModal() {
188        const modalTemplateAddCert =
189            require('./certificate-modal-add-cert.html');
190        $uibModal
191            .open({
192              template: modalTemplateAddCert,
193              windowTopClass: 'uib-modal',
194              scope: $scope,
195              ariaLabelledBy: 'modal_label',
196            })
197            .result.catch(function() {
198              // do nothing
199            });
200      };
201
202      $scope.addCsrModal = function() {
203        openCsrModal();
204      };
205
206      function openCsrModal() {
207        const modalTemplateCsrGen = require('./certificate-modal-csr-gen.html');
208        $uibModal
209            .open({
210              template: modalTemplateCsrGen,
211              windowTopClass: 'uib-modal',
212              scope: $scope,
213              ariaLabelledBy: 'modal_label',
214              size: 'lg',
215            })
216            .result.catch(function() {
217              resetCSRModal();
218            });
219      };
220
221      // resetting the modal when user clicks cancel/closes the
222      // modal
223      const resetCSRModal = function() {
224        $scope.newCSR.certificateCollection = $scope.selectOption;
225        $scope.newCSR.commonName = '';
226        $scope.newCSR.contactPerson = '';
227        $scope.newCSR.city = '';
228        $scope.names = [];
229        $scope.newCSR.challengePassword = '';
230        $scope.newCSR.emailAddress = '';
231        $scope.newCSR.countryCode = '';
232        $scope.newCSR.keyCurveId = '';
233        $scope.newCSR.firstAlternativeName = '';
234        $scope.newCSR.keyBitLength = $scope.selectOption;
235        $scope.newCSR.keyPairAlgorithm = $scope.selectOption;
236        $scope.newCSR.organization = '';
237        $scope.newCSR.companyUnit = '';
238        $scope.newCSR.state = '';
239      };
240
241      // copies the CSR code
242      $scope.copySuccess = function(event) {
243        $scope.copied = true;
244        $timeout(function() {
245          $scope.copied = false;
246        }, 5000);
247      };
248      $scope.copyFailed = function(err) {
249        console.log(JSON.stringify(err));
250      };
251
252
253      var getBmcTime = function() {
254        APIUtils.getBMCTime().then(function(data) {
255          $scope.bmcTime = data.data.Elapsed;
256        });
257
258        return $scope.bmcTime;
259      };
260
261      var updateAvailableTypes = function(certificate) {
262        $scope.availableCertificateTypes =
263            $scope.availableCertificateTypes.filter(function(type) {
264              if (type.Description == 'TrustStore Certificate') {
265                return true;
266              }
267              return type.Description !== certificate.Description;
268            });
269      };
270
271      $scope.getDays = function(endDate) {
272        // finds number of days until certificate expiration
273        // dividing bmc time by 1000 converts milliseconds to seconds
274        var ms = (new Date(endDate).getTime()) - ($scope.bmcTime) / 1000;
275        return Math.floor(ms / (24 * 60 * 60 * 1000));
276      };
277
278      $scope.loadCertificates();
279    }
280  ]);
281})(angular);
282