21
21
-->
22
22
23
23
<template>
24
- <div>
24
+ <div class="certificate-settings" >
25
25
<NcSelect v-model="alias"
26
+ class="certificate-settings__alias"
26
27
:options="aliases"
27
28
:searchable="false"
28
29
:placeholder="t('mail', 'Select an alias')"
31
32
@input="savedCertificate = null" />
32
33
<NcSelect v-if="alias !== null"
33
34
v-model="savedCertificate"
35
+ class="certificate-settings__certificate"
34
36
:options="smimeCertOptions"
35
37
:aria-label-combobox="t('mail', 'Select certificates')"
36
38
:searchable="false" />
37
- <ButtonVue type="primary"
39
+ <NcButton type="primary"
40
+ class="certificate-settings__submit"
38
41
:disabled="certificate === null"
39
42
:aria-label="t('mail', 'Update Certificate')"
40
43
@click="updateSmimeCertificate">
41
44
{{ t('mail', 'Update Certificate') }}
42
- </ButtonVue>
45
+ </NcButton>
46
+ <NcNoteCard v-if="alias && !savedCertificate.isChainVerified"
47
+ type="warning">
48
+ <p>{{ t('mail', 'The selected certificate is not trusted by the server. Recipients might not be able to verify your signature.') }}</p>
49
+ </NcNoteCard>
43
50
</div>
44
51
</template>
45
52
46
53
<script>
47
- import { NcSelect, NcButton as ButtonVue } from '@nextcloud/vue'
54
+ import { NcSelect, NcButton, NcNoteCard } from '@nextcloud/vue'
48
55
import { compareSmimeCertificates } from '../util/smime.js'
49
56
import { mapGetters } from 'vuex'
50
57
import { showError, showSuccess } from '@nextcloud/dialogs'
51
58
import Logger from '../logger.js'
52
59
import moment from '@nextcloud/moment'
53
60
61
+ const noCertificateOption = () => ({
62
+ label: t('mail', 'No certificate'),
63
+ isChainVerified: true,
64
+ })
65
+
54
66
export default {
55
67
name: 'CertificateSettings',
56
68
components: {
57
69
NcSelect,
58
- ButtonVue,
70
+ NcButton,
71
+ NcNoteCard,
59
72
},
60
73
props: {
61
74
account: {
@@ -79,7 +92,7 @@ export default {
79
92
return this.certificate
80
93
}
81
94
const saved = this.smimeCertOptions.find(certificate => this.alias.smimeCertificateId === certificate.id)
82
- return saved || { label: t('mail', 'No certificate') }
95
+ return saved || noCertificateOption()
83
96
},
84
97
set(newVal) {
85
98
this.certificate = newVal
@@ -116,13 +129,13 @@ export default {
116
129
return cert.hasKey
117
130
&& cert.emailAddress === this.alias.alias
118
131
&& cert.info.notAfter >= now
119
- && cert.purposes.sign
120
- && cert.purposes.encrypt
132
+ && cert.info. purposes.sign
133
+ && cert.info. purposes.encrypt
121
134
// TODO: select a separate certificate for encryption?!
122
135
})
123
136
.map(this.mapCertificateToOption)
124
137
.sort(compareSmimeCertificates)
125
- certs.push({ label: t('mail', 'No certificate') } )
138
+ certs.push(noCertificateOption() )
126
139
127
140
return certs
128
141
},
@@ -169,19 +182,37 @@ export default {
169
182
commonName: cert.info.commonName ?? cert.info.emailAddress,
170
183
expiryDate: moment.unix(cert.info.notAfter).format('LL'),
171
184
})
172
- return { ...cert, label }
185
+ return {
186
+ ...cert,
187
+ label,
188
+ isChainVerified: cert.info.isChainVerified,
189
+ }
173
190
},
174
191
},
175
192
}
176
193
</script>
177
194
178
195
<style lang="scss" scoped>
179
- .multiselect--single {
180
- width: 100%;
181
- margin-bottom: 4px;
182
- }
196
+ .certificate-settings {
197
+ &__alias,
198
+ &__certificate {
199
+ width: 100%;
200
+ }
201
+
202
+ &__alias + &__certificate {
203
+ margin-top: 5px
204
+ }
205
+
206
+ &__submit {
207
+ margin-top: 1rem;
208
+ }
183
209
184
- .button-vue {
185
- margin-top: 4px !important;
210
+ &__warning {
211
+ display: flex;
212
+ align-items: center;
213
+ margin-top: 10px;
214
+ gap: 10px;
215
+ color: var(--color-warning-text);
216
+ }
186
217
}
187
218
</style>
0 commit comments