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