From 52b0223005c91dc95f82ef0752ea2f3ae50788e6 Mon Sep 17 00:00:00 2001 From: Yoshie Muranaka Date: Thu, 20 Feb 2020 08:00:45 -0800 Subject: Add password requirements to local user page - Make api call to get user account settings - Update add/edit user form to include dynamic password requirement values - Fix edit username bug by adding input listener to field that sets form control to $dirty state and adds property to PATCH request Signed-off-by: Yoshie Muranaka Change-Id: I3535f4214ee12c95d5e502134bf3e36597d2421a --- .../AccessControl/LocalUserMangementStore.js | 44 ++++++++++++- .../LocalUserManagement/LocalUserManagement.vue | 19 +++++- .../LocalUserManagement/ModalSettings.vue | 4 +- .../LocalUserManagement/ModalUser.vue | 76 +++++++++++++--------- 4 files changed, 107 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/store/modules/AccessControl/LocalUserMangementStore.js b/src/store/modules/AccessControl/LocalUserMangementStore.js index eb5822e1..67c3a1e4 100644 --- a/src/store/modules/AccessControl/LocalUserMangementStore.js +++ b/src/store/modules/AccessControl/LocalUserMangementStore.js @@ -19,16 +19,44 @@ const getResponseCount = responses => { const LocalUserManagementStore = { namespaced: true, state: { - allUsers: [] + allUsers: [], + accountLockoutDuration: null, + accountLockoutThreshold: null, + accountMinPasswordLength: null, + accountMaxPasswordLength: null }, getters: { allUsers(state) { return state.allUsers; + }, + accountSettings(state) { + return { + lockoutDuration: state.accountLockoutDuration, + lockoutThreshold: state.accountLockoutThreshold + }; + }, + accountPasswordRequirements(state) { + return { + minLength: state.accountMinPasswordLength, + maxLength: state.accountMaxPasswordLength + }; } }, mutations: { setUsers(state, allUsers) { state.allUsers = allUsers; + }, + setLockoutDuration(state, lockoutDuration) { + state.accountLockoutDuration = lockoutDuration; + }, + setLockoutThreshold(state, lockoutThreshold) { + state.accountLockoutThreshold = lockoutThreshold; + }, + setAccountMinPasswordLength(state, minPasswordLength) { + state.accountMinPasswordLength = minPasswordLength; + }, + setAccountMaxPasswordLength(state, maxPasswordLength) { + state.accountMaxPasswordLength = maxPasswordLength; } }, actions: { @@ -46,6 +74,20 @@ const LocalUserManagementStore = { throw new Error('Error loading local users.'); }); }, + getAccountSettings({ commit }) { + api + .get('/redfish/v1/AccountService') + .then(({ data }) => { + commit('setLockoutDuration', data.AccountLockoutDuration); + commit('setLockoutThreshold', data.AccountLockoutThreshold); + commit('setAccountMinPasswordLength', data.MinPasswordLength); + commit('setAccountMaxPasswordLength', data.MaxPasswordLength); + }) + .catch(error => { + console.log(error); + throw new Error('Error loading account settings.'); + }); + }, async createUser({ dispatch }, { username, password, privilege, status }) { const data = { UserName: username, diff --git a/src/views/AccessControl/LocalUserManagement/LocalUserManagement.vue b/src/views/AccessControl/LocalUserManagement/LocalUserManagement.vue index 8797da77..97b00e49 100644 --- a/src/views/AccessControl/LocalUserManagement/LocalUserManagement.vue +++ b/src/views/AccessControl/LocalUserManagement/LocalUserManagement.vue @@ -75,8 +75,12 @@ - - + + @@ -116,7 +120,6 @@ export default { data() { return { activeUser: null, - settings: null, fields: [ { key: 'checkbox', @@ -174,15 +177,25 @@ export default { ...user }; }); + }, + settings() { + return this.$store.getters['localUsers/accountSettings']; + }, + passwordRequirements() { + return this.$store.getters['localUsers/accountPasswordRequirements']; } }, created() { this.getUsers(); + this.getAccountSettings(); }, methods: { getUsers() { this.$store.dispatch('localUsers/getUsers'); }, + getAccountSettings() { + this.$store.dispatch('localUsers/getAccountSettings'); + }, initModalUser(user) { this.activeUser = user; this.$bvModal.show('modal-user'); diff --git a/src/views/AccessControl/LocalUserManagement/ModalSettings.vue b/src/views/AccessControl/LocalUserManagement/ModalSettings.vue index a0d62941..afe2d95e 100644 --- a/src/views/AccessControl/LocalUserManagement/ModalSettings.vue +++ b/src/views/AccessControl/LocalUserManagement/ModalSettings.vue @@ -6,8 +6,8 @@ export default { props: { settings: { - type: String, - default: '' + type: Object, + required: true } } }; diff --git a/src/views/AccessControl/LocalUserManagement/ModalUser.vue b/src/views/AccessControl/LocalUserManagement/ModalUser.vue index 448276b5..4a6a0bcf 100644 --- a/src/views/AccessControl/LocalUserManagement/ModalUser.vue +++ b/src/views/AccessControl/LocalUserManagement/ModalUser.vue @@ -43,6 +43,7 @@ aria-describedby="username-help-block" :state="getValidationState($v.form.username)" :disabled="!newUser && originalUsername === 'root'" + @input="$v.form.username.$touch()" /> @@ -158,6 +168,10 @@ export default { user: { type: Object, default: null + }, + passwordRequirements: { + type: Object, + required: true } }, data() { @@ -187,33 +201,35 @@ export default { this.form.privilege = value.privilege; } }, - validations: { - form: { - status: { - required - }, - username: { - required, - maxLength: maxLength(16), - pattern: helpers.regex('pattern', /^([a-zA-Z_][a-zA-Z0-9_]*)/) - }, - privilege: { - required - }, - password: { - required: requiredIf(function() { - return this.requirePassword(); - }), - minLength: minLength(8), //TODO: Update to dynamic backend values - maxLength: maxLength(20) //TODO: UPdate to dynamic backend values - }, - passwordConfirmation: { - required: requiredIf(function() { - return this.requirePassword(); - }), - sameAsPassword: sameAs('password') + validations() { + return { + form: { + status: { + required + }, + username: { + required, + maxLength: maxLength(16), + pattern: helpers.regex('pattern', /^([a-zA-Z_][a-zA-Z0-9_]*)/) + }, + privilege: { + required + }, + password: { + required: requiredIf(function() { + return this.requirePassword(); + }), + minLength: minLength(this.passwordRequirements.minLength), + maxLength: maxLength(this.passwordRequirements.maxLength) + }, + passwordConfirmation: { + required: requiredIf(function() { + return this.requirePassword(); + }), + sameAsPassword: sameAs('password') + } } - } + }; }, methods: { handleSubmit() { -- cgit v1.2.3