1import api from '@/store/api';
2import i18n from '@/i18n';
3
4export const CERTIFICATE_TYPES = [
5  {
6    type: 'HTTPS Certificate',
7    location: '/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/',
8    label: i18n.t('pageCertificates.httpsCertificate'),
9  },
10  {
11    type: 'LDAP Certificate',
12    location: '/redfish/v1/AccountService/LDAP/Certificates/',
13    label: i18n.t('pageCertificates.ldapCertificate'),
14  },
15  {
16    type: 'TrustStore Certificate',
17    location: '/redfish/v1/Managers/bmc/Truststore/Certificates/',
18    // Web UI will show 'CA Certificate' instead of
19    // 'TrustStore Certificate' after user testing revealed
20    // the term 'TrustStore Certificate' wasn't recognized/was unfamilar
21    label: i18n.t('pageCertificates.caCertificate'),
22  },
23];
24
25const getCertificateProp = (type, prop) => {
26  const certificate = CERTIFICATE_TYPES.find(
27    (certificate) => certificate.type === type,
28  );
29  return certificate ? certificate[prop] : null;
30};
31
32const CertificatesStore = {
33  namespaced: true,
34  state: {
35    allCertificates: [],
36    availableUploadTypes: [],
37  },
38  getters: {
39    allCertificates: (state) => state.allCertificates,
40    availableUploadTypes: (state) => state.availableUploadTypes,
41  },
42  mutations: {
43    setCertificates(state, certificates) {
44      state.allCertificates = certificates;
45    },
46    setAvailableUploadTypes(state, availableUploadTypes) {
47      state.availableUploadTypes = availableUploadTypes;
48    },
49  },
50  actions: {
51    async getCertificates({ commit }) {
52      return await api
53        .get('/redfish/v1/CertificateService/CertificateLocations')
54        .then(
55          ({
56            data: {
57              Links: { Certificates },
58            },
59          }) => Certificates.map((certificate) => certificate['@odata.id']),
60        )
61        .then((certificateLocations) => {
62          const promises = certificateLocations.map((location) =>
63            api.get(location),
64          );
65          api.all(promises).then(
66            api.spread((...responses) => {
67              const certificates = responses.map(({ data }) => {
68                const {
69                  Name,
70                  ValidNotAfter,
71                  ValidNotBefore,
72                  Issuer = {},
73                  Subject = {},
74                } = data;
75                return {
76                  type: Name,
77                  location: data['@odata.id'],
78                  certificate: getCertificateProp(Name, 'label'),
79                  issuedBy: Issuer.CommonName,
80                  issuedTo: Subject.CommonName,
81                  validFrom: new Date(ValidNotBefore),
82                  validUntil: new Date(ValidNotAfter),
83                };
84              });
85              const availableUploadTypes = CERTIFICATE_TYPES.filter(
86                ({ type }) =>
87                  !certificates
88                    .map((certificate) => certificate.type)
89                    .includes(type),
90              );
91
92              commit('setCertificates', certificates);
93              commit('setAvailableUploadTypes', availableUploadTypes);
94            }),
95          );
96        });
97    },
98    async addNewCertificate({ dispatch }, { file, type }) {
99      return await api
100        .post(getCertificateProp(type, 'location'), file, {
101          headers: { 'Content-Type': 'application/x-pem-file' },
102        })
103        .then(() => dispatch('getCertificates'))
104        .then(() =>
105          i18n.t('pageCertificates.toast.successAddCertificate', {
106            certificate: getCertificateProp(type, 'label'),
107          }),
108        )
109        .catch((error) => {
110          console.log(error);
111          throw new Error(i18n.t('pageCertificates.toast.errorAddCertificate'));
112        });
113    },
114    async replaceCertificate(
115      { dispatch },
116      { certificateString, location, type },
117    ) {
118      const data = {};
119      data.CertificateString = certificateString;
120      data.CertificateType = 'PEM';
121      data.CertificateUri = { '@odata.id': location };
122
123      return await api
124        .post(
125          '/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate',
126          data,
127        )
128        .then(() => dispatch('getCertificates'))
129        .then(() =>
130          i18n.t('pageCertificates.toast.successReplaceCertificate', {
131            certificate: getCertificateProp(type, 'label'),
132          }),
133        )
134        .catch((error) => {
135          console.log(error);
136          throw new Error(
137            i18n.t('pageCertificates.toast.errorReplaceCertificate'),
138          );
139        });
140    },
141    async deleteCertificate({ dispatch }, { type, location }) {
142      return await api
143        .delete(location)
144        .then(() => dispatch('getCertificates'))
145        .then(() =>
146          i18n.t('pageCertificates.toast.successDeleteCertificate', {
147            certificate: getCertificateProp(type, 'label'),
148          }),
149        )
150        .catch((error) => {
151          console.log(error);
152          throw new Error(
153            i18n.t('pageCertificates.toast.errorDeleteCertificate'),
154          );
155        });
156    },
157    async generateCsr(_, userData) {
158      const {
159        certificateType,
160        country,
161        state,
162        city,
163        companyName,
164        companyUnit,
165        commonName,
166        keyPairAlgorithm,
167        keyBitLength,
168        keyCurveId,
169        challengePassword,
170        contactPerson,
171        emailAddress,
172        alternateName,
173      } = userData;
174      const data = {};
175
176      data.CertificateCollection = {
177        '@odata.id': getCertificateProp(certificateType, 'location'),
178      };
179      data.Country = country;
180      data.State = state;
181      data.City = city;
182      data.Organization = companyName;
183      data.OrganizationalUnit = companyUnit;
184      data.CommonName = commonName;
185      data.KeyPairAlgorithm = keyPairAlgorithm;
186      data.AlternativeNames = alternateName;
187
188      if (keyCurveId) data.KeyCurveId = keyCurveId;
189      if (keyBitLength) data.KeyBitLength = keyBitLength;
190      if (challengePassword) data.ChallengePassword = challengePassword;
191      if (contactPerson) data.ContactPerson = contactPerson;
192      if (emailAddress) data.Email = emailAddress;
193
194      return await api
195        .post(
196          '/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR',
197          data,
198        )
199        //TODO: Success response also throws error so
200        // can't accurately show legitimate error in UI
201        .catch((error) => console.log(error));
202    },
203  },
204};
205
206export default CertificatesStore;
207