From 0a505f965168617515269553682fee32a32d3b17 Mon Sep 17 00:00:00 2001 From: Chelsea Shaw <82459713+hashishaw@users.noreply.github.com> Date: Mon, 22 Apr 2024 12:13:53 -0500 Subject: [PATCH] Update userpass validations to handle password_hash (#26577) * Update userpass validations to handle password_hash * Add changelog --- changelog/26577.txt | 3 ++ ui/app/components/generated-item.js | 29 ++++++++++++------- ui/app/services/path-help.js | 24 ++++++++------- .../templates/components/generated-item.hbs | 7 +---- 4 files changed, 37 insertions(+), 26 deletions(-) create mode 100644 changelog/26577.txt diff --git a/changelog/26577.txt b/changelog/26577.txt new file mode 100644 index 0000000000..8293f5403f --- /dev/null +++ b/changelog/26577.txt @@ -0,0 +1,3 @@ +```release-note:improvement +ui: Update userpass user form to allow setting `password_hash` field. +``` \ No newline at end of file diff --git a/ui/app/components/generated-item.js b/ui/app/components/generated-item.js index 4b10a55afc..83af3dfcdd 100644 --- a/ui/app/components/generated-item.js +++ b/ui/app/components/generated-item.js @@ -35,8 +35,27 @@ export default Component.extend({ props: computed('model', function () { return this.model.serialize(); }), + validateForm() { + // Only validate on new models because blank passwords will not be updated + // in practice this only happens for userpass users + if (this.model.validate && this.model.isNew) { + const { isValid, state } = this.model.validate(); + this.setProperties({ + modelValidations: state, + isFormInvalid: !isValid, + }); + return isValid; + } else { + this.set('isFormInvalid', false); + return true; + } + }, saveModel: task( waitFor(function* () { + const isValid = this.validateForm(); + if (!isValid) { + return; + } try { yield this.model.save(); } catch (err) { @@ -71,16 +90,6 @@ export default Component.extend({ actions: { onKeyUp(name, value) { this.model.set(name, value); - if (this.model.validate) { - // Set validation error message for updated attribute - const { isValid, state } = this.model.validate(); - this.setProperties({ - modelValidations: state, - isFormInvalid: !isValid, - }); - } else { - this.set('isFormInvalid', false); - } }, deleteItem() { this.model.destroyRecord().then(() => { diff --git a/ui/app/services/path-help.js b/ui/app/services/path-help.js index 81c48031d9..c686ce583d 100644 --- a/ui/app/services/path-help.js +++ b/ui/app/services/path-help.js @@ -27,6 +27,7 @@ import { pathToHelpUrlSegment, reducePathsByPathName, } from 'vault/utils/openapi-helpers'; +import { isPresent } from '@ember/utils'; export default class PathHelpService extends Service { @service store; @@ -272,16 +273,19 @@ export default class PathHelpService extends Service { // Build and add validations on model // NOTE: For initial phase, initialize validations only for user pass auth if (backend === 'userpass') { - const validations = fieldGroups.reduce((obj, element) => { - if (element.default) { - element.default.forEach((v) => { - const key = v.options.fieldValue || v.name; - obj[key] = [{ type: 'presence', message: `${v.name} can't be blank` }]; - }); - } - return obj; - }, {}); - + const validations = { + password: [ + { + validator(model) { + return ( + !(isPresent(model.password) && isPresent(model.passwordHash)) && + (isPresent(model.password) || isPresent(model.passwordHash)) + ); + }, + message: 'You must provide either password or password hash, but not both.', + }, + ], + }; newModel = withModelValidations(validations)(class GeneratedItemModel extends newModel {}); } } diff --git a/ui/app/templates/components/generated-item.hbs b/ui/app/templates/components/generated-item.hbs index 60cf6bfa06..785e3b4a85 100644 --- a/ui/app/templates/components/generated-item.hbs +++ b/ui/app/templates/components/generated-item.hbs @@ -59,12 +59,7 @@