From 8d92c3026bb189abfa51b5a59a1ef7d461fc5fe0 Mon Sep 17 00:00:00 2001 From: Chelsea Shaw <82459713+hashishaw@users.noreply.github.com> Date: Mon, 11 Mar 2024 16:44:26 -0500 Subject: [PATCH] UI: Ember deprecation - reopen class (#25851) Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com> --- .../components/auth-config-form/config.hbs | 12 +- ui/app/components/auth-config-form/config.js | 53 +++--- .../components/auth-config-form/options.hbs | 18 +- ui/app/components/auth-config-form/options.js | 82 +++++---- .../components/section-tabs.hbs | 6 +- ui/app/components/section-tabs.js | 18 +- ui/app/lib/attach-capabilities.js | 87 --------- .../components/wizard/mount-info.hbs | 2 +- .../vault/cluster/access/method/section.hbs | 2 +- .../vault/cluster/settings/auth/configure.hbs | 2 +- .../settings/auth/configure/section.hbs | 4 +- ui/tests/unit/lib/attach-capabilities-test.js | 168 ------------------ 12 files changed, 91 insertions(+), 363 deletions(-) rename ui/app/{templates => }/components/auth-config-form/config.hbs (67%) rename ui/app/{templates => }/components/auth-config-form/options.hbs (62%) rename ui/app/{templates => }/components/section-tabs.hbs (68%) delete mode 100644 ui/app/lib/attach-capabilities.js delete mode 100644 ui/tests/unit/lib/attach-capabilities-test.js diff --git a/ui/app/templates/components/auth-config-form/config.hbs b/ui/app/components/auth-config-form/config.hbs similarity index 67% rename from ui/app/templates/components/auth-config-form/config.hbs rename to ui/app/components/auth-config-form/config.hbs index d0aa09c9e9..4ec1c759a1 100644 --- a/ui/app/templates/components/auth-config-form/config.hbs +++ b/ui/app/components/auth-config-form/config.hbs @@ -3,16 +3,16 @@ SPDX-License-Identifier: BUSL-1.1 ~}} -
+
- - {{#if this.model.attrs}} - {{#each this.model.attrs as |attr|}} + + {{#if @model.attrs}} + {{#each @model.attrs as |attr|}} {{/each}} - {{else if this.model.fieldGroups}} - + {{else if @model.fieldGroups}} + {{/if}}
diff --git a/ui/app/components/auth-config-form/config.js b/ui/app/components/auth-config-form/config.js index c2592f5e74..10a904c844 100644 --- a/ui/app/components/auth-config-form/config.js +++ b/ui/app/components/auth-config-form/config.js @@ -5,7 +5,7 @@ import AdapterError from '@ember-data/adapter/error'; import { service } from '@ember/service'; -import Component from '@ember/component'; +import Component from '@glimmer/component'; import { task } from 'ember-concurrency'; import { waitFor } from '@ember/test-waiters'; @@ -14,40 +14,31 @@ import { waitFor } from '@ember/test-waiters'; * The `AuthConfigForm/Config` is the base form to configure auth methods. * * @example - * ```js - * {{auth-config-form/config model.model}} - * ``` + * * * @property model=null {DS.Model} - The corresponding auth model that is being configured. * */ -const AuthConfigBase = Component.extend({ - tagName: '', - model: null, +export default class AuthConfigBase extends Component { + @service flashMessages; + @service router; - flashMessages: service(), - router: service(), - saveModel: task( - waitFor(function* () { - try { - yield this.model.save(); - } catch (err) { - // AdapterErrors are handled by the error-message component - // in the form - if (err instanceof AdapterError === false) { - throw err; - } - return; + @task + @waitFor + *saveModel(evt) { + evt.preventDefault(); + try { + yield this.args.model.save(); + } catch (err) { + // AdapterErrors are handled by the error-message component + // in the form + if (err instanceof AdapterError === false) { + throw err; } - this.router.transitionTo('vault.cluster.access.methods').followRedirects(); - this.flashMessages.success('The configuration was saved successfully.'); - }) - ), -}); - -AuthConfigBase.reopenClass({ - positionalParams: ['model'], -}); - -export default AuthConfigBase; + return; + } + this.router.transitionTo('vault.cluster.access.methods').followRedirects(); + this.flashMessages.success('The configuration was saved successfully.'); + } +} diff --git a/ui/app/templates/components/auth-config-form/options.hbs b/ui/app/components/auth-config-form/options.hbs similarity index 62% rename from ui/app/templates/components/auth-config-form/options.hbs rename to ui/app/components/auth-config-form/options.hbs index e77b26155a..99e3af5a58 100644 --- a/ui/app/templates/components/auth-config-form/options.hbs +++ b/ui/app/components/auth-config-form/options.hbs @@ -3,26 +3,26 @@ SPDX-License-Identifier: BUSL-1.1 ~}} - +
- + - {{#each this.model.tuneAttrs as |attr|}} - {{#if (not (includes attr.name this.model.userLockoutConfig.modelAttrs))}} - + {{#each @model.tuneAttrs as |attr|}} + {{#if (not (includes attr.name @model.userLockoutConfig.modelAttrs))}} + {{/if}} {{/each}} - {{#if this.model.supportsUserLockoutConfig}} + {{#if @model.supportsUserLockoutConfig}}
User lockout configuration Specifies the user lockout settings for this auth mount. - {{#each this.model.tuneAttrs as |attr|}} - {{#if (includes attr.name this.model.userLockoutConfig.modelAttrs)}} - + {{#each @model.tuneAttrs as |attr|}} + {{#if (includes attr.name @model.userLockoutConfig.modelAttrs)}} + {{/if}} {{/each}} {{/if}} diff --git a/ui/app/components/auth-config-form/options.js b/ui/app/components/auth-config-form/options.js index 9c12b16adf..5f345291d0 100644 --- a/ui/app/components/auth-config-form/options.js +++ b/ui/app/components/auth-config-form/options.js @@ -8,63 +8,61 @@ import AuthConfigComponent from './config'; import { service } from '@ember/service'; import { task } from 'ember-concurrency'; import { waitFor } from '@ember/test-waiters'; +import { tracked } from '@glimmer/tracking'; +import errorMessage from 'vault/utils/error-message'; /** * @module AuthConfigForm/Options * The `AuthConfigForm/Options` is options portion of the auth config form. * * @example - * ```js - * {{auth-config-form/options model.model}} - * ``` + * * * @property model=null {DS.Model} - The corresponding auth model that is being configured. * */ -export default AuthConfigComponent.extend({ - flashMessages: service(), - router: service(), +export default class AuthConfigOptions extends AuthConfigComponent { + @service flashMessages; + @service router; - saveModel: task( - waitFor(function* () { - const data = this.model.config.serialize(); - data.description = this.model.description; + @tracked errorMessage; - if (this.model.supportsUserLockoutConfig) { - data.user_lockout_config = {}; - this.model.userLockoutConfig.apiParams.forEach((attr) => { - if (Object.keys(data).includes(attr)) { - data.user_lockout_config[attr] = data[attr]; - delete data[attr]; - } - }); - } + @task + @waitFor + *saveModel(evt) { + evt.preventDefault(); + this.errorMessage = null; + const data = this.args.model.config.serialize(); + data.description = this.args.model.description; - // token_type should not be tuneable for the token auth method. - if (this.model.methodType === 'token') { - delete data.token_type; - } - - try { - yield this.model.tune(data); - } catch (err) { - // AdapterErrors are handled by the error-message component - // in the form - if (err instanceof AdapterError === false) { - throw err; + if (this.args.model.supportsUserLockoutConfig) { + data.user_lockout_config = {}; + this.args.model.userLockoutConfig.apiParams.forEach((attr) => { + if (Object.keys(data).includes(attr)) { + data.user_lockout_config[attr] = data[attr]; + delete data[attr]; } + }); + } + + // token_type should not be tuneable for the token auth method. + if (this.args.model.methodType === 'token') { + delete data.token_type; + } + + try { + yield this.args.model.tune(data); + } catch (err) { + if (err instanceof AdapterError) { // because we're not calling model.save the model never updates with - // the error. Forcing the error message by manually setting the errorMessage - try { - this.model.set('errorMessage', err.errors?.join(',')); - } catch { - // do nothing - } + // the error, so we set it manually in the component instead. + this.errorMessage = errorMessage(err); return; } - this.router.transitionTo('vault.cluster.access.methods').followRedirects(); - this.flashMessages.success('The configuration was saved successfully.'); - }) - ), -}); + throw err; + } + this.router.transitionTo('vault.cluster.access.methods').followRedirects(); + this.flashMessages.success('The configuration was saved successfully.'); + } +} diff --git a/ui/app/templates/components/section-tabs.hbs b/ui/app/components/section-tabs.hbs similarity index 68% rename from ui/app/templates/components/section-tabs.hbs rename to ui/app/components/section-tabs.hbs index 6b408df60b..60ee2e2096 100644 --- a/ui/app/templates/components/section-tabs.hbs +++ b/ui/app/components/section-tabs.hbs @@ -3,14 +3,14 @@ SPDX-License-Identifier: BUSL-1.1 ~}} -{{#let (tabs-for-auth-section this.model this.tabType this.paths) as |tabs|}} +{{#let (tabs-for-auth-section @model this.tabType @paths) as |tabs|}} {{#if tabs.length}}
-
{{/if}} -{{section-tabs this.model "authShow" this.paths}} + {{#if (eq this.section "configuration")}} diff --git a/ui/app/templates/vault/cluster/settings/auth/configure.hbs b/ui/app/templates/vault/cluster/settings/auth/configure.hbs index 4014d5310b..d75976c85d 100644 --- a/ui/app/templates/vault/cluster/settings/auth/configure.hbs +++ b/ui/app/templates/vault/cluster/settings/auth/configure.hbs @@ -19,7 +19,7 @@ -{{section-tabs this.model}} + diff --git a/ui/app/templates/vault/cluster/settings/auth/configure/section.hbs b/ui/app/templates/vault/cluster/settings/auth/configure/section.hbs index 8dfd7c834a..8441f24ed1 100644 --- a/ui/app/templates/vault/cluster/settings/auth/configure/section.hbs +++ b/ui/app/templates/vault/cluster/settings/auth/configure/section.hbs @@ -4,7 +4,7 @@ ~}} {{#if (eq this.model.section "options")}} - {{auth-config-form/options this.model.model}} + {{else}} - {{auth-config-form/config this.model.model}} + {{/if}} \ No newline at end of file diff --git a/ui/tests/unit/lib/attach-capabilities-test.js b/ui/tests/unit/lib/attach-capabilities-test.js deleted file mode 100644 index 3a5568d1f1..0000000000 --- a/ui/tests/unit/lib/attach-capabilities-test.js +++ /dev/null @@ -1,168 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Model from '@ember-data/model'; -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; -import attachCapabilities from 'vault/lib/attach-capabilities'; -import apiPath from 'vault/utils/api-path'; - -const MODEL_TYPE = 'test-form-model'; - -const makeModelClass = () => { - return Model.extend(); -}; - -module('Unit | lib | attach capabilities', function (hooks) { - setupTest(hooks); - - test('it attaches passed capabilities', function (assert) { - let mc = makeModelClass(); - mc = attachCapabilities(mc, { - updatePath: apiPath`update/{'id'}`, - deletePath: apiPath`delete/{'id'}`, - }); - let relationship = mc.relationshipsByName.get('updatePath'); - - assert.strictEqual(relationship.key, 'updatePath', 'has updatePath relationship'); - assert.strictEqual(relationship.kind, 'belongsTo', 'kind of relationship is belongsTo'); - assert.strictEqual(relationship.type, 'capabilities', 'updatePath is a related capabilities model'); - - relationship = mc.relationshipsByName.get('deletePath'); - assert.strictEqual(relationship.key, 'deletePath', 'has deletePath relationship'); - assert.strictEqual(relationship.kind, 'belongsTo', 'kind of relationship is belongsTo'); - assert.strictEqual(relationship.type, 'capabilities', 'deletePath is a related capabilities model'); - }); - - test('it adds a static method to the model class', function (assert) { - let mc = makeModelClass(); - mc = attachCapabilities(mc, { - updatePath: apiPath`update/{'id'}`, - deletePath: apiPath`delete/{'id'}`, - }); - const relatedCapabilities = !!mc.relatedCapabilities && typeof mc.relatedCapabilities === 'function'; - assert.true(relatedCapabilities, 'model class now has a relatedCapabilities static function'); - }); - - test('calling static method with single response JSON-API document adds expected relationships', function (assert) { - let mc = makeModelClass(); - mc = attachCapabilities(mc, { - updatePath: apiPath`update/${'id'}`, - deletePath: apiPath`delete/${'id'}`, - }); - const jsonAPIDocSingle = { - data: { - id: 'test', - type: MODEL_TYPE, - attributes: {}, - relationships: {}, - }, - included: [], - }; - - const expected = { - data: { - id: 'test', - type: MODEL_TYPE, - attributes: {}, - relationships: { - updatePath: { - data: { - type: 'capabilities', - id: 'update/test', - }, - }, - deletePath: { - data: { - type: 'capabilities', - id: 'delete/test', - }, - }, - }, - }, - included: [], - }; - - mc.relatedCapabilities(jsonAPIDocSingle); - - assert.strictEqual( - Object.keys(jsonAPIDocSingle.data.relationships).length, - 2, - 'document now has 2 relationships' - ); - assert.deepEqual(jsonAPIDocSingle, expected, 'has the exected new document structure'); - }); - - test('calling static method with an arrary response JSON-API document adds expected relationships', function (assert) { - let mc = makeModelClass(); - mc = attachCapabilities(mc, { - updatePath: apiPath`update/${'id'}`, - deletePath: apiPath`delete/${'id'}`, - }); - const jsonAPIDocSingle = { - data: [ - { - id: 'test', - type: MODEL_TYPE, - attributes: {}, - relationships: {}, - }, - { - id: 'foo', - type: MODEL_TYPE, - attributes: {}, - relationships: {}, - }, - ], - included: [], - }; - - const expected = { - data: [ - { - id: 'test', - type: MODEL_TYPE, - attributes: {}, - relationships: { - updatePath: { - data: { - type: 'capabilities', - id: 'update/test', - }, - }, - deletePath: { - data: { - type: 'capabilities', - id: 'delete/test', - }, - }, - }, - }, - { - id: 'foo', - type: MODEL_TYPE, - attributes: {}, - relationships: { - updatePath: { - data: { - type: 'capabilities', - id: 'update/foo', - }, - }, - deletePath: { - data: { - type: 'capabilities', - id: 'delete/foo', - }, - }, - }, - }, - ], - included: [], - }; - mc.relatedCapabilities(jsonAPIDocSingle); - assert.deepEqual(jsonAPIDocSingle, expected, 'has the exected new document structure'); - }); -});