1<template> 2 <b-modal id="modal-user" ref="modal" @hidden="resetForm"> 3 <template #modal-title> 4 <template v-if="newUser"> 5 {{ $t('pageUserManagement.addUser') }} 6 </template> 7 <template v-else> 8 {{ $t('pageUserManagement.editUser') }} 9 </template> 10 </template> 11 <b-form id="form-user" novalidate @submit.prevent="handleSubmit"> 12 <b-container> 13 <!-- Manual unlock form control --> 14 <b-row v-if="!newUser && manualUnlockPolicy && user.Locked"> 15 <b-col sm="9"> 16 <alert :show="true" variant="warning" small> 17 <template v-if="!v$.form.manualUnlock.$dirty"> 18 {{ $t('pageUserManagement.modal.accountLocked') }} 19 </template> 20 <template v-else> 21 {{ $t('pageUserManagement.modal.clickSaveToUnlockAccount') }} 22 </template> 23 </alert> 24 </b-col> 25 <b-col sm="3"> 26 <input 27 v-model="form.manualUnlock" 28 data-test-id="userManagement-input-manualUnlock" 29 type="hidden" 30 /> 31 <b-button 32 variant="primary" 33 :disabled="v$.form.manualUnlock.$dirty" 34 data-test-id="userManagement-button-manualUnlock" 35 @click="v$.form.manualUnlock.$touch()" 36 > 37 {{ $t('pageUserManagement.modal.unlock') }} 38 </b-button> 39 </b-col> 40 </b-row> 41 <b-row> 42 <b-col> 43 <b-form-group :label="$t('pageUserManagement.modal.accountStatus')"> 44 <b-form-radio 45 v-model="form.status" 46 name="user-status" 47 :value="true" 48 data-test-id="userManagement-radioButton-statusEnabled" 49 @input="v$.form.status.$touch()" 50 > 51 {{ $t('global.status.enabled') }} 52 </b-form-radio> 53 <b-form-radio 54 v-model="form.status" 55 name="user-status" 56 data-test-id="userManagement-radioButton-statusDisabled" 57 :value="false" 58 :disabled="!newUser && originalUsername === disabled" 59 @input="v$.form.status.$touch()" 60 > 61 {{ $t('global.status.disabled') }} 62 </b-form-radio> 63 </b-form-group> 64 <b-form-group 65 :label="$t('pageUserManagement.modal.username')" 66 label-for="username" 67 > 68 <b-form-text id="username-help-block"> 69 {{ $t('pageUserManagement.modal.cannotStartWithANumber') }} 70 <br /> 71 {{ 72 $t( 73 'pageUserManagement.modal.noSpecialCharactersExceptUnderscore', 74 ) 75 }} 76 </b-form-text> 77 <b-form-input 78 id="username" 79 v-model="form.username" 80 type="text" 81 aria-describedby="username-help-block" 82 data-test-id="userManagement-input-username" 83 :state="getValidationState(v$.form.username)" 84 :disabled="!newUser && originalUsername === disabled" 85 @input="v$.form.username.$touch()" 86 /> 87 <b-form-invalid-feedback role="alert"> 88 <template v-if="v$.form.username.required.$invalid"> 89 {{ $t('global.form.fieldRequired') }} 90 </template> 91 <template v-else-if="v$.form.username.maxLength.$invalid"> 92 {{ 93 $t('global.form.lengthMustBeBetween', { min: 1, max: 16 }) 94 }} 95 </template> 96 <template v-else-if="v$.form.username.pattern.$invalid"> 97 {{ $t('global.form.invalidFormat') }} 98 </template> 99 </b-form-invalid-feedback> 100 </b-form-group> 101 <b-form-group 102 :label="$t('pageUserManagement.modal.privilege')" 103 label-for="privilege" 104 > 105 <b-form-select 106 id="privilege" 107 v-model="form.privilege" 108 :options="privilegeTypes" 109 data-test-id="userManagement-select-privilege" 110 :state="getValidationState(v$.form.privilege)" 111 :disabled="!newUser && originalUsername === 'root'" 112 @input="v$.form.privilege.$touch()" 113 > 114 <template #first> 115 <b-form-select-option :value="null" disabled> 116 {{ $t('global.form.selectAnOption') }} 117 </b-form-select-option> 118 </template> 119 </b-form-select> 120 <b-form-invalid-feedback role="alert"> 121 <template v-if="v$.form.privilege.required.$invalid"> 122 {{ $t('global.form.fieldRequired') }} 123 </template> 124 </b-form-invalid-feedback> 125 </b-form-group> 126 </b-col> 127 <b-col> 128 <b-form-group 129 :label="$t('pageUserManagement.modal.userPassword')" 130 label-for="password" 131 > 132 <b-form-text id="password-help-block"> 133 {{ 134 $t('pageUserManagement.modal.passwordMustBeBetween', { 135 min: passwordRequirements.minLength, 136 max: passwordRequirements.maxLength, 137 }) 138 }} 139 </b-form-text> 140 <input-password-toggle> 141 <b-form-input 142 id="password" 143 v-model="form.password" 144 type="password" 145 data-test-id="userManagement-input-password" 146 aria-describedby="password-help-block" 147 :state="getValidationState(v$.form.password)" 148 class="form-control-with-button" 149 @input="v$.form.password.$touch()" 150 /> 151 <b-form-invalid-feedback role="alert"> 152 <template v-if="v$.form.password.required.$invalid"> 153 {{ $t('global.form.fieldRequired') }} 154 </template> 155 <template 156 v-if=" 157 v$.form.password.minLength.$invalid || 158 v$.form.password.maxLength.$invalid 159 " 160 > 161 {{ 162 $t('pageUserManagement.modal.passwordMustBeBetween', { 163 min: passwordRequirements.minLength, 164 max: passwordRequirements.maxLength, 165 }) 166 }} 167 </template> 168 </b-form-invalid-feedback> 169 </input-password-toggle> 170 </b-form-group> 171 <b-form-group 172 :label="$t('pageUserManagement.modal.confirmUserPassword')" 173 label-for="password-confirmation" 174 > 175 <input-password-toggle> 176 <b-form-input 177 id="password-confirmation" 178 v-model="form.passwordConfirmation" 179 data-test-id="userManagement-input-passwordConfirmation" 180 type="password" 181 :state="getValidationState(v$.form.passwordConfirmation)" 182 class="form-control-with-button" 183 @input="v$.form.passwordConfirmation.$touch()" 184 /> 185 <b-form-invalid-feedback role="alert"> 186 <template 187 v-if="v$.form.passwordConfirmation.required.$invalid" 188 > 189 {{ $t('global.form.fieldRequired') }} 190 </template> 191 <template 192 v-else-if=" 193 v$.form.passwordConfirmation.sameAsPassword.$invalid 194 " 195 > 196 {{ $t('pageUserManagement.modal.passwordsDoNotMatch') }} 197 </template> 198 </b-form-invalid-feedback> 199 </input-password-toggle> 200 </b-form-group> 201 </b-col> 202 </b-row> 203 </b-container> 204 </b-form> 205 <template #modal-footer="{ cancel }"> 206 <b-button 207 variant="secondary" 208 data-test-id="userManagement-button-cancel" 209 @click="cancel()" 210 > 211 {{ $t('global.action.cancel') }} 212 </b-button> 213 <b-button 214 form="form-user" 215 data-test-id="userManagement-button-submit" 216 type="submit" 217 variant="primary" 218 @click="onOk" 219 > 220 <template v-if="newUser"> 221 {{ $t('pageUserManagement.addUser') }} 222 </template> 223 <template v-else> 224 {{ $t('global.action.save') }} 225 </template> 226 </b-button> 227 </template> 228 </b-modal> 229</template> 230 231<script> 232import { 233 required, 234 maxLength, 235 minLength, 236 requiredIf, 237} from '@vuelidate/validators'; 238import { helpers, sameAs } from 'vuelidate/lib/validators'; 239import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; 240import { useVuelidate } from '@vuelidate/core'; 241 242import InputPasswordToggle from '@/components/Global/InputPasswordToggle'; 243import Alert from '@/components/Global/Alert'; 244import { useI18n } from 'vue-i18n'; 245 246export default { 247 components: { Alert, InputPasswordToggle }, 248 mixins: [VuelidateMixin], 249 props: { 250 user: { 251 type: Object, 252 default: null, 253 }, 254 passwordRequirements: { 255 type: Object, 256 required: true, 257 }, 258 }, 259 setup() { 260 return { 261 v$: useVuelidate(), 262 }; 263 }, 264 data() { 265 return { 266 $t: useI18n().t, 267 originalUsername: '', 268 form: { 269 status: true, 270 username: '', 271 privilege: null, 272 password: '', 273 passwordConfirmation: '', 274 manualUnlock: false, 275 }, 276 disabled: this.$store.getters['global/username'], 277 }; 278 }, 279 computed: { 280 newUser() { 281 return this.user ? false : true; 282 }, 283 accountSettings() { 284 return this.$store.getters['userManagement/accountSettings']; 285 }, 286 manualUnlockPolicy() { 287 return !this.accountSettings.accountLockoutDuration; 288 }, 289 privilegeTypes() { 290 return this.$store.getters['userManagement/accountRoles']; 291 }, 292 }, 293 watch: { 294 user: function (value) { 295 if (value === null) return; 296 this.originalUsername = value.username; 297 this.form.username = value.username; 298 this.form.status = value.Enabled; 299 this.form.privilege = value.privilege; 300 }, 301 }, 302 validations() { 303 return { 304 form: { 305 status: { 306 required, 307 }, 308 username: { 309 required, 310 maxLength: maxLength(16), 311 pattern: helpers.regex('pattern', /^([a-zA-Z_][a-zA-Z0-9_]*)/), 312 }, 313 privilege: { 314 required, 315 }, 316 password: { 317 required: requiredIf(function () { 318 return this.requirePassword(); 319 }), 320 minLength: minLength(this.passwordRequirements.minLength), 321 maxLength: maxLength(this.passwordRequirements.maxLength), 322 }, 323 passwordConfirmation: { 324 required: requiredIf(function () { 325 return this.requirePassword(); 326 }), 327 sameAsPassword: sameAs('password'), 328 }, 329 manualUnlock: {}, 330 }, 331 }; 332 }, 333 methods: { 334 handleSubmit() { 335 let userData = {}; 336 337 if (this.newUser) { 338 this.v$.$touch(); 339 if (this.v$.$invalid) return; 340 userData.username = this.form.username; 341 userData.status = this.form.status; 342 userData.privilege = this.form.privilege; 343 userData.password = this.form.password; 344 } else { 345 if (this.v$.$invalid) return; 346 userData.originalUsername = this.originalUsername; 347 if (this.v$.form.status.$dirty) { 348 userData.status = this.form.status; 349 } 350 if (this.v$.form.username.$dirty) { 351 userData.username = this.form.username; 352 } 353 if (this.v$.form.privilege.$dirty) { 354 userData.privilege = this.form.privilege; 355 } 356 if (this.v$.form.password.$dirty) { 357 userData.password = this.form.password; 358 } 359 if (this.v$.form.manualUnlock.$dirty) { 360 // If form manualUnlock control $dirty then 361 // set user Locked property to false 362 userData.locked = false; 363 } 364 if (Object.entries(userData).length === 1) { 365 this.closeModal(); 366 return; 367 } 368 } 369 370 this.$emit('ok', { isNewUser: this.newUser, userData }); 371 this.closeModal(); 372 }, 373 closeModal() { 374 this.$nextTick(() => { 375 this.$refs.modal.hide(); 376 }); 377 }, 378 resetForm() { 379 this.form.originalUsername = ''; 380 this.form.status = true; 381 this.form.username = ''; 382 this.form.privilege = null; 383 this.form.password = ''; 384 this.form.passwordConfirmation = ''; 385 this.v$.$reset(); 386 this.$emit('hidden'); 387 }, 388 requirePassword() { 389 if (this.newUser) return true; 390 if (this.v$.form.password.$dirty) return true; 391 if (this.v$.form.passwordConfirmation.$dirty) return true; 392 return false; 393 }, 394 onOk(bvModalEvt) { 395 // prevent modal close 396 bvModalEvt.preventDefault(); 397 this.handleSubmit(); 398 }, 399 }, 400}; 401</script> 402