blob: bce50d7271d08b1be47b2685371745c43439b732 [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">
SurenNewared0df7d22020-07-22 16:41:20 +053036 <b-button
37 v-b-modal.generate-csr
38 data-test-id="sslCertificates-button-generateCsr"
39 variant="link"
40 >
Yoshie Muranaka532a4b02020-03-27 11:00:50 -070041 <icon-add />
42 {{ $t('pageSslCertificates.generateCsr') }}
43 </b-button>
Yoshie Muranaka37393812020-03-24 15:25:24 -070044 <b-button
45 variant="primary"
46 :disabled="certificatesForUpload.length === 0"
47 @click="initModalUploadCertificate(null)"
48 >
49 <icon-add />
50 {{ $t('pageSslCertificates.addNewCertificate') }}
51 </b-button>
52 </b-col>
53 </b-row>
54 <b-row>
Yoshie Muranaka3111b6f2020-04-21 19:48:38 -070055 <b-col xl="11">
SurenNeware307382e2020-07-27 20:45:14 +053056 <b-table
57 responsive="md"
58 show-empty
Sukanya Pandeyfde429e2020-09-14 20:48:39 +053059 hover
SurenNeware307382e2020-07-27 20:45:14 +053060 :fields="fields"
61 :items="tableItems"
62 :empty-text="$t('global.table.emptyMessage')"
63 >
Yoshie Muranaka37393812020-03-24 15:25:24 -070064 <template v-slot:cell(validFrom)="{ value }">
65 {{ value | formatDate }}
66 </template>
67
68 <template v-slot:cell(validUntil)="{ value }">
Yoshie Muranakae45f54b2020-03-26 15:23:34 -070069 <status-icon
70 v-if="getDaysUntilExpired(value) < 31"
71 :status="getIconStatus(value)"
72 />
Yoshie Muranaka37393812020-03-24 15:25:24 -070073 {{ value | formatDate }}
74 </template>
75
76 <template v-slot:cell(actions)="{ value, item }">
77 <table-row-action
78 v-for="(action, index) in value"
79 :key="index"
80 :value="action.value"
81 :title="action.title"
82 :enabled="action.enabled"
83 @click:tableAction="onTableRowAction($event, item)"
84 >
85 <template v-slot:icon>
86 <icon-replace v-if="action.value === 'replace'" />
87 <icon-trashcan v-if="action.value === 'delete'" />
88 </template>
89 </table-row-action>
90 </template>
91 </b-table>
92 </b-col>
93 </b-row>
94
95 <!-- Modals -->
96 <modal-upload-certificate :certificate="modalCertificate" @ok="onModalOk" />
Yoshie Muranaka532a4b02020-03-27 11:00:50 -070097 <modal-generate-csr />
Yoshie Muranaka37393812020-03-24 15:25:24 -070098 </b-container>
99</template>
100
101<script>
102import IconAdd from '@carbon/icons-vue/es/add--alt/20';
103import IconReplace from '@carbon/icons-vue/es/renew/20';
104import IconTrashcan from '@carbon/icons-vue/es/trash-can/20';
105
Yoshie Muranaka532a4b02020-03-27 11:00:50 -0700106import ModalGenerateCsr from './ModalGenerateCsr';
Yoshie Muranaka37393812020-03-24 15:25:24 -0700107import ModalUploadCertificate from './ModalUploadCertificate';
SurenNeware5e25e282020-07-08 15:57:23 +0530108import PageTitle from '@/components/Global/PageTitle';
109import TableRowAction from '@/components/Global/TableRowAction';
110import StatusIcon from '@/components/Global/StatusIcon';
111import Alert from '@/components/Global/Alert';
Yoshie Muranaka37393812020-03-24 15:25:24 -0700112
SurenNeware5e25e282020-07-08 15:57:23 +0530113import BVToastMixin from '@/components/Mixins/BVToastMixin';
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700114import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
Yoshie Muranaka37393812020-03-24 15:25:24 -0700115
116export default {
117 name: 'SslCertificates',
118 components: {
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700119 Alert,
Yoshie Muranaka37393812020-03-24 15:25:24 -0700120 IconAdd,
121 IconReplace,
122 IconTrashcan,
Yoshie Muranaka532a4b02020-03-27 11:00:50 -0700123 ModalGenerateCsr,
Yoshie Muranaka37393812020-03-24 15:25:24 -0700124 ModalUploadCertificate,
125 PageTitle,
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700126 StatusIcon,
Yoshie Muranaka37393812020-03-24 15:25:24 -0700127 TableRowAction
128 },
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700129 mixins: [BVToastMixin, LoadingBarMixin],
Yoshie Muranaka37393812020-03-24 15:25:24 -0700130 data() {
131 return {
132 modalCertificate: null,
133 fields: [
134 {
135 key: 'certificate',
136 label: this.$t('pageSslCertificates.table.certificate')
137 },
138 {
139 key: 'issuedBy',
140 label: this.$t('pageSslCertificates.table.issuedBy')
141 },
142 {
143 key: 'issuedTo',
144 label: this.$t('pageSslCertificates.table.issuedTo')
145 },
146 {
147 key: 'validFrom',
148 label: this.$t('pageSslCertificates.table.validFrom')
149 },
150 {
151 key: 'validUntil',
152 label: this.$t('pageSslCertificates.table.validUntil')
153 },
154 {
155 key: 'actions',
156 label: '',
SurenNeware5e25e282020-07-08 15:57:23 +0530157 tdClass: 'text-right text-nowrap'
Yoshie Muranaka37393812020-03-24 15:25:24 -0700158 }
159 ]
160 };
161 },
162 computed: {
163 certificates() {
164 return this.$store.getters['sslCertificates/allCertificates'];
165 },
166 tableItems() {
167 return this.certificates.map(certificate => {
168 return {
169 ...certificate,
170 actions: [
171 {
172 value: 'replace',
173 title: this.$t('pageSslCertificates.replaceCertificate')
174 },
175 {
176 value: 'delete',
177 title: this.$t('pageSslCertificates.deleteCertificate'),
178 enabled:
179 certificate.type === 'TrustStore Certificate' ? true : false
180 }
181 ]
182 };
183 });
184 },
185 certificatesForUpload() {
186 return this.$store.getters['sslCertificates/availableUploadTypes'];
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700187 },
188 bmcTime() {
189 return this.$store.getters['global/bmcTime'];
190 },
191 expiredCertificateTypes() {
192 return this.certificates.reduce((acc, val) => {
193 const daysUntilExpired = this.getDaysUntilExpired(val.validUntil);
194 if (daysUntilExpired < 1) {
195 acc.push(val.certificate);
196 }
197 return acc;
198 }, []);
199 },
200 expiringCertificateTypes() {
201 return this.certificates.reduce((acc, val) => {
202 const daysUntilExpired = this.getDaysUntilExpired(val.validUntil);
203 if (daysUntilExpired < 31 && daysUntilExpired > 0) {
204 acc.push(val.certificate);
205 }
206 return acc;
207 }, []);
Yoshie Muranaka37393812020-03-24 15:25:24 -0700208 }
209 },
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700210 async created() {
211 this.startLoader();
212 await this.$store.dispatch('global/getBmcTime');
213 this.$store
214 .dispatch('sslCertificates/getCertificates')
215 .finally(() => this.endLoader());
216 },
217 beforeRouteLeave(to, from, next) {
218 this.hideLoader();
219 next();
Yoshie Muranaka37393812020-03-24 15:25:24 -0700220 },
221 methods: {
222 onTableRowAction(event, rowItem) {
223 switch (event) {
224 case 'replace':
225 this.initModalUploadCertificate(rowItem);
226 break;
227 case 'delete':
228 this.initModalDeleteCertificate(rowItem);
229 break;
230 default:
231 break;
232 }
233 },
234 initModalUploadCertificate(certificate = null) {
235 this.modalCertificate = certificate;
236 this.$bvModal.show('upload-certificate');
237 },
238 initModalDeleteCertificate(certificate) {
239 this.$bvModal
240 .msgBoxConfirm(
241 this.$t('pageSslCertificates.modal.deleteConfirmMessage', {
242 issuedBy: certificate.issuedBy,
243 certificate: certificate.certificate
244 }),
245 {
246 title: this.$t('pageSslCertificates.deleteCertificate'),
247 okTitle: this.$t('global.action.delete')
248 }
249 )
250 .then(deleteConfirmed => {
251 if (deleteConfirmed) this.deleteCertificate(certificate);
252 });
253 },
254 onModalOk({ addNew, file, type, location }) {
255 if (addNew) {
256 // Upload a new certificate
257 this.addNewCertificate(file, type);
258 } else {
259 // Replace an existing certificate
260 this.replaceCertificate(file, type, location);
261 }
262 },
263 addNewCertificate(file, type) {
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700264 this.startLoader();
Yoshie Muranaka37393812020-03-24 15:25:24 -0700265 this.$store
266 .dispatch('sslCertificates/addNewCertificate', { file, type })
267 .then(success => this.successToast(success))
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700268 .catch(({ message }) => this.errorToast(message))
269 .finally(() => this.endLoader());
Yoshie Muranaka37393812020-03-24 15:25:24 -0700270 },
271 replaceCertificate(file, type, location) {
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700272 this.startLoader();
Yoshie Muranaka37393812020-03-24 15:25:24 -0700273 const reader = new FileReader();
274 reader.readAsBinaryString(file);
275 reader.onloadend = event => {
276 const certificateString = event.target.result;
277 this.$store
278 .dispatch('sslCertificates/replaceCertificate', {
279 certificateString,
280 type,
281 location
282 })
283 .then(success => this.successToast(success))
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700284 .catch(({ message }) => this.errorToast(message))
285 .finally(() => this.endLoader());
Yoshie Muranaka37393812020-03-24 15:25:24 -0700286 };
287 },
288 deleteCertificate({ type, location }) {
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700289 this.startLoader();
Yoshie Muranaka37393812020-03-24 15:25:24 -0700290 this.$store
291 .dispatch('sslCertificates/deleteCertificate', {
292 type,
293 location
294 })
295 .then(success => this.successToast(success))
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700296 .catch(({ message }) => this.errorToast(message))
297 .finally(() => this.endLoader());
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700298 },
299 getDaysUntilExpired(date) {
300 if (this.bmcTime) {
301 const validUntilMs = date.getTime();
302 const currentBmcTimeMs = this.bmcTime.getTime();
303 const oneDayInMs = 24 * 60 * 60 * 1000;
304 return Math.round((validUntilMs - currentBmcTimeMs) / oneDayInMs);
305 }
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700306 return new Date();
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700307 },
308 getIconStatus(date) {
309 const daysUntilExpired = this.getDaysUntilExpired(date);
310 if (daysUntilExpired < 1) {
311 return 'danger';
312 } else if (daysUntilExpired < 31) {
313 return 'warning';
314 }
Yoshie Muranaka37393812020-03-24 15:25:24 -0700315 }
316 }
317};
318</script>