xref: /openbmc/webui-vue/src/views/SecurityAndAccess/Certificates/ModalUploadCertificate.vue (revision d36ac8a8be8636ddd0e64ce005d507b21bcdeb00)
1<template>
2  <b-modal
3    id="upload-certificate"
4    ref="modal"
5    :title="modalTitle"
6    @ok="onOk"
7    @hidden="resetForm"
8  >
9    <b-form>
10      <!-- Replace Certificate type -->
11      <template v-if="certificate !== null">
12        <dl class="mb-4">
13          <dt>{{ i18n.t('pageCertificates.modal.certificateType') }}</dt>
14          <dd>{{ certificate.certificate }}</dd>
15        </dl>
16      </template>
17
18      <!-- Add new Certificate type -->
19      <template v-else>
20        <b-form-group
21          :label="i18n.t('pageCertificates.modal.certificateType')"
22          label-for="certificate-type"
23        >
24          <b-form-select
25            id="certificate-type"
26            v-model="form.certificateType"
27            :options="certificateOptions"
28            :state="getValidationState(v$.form.certificateType)"
29            @input="v$.form.certificateType.$touch()"
30          >
31          </b-form-select>
32          <b-form-invalid-feedback role="alert">
33            <template v-if="v$.form.certificateType.required.$invalid">
34              {{ i18n.t('global.form.fieldRequired') }}
35            </template>
36          </b-form-invalid-feedback>
37        </b-form-group>
38      </template>
39
40      <b-form-group :label="i18n.t('pageCertificates.modal.certificateFile')">
41        <form-file
42          id="certificate-file"
43          v-model="form.file"
44          accept=".pem"
45          :state="getValidationState(v$.form.file)"
46        >
47          <template #invalid>
48            <b-form-invalid-feedback role="alert">
49              {{ i18n.t('global.form.required') }}
50            </b-form-invalid-feedback>
51          </template>
52        </form-file>
53      </b-form-group>
54    </b-form>
55    <template #modal-ok>
56      <template v-if="certificate">
57        {{ i18n.t('global.action.replace') }}
58      </template>
59      <template v-else>
60        {{ i18n.t('global.action.add') }}
61      </template>
62    </template>
63    <template #modal-cancel>
64      {{ i18n.t('global.action.cancel') }}
65    </template>
66  </b-modal>
67</template>
68
69<script>
70import { required, requiredIf } from '@vuelidate/validators';
71import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js';
72import { useVuelidate } from '@vuelidate/core';
73
74import FormFile from '@/components/Global/FormFile';
75import { useI18n } from 'vue-i18n';
76
77export default {
78  components: { FormFile },
79  mixins: [VuelidateMixin],
80  props: {
81    certificate: {
82      type: Object,
83      default: null,
84      validator: (prop) => {
85        if (prop === null) return true;
86        return (
87          Object.prototype.hasOwnProperty.call(prop, 'type') &&
88          Object.prototype.hasOwnProperty.call(prop, 'certificate')
89        );
90      },
91    },
92  },
93  emits: ['ok'],
94  setup() {
95    const i18n = useI18n();
96    return {
97      v$: useVuelidate(),
98      i18n,
99    };
100  },
101  data() {
102    return {
103      form: {
104        certificateType: null,
105        file: null,
106      },
107    };
108  },
109  computed: {
110    modalTitle() {
111      return this.certificate
112        ? this.i18n.t('pageCertificates.replaceCertificate')
113        : this.i18n.t('pageCertificates.addNewCertificate');
114    },
115    certificateTypes() {
116      return this.$store.getters['certificates/availableUploadTypes'];
117    },
118    certificateOptions() {
119      return this.certificateTypes.map(({ type, label }) => {
120        return {
121          text: label,
122          value: type,
123        };
124      });
125    },
126  },
127  watch: {
128    certificateOptions: function (options) {
129      if (options.length) {
130        this.form.certificateType = options[0].value;
131      }
132    },
133  },
134  validations() {
135    return {
136      form: {
137        certificateType: {
138          required: requiredIf(function () {
139            return !this.certificate;
140          }),
141        },
142        file: {
143          required,
144        },
145      },
146    };
147  },
148  methods: {
149    handleSubmit() {
150      this.v$.$touch();
151      if (this.v$.$invalid) return;
152      this.$emit('ok', {
153        addNew: !this.certificate,
154        file: this.form.file,
155        location: this.certificate ? this.certificate.location : null,
156        type: this.certificate
157          ? this.certificate.type
158          : this.form.certificateType,
159      });
160      this.closeModal();
161    },
162    closeModal() {
163      this.$nextTick(() => {
164        this.$refs.modal.hide();
165      });
166    },
167    resetForm() {
168      this.form.certificateType = this.certificateOptions.length
169        ? this.certificateOptions[0].value
170        : null;
171      this.form.file = null;
172      this.v$.$reset();
173    },
174    onOk(bvModalEvt) {
175      // prevent modal close
176      bvModalEvt.preventDefault();
177      this.handleSubmit();
178    },
179  },
180};
181</script>
182