blob: 572759568618e76fc14c21e322ad3f15eb82a7ce [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
59 :fields="fields"
60 :items="tableItems"
61 :empty-text="$t('global.table.emptyMessage')"
62 >
Yoshie Muranaka37393812020-03-24 15:25:24 -070063 <template v-slot:cell(validFrom)="{ value }">
64 {{ value | formatDate }}
65 </template>
66
67 <template v-slot:cell(validUntil)="{ value }">
Yoshie Muranakae45f54b2020-03-26 15:23:34 -070068 <status-icon
69 v-if="getDaysUntilExpired(value) < 31"
70 :status="getIconStatus(value)"
71 />
Yoshie Muranaka37393812020-03-24 15:25:24 -070072 {{ value | formatDate }}
73 </template>
74
75 <template v-slot:cell(actions)="{ value, item }">
76 <table-row-action
77 v-for="(action, index) in value"
78 :key="index"
79 :value="action.value"
80 :title="action.title"
81 :enabled="action.enabled"
82 @click:tableAction="onTableRowAction($event, item)"
83 >
84 <template v-slot:icon>
85 <icon-replace v-if="action.value === 'replace'" />
86 <icon-trashcan v-if="action.value === 'delete'" />
87 </template>
88 </table-row-action>
89 </template>
90 </b-table>
91 </b-col>
92 </b-row>
93
94 <!-- Modals -->
95 <modal-upload-certificate :certificate="modalCertificate" @ok="onModalOk" />
Yoshie Muranaka532a4b02020-03-27 11:00:50 -070096 <modal-generate-csr />
Yoshie Muranaka37393812020-03-24 15:25:24 -070097 </b-container>
98</template>
99
100<script>
101import IconAdd from '@carbon/icons-vue/es/add--alt/20';
102import IconReplace from '@carbon/icons-vue/es/renew/20';
103import IconTrashcan from '@carbon/icons-vue/es/trash-can/20';
104
Yoshie Muranaka532a4b02020-03-27 11:00:50 -0700105import ModalGenerateCsr from './ModalGenerateCsr';
Yoshie Muranaka37393812020-03-24 15:25:24 -0700106import ModalUploadCertificate from './ModalUploadCertificate';
SurenNeware5e25e282020-07-08 15:57:23 +0530107import PageTitle from '@/components/Global/PageTitle';
108import TableRowAction from '@/components/Global/TableRowAction';
109import StatusIcon from '@/components/Global/StatusIcon';
110import Alert from '@/components/Global/Alert';
Yoshie Muranaka37393812020-03-24 15:25:24 -0700111
SurenNeware5e25e282020-07-08 15:57:23 +0530112import BVToastMixin from '@/components/Mixins/BVToastMixin';
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700113import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
Yoshie Muranaka37393812020-03-24 15:25:24 -0700114
115export default {
116 name: 'SslCertificates',
117 components: {
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700118 Alert,
Yoshie Muranaka37393812020-03-24 15:25:24 -0700119 IconAdd,
120 IconReplace,
121 IconTrashcan,
Yoshie Muranaka532a4b02020-03-27 11:00:50 -0700122 ModalGenerateCsr,
Yoshie Muranaka37393812020-03-24 15:25:24 -0700123 ModalUploadCertificate,
124 PageTitle,
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700125 StatusIcon,
Yoshie Muranaka37393812020-03-24 15:25:24 -0700126 TableRowAction
127 },
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700128 mixins: [BVToastMixin, LoadingBarMixin],
Yoshie Muranaka37393812020-03-24 15:25:24 -0700129 data() {
130 return {
131 modalCertificate: null,
132 fields: [
133 {
134 key: 'certificate',
135 label: this.$t('pageSslCertificates.table.certificate')
136 },
137 {
138 key: 'issuedBy',
139 label: this.$t('pageSslCertificates.table.issuedBy')
140 },
141 {
142 key: 'issuedTo',
143 label: this.$t('pageSslCertificates.table.issuedTo')
144 },
145 {
146 key: 'validFrom',
147 label: this.$t('pageSslCertificates.table.validFrom')
148 },
149 {
150 key: 'validUntil',
151 label: this.$t('pageSslCertificates.table.validUntil')
152 },
153 {
154 key: 'actions',
155 label: '',
SurenNeware5e25e282020-07-08 15:57:23 +0530156 tdClass: 'text-right text-nowrap'
Yoshie Muranaka37393812020-03-24 15:25:24 -0700157 }
158 ]
159 };
160 },
161 computed: {
162 certificates() {
163 return this.$store.getters['sslCertificates/allCertificates'];
164 },
165 tableItems() {
166 return this.certificates.map(certificate => {
167 return {
168 ...certificate,
169 actions: [
170 {
171 value: 'replace',
172 title: this.$t('pageSslCertificates.replaceCertificate')
173 },
174 {
175 value: 'delete',
176 title: this.$t('pageSslCertificates.deleteCertificate'),
177 enabled:
178 certificate.type === 'TrustStore Certificate' ? true : false
179 }
180 ]
181 };
182 });
183 },
184 certificatesForUpload() {
185 return this.$store.getters['sslCertificates/availableUploadTypes'];
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700186 },
187 bmcTime() {
188 return this.$store.getters['global/bmcTime'];
189 },
190 expiredCertificateTypes() {
191 return this.certificates.reduce((acc, val) => {
192 const daysUntilExpired = this.getDaysUntilExpired(val.validUntil);
193 if (daysUntilExpired < 1) {
194 acc.push(val.certificate);
195 }
196 return acc;
197 }, []);
198 },
199 expiringCertificateTypes() {
200 return this.certificates.reduce((acc, val) => {
201 const daysUntilExpired = this.getDaysUntilExpired(val.validUntil);
202 if (daysUntilExpired < 31 && daysUntilExpired > 0) {
203 acc.push(val.certificate);
204 }
205 return acc;
206 }, []);
Yoshie Muranaka37393812020-03-24 15:25:24 -0700207 }
208 },
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700209 async created() {
210 this.startLoader();
211 await this.$store.dispatch('global/getBmcTime');
212 this.$store
213 .dispatch('sslCertificates/getCertificates')
214 .finally(() => this.endLoader());
215 },
216 beforeRouteLeave(to, from, next) {
217 this.hideLoader();
218 next();
Yoshie Muranaka37393812020-03-24 15:25:24 -0700219 },
220 methods: {
221 onTableRowAction(event, rowItem) {
222 switch (event) {
223 case 'replace':
224 this.initModalUploadCertificate(rowItem);
225 break;
226 case 'delete':
227 this.initModalDeleteCertificate(rowItem);
228 break;
229 default:
230 break;
231 }
232 },
233 initModalUploadCertificate(certificate = null) {
234 this.modalCertificate = certificate;
235 this.$bvModal.show('upload-certificate');
236 },
237 initModalDeleteCertificate(certificate) {
238 this.$bvModal
239 .msgBoxConfirm(
240 this.$t('pageSslCertificates.modal.deleteConfirmMessage', {
241 issuedBy: certificate.issuedBy,
242 certificate: certificate.certificate
243 }),
244 {
245 title: this.$t('pageSslCertificates.deleteCertificate'),
246 okTitle: this.$t('global.action.delete')
247 }
248 )
249 .then(deleteConfirmed => {
250 if (deleteConfirmed) this.deleteCertificate(certificate);
251 });
252 },
253 onModalOk({ addNew, file, type, location }) {
254 if (addNew) {
255 // Upload a new certificate
256 this.addNewCertificate(file, type);
257 } else {
258 // Replace an existing certificate
259 this.replaceCertificate(file, type, location);
260 }
261 },
262 addNewCertificate(file, type) {
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700263 this.startLoader();
Yoshie Muranaka37393812020-03-24 15:25:24 -0700264 this.$store
265 .dispatch('sslCertificates/addNewCertificate', { file, type })
266 .then(success => this.successToast(success))
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700267 .catch(({ message }) => this.errorToast(message))
268 .finally(() => this.endLoader());
Yoshie Muranaka37393812020-03-24 15:25:24 -0700269 },
270 replaceCertificate(file, type, location) {
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700271 this.startLoader();
Yoshie Muranaka37393812020-03-24 15:25:24 -0700272 const reader = new FileReader();
273 reader.readAsBinaryString(file);
274 reader.onloadend = event => {
275 const certificateString = event.target.result;
276 this.$store
277 .dispatch('sslCertificates/replaceCertificate', {
278 certificateString,
279 type,
280 location
281 })
282 .then(success => this.successToast(success))
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700283 .catch(({ message }) => this.errorToast(message))
284 .finally(() => this.endLoader());
Yoshie Muranaka37393812020-03-24 15:25:24 -0700285 };
286 },
287 deleteCertificate({ type, location }) {
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700288 this.startLoader();
Yoshie Muranaka37393812020-03-24 15:25:24 -0700289 this.$store
290 .dispatch('sslCertificates/deleteCertificate', {
291 type,
292 location
293 })
294 .then(success => this.successToast(success))
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700295 .catch(({ message }) => this.errorToast(message))
296 .finally(() => this.endLoader());
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700297 },
298 getDaysUntilExpired(date) {
299 if (this.bmcTime) {
300 const validUntilMs = date.getTime();
301 const currentBmcTimeMs = this.bmcTime.getTime();
302 const oneDayInMs = 24 * 60 * 60 * 1000;
303 return Math.round((validUntilMs - currentBmcTimeMs) / oneDayInMs);
304 }
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700305 return new Date();
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700306 },
307 getIconStatus(date) {
308 const daysUntilExpired = this.getDaysUntilExpired(date);
309 if (daysUntilExpired < 1) {
310 return 'danger';
311 } else if (daysUntilExpired < 31) {
312 return 'warning';
313 }
Yoshie Muranaka37393812020-03-24 15:25:24 -0700314 }
315 }
316};
317</script>