blob: aeb547d7a4447fc1518b478d52ec2970abacae54 [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">
SurenNeware5e25e282020-07-08 15:57:23 +053056 <b-table responsive="md" :fields="fields" :items="tableItems">
Yoshie Muranaka37393812020-03-24 15:25:24 -070057 <template v-slot:cell(validFrom)="{ value }">
58 {{ value | formatDate }}
59 </template>
60
61 <template v-slot:cell(validUntil)="{ value }">
Yoshie Muranakae45f54b2020-03-26 15:23:34 -070062 <status-icon
63 v-if="getDaysUntilExpired(value) < 31"
64 :status="getIconStatus(value)"
65 />
Yoshie Muranaka37393812020-03-24 15:25:24 -070066 {{ value | formatDate }}
67 </template>
68
69 <template v-slot:cell(actions)="{ value, item }">
70 <table-row-action
71 v-for="(action, index) in value"
72 :key="index"
73 :value="action.value"
74 :title="action.title"
75 :enabled="action.enabled"
76 @click:tableAction="onTableRowAction($event, item)"
77 >
78 <template v-slot:icon>
79 <icon-replace v-if="action.value === 'replace'" />
80 <icon-trashcan v-if="action.value === 'delete'" />
81 </template>
82 </table-row-action>
83 </template>
84 </b-table>
85 </b-col>
86 </b-row>
87
88 <!-- Modals -->
89 <modal-upload-certificate :certificate="modalCertificate" @ok="onModalOk" />
Yoshie Muranaka532a4b02020-03-27 11:00:50 -070090 <modal-generate-csr />
Yoshie Muranaka37393812020-03-24 15:25:24 -070091 </b-container>
92</template>
93
94<script>
95import IconAdd from '@carbon/icons-vue/es/add--alt/20';
96import IconReplace from '@carbon/icons-vue/es/renew/20';
97import IconTrashcan from '@carbon/icons-vue/es/trash-can/20';
98
Yoshie Muranaka532a4b02020-03-27 11:00:50 -070099import ModalGenerateCsr from './ModalGenerateCsr';
Yoshie Muranaka37393812020-03-24 15:25:24 -0700100import ModalUploadCertificate from './ModalUploadCertificate';
SurenNeware5e25e282020-07-08 15:57:23 +0530101import PageTitle from '@/components/Global/PageTitle';
102import TableRowAction from '@/components/Global/TableRowAction';
103import StatusIcon from '@/components/Global/StatusIcon';
104import Alert from '@/components/Global/Alert';
Yoshie Muranaka37393812020-03-24 15:25:24 -0700105
SurenNeware5e25e282020-07-08 15:57:23 +0530106import BVToastMixin from '@/components/Mixins/BVToastMixin';
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700107import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
Yoshie Muranaka37393812020-03-24 15:25:24 -0700108
109export default {
110 name: 'SslCertificates',
111 components: {
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700112 Alert,
Yoshie Muranaka37393812020-03-24 15:25:24 -0700113 IconAdd,
114 IconReplace,
115 IconTrashcan,
Yoshie Muranaka532a4b02020-03-27 11:00:50 -0700116 ModalGenerateCsr,
Yoshie Muranaka37393812020-03-24 15:25:24 -0700117 ModalUploadCertificate,
118 PageTitle,
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700119 StatusIcon,
Yoshie Muranaka37393812020-03-24 15:25:24 -0700120 TableRowAction
121 },
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700122 mixins: [BVToastMixin, LoadingBarMixin],
Yoshie Muranaka37393812020-03-24 15:25:24 -0700123 data() {
124 return {
125 modalCertificate: null,
126 fields: [
127 {
128 key: 'certificate',
129 label: this.$t('pageSslCertificates.table.certificate')
130 },
131 {
132 key: 'issuedBy',
133 label: this.$t('pageSslCertificates.table.issuedBy')
134 },
135 {
136 key: 'issuedTo',
137 label: this.$t('pageSslCertificates.table.issuedTo')
138 },
139 {
140 key: 'validFrom',
141 label: this.$t('pageSslCertificates.table.validFrom')
142 },
143 {
144 key: 'validUntil',
145 label: this.$t('pageSslCertificates.table.validUntil')
146 },
147 {
148 key: 'actions',
149 label: '',
SurenNeware5e25e282020-07-08 15:57:23 +0530150 tdClass: 'text-right text-nowrap'
Yoshie Muranaka37393812020-03-24 15:25:24 -0700151 }
152 ]
153 };
154 },
155 computed: {
156 certificates() {
157 return this.$store.getters['sslCertificates/allCertificates'];
158 },
159 tableItems() {
160 return this.certificates.map(certificate => {
161 return {
162 ...certificate,
163 actions: [
164 {
165 value: 'replace',
166 title: this.$t('pageSslCertificates.replaceCertificate')
167 },
168 {
169 value: 'delete',
170 title: this.$t('pageSslCertificates.deleteCertificate'),
171 enabled:
172 certificate.type === 'TrustStore Certificate' ? true : false
173 }
174 ]
175 };
176 });
177 },
178 certificatesForUpload() {
179 return this.$store.getters['sslCertificates/availableUploadTypes'];
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700180 },
181 bmcTime() {
182 return this.$store.getters['global/bmcTime'];
183 },
184 expiredCertificateTypes() {
185 return this.certificates.reduce((acc, val) => {
186 const daysUntilExpired = this.getDaysUntilExpired(val.validUntil);
187 if (daysUntilExpired < 1) {
188 acc.push(val.certificate);
189 }
190 return acc;
191 }, []);
192 },
193 expiringCertificateTypes() {
194 return this.certificates.reduce((acc, val) => {
195 const daysUntilExpired = this.getDaysUntilExpired(val.validUntil);
196 if (daysUntilExpired < 31 && daysUntilExpired > 0) {
197 acc.push(val.certificate);
198 }
199 return acc;
200 }, []);
Yoshie Muranaka37393812020-03-24 15:25:24 -0700201 }
202 },
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700203 async created() {
204 this.startLoader();
205 await this.$store.dispatch('global/getBmcTime');
206 this.$store
207 .dispatch('sslCertificates/getCertificates')
208 .finally(() => this.endLoader());
209 },
210 beforeRouteLeave(to, from, next) {
211 this.hideLoader();
212 next();
Yoshie Muranaka37393812020-03-24 15:25:24 -0700213 },
214 methods: {
215 onTableRowAction(event, rowItem) {
216 switch (event) {
217 case 'replace':
218 this.initModalUploadCertificate(rowItem);
219 break;
220 case 'delete':
221 this.initModalDeleteCertificate(rowItem);
222 break;
223 default:
224 break;
225 }
226 },
227 initModalUploadCertificate(certificate = null) {
228 this.modalCertificate = certificate;
229 this.$bvModal.show('upload-certificate');
230 },
231 initModalDeleteCertificate(certificate) {
232 this.$bvModal
233 .msgBoxConfirm(
234 this.$t('pageSslCertificates.modal.deleteConfirmMessage', {
235 issuedBy: certificate.issuedBy,
236 certificate: certificate.certificate
237 }),
238 {
239 title: this.$t('pageSslCertificates.deleteCertificate'),
240 okTitle: this.$t('global.action.delete')
241 }
242 )
243 .then(deleteConfirmed => {
244 if (deleteConfirmed) this.deleteCertificate(certificate);
245 });
246 },
247 onModalOk({ addNew, file, type, location }) {
248 if (addNew) {
249 // Upload a new certificate
250 this.addNewCertificate(file, type);
251 } else {
252 // Replace an existing certificate
253 this.replaceCertificate(file, type, location);
254 }
255 },
256 addNewCertificate(file, type) {
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700257 this.startLoader();
Yoshie Muranaka37393812020-03-24 15:25:24 -0700258 this.$store
259 .dispatch('sslCertificates/addNewCertificate', { file, type })
260 .then(success => this.successToast(success))
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700261 .catch(({ message }) => this.errorToast(message))
262 .finally(() => this.endLoader());
Yoshie Muranaka37393812020-03-24 15:25:24 -0700263 },
264 replaceCertificate(file, type, location) {
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700265 this.startLoader();
Yoshie Muranaka37393812020-03-24 15:25:24 -0700266 const reader = new FileReader();
267 reader.readAsBinaryString(file);
268 reader.onloadend = event => {
269 const certificateString = event.target.result;
270 this.$store
271 .dispatch('sslCertificates/replaceCertificate', {
272 certificateString,
273 type,
274 location
275 })
276 .then(success => this.successToast(success))
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700277 .catch(({ message }) => this.errorToast(message))
278 .finally(() => this.endLoader());
Yoshie Muranaka37393812020-03-24 15:25:24 -0700279 };
280 },
281 deleteCertificate({ type, location }) {
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700282 this.startLoader();
Yoshie Muranaka37393812020-03-24 15:25:24 -0700283 this.$store
284 .dispatch('sslCertificates/deleteCertificate', {
285 type,
286 location
287 })
288 .then(success => this.successToast(success))
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700289 .catch(({ message }) => this.errorToast(message))
290 .finally(() => this.endLoader());
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700291 },
292 getDaysUntilExpired(date) {
293 if (this.bmcTime) {
294 const validUntilMs = date.getTime();
295 const currentBmcTimeMs = this.bmcTime.getTime();
296 const oneDayInMs = 24 * 60 * 60 * 1000;
297 return Math.round((validUntilMs - currentBmcTimeMs) / oneDayInMs);
298 }
Yoshie Muranakae5be9ba2020-04-30 10:13:40 -0700299 return new Date();
Yoshie Muranakae45f54b2020-03-26 15:23:34 -0700300 },
301 getIconStatus(date) {
302 const daysUntilExpired = this.getDaysUntilExpired(date);
303 if (daysUntilExpired < 1) {
304 return 'danger';
305 } else if (daysUntilExpired < 31) {
306 return 'warning';
307 }
Yoshie Muranaka37393812020-03-24 15:25:24 -0700308 }
309 }
310};
311</script>