mirror of
https://github.com/hashicorp/vault.git
synced 2026-05-05 04:16:31 +02:00
UI: Custom login settings views (#30592)
* UI: Adding routes for custom login settings (#30404) * adding route block * adding to side nav * jk its diff * adding TODO, adding empty files * UI: Adding List view component for custom login settings (#30459) * first pass setting up list view * style fix * messing with routes * fix * undo * using mock data * renaming * [UI] API Service Error Parsing (#30454) * adds error parsing method to api service * replaces apiErrorMessage util instances with api service parseError * removes apiErrorMessage util and tests * removes ApiError type * fixes issue in isLocalStorageSupported error handling * remove cli folder (#30458) * [DOCS] Add explicit links to older release notes (#30461) * Add explicit links to older release notes * remove domain from URLs * add link to important changes as well * bump timeout for single flaky test (#30460) * adds list response parsing to api service (#30455) * update versions, and replace summary in important changes section (#30471) * Update CHANGELOG.md (#30456) * UI: Update Enterprise Client Count Datepicker (#30349) * date picker changes (mostly) for ent client counts * Move edit modal button + padding * only show start time in dropdown and add changelog * remove unused variable and update toggle width * remove unnecessary period end dates * tidy * update tests * Update changelog/30349.txt Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com> * improve date logic * add export button back in, re-arrange header, update dropdown * update when date is shown * add default for retention months * update tests and remove unnecessary tests * account for retention months that are not whole periods * update logic to show end date on export modal * update exported file name --------- Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com> * Prevent early-exit of plugin reload (#30329) * update to use util, update to this.cap --------- Co-authored-by: Jordan Reimer <zofskeez@gmail.com> Co-authored-by: Sarah Chavis <62406755+schavis@users.noreply.github.com> Co-authored-by: Angel Garbarino <Monkeychip@users.noreply.github.com> Co-authored-by: Ellie <ellie.sterner@hashicorp.com> Co-authored-by: Tony Wittinger <anwittin@users.noreply.github.com> Co-authored-by: lane-wetmore <lane.wetmore@hashicorp.com> Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com> Co-authored-by: kpcraig <3031348+kpcraig@users.noreply.github.com> * UI: Create details component for custom login rules (#30530) * setup * adding to view * fixing table keys * add breadcrumbs * fixes * removing default vals * pr comments * adding delete button to toolbar * adding delete functionality * reorder and fix error handling * updating api call, adding error template, fixing selectors * remove param * UI: Updating visibility attr on auth config to be a toggle with direct login link (#30548) * updating visibility attr to be a toggle, adding link placeholder * update test * test fix pt2 * updating to build link + copy button * updates * use the right word * using hds text * updating helper text, path * use encode directly * updating capabilities check, creating test files, empty state * UI: Update custom login to use api instead of mirage (#30640) * updating to use api, removing store * temp test fix * fixes on types, remove test funcs * fix assertion * adding tests * updating test * adding to tests * stub delete? * removing stubs, updating tests * fixes * moving cmd placement, updating inheritance * adding changelog * fix changelog * pr comments * update check & update test * remove empty state block * remove comment * Revert "remove empty state block" This reverts commit ce34d8c76fea3b43bb96c6acd342a5ba0471f441. * remove the right empty state --------- Co-authored-by: Jordan Reimer <zofskeez@gmail.com> Co-authored-by: Sarah Chavis <62406755+schavis@users.noreply.github.com> Co-authored-by: Angel Garbarino <Monkeychip@users.noreply.github.com> Co-authored-by: Ellie <ellie.sterner@hashicorp.com> Co-authored-by: Tony Wittinger <anwittin@users.noreply.github.com> Co-authored-by: lane-wetmore <lane.wetmore@hashicorp.com> Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com> Co-authored-by: kpcraig <3031348+kpcraig@users.noreply.github.com>
This commit is contained in:
parent
3eff32e851
commit
fbb446f974
7
changelog/30592.txt
Normal file
7
changelog/30592.txt
Normal file
@ -0,0 +1,7 @@
|
||||
```release-note:feature
|
||||
**Custom login settings**: Adding view to list and delete custom login rules
|
||||
```
|
||||
|
||||
```release-note:change
|
||||
ui: 'Custom messages' renamed to 'System Messages'
|
||||
```
|
||||
@ -11,6 +11,12 @@
|
||||
{{#each @model.tuneAttrs as |attr|}}
|
||||
{{#if (not (includes attr.name @model.userLockoutConfig.modelAttrs))}}
|
||||
<FormField data-test-field @attr={{attr}} @model={{@model}} />
|
||||
{{#if (eq attr.name "config.listingVisibility")}}
|
||||
<div class="has-top-margin-negative-s has-bottom-margin-l is-flex-center">
|
||||
<Hds::Text::Body @tag="p" @color="faint">UI login link:</Hds::Text::Body>
|
||||
<Hds::Copy::Snippet @textToCopy={{this.getLoginLink}} />
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
|
||||
|
||||
@ -65,4 +65,8 @@ export default class AuthConfigOptions extends AuthConfigComponent {
|
||||
this.router.transitionTo('vault.cluster.access.methods').followRedirects();
|
||||
this.flashMessages.success('The configuration was saved successfully.');
|
||||
}
|
||||
|
||||
get getLoginLink() {
|
||||
return `${window.origin}/ui/vault/auth?with=${encodeURIComponent(this.args.model.path)}`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,8 +122,16 @@
|
||||
<Nav.Title data-test-sidebar-nav-heading="Settings">Settings</Nav.Title>
|
||||
<Nav.Link
|
||||
@route="vault.cluster.config-ui.messages"
|
||||
@text="Custom Messages"
|
||||
data-test-sidebar-nav-link="Custom Messages"
|
||||
{{! formerly called 'Custom Messages' }}
|
||||
@text="System Messages"
|
||||
data-test-sidebar-nav-link="System Messages"
|
||||
/>
|
||||
{{#if (or this.isRootNamespace this.namespace.isHvdAdminNamespace)}}
|
||||
<Nav.Link
|
||||
@route="vault.cluster.config-ui.login-settings"
|
||||
@text="UI Login Rules"
|
||||
data-test-sidebar-nav-link="UI Login Rules"
|
||||
/>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</Hds::SideNav::Portal>
|
||||
@ -33,8 +33,12 @@ export default class MountConfigModel extends Model {
|
||||
auditNonHmacResponseKeys;
|
||||
|
||||
@attr('mountVisibility', {
|
||||
editType: 'boolean',
|
||||
label: 'List method when unauthenticated',
|
||||
label: 'Use as preferred UI login method',
|
||||
editType: 'toggleButton',
|
||||
helperTextEnabled:
|
||||
'This mount will be included in the unauthenticated UI login endpoint and display as a preferred login method.',
|
||||
helperTextDisabled:
|
||||
'Turn on the toggle to use this auth mount as a preferred login method during UI login.',
|
||||
defaultValue: false,
|
||||
})
|
||||
listingVisibility;
|
||||
|
||||
@ -16,6 +16,7 @@ export const SUDO_PATHS = [
|
||||
export const SUDO_PATH_PREFIXES = ['sys/leases/revoke-prefix', 'sys/leases/revoke-force'];
|
||||
|
||||
export const PATH_MAP = {
|
||||
customLogin: apiPath`sys/config/ui/login/default-auth/${'id'}`,
|
||||
customMessages: apiPath`sys/config/ui/custom-messages/${'id'}`,
|
||||
syncActivate: apiPath`sys/activation-flags/secrets-sync/activate`,
|
||||
syncDestination: apiPath`sys/sync/destinations/${'type'}/${'name'}`,
|
||||
|
||||
@ -0,0 +1,59 @@
|
||||
{{!
|
||||
Copyright (c) HashiCorp, Inc.
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
}}
|
||||
|
||||
<PageHeader as |p|>
|
||||
<p.top>
|
||||
<Page::Breadcrumbs @breadcrumbs={{@breadcrumbs}} />
|
||||
</p.top>
|
||||
<p.levelLeft>
|
||||
<h1 class="title is-3">
|
||||
{{@rule.name}}
|
||||
</h1>
|
||||
</p.levelLeft>
|
||||
</PageHeader>
|
||||
|
||||
<nav class="tabs" aria-label="navigation for rule details">
|
||||
<ul>
|
||||
<li>
|
||||
<LinkTo @route="login-settings.rule.details" @model={{@rule}} data-test-tab="rule">
|
||||
Details
|
||||
</LinkTo>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<Toolbar>
|
||||
<ToolbarActions>
|
||||
{{#if (has-capability this.capabilities "delete" pathKey="customLogin" params=@rule)}}
|
||||
<Hds::Button
|
||||
@text="Delete Rule"
|
||||
@color="secondary"
|
||||
class="toolbar-button"
|
||||
{{on "click" (fn (mut this.showConfirmModal) true)}}
|
||||
data-test-rule-delete
|
||||
/>
|
||||
{{/if}}
|
||||
</ToolbarActions>
|
||||
</Toolbar>
|
||||
{{#each-in @rule as |key value|}}
|
||||
{{#if (eq key "defaultAuthType")}}
|
||||
<InfoTableRow @alwaysRender={{true}} @label="Default method" @value={{value}} />
|
||||
{{else if (eq key "backupAuthTypes")}}
|
||||
<InfoTableRow @alwaysRender={{true}} @label="Backup methods" @value={{value}} />
|
||||
{{else if (eq key "disableInheritance")}}
|
||||
<InfoTableRow @alwaysRender={{true}} @label="Inheritance" @value={{stringify (not value)}} />
|
||||
{{else}}
|
||||
<InfoTableRow @alwaysRender={{true}} @label={{capitalize key}} @value={{value}} />
|
||||
{{/if}}
|
||||
{{/each-in}}
|
||||
|
||||
{{#if this.showConfirmModal}}
|
||||
<ConfirmModal
|
||||
@color="critical"
|
||||
@onClose={{fn (mut this.showConfirmModal) false}}
|
||||
@confirmMessage="This will permanently delete this rule."
|
||||
@onConfirm={{this.onDelete}}
|
||||
/>
|
||||
{{/if}}
|
||||
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import Component from '@glimmer/component';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { service } from '@ember/service';
|
||||
import { action } from '@ember/object';
|
||||
import errorMessage from 'vault/utils/error-message';
|
||||
|
||||
/**
|
||||
* @module Page::LoginSettingsRuleDetails
|
||||
* Page::LoginSettingsRuleDetails component is used to display rule information.
|
||||
* Shows detailed data, (eg which namespace it applies to, auth type used etc.) on a selected login rule from the custom login settings list.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* <Page::LoginSettingsRuleDetails @rule={{this.rule}} />
|
||||
* ```
|
||||
* @param {object} rule - holds login rule data, { backup_auth_types: string[] eg. ['token'], default_auth_type: string "oidc", disable_inheritance: boolean,
|
||||
* name: string "Login rule 1", namespace: string eg "admin/"}
|
||||
* */
|
||||
|
||||
export default class LoginSettingsRuleDetails extends Component {
|
||||
@service capabilities;
|
||||
@service flashMessages;
|
||||
@service('app-router') router;
|
||||
@service api;
|
||||
|
||||
@tracked showConfirmModal = false;
|
||||
|
||||
@action
|
||||
async onDelete() {
|
||||
const { rule } = this.args;
|
||||
|
||||
try {
|
||||
await this.api.sys.uiLoginDefaultAuthDeleteConfiguration(rule.name);
|
||||
|
||||
this.flashMessages.success(`Successfully deleted rule ${rule.name}.`);
|
||||
|
||||
this.router.transitionTo('vault.cluster.config-ui.login-settings.index');
|
||||
} catch (error) {
|
||||
const message = errorMessage(error, 'Error deleting rule. Please try again.');
|
||||
this.flashMessages.danger(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
{{!
|
||||
Copyright (c) HashiCorp, Inc.
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
}}
|
||||
|
||||
<PageHeader as |p|>
|
||||
<p.levelLeft>
|
||||
<h1 class="title is-3">
|
||||
UI Login Rules
|
||||
</h1>
|
||||
</p.levelLeft>
|
||||
</PageHeader>
|
||||
|
||||
<Toolbar />
|
||||
|
||||
{{#if @loginRules}}
|
||||
{{#each @loginRules as |rule|}}
|
||||
<div class="list-item-row linked-block-item is-no-underline">
|
||||
<div>
|
||||
<div class="is-grid align-items-center linked-block-title">
|
||||
<Hds::Icon @name="user-check" @size="24" />
|
||||
<div class="has-text-weight-semibold has-left-margin-xs" data-test-rule-name={{rule.Name}}>{{rule.Name}}</div>
|
||||
</div>
|
||||
<div class="has-top-margin-m" data-test-rule-path={{rule.Namespace}}>{{rule.Namespace}}</div>
|
||||
</div>
|
||||
<div class="linked-block-popup-menu">
|
||||
<Hds::Dropdown @isInline={{true}} as |dd|>
|
||||
<dd.ToggleIcon
|
||||
@icon="more-horizontal"
|
||||
@hasChevron={{false}}
|
||||
@text="login rules menu"
|
||||
data-test-popup-menu-trigger
|
||||
/>
|
||||
<dd.Interactive @route="login-settings.rule.details" @model={{rule.Name}} data-test-popup-menu="view-rule">
|
||||
View
|
||||
</dd.Interactive>
|
||||
{{#if (has-capability this.capabilities "delete" pathKey="customLogin" params=rule)}}
|
||||
<dd.Interactive
|
||||
@color="critical"
|
||||
data-test-popup-menu="delete-rule"
|
||||
{{on "click" (fn (mut this.ruleToDelete) rule)}}
|
||||
>Delete</dd.Interactive>
|
||||
{{/if}}
|
||||
</Hds::Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
<EmptyState
|
||||
data-test-empty-state="login-rules-list"
|
||||
@title="No UI login rules yet"
|
||||
@message="Login rules can be used to select default and back up login methods and customize which methods display in the web UI login form. Available to be created via the CLI or HTTP API."
|
||||
>
|
||||
{{! TODO: update href with tutorial link }}
|
||||
{{! <Hds::Link::Standalone @icon="arrow-right" @iconPosition="trailing" @text="Learn more" @href="/" /> }}
|
||||
</EmptyState>
|
||||
{{/if}}
|
||||
|
||||
{{#if this.ruleToDelete}}
|
||||
<ConfirmModal
|
||||
@color="critical"
|
||||
@onClose={{fn (mut this.ruleToDelete) null}}
|
||||
@confirmMessage="This will permanently delete this rule."
|
||||
@onConfirm={{this.onDelete}}
|
||||
/>
|
||||
{{/if}}
|
||||
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import Component from '@glimmer/component';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { service } from '@ember/service';
|
||||
import { action } from '@ember/object';
|
||||
import errorMessage from 'vault/utils/error-message';
|
||||
|
||||
/**
|
||||
* @module Page::LoginSettingsList
|
||||
* Page::LoginSettingsList components are used to display list of rules.
|
||||
* @example
|
||||
* ```js
|
||||
* <Page::LoginSettingsList @loginRules={{this.rules}} />
|
||||
* ```
|
||||
* @param {array} loginRules - array of rule objects
|
||||
*/
|
||||
|
||||
export default class LoginSettingsList extends Component {
|
||||
@service capabilities;
|
||||
@service flashMessages;
|
||||
@service('app-router') router;
|
||||
@tracked ruleToDelete = null; // set to the rule intended to delete
|
||||
@service api;
|
||||
|
||||
@action
|
||||
async onDelete() {
|
||||
try {
|
||||
await this.api.sys.uiLoginDefaultAuthDeleteConfiguration(this.ruleToDelete.id);
|
||||
this.flashMessages.success(`Successfully deleted rule ${this.ruleToDelete.id}.`);
|
||||
|
||||
this.router.transitionTo('vault.cluster.config-ui.login-settings');
|
||||
} catch (error) {
|
||||
const message = errorMessage(error, 'Error deleting rule. Please try again.');
|
||||
this.flashMessages.danger(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13,4 +13,10 @@ export default buildRoutes(function () {
|
||||
this.route('edit');
|
||||
});
|
||||
});
|
||||
|
||||
this.route('login-settings', function () {
|
||||
this.route('rule', { path: '/:name' }, function () {
|
||||
this.route('details');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
18
ui/lib/config-ui/addon/routes/login-settings/index.js
Normal file
18
ui/lib/config-ui/addon/routes/login-settings/index.js
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import Route from '@ember/routing/route';
|
||||
import { service } from '@ember/service';
|
||||
|
||||
export default class LoginSettingsRoute extends Route {
|
||||
@service api;
|
||||
|
||||
async model() {
|
||||
const res = await this.api.sys.uiLoginDefaultAuthList(true);
|
||||
const loginRules = this.api.keyInfoToArray({ keyInfo: res.keyInfo, keys: res.keys });
|
||||
|
||||
return { loginRules };
|
||||
}
|
||||
}
|
||||
36
ui/lib/config-ui/addon/routes/login-settings/rule/details.js
Normal file
36
ui/lib/config-ui/addon/routes/login-settings/rule/details.js
Normal file
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import Route from '@ember/routing/route';
|
||||
import { service } from '@ember/service';
|
||||
|
||||
export default class LoginSettingsRuleDetailsRoute extends Route {
|
||||
@service('app-router') router;
|
||||
@service api;
|
||||
|
||||
beforeModel() {
|
||||
const { name } = this.paramsFor('login-settings.rule');
|
||||
if (!name) {
|
||||
this.router.transitionTo('vault.cluster.config-ui.login-settings.index');
|
||||
}
|
||||
}
|
||||
|
||||
async model() {
|
||||
const { name } = this.paramsFor('login-settings.rule');
|
||||
|
||||
const rule = await this.api.sys.uiLoginDefaultAuthReadConfiguration(name);
|
||||
|
||||
return { rule: { name, ...rule.data } };
|
||||
}
|
||||
|
||||
setupController(controller, resolvedModel) {
|
||||
super.setupController(controller, resolvedModel);
|
||||
|
||||
controller.breadcrumbs = [
|
||||
{ label: 'UI login rules', route: 'login-settings' },
|
||||
{ label: resolvedModel.rule.name },
|
||||
];
|
||||
}
|
||||
}
|
||||
15
ui/lib/config-ui/addon/routes/login-settings/rule/index.js
Normal file
15
ui/lib/config-ui/addon/routes/login-settings/rule/index.js
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import Route from '@ember/routing/route';
|
||||
import { service } from '@ember/service';
|
||||
|
||||
export default class LoginSettingsRuleIndexRoute extends Route {
|
||||
@service('app-router') router;
|
||||
|
||||
redirect() {
|
||||
this.router.transitionTo('vault.cluster.config-ui.login-settings.rule.details');
|
||||
}
|
||||
}
|
||||
6
ui/lib/config-ui/addon/templates/error.hbs
Normal file
6
ui/lib/config-ui/addon/templates/error.hbs
Normal file
@ -0,0 +1,6 @@
|
||||
{{!
|
||||
Copyright (c) HashiCorp, Inc.
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
}}
|
||||
|
||||
<Page::Error @error={{this.model}} />
|
||||
@ -0,0 +1,6 @@
|
||||
{{!
|
||||
Copyright (c) HashiCorp, Inc.
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
}}
|
||||
|
||||
<LoginSettings::Page::List @loginRules={{this.model.loginRules}} />
|
||||
@ -0,0 +1,6 @@
|
||||
{{!
|
||||
Copyright (c) HashiCorp, Inc.
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
}}
|
||||
|
||||
<LoginSettings::Page::Details @rule={{this.model.rule}} @breadcrumbs={{this.breadcrumbs}} />
|
||||
@ -12,6 +12,8 @@ const assertFields = (assert, fields, customSelectors = {}) => {
|
||||
fields.forEach((param) => {
|
||||
if (Object.keys(customSelectors).includes(param)) {
|
||||
assert.dom(customSelectors[param]).exists();
|
||||
} else if (param === 'config.listingVisibility') {
|
||||
assert.dom(GENERAL.toggleInput('toggle-config.listingVisibility')).exists();
|
||||
} else {
|
||||
assert.dom(GENERAL.inputByAttr(param)).exists();
|
||||
}
|
||||
|
||||
82
ui/tests/acceptance/config-ui/login-settings-test.js
Normal file
82
ui/tests/acceptance/config-ui/login-settings-test.js
Normal file
@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import { module, test } from 'qunit';
|
||||
import { setupApplicationTest } from 'ember-qunit';
|
||||
import { click, visit, currentRouteName } from '@ember/test-helpers';
|
||||
import { login } from 'vault/tests/helpers/auth/auth-helpers';
|
||||
import { GENERAL } from 'vault/tests/helpers/general-selectors';
|
||||
import { runCmd } from 'vault/tests/helpers/commands';
|
||||
|
||||
module('Acceptance | Enterprise | config-ui/login-settings', function (hooks) {
|
||||
setupApplicationTest(hooks);
|
||||
|
||||
hooks.beforeEach(async function () {
|
||||
await login();
|
||||
|
||||
// create login rules
|
||||
await runCmd([
|
||||
`write sys/config/ui/login/default-auth/testRule backup_auth_types=userpass default_auth_type=okta disable_inheritance=false namespace=ns1`,
|
||||
'write sys/config/ui/login/default-auth/testRule2 backup_auth_types=oidc default_auth_type=ldap disable_inheritance=true namespace=ns2',
|
||||
]);
|
||||
});
|
||||
|
||||
hooks.afterEach(async function () {
|
||||
await login();
|
||||
|
||||
// cleanup login rules
|
||||
await runCmd([
|
||||
'delete sys/config/ui/login/default-auth/testRule',
|
||||
'delete sys/config/ui/login/default-auth/testRule2',
|
||||
]);
|
||||
});
|
||||
|
||||
test('fetched login rule list renders', async function (assert) {
|
||||
// Visit the login settings list index page
|
||||
await visit('vault/config-ui/login-settings');
|
||||
|
||||
// verify fetched rules are rendered in list
|
||||
assert.dom('.linked-block-item').exists({ count: 2 });
|
||||
// verify rule data namespaces render
|
||||
assert.dom('[data-test-rule-path="ns1/"]').exists();
|
||||
assert.dom('[data-test-rule-path="ns2/"]').exists();
|
||||
});
|
||||
|
||||
test('delete rule from list view', async function (assert) {
|
||||
// Visit the login settings list index page
|
||||
await visit('vault/config-ui/login-settings');
|
||||
|
||||
await click(GENERAL.menuTrigger);
|
||||
await click(GENERAL.menuItem('delete-rule'));
|
||||
|
||||
assert.dom(GENERAL.confirmationModal).exists();
|
||||
await click(GENERAL.confirmButton);
|
||||
|
||||
// verify success message from deletion
|
||||
assert.dom(GENERAL.latestFlashContent).includesText('Successfully deleted rule testRule.');
|
||||
assert.dom('[data-test-rule-name="testRule"]').doesNotExist();
|
||||
});
|
||||
|
||||
test('navigate to rule details page and renders rule data', async function (assert) {
|
||||
// visit individual rule page
|
||||
await visit('vault/config-ui/login-settings');
|
||||
|
||||
await click(GENERAL.menuTrigger);
|
||||
await click(GENERAL.menuItem('view-rule'));
|
||||
|
||||
// verify that user is redirected to the rule details page
|
||||
assert.strictEqual(
|
||||
currentRouteName(),
|
||||
'vault.cluster.config-ui.login-settings.rule.details',
|
||||
'goes to rule details page'
|
||||
);
|
||||
|
||||
// verify fetched rule data is rendered
|
||||
assert.dom(GENERAL.infoRowValue('Name')).hasText('testRule');
|
||||
assert.dom(GENERAL.infoRowValue('Namespace')).hasText('ns1/');
|
||||
assert.dom(GENERAL.infoRowValue('Backup methods')).hasText('userpass');
|
||||
assert.dom(GENERAL.infoRowValue('Inheritance')).hasText('true');
|
||||
});
|
||||
});
|
||||
@ -7,7 +7,7 @@ export const CUSTOM_MESSAGES = {
|
||||
// General selectors that are common between custom messages
|
||||
inlineErrorMessage: `[data-test-inline-error-message]`,
|
||||
unauthCreateFormInfo: '[data-test-unauth-info]',
|
||||
navLink: '[data-test-sidebar-nav-link="Custom Messages"]',
|
||||
navLink: '[data-test-sidebar-nav-link="System Messages"]',
|
||||
radio: (radioName: string) => `[data-test-radio="${radioName}"]`,
|
||||
field: (fieldName: string) => `[data-test-field="${fieldName}"]`,
|
||||
input: (input: string) => `[data-test-input="${input}"]`,
|
||||
|
||||
@ -66,7 +66,7 @@ module('Integration | Component | auth-config-form options', function (hooks) {
|
||||
|
||||
assert.dom('[data-test-user-lockout-section]').hasText('User lockout configuration');
|
||||
|
||||
await click(GENERAL.inputByAttr('config.listingVisibility'));
|
||||
await click(GENERAL.toggleInput('toggle-config.listingVisibility'));
|
||||
await fillIn(GENERAL.inputByAttr('config.tokenType'), 'default-batch');
|
||||
|
||||
await click(GENERAL.ttl.toggle('Default Lease TTL'));
|
||||
@ -124,7 +124,7 @@ module('Integration | Component | auth-config-form options', function (hooks) {
|
||||
.dom('[data-test-user-lockout-section]')
|
||||
.doesNotExist(`${type} method does not render user lockout section`);
|
||||
|
||||
await click(GENERAL.inputByAttr('config.listingVisibility'));
|
||||
await click(GENERAL.toggleInput('toggle-config.listingVisibility'));
|
||||
await fillIn(GENERAL.inputByAttr('config.tokenType'), 'default-batch');
|
||||
|
||||
await click(GENERAL.ttl.toggle('Default Lease TTL'));
|
||||
@ -178,7 +178,7 @@ module('Integration | Component | auth-config-form options', function (hooks) {
|
||||
.dom(GENERAL.inputByAttr('config.tokenType'))
|
||||
.doesNotExist('does not render tokenType for token auth method');
|
||||
|
||||
await click(GENERAL.inputByAttr('config.listingVisibility'));
|
||||
await click(GENERAL.toggleInput('toggle-config.listingVisibility'));
|
||||
await click(GENERAL.ttl.toggle('Default Lease TTL'));
|
||||
await fillIn(GENERAL.ttl.input('Default Lease TTL'), '30');
|
||||
|
||||
|
||||
@ -74,7 +74,8 @@ module('Integration | Component | sidebar-nav-cluster', function (hooks) {
|
||||
'Vault Usage',
|
||||
'License',
|
||||
'Seal Vault',
|
||||
'Custom Messages',
|
||||
'System Messages',
|
||||
'UI Login Rules',
|
||||
];
|
||||
stubFeaturesAndPermissions(this.owner, true, true);
|
||||
await renderComponent();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user