From 0b26b1a6057166d34055a405eaf33792c29761cf Mon Sep 17 00:00:00 2001 From: Angel Garbarino Date: Tue, 12 Apr 2022 13:59:34 -0600 Subject: [PATCH] Ember upgrade to 3.28.6 (#14763) * initial upgrade running ember-cli-update --to 3.28 * bumps node-sass version * fragments bump * fixes overriding errors prop on policy model causing issues * bumps some addon versions related to Ember Global deprecation warning on build * bumps back ember-test-selectors version for now * removes ember-promise-helpers addon and creates await helper * upgrades ember-template-lint and adds prettier plugin * Ember 3.28 Upgrade Lint Fixes (#14890) * fixes js lint errors * fixes hbs lint errors * allow multiple node versions for now to get tests runinng * fixes tests * Upgrade ember-test-selectors (#14937) * updates ember-test-selectors, ember-cli-page-object and ember-cli-string-helpers * adds attributeBindings to classic components with data-test property * glimmerizes toolbar-link component and removes data-test args * glimmerizes toolbar-secret-link and secret-link components and removes data-test and class args * glimmerizes linked-block component * glimmerizes toggle-button component * updates toggle-button test * fixes remaining test selector issues * comments out test assertions related to cp-validations bug * adds todo to comment * Model Validations (#14991) * adds model-validations decorator and validators util * converts key-mixin to decorator * updates models to use validations decorator instead of ember-cp-validations * updates invocation of model validations * removes ember-cp-validations * reverts secret-v2 model updates * adds initials to TODO comment * flight-icons (#14993) * flight-icons * basic dropdown * UI/merge main (#14997) * Vault documentation: changing references from learn to tutorial (#14844) * changed learn to tutorial references * changed learn to tutorial * Update website/content/docs/plugins/plugin-portal.mdx Co-authored-by: Yoko Hyakuna * Update website/content/docs/platform/aws/run.mdx Co-authored-by: Yoko Hyakuna Co-authored-by: Yoko Hyakuna * UI/Only show form values if have read access (#14794) * only show value in edit form if has read capabilities * revert messing with form * delete secret data from secret * add check for selected version * remove added line * add changelog * modified text (#14854) * fixed a link issue (#14850) * docs: add known issue to 1.10 release notes (#14859) * Vault 3999 Change permissions for directory/archive created by debug command (#14846) * adding debug changes from ent * adding changelog * Vault 3992 ToB Config and Plugins Permissions (#14817) * updating changes from ent PR * adding changelog * fixing err * fixing semgrep error * updated references from learn to tutorial (#14866) * updated references from learn to tutorial (#14867) * changed reference from learn to tutorial (#14868) * Fix handling of default zero SignatureBits value with Any key type in PKI Secrets Engine (#14875) * Correctly handle minimums, default SignatureBits When using KeyType = "any" on a role (whether explicitly or implicitly via a sign-verbatim like operation), we need to update the value of SignatureBits from its new value 0 to a per-key-type default value. This will allow sign operations on these paths to function correctly, having the correctly inferred default signature bit length. Additionally, this allows the computed default value for key type to be used for minimum size validation in the RSA/ECDSA paths. We additionally enforce the 2048-minimum in this case as well. Signed-off-by: Alexander Scheel * Fix defaults and validation of "any" KeyType When certutil is given the placeholder any keytype, it attempts to validate and update the default zero value. However, in lacking a default value for SignatureBits, it cannot update the value from the zero value, thus causing validation to fail. Add more awareness to the placeholder "any" value to certutil. Signed-off-by: Alexander Scheel * Add role-based regression tests for key bits This adds regression tests for Key Type, Key Bits, and Signature Bits parameters on the role. We test several values, including the "any" value to ensure it correctly restricts key sizes. Signed-off-by: Alexander Scheel * Add sign-verbatim test for key type This ensures that we test sign-verbatim against a variety of key types. Signed-off-by: Alexander Scheel * Add changelog entry Signed-off-by: Alexander Scheel Co-authored-by: Steven Clark * Subtle docs change for allow_store_key (#14889) * Subtle docs change for allow_store_key * errant space * Adds Vault version prerelease and metadata to logical.PluginEnvironment (#14851) * docs: fix formatting on plugin upgrade page (#14874) * docs: fix formatting on plugin upgrade page * fix more formatting issues * Update CC docs (#14714) * Update CC docs * Add sample response * Address review feedback * Update website/content/api-docs/system/internal-counters.mdx Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> * Update website/content/api-docs/system/internal-counters.mdx Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> * Update website/content/api-docs/system/internal-counters.mdx Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> * Update website/content/api-docs/system/internal-counters.mdx Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> * Update website/content/api-docs/system/internal-counters.mdx Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> * Update website/content/api-docs/system/internal-counters.mdx Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> * Update website/content/api-docs/system/internal-counters.mdx Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> * Update website/content/api-docs/system/internal-counters.mdx Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> * Update website/content/api-docs/system/internal-counters.mdx Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> * Update website/content/api-docs/system/internal-counters.mdx Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> * Update website/content/api-docs/system/internal-counters.mdx Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> * Update website/content/api-docs/system/internal-counters.mdx Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> * Update website/content/api-docs/system/internal-counters.mdx Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> * Update website/content/api-docs/system/internal-counters.mdx Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> * Update website/content/api-docs/system/internal-counters.mdx Co-authored-by: Meggie * Update website/content/api-docs/system/internal-counters.mdx Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> * Update website/content/api-docs/system/internal-counters.mdx Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> * Minor edits * Update partial month API Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> Co-authored-by: Meggie * Docs improvements for Managed Keys (#14756) * Add more color around managed keys in their concepts page, and create additional links between the various docs pages related to them. * Typos * sdk/useragent: plugin version string consistent with Vault version string (#14912) * clean up (#14911) * website: fix usages of img tag (#14910) * fix usages of img tag and integrate dev-portal workflows * Adjust Makefile * remove mount_accessor from the docs (#14927) * Add extra test coverage to PKI (#14767) * Add PKI test for delete role - Create a role, validate that defaults are what we expect and delete the role, verifying it is gone on subsequent read attempts. * Add PKI test for crl/rotate command - Missing a unit test that validates the crl/rotate command works. The test validates the rotate command was successful by checking if we have a different/new update time on the CRL. * Rework PKI TestBackend_PathFetchValidRaw test to not write directly to storage - Rework the existing test to not write directly to storage as we might change that in the future. - Add tests that validate the ca_chain behaviour of not returning the root authority cert * PR Feedback * Additional PR feedback * Use WriteWithContext in auth helpers (#14775) * Add ability to pass certificate PEM bytes to vault/api (#14753) * Respect increment value in grace period calculations (api/LifetimeWatcher) (#14836) * Mount flag syntax to mitigate confusion from KV-v2 path discrepancies (#14807) * Add explanation to help text and flag usage text * KV get with new mount flag * Clearer naming * KV Put, Patch, Metadata Get + corresponding tests * KV Delete, Destroy, Rollback, Undelete, MetadataDelete, MetadataPatch, MetadataPut * Update KV-v2 docs to use mount flag syntax * Add changelog * Run make fmt * Clarify deprecation message in help string * Address style comments * Update vault-plugin-auth-gcp to newest pseudo-version (#14923) * docs: added hello-vault-spring repo link to developer-qs.mdx. (#14928) * Update developer-qs.mdx docs: added link to Java / Spring Boot sample app repo in developer quick start. * removed space. * trigger ci Co-authored-by: taoism4504 * OIDC Login Bug (#14916) * fixes issue logging in with oidc from listed auth path tab * adds changelog entry * adds more tests for oidc auth workflow * updates oidc auth method test to use non-standard path * Fix handling of SignatureBits for ECDSA issuers (#14943) When adding SignatureBits control logic, we incorrectly allowed specification of SignatureBits in the case of an ECDSA issuer. As noted in the original request, NIST and Mozilla (and others) are fairly prescriptive in the choice of signatures (matching the size of the NIST P-curve), and we shouldn't usually use a smaller (or worse, larger and truncate!) hash. Ignore the configuration of signature bits and always use autodetection for ECDSA like ed25519. Signed-off-by: Alexander Scheel * Bug Fix and Glimmerize secret-edit component (#14941) * inital glimmerize * wip * wip * wip * fix maybeQueryRecord * fix * fix * fix test * cleanup * add changelog * clean up * Agent error log level is mismatched (#14424) * [VAULT-1618] Agent error log level is mismatched `logLevelToStringPtr` translates `go-hclog`'s `ERROR` to `"ERROR"` for Consul Template's runner, but that expects `ERR` and is quite strict about it. This will address https://github.com/hashicorp/vault-k8s/issues/223 after it is set as the default image in `vault-k8s`. I didn't find a simple way to test this other than starting up a full server and agent and letting them run, which is unfortunately fairly slow. I confirmed that this addresses the original issue by modifying the helm chart with the values in this commit and patching the log level to `err`. * VAULT-1618 Add changelog/14424.txt * VAULT-1618 Update changelog/14424.txt based on @kalafut suggestion Co-authored-by: Jim Kalafut * VAULT-1618 Move cancel and server stop into defer in tests * VAULT-1618 Triggering CircleCI tests * VAULT-1618 Replace ioutil with os functions for agent template tests Co-authored-by: Jim Kalafut * UI/Add months to activity serializer (#14942) * add mock monthly data to mirage handler * add months to serializer for activity response * change selectors Co-authored-by: Chelsea Shaw <82459713+hashishaw@users.noreply.github.com> * clean up serializer * please stop being flakey <3 Co-authored-by: Chelsea Shaw <82459713+hashishaw@users.noreply.github.com> * Revert the WithContext changes to vault tests (#14947) * adding env var (#14958) * Fix dead link for JWT supported algorithms (#14953) * Don't clone OutputCurlString value (#14968) * Don't clone OutputCurlString value, add flag to docs * Add changelog * Ensure initialMmapSize is 0 on Windows (#14977) * ensure initialMmapSize is 0 on windows * add changelog * Vault 3992 documentation changes (#14918) * doc changes * adding config changes * adding chnages to plugins * using include * making doc changes * adding newline * aws auth displayName (#14954) * set displayName to include RoleSessionName * Add Windows error (#14982) * Warnings indicating ignored and replaced parameters (#14962) * Warnings indicating ignored and replaced parameters * Avoid additional var creation * Add warnings only if the response is non-nil * Return the response even when error is non-nil * Fix tests * Rearrange comments * Print warning in the log * Fix another test * Add CL * Fix edit capabilities call in auth method (#14966) * Fix edit capabilities call in auth method - Capabilities call was not getting triggered correctly as apiPath method was missing the correct context. * Added changelog * make linting fix Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> Co-authored-by: Yoko Hyakuna Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com> Co-authored-by: Austin Gebauer <34121980+austingebauer@users.noreply.github.com> Co-authored-by: akshya96 <87045294+akshya96@users.noreply.github.com> Co-authored-by: Alexander Scheel Co-authored-by: Steven Clark Co-authored-by: Scott Miller Co-authored-by: John-Michael Faircloth Co-authored-by: Vishal Nayak Co-authored-by: Meggie Co-authored-by: Bryce Kalow Co-authored-by: Josh Black Co-authored-by: Anton Averchenkov <84287187+averche@users.noreply.github.com> Co-authored-by: VAL Co-authored-by: Robert <17119716+robmonte@users.noreply.github.com> Co-authored-by: mryan-hashi <88851444+mryan-hashi@users.noreply.github.com> Co-authored-by: taoism4504 Co-authored-by: Jordan Reimer Co-authored-by: Christopher Swenson Co-authored-by: Jim Kalafut Co-authored-by: Chelsea Shaw <82459713+hashishaw@users.noreply.github.com> Co-authored-by: Tom Proctor Co-authored-by: Jose Estrada Co-authored-by: Arnav Palnitkar * skips kmip tests with concurrency issues for now * changelog * skips another test * Remove ModelWrap Component (#15001) * removes ModelWrap component which was not working in Ember 3.28 * removes kmip test skips * updates role controller class name * adds annotations to model-validations file * pr feedback * lint fixes after main merge Co-authored-by: Jordan Reimer Co-authored-by: Loann Le <84412881+taoism4504@users.noreply.github.com> Co-authored-by: Yoko Hyakuna Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com> Co-authored-by: Austin Gebauer <34121980+austingebauer@users.noreply.github.com> Co-authored-by: akshya96 <87045294+akshya96@users.noreply.github.com> Co-authored-by: Alexander Scheel Co-authored-by: Steven Clark Co-authored-by: Scott Miller Co-authored-by: John-Michael Faircloth Co-authored-by: Vishal Nayak Co-authored-by: Meggie Co-authored-by: Bryce Kalow Co-authored-by: Josh Black Co-authored-by: Anton Averchenkov <84287187+averche@users.noreply.github.com> Co-authored-by: VAL Co-authored-by: Robert <17119716+robmonte@users.noreply.github.com> Co-authored-by: mryan-hashi <88851444+mryan-hashi@users.noreply.github.com> Co-authored-by: taoism4504 Co-authored-by: Christopher Swenson Co-authored-by: Jim Kalafut Co-authored-by: Chelsea Shaw <82459713+hashishaw@users.noreply.github.com> Co-authored-by: Tom Proctor Co-authored-by: Jose Estrada Co-authored-by: Arnav Palnitkar --- changelog/14763.txt | 3 + ui/.eslintignore | 1 + ui/.eslintrc.js | 24 +- ui/.template-lintrc.js | 40 +- ui/app/components/b64-toggle.js | 2 +- ui/app/components/console/log-json.js | 1 + ui/app/components/console/log-text.js | 1 + ui/app/components/console/output-log.js | 1 + ui/app/components/console/ui-panel.js | 1 + ui/app/components/generated-item.js | 16 +- ui/app/components/hover-copy-button.js | 1 + ui/app/components/identity/edit-form.js | 1 + ui/app/components/mount-backend-form.js | 25 +- ui/app/components/nav-header.js | 1 + ui/app/components/pgp-file.js | 1 + ui/app/components/radial-progress.js | 2 +- ui/app/components/regex-validator.hbs | 2 +- ui/app/components/secret-edit-metadata.js | 8 +- ui/app/components/secret-link.js | 42 +- ui/app/components/toolbar-secret-link.js | 21 +- ui/app/decorators/model-validations.js | 94 + ui/app/helpers/await.js | 31 + ui/app/mixins/policy-edit-controller.js | 5 +- ui/app/models/auth-method.js | 22 +- ui/app/models/policy.js | 1 - ui/app/models/secret-engine.js | 31 +- ui/app/models/secret-v2.js | 26 +- .../vault/cluster/secrets/backend/list.js | 4 +- ui/app/services/path-help.js | 16 +- ui/app/templates/components/alert-popup.hbs | 2 +- ui/app/templates/components/alphabet-edit.hbs | 4 +- .../components/auth-config-form/config.hbs | 2 +- .../components/auth-config-form/options.hbs | 2 +- .../components/auth-form-options.hbs | 2 +- ui/app/templates/components/auth-form.hbs | 2 +- ui/app/templates/components/auth-info.hbs | 4 +- ui/app/templates/components/auth-jwt.hbs | 2 +- .../templates/components/clients/history.hbs | 2 +- .../components/clients/running-total.hbs | 3 +- ui/app/templates/components/config-pki-ca.hbs | 6 +- ui/app/templates/components/config-pki.hbs | 2 +- .../components/configure-aws-secret.hbs | 2 +- .../components/configure-ssh-secret.hbs | 2 +- .../components/control-group-success.hbs | 2 +- ui/app/templates/components/control-group.hbs | 6 +- .../components/database-connection.hbs | 72 +- .../components/database-role-edit.hbs | 6 +- .../components/diff-version-selector.hbs | 2 +- .../components/form-field-groups-loop.hbs | 32 +- .../components/generate-credentials.hbs | 2 +- .../components/generated-item-list.hbs | 2 +- .../templates/components/generated-item.hbs | 4 +- .../components/identity/edit-form.hbs | 2 +- .../components/identity/entity-nav.hbs | 4 +- .../components/identity/item-aliases.hbs | 4 +- .../components/identity/item-groups.hbs | 4 +- .../components/identity/item-members.hbs | 8 +- .../identity/item-parent-groups.hbs | 4 +- .../components/identity/item-policies.hbs | 4 +- .../templates/components/kv-object-editor.hbs | 2 +- .../templates/components/license-banners.hbs | 10 +- ui/app/templates/components/mfa-form.hbs | 4 +- .../components/mount-backend-form.hbs | 2 +- .../templates/components/namespace-picker.hbs | 10 +- ui/app/templates/components/nav-header.hbs | 4 +- ui/app/templates/components/role-aws-edit.hbs | 8 +- ui/app/templates/components/role-pki-edit.hbs | 8 +- ui/app/templates/components/role-ssh-edit.hbs | 8 +- .../components/secret-create-or-update.hbs | 10 +- .../components/secret-edit-metadata.hbs | 2 +- .../components/secret-edit-toolbar.hbs | 6 +- ui/app/templates/components/secret-link.hbs | 12 +- .../components/secret-list/aws-role-item.hbs | 13 +- .../secret-list/database-list-item.hbs | 12 +- .../templates/components/secret-list/item.hbs | 28 +- .../components/secret-list/pki-cert-item.hbs | 14 +- .../components/secret-list/pki-role-item.hbs | 17 +- .../components/secret-list/ssh-role-item.hbs | 20 +- .../secret-list/transform-list-item.hbs | 21 +- .../transform-transformation-item.hbs | 21 +- .../components/secret-version-menu.hbs | 4 +- .../templates/components/selectable-card.hbs | 2 +- ui/app/templates/components/text-file.hbs | 6 +- .../components/token-expire-warning.hbs | 2 +- ui/app/templates/components/tool-hash.hbs | 2 +- ui/app/templates/components/tool-unwrap.hbs | 2 - .../components/toolbar-secret-link.hbs | 19 +- .../transform-advanced-templating.hbs | 4 +- .../components/transform-create-form.hbs | 2 +- .../components/transform-edit-form.hbs | 2 +- .../components/transform-role-edit.hbs | 4 +- .../components/transform-template-edit.hbs | 4 +- .../components/transformation-edit.hbs | 2 +- .../components/transit-form-create.hbs | 4 +- .../components/transit-form-edit.hbs | 4 +- .../components/transit-form-show.hbs | 19 +- .../components/transit-key-action/sign.hbs | 2 +- .../components/transit-key-action/verify.hbs | 4 +- ui/app/templates/components/ui-wizard.hbs | 2 +- .../templates/components/wizard-progress.hbs | 2 +- .../components/wizard/features-selection.hbs | 2 +- ui/app/templates/vault/cluster.hbs | 6 +- .../cluster/access/identity/aliases/index.hbs | 12 +- .../cluster/access/identity/aliases/show.hbs | 2 +- .../vault/cluster/access/identity/index.hbs | 12 +- .../vault/cluster/access/identity/show.hbs | 4 +- .../vault/cluster/access/method/section.hbs | 2 +- ui/app/templates/vault/cluster/init.hbs | 14 +- .../vault/cluster/policies/index.hbs | 14 +- .../templates/vault/cluster/policy/edit.hbs | 2 +- .../templates/vault/cluster/policy/show.hbs | 2 +- .../cluster/secrets/backend/configuration.hbs | 2 +- .../vault/cluster/secrets/backend/list.hbs | 9 +- .../cluster/secrets/backend/overview.hbs | 6 +- .../vault/cluster/secrets/backend/sign.hbs | 10 +- .../backend/transit-actions-layout.hbs | 6 +- .../cluster/secrets/backend/versions.hbs | 6 +- .../vault/cluster/secrets/backends.hbs | 2 +- .../vault/cluster/settings/auth/configure.hbs | 2 +- .../settings/configure-secret-backend.hbs | 2 +- ui/app/utils/build-api-validators.js | 30 - ui/app/utils/validators.js | 23 + ui/config/ember-cli-update.json | 2 +- ui/config/targets.js | 15 +- ui/lib/core/addon/components/form-field.js | 1 + .../addon/components/info-table-item-array.js | 1 + .../core/addon/components/info-table-row.hbs | 2 +- ui/lib/core/addon/components/info-tooltip.js | 1 + ui/lib/core/addon/components/linked-block.hbs | 3 + ui/lib/core/addon/components/linked-block.js | 41 +- ui/lib/core/addon/components/model-wrap.js | 37 - .../addon/components/replication-header.js | 1 + ui/lib/core/addon/components/search-select.js | 1 + ui/lib/core/addon/components/string-list.js | 1 + .../core/addon/components/toggle-button.hbs | 7 + ui/lib/core/addon/components/toggle-button.js | 54 +- ui/lib/core/addon/components/toolbar-link.hbs | 22 + ui/lib/core/addon/components/toolbar-link.js | 21 +- ui/lib/core/addon/components/ttl-picker.js | 1 + .../addon/templates/components/box-radio.hbs | 2 +- .../addon/templates/components/chevron.hbs | 2 +- .../addon/templates/components/confirm.hbs | 4 +- .../templates/components/field-group-show.hbs | 2 +- .../components/form-field-groups.hbs | 32 +- .../addon/templates/components/form-field.hbs | 4 +- .../components/form-save-buttons.hbs | 4 +- .../addon/templates/components/list-item.hbs | 2 +- .../templates/components/masked-input.hbs | 12 +- .../core/addon/templates/components/modal.hbs | 2 +- .../addon/templates/components/model-wrap.hbs | 1 - .../templates/components/navigate-input.hbs | 2 +- .../addon/templates/components/read-more.hbs | 2 +- .../components/replication-dashboard.hbs | 4 +- .../components/replication-secondary-card.hbs | 2 +- .../components/replication-summary-card.hbs | 2 +- .../addon/templates/components/select.hbs | 4 +- .../templates/components/toggle-button.hbs | 5 - .../templates/components/toolbar-link.hbs | 44 - .../templates/components/ttl-picker2.hbs | 2 +- ui/lib/core/app/components/model-wrap.js | 1 - ui/lib/core/package.json | 2 +- ui/lib/core/stories/toggle-button.md | 24 +- .../addon/controllers/credentials/show.js | 20 + ui/lib/kmip/addon/controllers/role.js | 21 + .../components/edit-form-kmip-role.hbs | 2 +- .../kmip/addon/templates/credentials/show.hbs | 31 +- ui/lib/kmip/addon/templates/role.hbs | 27 +- .../components/path-filter-config-list.js | 1 + .../components/known-secondaries-card.hbs | 2 +- .../components/path-filter-config-list.hbs | 6 +- .../components/replication-primary-card.hbs | 2 +- .../components/replication-summary.hbs | 12 +- .../mode/secondaries/config-show.hbs | 4 +- .../templates/mode/secondaries/index.hbs | 2 +- ui/package.json | 76 +- .../identity/entities/aliases/create-test.js | 2 + .../access/identity/entities/create-test.js | 2 + .../identity/groups/aliases/create-test.js | 2 + .../access/identity/groups/create-test.js | 2 + ui/tests/acceptance/access/methods-test.js | 2 +- ui/tests/acceptance/auth-list-test.js | 3 + ui/tests/acceptance/auth-test.js | 2 + ui/tests/acceptance/client-current-test.js | 5 +- ui/tests/acceptance/client-history-test.js | 5 + ui/tests/acceptance/console-test.js | 4 +- .../acceptance/enterprise-replication-test.js | 1 + ui/tests/acceptance/init-test.js | 2 + ui/tests/acceptance/mfa-test.js | 9 + ui/tests/acceptance/oidc-auth-method-test.js | 12 +- .../secrets/backend/database/secret-test.js | 1 + .../secrets/backend/kv/secret-test.js | 6 +- .../secrets/backend/pki/cert-test.js | 3 + .../secrets/backend/pki/list-test.js | 3 + .../secrets/backend/ssh/role-test.js | 3 + ui/tests/acceptance/settings-test.js | 2 +- .../settings/auth/configure/section-test.js | 2 +- .../pki/section-cert-test.js | 3 + ui/tests/acceptance/ssh-test.js | 1 + ui/tests/acceptance/tools-test.js | 2 +- ui/tests/acceptance/transit-test.js | 4 +- ui/tests/index.html | 2 +- .../auth-config-form/options-test.js | 28 +- .../integration/components/auth-form-test.js | 5 +- .../integration/components/auth-jwt-test.js | 13 +- .../components/autocomplete-input-test.js | 1 + .../components/clients/config-test.js | 21 +- .../components/control-group-success-test.js | 10 +- .../components/control-group-test.js | 10 +- .../components/date-dropdown-test.js | 23 +- .../components/edit-form-kmip-role-test.js | 6 +- .../integration/components/edit-form-test.js | 1 + .../components/features-selection-test.js | 6 +- .../integration/components/form-field-test.js | 2 +- .../integration/components/info-table-test.js | 1 + .../components/json-editor-test.js | 4 +- .../known-secondaries-table-test.js | 2 + .../integration/components/mfa-form-test.js | 2 + .../components/replication-actions-test.js | 1 + .../components/shamir-flow-test.js | 1 + .../components/shamir-modal-flow-test.js | 8 +- .../components/string-list-test.js | 11 + .../components/toggle-button-test.js | 31 +- .../components/transit-key-actions-test.js | 1 + .../components/ttl-picker2-test.js | 2 +- .../integration/helpers/add-to-array-test.js | 2 +- .../integration/helpers/date-from-now-test.js | 2 +- .../helpers/remove-from-array-test.js | 2 +- ui/tests/integration/services/auth-test.js | 20 +- .../integration/utils/field-to-attrs-test.js | 9 + ui/tests/unit/adapters/capabilities-test.js | 4 +- ui/tests/unit/adapters/cluster-test.js | 110 +- ui/tests/unit/adapters/secret-test.js | 4 +- .../unit/adapters/secret-v2-version-test.js | 43 +- ui/tests/unit/adapters/tools-test.js | 20 +- ui/tests/unit/adapters/transit-key-test.js | 4 +- .../unit/decorators/model-validations-test.js | 84 + ui/tests/unit/helpers/await-test.js | 73 + ui/tests/unit/helpers/filter-wildcard-test.js | 6 +- .../unit/helpers/is-wildcard-string-test.js | 12 +- ui/tests/unit/lib/attach-capabilities-test.js | 6 +- ui/tests/unit/lib/console-helpers-test.js | 2 +- ui/tests/unit/models/role-jwt-test.js | 2 + ui/tests/unit/models/secret-engine-test.js | 3 + .../unit/models/secret-v2-version-test.js | 6 +- ui/tests/unit/models/transit-key-test.js | 2 + ui/tests/unit/serializers/policy-test.js | 2 +- ui/tests/unit/services/console-test.js | 1 + ui/tests/unit/services/control-group-test.js | 11 +- ui/tests/unit/services/permissions-test.js | 34 +- ui/tests/unit/services/store-test.js | 2 +- ui/tests/unit/services/version-test.js | 20 +- ui/tests/unit/services/wizard-test.js | 52 +- ui/tests/unit/utils/api-path-test.js | 2 +- ui/tests/unit/utils/chart-helpers-test.js | 1 + ui/tests/unit/utils/openapi-to-attrs-test.js | 5 + ui/tests/unit/utils/validators-test.js | 51 + ui/yarn.lock | 2798 +++++++++++------ 257 files changed, 3297 insertions(+), 2064 deletions(-) create mode 100644 changelog/14763.txt create mode 100644 ui/app/decorators/model-validations.js create mode 100644 ui/app/helpers/await.js delete mode 100644 ui/app/utils/build-api-validators.js create mode 100644 ui/app/utils/validators.js create mode 100644 ui/lib/core/addon/components/linked-block.hbs delete mode 100644 ui/lib/core/addon/components/model-wrap.js create mode 100644 ui/lib/core/addon/components/toggle-button.hbs create mode 100644 ui/lib/core/addon/components/toolbar-link.hbs delete mode 100644 ui/lib/core/addon/templates/components/model-wrap.hbs delete mode 100644 ui/lib/core/addon/templates/components/toggle-button.hbs delete mode 100644 ui/lib/core/addon/templates/components/toolbar-link.hbs delete mode 100644 ui/lib/core/app/components/model-wrap.js create mode 100644 ui/lib/kmip/addon/controllers/credentials/show.js create mode 100644 ui/lib/kmip/addon/controllers/role.js create mode 100644 ui/tests/unit/decorators/model-validations-test.js create mode 100644 ui/tests/unit/helpers/await-test.js create mode 100644 ui/tests/unit/utils/validators-test.js diff --git a/changelog/14763.txt b/changelog/14763.txt new file mode 100644 index 0000000000000..8eb8ff05c7151 --- /dev/null +++ b/changelog/14763.txt @@ -0,0 +1,3 @@ +```release-note:change +ui: Upgrade Ember to version 3.28 +``` \ No newline at end of file diff --git a/ui/.eslintignore b/ui/.eslintignore index 7fc1479f0cc2e..b23faf8366fc8 100644 --- a/ui/.eslintignore +++ b/ui/.eslintignore @@ -17,6 +17,7 @@ # misc /coverage/ !.* +.*/ .eslintcache # ember-try diff --git a/ui/.eslintrc.js b/ui/.eslintrc.js index 5beeccf83a133..16b2b22d38bc5 100644 --- a/ui/.eslintrc.js +++ b/ui/.eslintrc.js @@ -32,16 +32,15 @@ module.exports = { // node files { files: [ - '.eslintrc.js', - '.prettierrc.js', - '.template-lintrc.js', - 'ember-cli-build.js', - 'testem.js', - 'blueprints/*/index.js', - 'config/**/*.js', - 'lib/*/index.js', - 'scripts/start-vault.js', - 'server/**/*.js', + './.eslintrc.js', + './.prettierrc.js', + './.template-lintrc.js', + './ember-cli-build.js', + './testem.js', + './blueprints/*/index.js', + './config/**/*.js', + './lib/*/index.js', + './server/**/*.js', ], parserOptions: { sourceType: 'script', @@ -58,5 +57,10 @@ module.exports = { 'node/no-unpublished-require': 'off', }, }, + { + // Test files: + files: ['tests/**/*-test.{js,ts}'], + extends: ['plugin:qunit/recommended'], + }, ], }; diff --git a/ui/.template-lintrc.js b/ui/.template-lintrc.js index 3b0e2a354953b..f61b165724d1b 100644 --- a/ui/.template-lintrc.js +++ b/ui/.template-lintrc.js @@ -1,14 +1,40 @@ 'use strict'; -const recommended = require('ember-template-lint/lib/config/recommended').rules; // octane extends recommended - no additions as of 3.14 -const stylistic = require('ember-template-lint/lib/config/stylistic').rules; -const testOverrides = { ...recommended, ...stylistic }; -for (const key in testOverrides) { - testOverrides[key] = false; +const fs = require('fs'); +let testOverrides = {}; +try { + // ember-template-lint no longer exports anything so we cannot access the rule definitions conventionally + // read file, convert to json string and parse + const toJSON = (str) => { + return JSON.parse( + str + .slice(str.indexOf(':') + 2) // get rid of export statement + .slice(0, -(str.length - str.lastIndexOf(','))) // remove trailing brackets from export + .replace(/:.*,/g, `: ${false},`) // convert values to false + .replace(/,([^,]*)$/, '$1') // remove last comma + .replace(/'/g, '"') // convert to double quotes + .replace(/(\w[^"].*[^"]):/g, '"$1":') // wrap quotes around single word keys + .trim() + ); + }; + const recommended = toJSON( + fs.readFileSync('node_modules/ember-template-lint/lib/config/recommended.js').toString() + ); + const stylistic = toJSON( + fs.readFileSync('node_modules/ember-template-lint/lib/config/stylistic.js').toString() + ); + testOverrides = { + ...recommended, + ...stylistic, + prettier: false, + }; +} catch (error) { + console.log(error); } module.exports = { - extends: ['octane', 'stylistic'], + plugins: ['ember-template-lint-plugin-prettier'], + extends: ['recommended', 'ember-template-lint-plugin-prettier:recommended'], rules: { 'no-bare-strings': 'off', 'no-action': 'off', @@ -22,7 +48,7 @@ module.exports = { }, ignore: ['lib/story-md', 'tests/**'], // ember language server vscode extension does not currently respect the ignore field - // override all rules manually as workround to align with cli + // override all rules manually as workaround to align with cli overrides: [ { files: ['**/*-test.js'], diff --git a/ui/app/components/b64-toggle.js b/ui/app/components/b64-toggle.js index 1db074e3e2854..0f631ba67131b 100644 --- a/ui/app/components/b64-toggle.js +++ b/ui/app/components/b64-toggle.js @@ -8,7 +8,7 @@ const B64 = 'base64'; const UTF8 = 'utf-8'; export default Component.extend({ tagName: 'button', - attributeBindings: ['type'], + attributeBindings: ['type', 'data-test-transit-b64-toggle'], type: 'button', classNames: ['button', 'b64-toggle'], classNameBindings: ['isInput:is-input:is-textarea'], diff --git a/ui/app/components/console/log-json.js b/ui/app/components/console/log-json.js index 2eef304e8dead..a176c260ede15 100644 --- a/ui/app/components/console/log-json.js +++ b/ui/app/components/console/log-json.js @@ -2,4 +2,5 @@ import Component from '@ember/component'; export default Component.extend({ 'data-test-component': 'console/log-json', + attributeBindings: ['data-test-component'], }); diff --git a/ui/app/components/console/log-text.js b/ui/app/components/console/log-text.js index 227e2c872d4ea..ebd80a51ec193 100644 --- a/ui/app/components/console/log-text.js +++ b/ui/app/components/console/log-text.js @@ -2,4 +2,5 @@ import Component from '@ember/component'; export default Component.extend({ 'data-test-component': 'console/log-text', + attributeBindings: ['data-test-component'], }); diff --git a/ui/app/components/console/output-log.js b/ui/app/components/console/output-log.js index b5f6864487a9c..c2993f582d5da 100644 --- a/ui/app/components/console/output-log.js +++ b/ui/app/components/console/output-log.js @@ -2,5 +2,6 @@ import Component from '@ember/component'; export default Component.extend({ 'data-test-component': 'console/output-log', + attributeBindings: ['data-test-component'], log: null, }); diff --git a/ui/app/components/console/ui-panel.js b/ui/app/components/console/ui-panel.js index ea52fee8ba4e8..572dec8065ea3 100644 --- a/ui/app/components/console/ui-panel.js +++ b/ui/app/components/console/ui-panel.js @@ -20,6 +20,7 @@ export default Component.extend({ controlGroup: service(), store: service(), 'data-test-component': 'console/ui-panel', + attributeBindings: ['data-test-component'], classNames: 'console-ui-panel', classNameBindings: ['isFullscreen:fullscreen'], diff --git a/ui/app/components/generated-item.js b/ui/app/components/generated-item.js index 9b82a7e8ad99c..06f17ce8b2346 100644 --- a/ui/app/components/generated-item.js +++ b/ui/app/components/generated-item.js @@ -67,16 +67,16 @@ export default Component.extend({ actions: { onKeyUp(name, value) { this.model.set(name, value); - if (this.model.validations) { + if (this.model.validate) { // Set validation error message for updated attribute - this.model.validations.attrs[name] && this.model.validations.attrs[name].isValid - ? set(this.validationMessages, name, '') - : set(this.validationMessages, name, this.model.validations.attrs[name].message); - + const { isValid, state } = this.model.validate(); + if (state[name]) { + state[name].isValid + ? set(this.validationMessages, name, '') + : set(this.validationMessages, name, state[name].errors.join('. ')); + } // Set form button state - this.model.validate().then(({ validations }) => { - this.set('isFormInvalid', !validations.isValid); - }); + this.set('isFormInvalid', !isValid); } else { this.set('isFormInvalid', false); } diff --git a/ui/app/components/hover-copy-button.js b/ui/app/components/hover-copy-button.js index 8c4f08ee37996..63a4564ab8464 100644 --- a/ui/app/components/hover-copy-button.js +++ b/ui/app/components/hover-copy-button.js @@ -2,6 +2,7 @@ import Component from '@ember/component'; export default Component.extend({ 'data-test-hover-copy': true, + attributeBindings: ['data-test-hover-copy'], classNameBindings: 'alwaysShow:hover-copy-button-static:hover-copy-button', copyValue: null, alwaysShow: false, diff --git a/ui/app/components/identity/edit-form.js b/ui/app/components/identity/edit-form.js index b4e4bfde2f1d2..ae8b6c148e9d1 100644 --- a/ui/app/components/identity/edit-form.js +++ b/ui/app/components/identity/edit-form.js @@ -8,6 +8,7 @@ import { waitFor } from '@ember/test-waiters'; export default Component.extend({ flashMessages: service(), 'data-test-component': 'identity-edit-form', + attributeBindings: ['data-test-component'], model: null, // 'create', 'edit', 'merge' diff --git a/ui/app/components/mount-backend-form.js b/ui/app/components/mount-backend-form.js index 3f874362af2a2..481fac75b8561 100644 --- a/ui/app/components/mount-backend-form.js +++ b/ui/app/components/mount-backend-form.js @@ -45,7 +45,7 @@ export default Component.extend({ showEnable: false, - // cp-validation related properties + // validation related properties validationMessages: null, isFormInvalid: false, @@ -166,27 +166,24 @@ export default Component.extend({ actions: { onKeyUp(name, value) { + this.mountModel.set(name, value); + const { + isValid, + state: { path, maxVersions }, + } = this.mountModel.validate(); // validate path if (name === 'path') { - this.mountModel.set('path', value); - this.mountModel.validations.attrs.path.isValid + path.isValid ? set(this.validationMessages, 'path', '') - : set(this.validationMessages, 'path', this.mountModel.validations.attrs.path.message); + : set(this.validationMessages, 'path', path.errors.join('. ')); } // check maxVersions is a number if (name === 'maxVersions') { - this.mountModel.set('maxVersions', value); - this.mountModel.validations.attrs.maxVersions.isValid + maxVersions.isValid ? set(this.validationMessages, 'maxVersions', '') - : set( - this.validationMessages, - 'maxVersions', - this.mountModel.validations.attrs.maxVersions.message - ); + : set(this.validationMessages, 'maxVersions', maxVersions.errors.join('. ')); } - this.mountModel.validate().then(({ validations }) => { - this.set('isFormInvalid', !validations.isValid); - }); + this.set('isFormInvalid', !isValid); }, onTypeChange(path, value) { if (path === 'type') { diff --git a/ui/app/components/nav-header.js b/ui/app/components/nav-header.js index 3726af4a3f628..7697c6fc1a0bc 100644 --- a/ui/app/components/nav-header.js +++ b/ui/app/components/nav-header.js @@ -5,6 +5,7 @@ import { computed } from '@ember/object'; export default Component.extend({ router: service(), 'data-test-navheader': true, + attributeBindings: ['data-test-navheader'], classNameBindings: 'consoleFullscreen:panel-fullscreen', tagName: 'header', navDrawerOpen: false, diff --git a/ui/app/components/pgp-file.js b/ui/app/components/pgp-file.js index e3ff786754ec6..fd1a7d1fbbe27 100644 --- a/ui/app/components/pgp-file.js +++ b/ui/app/components/pgp-file.js @@ -7,6 +7,7 @@ const BASE_64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/] export default Component.extend({ 'data-test-pgp-file': true, + attributeBindings: ['data-test-pgp-file'], classNames: ['box', 'is-fullwidth', 'is-marginless', 'is-shadowless'], key: null, index: null, diff --git a/ui/app/components/radial-progress.js b/ui/app/components/radial-progress.js index e3bec6380837a..ba2693d3cd898 100644 --- a/ui/app/components/radial-progress.js +++ b/ui/app/components/radial-progress.js @@ -5,7 +5,7 @@ export default Component.extend({ 'data-test-radial-progress': true, tagName: 'svg', classNames: 'radial-progress', - attributeBindings: ['size:width', 'size:height', 'viewBox'], + attributeBindings: ['size:width', 'size:height', 'viewBox', 'data-test-radial-progress'], progressDecimal: null, size: 20, strokeWidth: 1, diff --git a/ui/app/components/regex-validator.hbs b/ui/app/components/regex-validator.hbs index 8a6eb18c951ee..10b3a36af6149 100644 --- a/ui/app/components/regex-validator.hbs +++ b/ui/app/components/regex-validator.hbs @@ -62,7 +62,7 @@ spellcheck="false" value={{this.testValue}} {{on "change" this.updateTestValue}} - class="input {{if this.regexError "has-error"}}" + class="input {{if this.regexError 'has-error'}}" /> {{#if this.testValue}} diff --git a/ui/app/components/secret-edit-metadata.js b/ui/app/components/secret-edit-metadata.js index 88b09dfb20f43..09fe2750a1d60 100644 --- a/ui/app/components/secret-edit-metadata.js +++ b/ui/app/components/secret-edit-metadata.js @@ -54,6 +54,7 @@ export default class SecretEditMetadata extends Component { if (value) { if (name === 'customMetadata') { // cp validations won't work on an object so performing validations here + // JLR TODO: review this and incorporate into model-validations system /* eslint-disable no-useless-escape */ let regex = /^[^\\]+$/g; // looking for a backward slash value.match(regex) @@ -62,9 +63,12 @@ export default class SecretEditMetadata extends Component { } if (name === 'maxVersions') { this.args.model.maxVersions = value; - this.args.model.validations.attrs.maxVersions.isValid + const { + state: { maxVersions }, + } = this.args.model.validate(); + maxVersions.isValid ? set(this.validationMessages, name, '') - : set(this.validationMessages, name, this.args.model.validations.attrs.maxVersions.message); + : set(this.validationMessages, name, maxVersions.errors.join('. ')); } } diff --git a/ui/app/components/secret-link.js b/ui/app/components/secret-link.js index 30c516a1919c8..15a1ec41a2d2e 100644 --- a/ui/app/components/secret-link.js +++ b/ui/app/components/secret-link.js @@ -1,28 +1,26 @@ -import { computed } from '@ember/object'; -import Component from '@ember/component'; +import Component from '@glimmer/component'; +import { action } from '@ember/object'; import { encodePath } from 'vault/utils/path-encoding-helpers'; -export default Component.extend({ - onLinkClick() {}, - tagName: '', - // so that ember-test-selectors doesn't log a warning - supportsDataTestProperties: true, - mode: 'list', - - secret: null, - queryParams: null, - ariaLabel: null, - - link: computed('mode', 'secret', function () { - const route = `vault.cluster.secrets.backend.${this.mode}`; - if ((this.mode !== 'versions' && !this.secret) || this.secret === ' ') { +export default class SecretLink extends Component { + get link() { + const { mode, secret } = this.args; + const route = `vault.cluster.secrets.backend.${mode}`; + if ((mode !== 'versions' && !secret) || secret === ' ') { return { route: `${route}-root`, models: [] }; } else { - return { route, models: [encodePath(this.secret)] }; + return { route, models: [encodePath(secret)] }; } - }), - query: computed('queryParams', function () { - const qp = this.queryParams || {}; + } + get query() { + const qp = this.args.queryParams || {}; return qp.isQueryParams ? qp.values : qp; - }), -}); + } + + @action + onLinkClick() { + if (this.args.onLinkClick) { + this.args.onLinkClick(...arguments); + } + } +} diff --git a/ui/app/components/toolbar-secret-link.js b/ui/app/components/toolbar-secret-link.js index e1c6347dc02b2..44a1348ca673d 100644 --- a/ui/app/components/toolbar-secret-link.js +++ b/ui/app/components/toolbar-secret-link.js @@ -1,3 +1,4 @@ +import Component from '@glimmer/component'; /** * @module ToolbarSecretLink * `ToolbarSecretLink` styles SecretLink for the Toolbar. @@ -16,18 +17,8 @@ * * @param type="" {String} - Use "add" to change icon */ - -import OuterHTML from './outer-html'; -import { computed } from '@ember/object'; - -export default OuterHTML.extend({ - glyph: computed('type', function () { - if (this.type == 'add') { - return 'plus'; - } else { - return 'chevron-right'; - } - }), - tagName: '', - supportsDataTestProperties: true, -}); +export default class ToolbarSecretLink extends Component { + get glyph() { + return this.args.type === 'add' ? 'plus' : 'chevron-right'; + } +} diff --git a/ui/app/decorators/model-validations.js b/ui/app/decorators/model-validations.js new file mode 100644 index 0000000000000..4cf91310eeaf8 --- /dev/null +++ b/ui/app/decorators/model-validations.js @@ -0,0 +1,94 @@ +/* eslint-disable no-console */ +import validators from 'vault/utils/validators'; + +/** + * used to validate properties on a class + * + * decorator expects validations object with the following shape: + * { [propertyKeyName]: [{ type, options, message }] } + * each key in the validations object should refer to the property on the class to apply the validation to + * type refers to the type of validation to apply -- must be exported from validators util for lookup + * options is an optional object for given validator -- min, max, nullable etc. -- see validators in util + * message is added to the errors array and returned from the validate method if validation fails + * each property supports multiple validations provided as an array -- for example, presence and length for string + * + * validations must be invoked using the validate method which is added directly to the decorated class + * const { isValid, state } = this.model.validate(); + * isValid represents the validity of the full class -- if no properties provided in the validations object are invalid this will be true + * state represents the error state of the properties defined in the validations object + * const { isValid, errors } = state[propertyKeyName]; + * isValid represents the validity of the property + * errors will be populated with messages defined in the validations object when validations fail + * since a property can have multiple validations, errors is always returned as an array + * + * full example + * + * import Model from '@ember-data/model'; + * import withModelValidations from 'vault/decorators/model-validations'; + * + * const validations = { foo: [{ type: 'presence', message: 'foo is a required field' }] }; + * @withModelValidations(validations) + * class SomeModel extends Model { foo = null; } + * + * const model = new SomeModel(); + * const { isValid, state } = model.validate(); + * -> isValid = false; + * -> state.foo.isValid = false; + * -> state.foo.errors = ['foo is a required field']; + */ + +export function withModelValidations(validations) { + return function decorator(SuperClass) { + return class ModelValidations extends SuperClass { + static _validations; + + constructor() { + super(...arguments); + if (!validations || typeof validations !== 'object') { + throw new Error('Validations object must be provided to constructor for setup'); + } + this._validations = validations; + } + + validate() { + let isValid = true; + const state = {}; + + for (const key in this._validations) { + const rules = this._validations[key]; + + if (!Array.isArray(rules)) { + console.error( + `Must provide validations as an array for property "${key}" on ${this.modelName} model` + ); + continue; + } + + state[key] = { errors: [] }; + + for (const rule of rules) { + const { type, options, message } = rule; + if (!validators[type]) { + console.error( + `Validator type: "${type}" not found. Available validators: ${Object.keys(validators).join( + ', ' + )}` + ); + continue; + } + if (!validators[type](this[key], options)) { + // consider setting a prop like validationErrors directly on the model + // for now return an errors object + state[key].errors.push(message); + if (isValid) { + isValid = false; + } + } + } + state[key].isValid = !state[key].errors.length; + } + return { isValid, state }; + } + }; + }; +} diff --git a/ui/app/helpers/await.js b/ui/app/helpers/await.js new file mode 100644 index 0000000000000..711276c28a4cb --- /dev/null +++ b/ui/app/helpers/await.js @@ -0,0 +1,31 @@ +import Helper from '@ember/component/helper'; +import { Promise } from 'rsvp'; + +export default class AwaitHelper extends Helper { + compute([promise]) { + if (!promise || typeof promise.then !== 'function') { + return promise; + } + if (promise !== this.lastPromise) { + this.lastPromise = promise; + this.value = null; + this.resolve(promise); + } + return this.value; + } + async resolve(promise) { + let value; + try { + value = await Promise.resolve(promise); + } catch (error) { + value = error; + } finally { + // ensure this promise is still the newest promise + // otherwise avoid firing recompute since a newer promise is in flight + if (promise === this.lastPromise) { + this.value = value; + this.recompute(); + } + } + } +} diff --git a/ui/app/mixins/policy-edit-controller.js b/ui/app/mixins/policy-edit-controller.js index 4361bfe438b73..8f77988491016 100644 --- a/ui/app/mixins/policy-edit-controller.js +++ b/ui/app/mixins/policy-edit-controller.js @@ -36,8 +36,9 @@ export default Mixin.create({ } return this.transitionToRoute('vault.cluster.policy.show', m.get('policyType'), m.get('name')); }) - .catch((e) => { - model.set('errors', e.errors); + .catch(() => { + // swallow error -- model.errors set by Adapter + return; }); }, diff --git a/ui/app/models/auth-method.js b/ui/app/models/auth-method.js index ea73dd9031be1..a54cc80d4f020 100644 --- a/ui/app/models/auth-method.js +++ b/ui/app/models/auth-method.js @@ -1,22 +1,22 @@ import Model, { hasMany, attr } from '@ember-data/model'; -import { alias } from '@ember/object/computed'; -import { computed } from '@ember/object'; +import { alias } from '@ember/object/computed'; // eslint-disable-line +import { computed } from '@ember/object'; // eslint-disable-line import { fragment } from 'ember-data-model-fragments/attributes'; import fieldToAttrs, { expandAttributeMeta } from 'vault/utils/field-to-attrs'; import { memberAction } from 'ember-api-actions'; -import { validator, buildValidations } from 'ember-cp-validations'; - import apiPath from 'vault/utils/api-path'; import attachCapabilities from 'vault/lib/attach-capabilities'; +import { withModelValidations } from 'vault/decorators/model-validations'; -const Validations = buildValidations({ - path: validator('presence', { - presence: true, - message: "Path can't be blank.", - }), -}); +const validations = { + path: [{ type: 'presence', message: "Path can't be blank." }], +}; -let ModelExport = Model.extend(Validations, { +// unsure if ember-api-actions will work on native JS class model +// for now create class to use validations and then use classic extend pattern +@withModelValidations(validations) +class AuthMethodModel extends Model {} +const ModelExport = AuthMethodModel.extend({ authConfigs: hasMany('auth-config', { polymorphic: true, inverse: 'backend', async: false }), path: attr('string'), accessor: attr('string'), diff --git a/ui/app/models/policy.js b/ui/app/models/policy.js index af8c3d8a4497b..647e367eca8b6 100644 --- a/ui/app/models/policy.js +++ b/ui/app/models/policy.js @@ -4,7 +4,6 @@ import { computed } from '@ember/object'; import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities'; export default Model.extend({ - errors: attr('array'), name: attr('string'), policy: attr('string'), policyType: computed('constructor.modelName', function () { diff --git a/ui/app/models/secret-engine.js b/ui/app/models/secret-engine.js index 45bb60df192a7..b30b01b3d2af1 100644 --- a/ui/app/models/secret-engine.js +++ b/ui/app/models/secret-engine.js @@ -1,34 +1,25 @@ import Model, { attr } from '@ember-data/model'; -import { computed } from '@ember/object'; -import { equal } from '@ember/object/computed'; +import { computed } from '@ember/object'; // eslint-disable-line +import { equal } from '@ember/object/computed'; // eslint-disable-line import { fragment } from 'ember-data-model-fragments/attributes'; import fieldToAttrs, { expandAttributeMeta } from 'vault/utils/field-to-attrs'; -import { validator, buildValidations } from 'ember-cp-validations'; +import { withModelValidations } from 'vault/decorators/model-validations'; // identity will be managed separately and the inclusion // of the system backend is an implementation detail const LIST_EXCLUDED_BACKENDS = ['system', 'identity']; -const Validations = buildValidations({ - path: validator('presence', { - presence: true, - message: "Path can't be blank.", - }), +const validations = { + path: [{ type: 'presence', message: "Path can't be blank." }], maxVersions: [ - validator('number', { - allowString: true, - integer: true, - message: 'Maximum versions must be a number.', - }), - validator('length', { - min: 1, - max: 16, - message: 'You cannot go over 16 characters.', - }), + { type: 'number', options: { asString: true }, message: 'Maximum versions must be a number.' }, + { type: 'length', options: { min: 1, max: 16 }, message: 'You cannot go over 16 characters.' }, ], -}); +}; -export default Model.extend(Validations, { +@withModelValidations(validations) +class SecretEngineModel extends Model {} +export default SecretEngineModel.extend({ path: attr('string'), accessor: attr('string'), name: attr('string'), diff --git a/ui/app/models/secret-v2.js b/ui/app/models/secret-v2.js index f4db1443c186a..1f95d6e3d224c 100644 --- a/ui/app/models/secret-v2.js +++ b/ui/app/models/secret-v2.js @@ -1,27 +1,21 @@ import Model, { belongsTo, hasMany, attr } from '@ember-data/model'; -import { computed } from '@ember/object'; -import { alias } from '@ember/object/computed'; +import { computed } from '@ember/object'; // eslint-disable-line +import { alias } from '@ember/object/computed'; // eslint-disable-line import { expandAttributeMeta } from 'vault/utils/field-to-attrs'; import KeyMixin from 'vault/mixins/key-mixin'; import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities'; -import { validator, buildValidations } from 'ember-cp-validations'; +import { withModelValidations } from 'vault/decorators/model-validations'; -const Validations = buildValidations({ +const validations = { maxVersions: [ - validator('number', { - allowString: true, - integer: true, - message: 'Maximum versions must be a number.', - }), - validator('length', { - min: 1, - max: 16, - message: 'You cannot go over 16 characters.', - }), + { type: 'number', options: { asString: true }, message: 'Maximum versions must be a number.' }, + { type: 'length', options: { min: 1, max: 16 }, message: 'You cannot go over 16 characters.' }, ], -}); +}; -export default Model.extend(KeyMixin, Validations, { +@withModelValidations(validations) +class SecretV2Model extends Model {} +export default SecretV2Model.extend(KeyMixin, { failedServerRead: attr('boolean'), engine: belongsTo('secret-engine', { async: false }), engineId: attr('string'), diff --git a/ui/app/routes/vault/cluster/secrets/backend/list.js b/ui/app/routes/vault/cluster/secrets/backend/list.js index cf8d2930f55ad..6245fce39a679 100644 --- a/ui/app/routes/vault/cluster/secrets/backend/list.js +++ b/ui/app/routes/vault/cluster/secrets/backend/list.js @@ -36,8 +36,8 @@ export default Route.extend({ case 'alphabet': modelType = 'transform/alphabet'; break; - default: - modelType = 'transform'; // CBS TODO: transform/transformation + default: // CBS TODO: transform/transformation + modelType = 'transform'; break; } return modelType; diff --git a/ui/app/services/path-help.js b/ui/app/services/path-help.js index cd2f346731c09..8e51da5a5b718 100644 --- a/ui/app/services/path-help.js +++ b/ui/app/services/path-help.js @@ -14,7 +14,7 @@ import { resolve, reject } from 'rsvp'; import { debug } from '@ember/debug'; import { dasherize, capitalize } from '@ember/string'; import { singularize } from 'ember-inflector'; -import buildValidations from 'vault/utils/build-api-validators'; +import { withModelValidations } from 'vault/decorators/model-validations'; import generatedItemAdapter from 'vault/adapters/generated-item-list'; export function sanitizePath(path) { @@ -36,6 +36,7 @@ export default Service.extend({ getNewModel(modelType, backend, apiPath, itemType) { let owner = getOwner(this); const modelName = `model:${modelType}`; + const modelFactory = owner.factoryFor(modelName); let newModel, helpUrl; // if we have a factory, we need to take the existing model into account @@ -298,8 +299,17 @@ export default Service.extend({ // Build and add validations on model // NOTE: For initial phase, initialize validations only for user pass auth if (backend === 'userpass') { - let validations = buildValidations(fieldGroups); - newModel = newModel.extend(validations); + const validations = fieldGroups.reduce((obj, element) => { + if (element.default) { + element.default.forEach((v) => { + obj[v.name] = [{ type: 'presence', message: `${v.name} can't be black` }]; + }); + } + return obj; + }, {}); + @withModelValidations(validations) + class GeneratedItemModel extends newModel {} + newModel = GeneratedItemModel; } } } catch (err) { diff --git a/ui/app/templates/components/alert-popup.hbs b/ui/app/templates/components/alert-popup.hbs index e74ed6c5a94e9..2a08deced4b05 100644 --- a/ui/app/templates/components/alert-popup.hbs +++ b/ui/app/templates/components/alert-popup.hbs @@ -11,7 +11,7 @@ {{this.type.text}} {{#if this.message}} -

{{this.message}}

+

{{this.message}}

{{/if}} diff --git a/ui/app/templates/components/alphabet-edit.hbs b/ui/app/templates/components/alphabet-edit.hbs index 67d4937f77d55..8d58eff1b0058 100644 --- a/ui/app/templates/components/alphabet-edit.hbs +++ b/ui/app/templates/components/alphabet-edit.hbs @@ -35,7 +35,7 @@ Edit alphabet @@ -89,7 +89,7 @@ Cancel diff --git a/ui/app/templates/components/auth-config-form/config.hbs b/ui/app/templates/components/auth-config-form/config.hbs index cc91e466438d2..d60d73724d970 100644 --- a/ui/app/templates/components/auth-config-form/config.hbs +++ b/ui/app/templates/components/auth-config-form/config.hbs @@ -14,7 +14,7 @@ diff --git a/ui/app/templates/components/auth-jwt.hbs b/ui/app/templates/components/auth-jwt.hbs index 7bad92761ef23..e178623edc85a 100644 --- a/ui/app/templates/components/auth-jwt.hbs +++ b/ui/app/templates/components/auth-jwt.hbs @@ -45,7 +45,7 @@ data-test-auth-submit={{true}} type="submit" disabled={{@disabled}} - class="button is-primary {{if @disabled "is-loading"}}" + class="button is-primary {{if @disabled 'is-loading'}}" id="auth-submit" > {{#if this.isOIDC}} diff --git a/ui/app/templates/components/clients/history.hbs b/ui/app/templates/components/clients/history.hbs index 6bad4a549530d..f7f93304de694 100644 --- a/ui/app/templates/components/clients/history.hbs +++ b/ui/app/templates/components/clients/history.hbs @@ -138,7 +138,7 @@ @runningTotals={{this.totalUsageCounts}} @timestamp={{this.responseTimestamp}} /> - {{!-- TODO CMB: remove UsageStats component from history tab (and update associated tests) --}} + {{! TODO CMB: remove UsageStats component from history tab (and update associated tests) }} {{#if this.hasAttributionData}}

Vault client counts

- A client is any user or service that interacts with Vault. They are made up of entity clients and non-entity clients. The total client count number is an important consideration for Vault billing. + A client is any user or service that interacts with Vault. They are made up of entity clients and non-entity clients. + The total client count number is an important consideration for Vault billing.

diff --git a/ui/app/templates/components/config-pki-ca.hbs b/ui/app/templates/components/config-pki-ca.hbs index 3bf28bfb2b78a..2ea45a304b66e 100644 --- a/ui/app/templates/components/config-pki-ca.hbs +++ b/ui/app/templates/components/config-pki-ca.hbs @@ -73,7 +73,7 @@
- + Cancel
@@ -246,21 +248,23 @@ {{/each}} {{else}} - - {{#if (get this (camelize (concat "show" group)))}} -
- {{#each fields as |attr|}} - - {{/each}} -
- {{/if}} + {{#let (camelize (concat "show" group)) as |prop|}} + + {{#if (get this prop)}} +
+ {{#each fields as |attr|}} + + {{/each}} +
+ {{/if}} + {{/let}} {{/if}} {{/each-in}} {{/each}} @@ -287,7 +291,7 @@
- + Cancel
diff --git a/ui/app/templates/components/database-role-edit.hbs b/ui/app/templates/components/database-role-edit.hbs index 9293e23e2ec22..416608324547a 100644 --- a/ui/app/templates/components/database-role-edit.hbs +++ b/ui/app/templates/components/database-role-edit.hbs @@ -52,7 +52,7 @@ @mode="edit" @replace={{true}} @queryParams={{query-params itemType="role"}} - @data-test-edit-link={{true}} + data-test-edit-link={{true}} > Edit role
@@ -119,7 +119,7 @@ data-test-secret-save type="submit" disabled={{this.loading}} - class="button is-primary {{if this.loading "is-loading"}}" + class="button is-primary {{if this.loading 'is-loading'}}" > {{#if (eq @mode "create")}} Create role @@ -145,7 +145,7 @@ {{/if}}
- + Cancel
diff --git a/ui/app/templates/components/diff-version-selector.hbs b/ui/app/templates/components/diff-version-selector.hbs index aa66f777e6c2a..ccc3127e7b701 100644 --- a/ui/app/templates/components/diff-version-selector.hbs +++ b/ui/app/templates/components/diff-version-selector.hbs @@ -25,7 +25,7 @@ {{leftSideSecretVersion.version}} {{#if (and - (eq leftSideSecretVersion.version (or this.leftSideVersionSelected @args.model.currentVersion)) + (eq leftSideSecretVersion.version (or this.leftSideVersionSelected @model.currentVersion)) (not leftSideSecretVersion.destroyed) (not leftSideSecretVersion.deleted) ) diff --git a/ui/app/templates/components/form-field-groups-loop.hbs b/ui/app/templates/components/form-field-groups-loop.hbs index 37afcf163d8ae..fdb5c9b9f5e2a 100644 --- a/ui/app/templates/components/form-field-groups-loop.hbs +++ b/ui/app/templates/components/form-field-groups-loop.hbs @@ -8,21 +8,23 @@ {{/unless}} {{/each}} {{else}} - - {{#if (get @model (camelize (concat "show" group)))}} -
- {{#each fields as |attr|}} - - {{/each}} -
- {{/if}} + {{#let (camelize (concat "show" group)) as |prop|}} + + {{#if (get @model prop)}} +
+ {{#each fields as |attr|}} + + {{/each}} +
+ {{/if}} + {{/let}} {{/if}} {{/each-in}} {{/each}} \ No newline at end of file diff --git a/ui/app/templates/components/generate-credentials.hbs b/ui/app/templates/components/generate-credentials.hbs index f79df2bba7d3e..2cf94f28864be 100644 --- a/ui/app/templates/components/generate-credentials.hbs +++ b/ui/app/templates/components/generate-credentials.hbs @@ -145,7 +145,7 @@