1<template> 2 <b-container fluid="xl"> 3 <page-title :description="$t('pageLdap.pageDescription')" /> 4 <page-section :section-title="$t('pageLdap.settings')"> 5 <b-form novalidate @submit.prevent="handleSubmit"> 6 <b-row> 7 <b-col> 8 <b-form-group 9 class="mb-3" 10 :label="$t('pageLdap.form.ldapAuthentication')" 11 :disabled="loading" 12 > 13 <b-form-checkbox 14 v-model="form.ldapAuthenticationEnabled" 15 data-test-id="ldap-checkbox-ldapAuthenticationEnabled" 16 @change="onChangeldapAuthenticationEnabled" 17 > 18 {{ $t('global.action.enable') }} 19 </b-form-checkbox> 20 </b-form-group> 21 </b-col> 22 </b-row> 23 <div class="form-background p-3"> 24 <b-form-group 25 class="m-0" 26 :label="$t('pageLdap.ariaLabel.ldapSettings')" 27 label-class="sr-only" 28 :disabled="!form.ldapAuthenticationEnabled || loading" 29 > 30 <b-row> 31 <b-col md="3" lg="4" xl="3"> 32 <b-form-group 33 class="mb-4" 34 :label="$t('pageLdap.form.secureLdapUsingSsl')" 35 > 36 <b-form-text id="enable-secure-help-block"> 37 {{ $t('pageLdap.form.secureLdapHelper') }} 38 </b-form-text> 39 <b-form-checkbox 40 id="enable-secure-ldap" 41 v-model="form.secureLdapEnabled" 42 aria-describedby="enable-secure-help-block" 43 data-test-id="ldap-checkbox-secureLdapEnabled" 44 :disabled=" 45 !caCertificateExpiration || !ldapCertificateExpiration 46 " 47 @change="$v.form.secureLdapEnabled.$touch()" 48 > 49 {{ $t('global.action.enable') }} 50 </b-form-checkbox> 51 </b-form-group> 52 <dl> 53 <dt>{{ $t('pageLdap.form.caCertificateValidUntil') }}</dt> 54 <dd v-if="caCertificateExpiration"> 55 {{ caCertificateExpiration | formatDate }} 56 </dd> 57 <dd v-else>--</dd> 58 <dt>{{ $t('pageLdap.form.ldapCertificateValidUntil') }}</dt> 59 <dd v-if="ldapCertificateExpiration"> 60 {{ ldapCertificateExpiration | formatDate }} 61 </dd> 62 <dd v-else>--</dd> 63 </dl> 64 <b-link 65 class="d-inline-block mb-4 m-md-0" 66 to="/security-and-access/certificates" 67 > 68 {{ $t('pageLdap.form.manageSslCertificates') }} 69 </b-link> 70 </b-col> 71 <b-col md="9" lg="8" xl="9"> 72 <b-row> 73 <b-col> 74 <b-form-group :label="$t('pageLdap.form.serviceType')"> 75 <b-form-radio 76 v-model="form.activeDirectoryEnabled" 77 data-test-id="ldap-radio-activeDirectoryEnabled" 78 :value="false" 79 @change="onChangeServiceType" 80 > 81 {{ $t('pageLdap.form.openLDAP') }} 82 </b-form-radio> 83 <b-form-radio 84 v-model="form.activeDirectoryEnabled" 85 data-test-id="ldap-radio-activeDirectoryEnabled" 86 :value="true" 87 @change="onChangeServiceType" 88 > 89 {{ $t('pageLdap.form.activeDirectory') }} 90 </b-form-radio> 91 </b-form-group> 92 </b-col> 93 </b-row> 94 <b-row> 95 <b-col sm="6" xl="4"> 96 <b-form-group label-for="server-uri"> 97 <template #label> 98 {{ $t('pageLdap.form.serverUri') }} 99 <info-tooltip 100 :title="$t('pageLdap.form.serverUriTooltip')" 101 /> 102 </template> 103 <b-input-group :prepend="ldapProtocol"> 104 <b-form-input 105 id="server-uri" 106 v-model="form.serverUri" 107 data-test-id="ldap-input-serverUri" 108 :state="getValidationState($v.form.serverUri)" 109 @change="$v.form.serverUri.$touch()" 110 /> 111 <b-form-invalid-feedback role="alert"> 112 {{ $t('global.form.fieldRequired') }} 113 </b-form-invalid-feedback> 114 </b-input-group> 115 </b-form-group> 116 </b-col> 117 <b-col sm="6" xl="4"> 118 <b-form-group 119 :label="$t('pageLdap.form.bindDn')" 120 label-for="bind-dn" 121 > 122 <b-form-input 123 id="bind-dn" 124 v-model="form.bindDn" 125 data-test-id="ldap-input-bindDn" 126 :state="getValidationState($v.form.bindDn)" 127 @change="$v.form.bindDn.$touch()" 128 /> 129 <b-form-invalid-feedback role="alert"> 130 {{ $t('global.form.fieldRequired') }} 131 </b-form-invalid-feedback> 132 </b-form-group> 133 </b-col> 134 <b-col sm="6" xl="4"> 135 <b-form-group 136 :label="$t('pageLdap.form.bindPassword')" 137 label-for="bind-password" 138 > 139 <input-password-toggle 140 data-test-id="ldap-input-togglePassword" 141 > 142 <b-form-input 143 id="bind-password" 144 v-model="form.bindPassword" 145 type="password" 146 :state="getValidationState($v.form.bindPassword)" 147 class="form-control-with-button" 148 @change="$v.form.bindPassword.$touch()" 149 /> 150 <b-form-invalid-feedback role="alert"> 151 {{ $t('global.form.fieldRequired') }} 152 </b-form-invalid-feedback> 153 </input-password-toggle> 154 </b-form-group> 155 </b-col> 156 <b-col sm="6" xl="4"> 157 <b-form-group 158 :label="$t('pageLdap.form.baseDn')" 159 label-for="base-dn" 160 > 161 <b-form-input 162 id="base-dn" 163 v-model="form.baseDn" 164 data-test-id="ldap-input-baseDn" 165 :state="getValidationState($v.form.baseDn)" 166 @change="$v.form.baseDn.$touch()" 167 /> 168 <b-form-invalid-feedback role="alert"> 169 {{ $t('global.form.fieldRequired') }} 170 </b-form-invalid-feedback> 171 </b-form-group> 172 </b-col> 173 <b-col sm="6" xl="4"> 174 <b-form-group label-for="user-id-attribute"> 175 <template #label> 176 {{ $t('pageLdap.form.userIdAttribute') }} - 177 <span class="form-text d-inline"> 178 {{ $t('global.form.optional') }} 179 </span> 180 </template> 181 <b-form-input 182 id="user-id-attribute" 183 v-model="form.userIdAttribute" 184 data-test-id="ldap-input-userIdAttribute" 185 @change="$v.form.userIdAttribute.$touch()" 186 /> 187 </b-form-group> 188 </b-col> 189 <b-col sm="6" xl="4"> 190 <b-form-group label-for="group-id-attribute"> 191 <template #label> 192 {{ $t('pageLdap.form.groupIdAttribute') }} - 193 <span class="form-text d-inline"> 194 {{ $t('global.form.optional') }} 195 </span> 196 </template> 197 <b-form-input 198 id="group-id-attribute" 199 v-model="form.groupIdAttribute" 200 data-test-id="ldap-input-groupIdAttribute" 201 @change="$v.form.groupIdAttribute.$touch()" 202 /> 203 </b-form-group> 204 </b-col> 205 </b-row> 206 </b-col> 207 </b-row> 208 </b-form-group> 209 </div> 210 <b-row class="mt-4 mb-5"> 211 <b-col> 212 <b-btn 213 variant="primary" 214 type="submit" 215 data-test-id="ldap-button-saveSettings" 216 :disabled="loading" 217 > 218 {{ $t('global.action.saveSettings') }} 219 </b-btn> 220 </b-col> 221 </b-row> 222 </b-form> 223 </page-section> 224 225 <!-- Role groups --> 226 <page-section :section-title="$t('pageLdap.roleGroups')"> 227 <table-role-groups /> 228 </page-section> 229 </b-container> 230</template> 231 232<script> 233import { mapGetters } from 'vuex'; 234import { find } from 'lodash'; 235import { requiredIf } from 'vuelidate/lib/validators'; 236 237import BVToastMixin from '@/components/Mixins/BVToastMixin'; 238import VuelidateMixin from '@/components/Mixins/VuelidateMixin'; 239import LoadingBarMixin, { loading } from '@/components/Mixins/LoadingBarMixin'; 240import InputPasswordToggle from '@/components/Global/InputPasswordToggle'; 241import PageTitle from '@/components/Global/PageTitle'; 242import PageSection from '@/components/Global/PageSection'; 243import InfoTooltip from '@/components/Global/InfoTooltip'; 244import TableRoleGroups from './TableRoleGroups'; 245 246export default { 247 name: 'Ldap', 248 components: { 249 InfoTooltip, 250 InputPasswordToggle, 251 PageTitle, 252 PageSection, 253 TableRoleGroups, 254 }, 255 mixins: [BVToastMixin, VuelidateMixin, LoadingBarMixin], 256 beforeRouteLeave(to, from, next) { 257 this.hideLoader(); 258 next(); 259 }, 260 data() { 261 return { 262 form: { 263 ldapAuthenticationEnabled: this.$store.getters['ldap/isServiceEnabled'], 264 secureLdapEnabled: false, 265 activeDirectoryEnabled: 266 this.$store.getters['ldap/isActiveDirectoryEnabled'], 267 serverUri: '', 268 bindDn: '', 269 bindPassword: '', 270 baseDn: '', 271 userIdAttribute: '', 272 groupIdAttribute: '', 273 loading, 274 }, 275 }; 276 }, 277 computed: { 278 ...mapGetters('ldap', [ 279 'isServiceEnabled', 280 'isActiveDirectoryEnabled', 281 'ldap', 282 'activeDirectory', 283 ]), 284 sslCertificates() { 285 return this.$store.getters['certificates/allCertificates']; 286 }, 287 caCertificateExpiration() { 288 const caCertificate = find(this.sslCertificates, { 289 type: 'TrustStore Certificate', 290 }); 291 if (caCertificate === undefined) return null; 292 return caCertificate.validUntil; 293 }, 294 ldapCertificateExpiration() { 295 const ldapCertificate = find(this.sslCertificates, { 296 type: 'LDAP Certificate', 297 }); 298 if (ldapCertificate === undefined) return null; 299 return ldapCertificate.validUntil; 300 }, 301 ldapProtocol() { 302 return this.form.secureLdapEnabled ? 'ldaps://' : 'ldap://'; 303 }, 304 }, 305 watch: { 306 isServiceEnabled: function (value) { 307 this.form.ldapAuthenticationEnabled = value; 308 }, 309 isActiveDirectoryEnabled: function (value) { 310 this.form.activeDirectoryEnabled = value; 311 this.setFormValues(); 312 }, 313 }, 314 validations: { 315 form: { 316 ldapAuthenticationEnabled: {}, 317 secureLdapEnabled: {}, 318 activeDirectoryEnabled: { 319 required: requiredIf(function () { 320 return this.form.ldapAuthenticationEnabled; 321 }), 322 }, 323 serverUri: { 324 required: requiredIf(function () { 325 return this.form.ldapAuthenticationEnabled; 326 }), 327 }, 328 bindDn: { 329 required: requiredIf(function () { 330 return this.form.ldapAuthenticationEnabled; 331 }), 332 }, 333 bindPassword: { 334 required: requiredIf(function () { 335 return this.form.ldapAuthenticationEnabled; 336 }), 337 }, 338 baseDn: { 339 required: requiredIf(function () { 340 return this.form.ldapAuthenticationEnabled; 341 }), 342 }, 343 userIdAttribute: {}, 344 groupIdAttribute: {}, 345 }, 346 }, 347 created() { 348 this.startLoader(); 349 this.$store 350 .dispatch('ldap/getAccountSettings') 351 .finally(() => this.endLoader()); 352 this.$store 353 .dispatch('certificates/getCertificates') 354 .finally(() => this.endLoader()); 355 this.setFormValues(); 356 }, 357 methods: { 358 setFormValues(serviceType) { 359 if (!serviceType) { 360 serviceType = this.isActiveDirectoryEnabled 361 ? this.activeDirectory 362 : this.ldap; 363 } 364 const { 365 serviceAddress = '', 366 bindDn = '', 367 baseDn = '', 368 userAttribute = '', 369 groupsAttribute = '', 370 } = serviceType; 371 const secureLdap = 372 serviceAddress && serviceAddress.includes('ldaps://') ? true : false; 373 const serverUri = serviceAddress 374 ? serviceAddress.replace(/ldaps?:\/\//, '') 375 : ''; 376 this.form.secureLdapEnabled = secureLdap; 377 this.form.serverUri = serverUri; 378 this.form.bindDn = bindDn; 379 this.form.bindPassword = ''; 380 this.form.baseDn = baseDn; 381 this.form.userIdAttribute = userAttribute; 382 this.form.groupIdAttribute = groupsAttribute; 383 }, 384 handleSubmit() { 385 this.$v.$touch(); 386 if (this.$v.$invalid) return; 387 const data = { 388 serviceEnabled: this.form.ldapAuthenticationEnabled, 389 activeDirectoryEnabled: this.form.activeDirectoryEnabled, 390 serviceAddress: `${this.ldapProtocol}${this.form.serverUri}`, 391 bindDn: this.form.bindDn, 392 bindPassword: this.form.bindPassword, 393 baseDn: this.form.baseDn, 394 userIdAttribute: this.form.userIdAttribute, 395 groupIdAttribute: this.form.groupIdAttribute, 396 }; 397 this.startLoader(); 398 this.$store 399 .dispatch('ldap/saveAccountSettings', data) 400 .then((success) => { 401 this.successToast(success); 402 }) 403 .catch(({ message }) => { 404 this.errorToast(message); 405 }) 406 .finally(() => { 407 this.form.bindPassword = ''; 408 this.$v.form.$reset(); 409 this.endLoader(); 410 }); 411 }, 412 onChangeServiceType(isActiveDirectoryEnabled) { 413 this.$v.form.activeDirectoryEnabled.$touch(); 414 const serviceType = isActiveDirectoryEnabled 415 ? this.activeDirectory 416 : this.ldap; 417 // Set form values according to user selected 418 // service type 419 this.setFormValues(serviceType); 420 }, 421 onChangeldapAuthenticationEnabled(isServiceEnabled) { 422 this.$v.form.ldapAuthenticationEnabled.$touch(); 423 if (!isServiceEnabled) { 424 // Request will fail if sent with empty values. 425 // The frontend only checks for required fields 426 // when the service is enabled. This is to prevent 427 // an error if a user clears any properties then 428 // disables the service. 429 this.setFormValues(); 430 } 431 }, 432 }, 433}; 434</script> 435