blob: 6f74c81a603befe026e283eff67b54d45c9bda66 [file] [log] [blame]
Yoshie Muranaka37393812020-03-24 15:25:24 -07001<template>
Yoshie Muranaka3111b6f2020-04-21 19:48:38 -07002 <b-container fluid="xl">
Yoshie Muranaka37393812020-03-24 15:25:24 -07003 <page-title />
4 <b-row>
Yoshie Muranaka3111b6f2020-04-21 19:48:38 -07005 <b-col xl="11">
Yoshie Muranakae45f54b2020-03-26 15:23:34 -07006 <!-- Expired certificates banner -->
7 <alert :show="expiredCertificateTypes.length > 0" variant="danger">
8 <template v-if="expiredCertificateTypes.length > 1">
9 {{ $t('pageSslCertificates.alert.certificatesExpiredMessage') }}
10 </template>
11 <template v-else>
12 {{
13 $t('pageSslCertificates.alert.certificateExpiredMessage', {
14 certificate: expiredCertificateTypes[0]
15 })
16 }}
17 </template>
18 </alert>
19 <!-- Expiring certificates banner -->
20 <alert :show="expiringCertificateTypes.length > 0" variant="warning">
21 <template v-if="expiringCertificateTypes.length > 1">
22 {{ $t('pageSslCertificates.alert.certificatesExpiringMessage') }}
23 </template>
24 <template v-else>
25 {{
26 $t('pageSslCertificates.alert.certificateExpiringMessage', {
27 certificate: expiringCertificateTypes[0]
28 })
29 }}
30 </template>
31 </alert>
32 </b-col>
33 </b-row>
34 <b-row>
Yoshie Muranaka3111b6f2020-04-21 19:48:38 -070035 <b-col xl="11" class="text-right">
Yoshie Muranaka532a4b02020-03-27 11:00:50 -070036 <b-button v-b-modal.generate-csr variant="link">
37 <icon-add />
38 {{ $t('pageSslCertificates.generateCsr') }}
39 </b-button>
Yoshie Muranaka37393812020-03-24 15:25:24 -070040 <b-button
41 variant="primary"
42 :disabled="certificatesForUpload.length === 0"
43 @click="initModalUploadCertificate(null)"
44 >
45 <icon-add />
46 {{ $t('pageSslCertificates.addNewCertificate') }}
47 </b-button>
48 </b-col>
49 </b-row>
50 <b-row>
Yoshie Muranaka3111b6f2020-04-21 19:48:38 -070051 <b-col xl="11">
Yoshie Muranaka37393812020-03-24 15:25:24 -070052 <b-table :fields="fields" :items="tableItems">
53 <template v-slot:cell(validFrom)="{ value }">
54 {{ value | formatDate }}
55 </template>
56
57 <template v-slot:cell(validUntil)="{ value }">
Yoshie Muranakae45f54b2020-03-26 15:23:34 -070058 <status-icon
59 v-if="getDaysUntilExpired(value) < 31"
60 :status="getIconStatus(value)"
61 />
Yoshie Muranaka37393812020-03-24 15:25:24 -070062 {{ value | formatDate }}
63 </template>
64
65 <template v-slot:cell(actions)="{ value, item }">
66 <table-row-action
67 v-for="(action, index) in value"
68 :key="index"
69 :value="action.value"
70 :title="action.title"
71 :enabled="action.enabled"
72 @click:tableAction="onTableRowAction($event, item)"
73 >
74 <template v-slot:icon>
75 <icon-replace v-if="action.value === 'replace'" />
76 <icon-trashcan v-if="action.value === 'delete'" />
77 </template>
78 </table-row-action>
79 </template>
80 </b-table>
81 </b-col>
82 </b-row>
83
84 <!-- Modals -->
85 <modal-upload-certificate :certificate="modalCertificate" @ok="onModalOk" />
Yoshie Muranaka532a4b02020-03-27 11:00:50 -070086 <modal-generate-csr />
Yoshie Muranaka37393812020-03-24 15:25:24 -070087 </b-container>
88</template>
89
90<script>
91import IconAdd from '@carbon/icons-vue/es/add--alt/20';
92import IconReplace from '@carbon/icons-vue/es/renew/20';
93import IconTrashcan from '@carbon/icons-vue/es/trash-can/20';
94
Yoshie Muranaka532a4b02020-03-27 11:00:50 -070095import ModalGenerateCsr from './ModalGenerateCsr';
Yoshie Muranaka37393812020-03-24 15:25:24 -070096import ModalUploadCertificate from './ModalUploadCertificate';
97import PageTitle from '../../../components/Global/PageTitle';
98import TableRowAction from '../../../components/Global/TableRowAction';
Yoshie Muranakae45f54b2020-03-26 15:23:34 -070099import StatusIcon from '../../../components/Global/StatusIcon';
100import Alert from '../../../components/Global/Alert';
Yoshie Muranaka37393812020-03-24 15:25:24 -0700101
102import BVToastMixin from '../../../components/Mixins/BVToastMixin';
103
104export default {
105 name: 'SslCertificates',
106 components: {
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700107 Alert,
Yoshie Muranaka37393812020-03-24 15:25:24 -0700108 IconAdd,
109 IconReplace,
110 IconTrashcan,
Yoshie Muranaka532a4b02020-03-27 11:00:50 -0700111 ModalGenerateCsr,
Yoshie Muranaka37393812020-03-24 15:25:24 -0700112 ModalUploadCertificate,
113 PageTitle,
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700114 StatusIcon,
Yoshie Muranaka37393812020-03-24 15:25:24 -0700115 TableRowAction
116 },
117 mixins: [BVToastMixin],
118 data() {
119 return {
120 modalCertificate: null,
121 fields: [
122 {
123 key: 'certificate',
124 label: this.$t('pageSslCertificates.table.certificate')
125 },
126 {
127 key: 'issuedBy',
128 label: this.$t('pageSslCertificates.table.issuedBy')
129 },
130 {
131 key: 'issuedTo',
132 label: this.$t('pageSslCertificates.table.issuedTo')
133 },
134 {
135 key: 'validFrom',
136 label: this.$t('pageSslCertificates.table.validFrom')
137 },
138 {
139 key: 'validUntil',
140 label: this.$t('pageSslCertificates.table.validUntil')
141 },
142 {
143 key: 'actions',
144 label: '',
145 tdClass: 'text-right'
146 }
147 ]
148 };
149 },
150 computed: {
151 certificates() {
152 return this.$store.getters['sslCertificates/allCertificates'];
153 },
154 tableItems() {
155 return this.certificates.map(certificate => {
156 return {
157 ...certificate,
158 actions: [
159 {
160 value: 'replace',
161 title: this.$t('pageSslCertificates.replaceCertificate')
162 },
163 {
164 value: 'delete',
165 title: this.$t('pageSslCertificates.deleteCertificate'),
166 enabled:
167 certificate.type === 'TrustStore Certificate' ? true : false
168 }
169 ]
170 };
171 });
172 },
173 certificatesForUpload() {
174 return this.$store.getters['sslCertificates/availableUploadTypes'];
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700175 },
176 bmcTime() {
177 return this.$store.getters['global/bmcTime'];
178 },
179 expiredCertificateTypes() {
180 return this.certificates.reduce((acc, val) => {
181 const daysUntilExpired = this.getDaysUntilExpired(val.validUntil);
182 if (daysUntilExpired < 1) {
183 acc.push(val.certificate);
184 }
185 return acc;
186 }, []);
187 },
188 expiringCertificateTypes() {
189 return this.certificates.reduce((acc, val) => {
190 const daysUntilExpired = this.getDaysUntilExpired(val.validUntil);
191 if (daysUntilExpired < 31 && daysUntilExpired > 0) {
192 acc.push(val.certificate);
193 }
194 return acc;
195 }, []);
Yoshie Muranaka37393812020-03-24 15:25:24 -0700196 }
197 },
198 created() {
199 this.$store.dispatch('sslCertificates/getCertificates');
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700200 this.$store.dispatch('global/getBmcTime');
Yoshie Muranaka37393812020-03-24 15:25:24 -0700201 },
202 methods: {
203 onTableRowAction(event, rowItem) {
204 switch (event) {
205 case 'replace':
206 this.initModalUploadCertificate(rowItem);
207 break;
208 case 'delete':
209 this.initModalDeleteCertificate(rowItem);
210 break;
211 default:
212 break;
213 }
214 },
215 initModalUploadCertificate(certificate = null) {
216 this.modalCertificate = certificate;
217 this.$bvModal.show('upload-certificate');
218 },
219 initModalDeleteCertificate(certificate) {
220 this.$bvModal
221 .msgBoxConfirm(
222 this.$t('pageSslCertificates.modal.deleteConfirmMessage', {
223 issuedBy: certificate.issuedBy,
224 certificate: certificate.certificate
225 }),
226 {
227 title: this.$t('pageSslCertificates.deleteCertificate'),
228 okTitle: this.$t('global.action.delete')
229 }
230 )
231 .then(deleteConfirmed => {
232 if (deleteConfirmed) this.deleteCertificate(certificate);
233 });
234 },
235 onModalOk({ addNew, file, type, location }) {
236 if (addNew) {
237 // Upload a new certificate
238 this.addNewCertificate(file, type);
239 } else {
240 // Replace an existing certificate
241 this.replaceCertificate(file, type, location);
242 }
243 },
244 addNewCertificate(file, type) {
245 this.$store
246 .dispatch('sslCertificates/addNewCertificate', { file, type })
247 .then(success => this.successToast(success))
248 .catch(({ message }) => this.errorToast(message));
249 },
250 replaceCertificate(file, type, location) {
251 const reader = new FileReader();
252 reader.readAsBinaryString(file);
253 reader.onloadend = event => {
254 const certificateString = event.target.result;
255 this.$store
256 .dispatch('sslCertificates/replaceCertificate', {
257 certificateString,
258 type,
259 location
260 })
261 .then(success => this.successToast(success))
262 .catch(({ message }) => this.errorToast(message));
263 };
264 },
265 deleteCertificate({ type, location }) {
266 this.$store
267 .dispatch('sslCertificates/deleteCertificate', {
268 type,
269 location
270 })
271 .then(success => this.successToast(success))
272 .catch(({ message }) => this.errorToast(message));
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700273 },
274 getDaysUntilExpired(date) {
275 if (this.bmcTime) {
276 const validUntilMs = date.getTime();
277 const currentBmcTimeMs = this.bmcTime.getTime();
278 const oneDayInMs = 24 * 60 * 60 * 1000;
279 return Math.round((validUntilMs - currentBmcTimeMs) / oneDayInMs);
280 }
281 return null;
282 },
283 getIconStatus(date) {
284 const daysUntilExpired = this.getDaysUntilExpired(date);
285 if (daysUntilExpired < 1) {
286 return 'danger';
287 } else if (daysUntilExpired < 31) {
288 return 'warning';
289 }
Yoshie Muranaka37393812020-03-24 15:25:24 -0700290 }
291 }
292};
293</script>