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 }} 56 </dd> 57 <dd v-else>--</dd> 58 <dt>{{ $t('pageLdap.form.ldapCertificateValidUntil') }}</dt> 59 <dd v-if="ldapCertificateExpiration"> 60 {{ ldapCertificateExpiration }} 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/validators'; 236import { useVuelidate } from '@vuelidate/core'; 237 238import BVToastMixin from '@/components/Mixins/BVToastMixin'; 239import VuelidateMixin from '@/components/Mixins/VuelidateMixin'; 240import LoadingBarMixin, { loading } from '@/components/Mixins/LoadingBarMixin'; 241import InputPasswordToggle from '@/components/Global/InputPasswordToggle'; 242import PageTitle from '@/components/Global/PageTitle'; 243import PageSection from '@/components/Global/PageSection'; 244import InfoTooltip from '@/components/Global/InfoTooltip'; 245import TableRoleGroups from './TableRoleGroups'; 246 247export default { 248 name: 'Ldap', 249 components: { 250 InfoTooltip, 251 InputPasswordToggle, 252 PageTitle, 253 PageSection, 254 TableRoleGroups, 255 }, 256 mixins: [BVToastMixin, VuelidateMixin, LoadingBarMixin], 257 beforeRouteLeave(to, from, next) { 258 this.hideLoader(); 259 next(); 260 }, 261 setup() { 262 return { 263 v$: useVuelidate(), 264 }; 265 }, 266 data() { 267 return { 268 form: { 269 ldapAuthenticationEnabled: this.$store.getters['ldap/isServiceEnabled'], 270 secureLdapEnabled: false, 271 activeDirectoryEnabled: 272 this.$store.getters['ldap/isActiveDirectoryEnabled'], 273 serverUri: '', 274 bindDn: '', 275 bindPassword: '', 276 baseDn: '', 277 userIdAttribute: '', 278 groupIdAttribute: '', 279 loading, 280 }, 281 }; 282 }, 283 computed: { 284 ...mapGetters('ldap', [ 285 'isServiceEnabled', 286 'isActiveDirectoryEnabled', 287 'ldap', 288 'activeDirectory', 289 ]), 290 sslCertificates() { 291 return this.$store.getters['certificates/allCertificates']; 292 }, 293 caCertificateExpiration() { 294 const caCertificate = find(this.sslCertificates, { 295 type: 'TrustStore Certificate', 296 }); 297 if (caCertificate === undefined) return null; 298 return caCertificate.validUntil; 299 }, 300 ldapCertificateExpiration() { 301 const ldapCertificate = find(this.sslCertificates, { 302 type: 'LDAP Certificate', 303 }); 304 if (ldapCertificate === undefined) return null; 305 return ldapCertificate.validUntil; 306 }, 307 ldapProtocol() { 308 return this.form.secureLdapEnabled ? 'ldaps://' : 'ldap://'; 309 }, 310 }, 311 watch: { 312 isServiceEnabled: function (value) { 313 this.form.ldapAuthenticationEnabled = value; 314 }, 315 isActiveDirectoryEnabled: function (value) { 316 this.form.activeDirectoryEnabled = value; 317 this.setFormValues(); 318 }, 319 }, 320 validations: { 321 form: { 322 ldapAuthenticationEnabled: {}, 323 secureLdapEnabled: {}, 324 activeDirectoryEnabled: { 325 required: requiredIf(function () { 326 return this.form.ldapAuthenticationEnabled; 327 }), 328 }, 329 serverUri: { 330 required: requiredIf(function () { 331 return this.form.ldapAuthenticationEnabled; 332 }), 333 }, 334 bindDn: { 335 required: requiredIf(function () { 336 return this.form.ldapAuthenticationEnabled; 337 }), 338 }, 339 bindPassword: { 340 required: requiredIf(function () { 341 return this.form.ldapAuthenticationEnabled; 342 }), 343 }, 344 baseDn: { 345 required: requiredIf(function () { 346 return this.form.ldapAuthenticationEnabled; 347 }), 348 }, 349 userIdAttribute: {}, 350 groupIdAttribute: {}, 351 }, 352 }, 353 created() { 354 this.startLoader(); 355 this.$store 356 .dispatch('ldap/getAccountSettings') 357 .finally(() => this.endLoader()); 358 this.$store 359 .dispatch('certificates/getCertificates') 360 .finally(() => this.endLoader()); 361 this.setFormValues(); 362 }, 363 methods: { 364 setFormValues(serviceType) { 365 if (!serviceType) { 366 serviceType = this.isActiveDirectoryEnabled 367 ? this.activeDirectory 368 : this.ldap; 369 } 370 const { 371 serviceAddress = '', 372 bindDn = '', 373 baseDn = '', 374 userAttribute = '', 375 groupsAttribute = '', 376 } = serviceType; 377 const secureLdap = 378 serviceAddress && serviceAddress.includes('ldaps://') ? true : false; 379 const serverUri = serviceAddress 380 ? serviceAddress.replace(/ldaps?:\/\//, '') 381 : ''; 382 this.form.secureLdapEnabled = secureLdap; 383 this.form.serverUri = serverUri; 384 this.form.bindDn = bindDn; 385 this.form.bindPassword = ''; 386 this.form.baseDn = baseDn; 387 this.form.userIdAttribute = userAttribute; 388 this.form.groupIdAttribute = groupsAttribute; 389 }, 390 handleSubmit() { 391 this.$v.$touch(); 392 if (this.$v.$invalid) return; 393 const data = { 394 serviceEnabled: this.form.ldapAuthenticationEnabled, 395 activeDirectoryEnabled: this.form.activeDirectoryEnabled, 396 serviceAddress: `${this.ldapProtocol}${this.form.serverUri}`, 397 bindDn: this.form.bindDn, 398 bindPassword: this.form.bindPassword, 399 baseDn: this.form.baseDn, 400 userIdAttribute: this.form.userIdAttribute, 401 groupIdAttribute: this.form.groupIdAttribute, 402 }; 403 this.startLoader(); 404 this.$store 405 .dispatch('ldap/saveAccountSettings', data) 406 .then((success) => { 407 this.successToast(success); 408 }) 409 .catch(({ message }) => { 410 this.errorToast(message); 411 }) 412 .finally(() => { 413 this.form.bindPassword = ''; 414 this.$v.form.$reset(); 415 this.endLoader(); 416 }); 417 }, 418 onChangeServiceType(isActiveDirectoryEnabled) { 419 this.$v.form.activeDirectoryEnabled.$touch(); 420 const serviceType = isActiveDirectoryEnabled 421 ? this.activeDirectory 422 : this.ldap; 423 // Set form values according to user selected 424 // service type 425 this.setFormValues(serviceType); 426 }, 427 onChangeldapAuthenticationEnabled(isServiceEnabled) { 428 this.$v.form.ldapAuthenticationEnabled.$touch(); 429 if (!isServiceEnabled) { 430 // Request will fail if sent with empty values. 431 // The frontend only checks for required fields 432 // when the service is enabled. This is to prevent 433 // an error if a user clears any properties then 434 // disables the service. 435 this.setFormValues(); 436 } 437 }, 438 }, 439}; 440</script> 441