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