mirror of
https://github.com/hashicorp/vault.git
synced 2026-05-07 21:36:26 +02:00
ui: VAULT-8673 Add empty states to certificates and roles (#18702)
* Add empty states to certificates and roles * Add tests for empty state * Fix naming of model properties
This commit is contained in:
parent
ef3e3eace2
commit
66ea2c0b18
@ -1,7 +1,8 @@
|
||||
import Route from '@ember/routing/route';
|
||||
import PkiOverviewRoute from '../overview';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { hash } from 'rsvp';
|
||||
|
||||
export default class PkiCertificatesIndexRoute extends Route {
|
||||
export default class PkiCertificatesIndexRoute extends PkiOverviewRoute {
|
||||
@service store;
|
||||
@service secretMountPath;
|
||||
@service pathHelp;
|
||||
@ -11,18 +12,23 @@ export default class PkiCertificatesIndexRoute extends Route {
|
||||
return this.pathHelp.getNewModel('pki/certificate', this.secretMountPath.currentPath);
|
||||
}
|
||||
|
||||
async fetchCertificates() {
|
||||
try {
|
||||
return await this.store.query('pki/certificate', { backend: this.secretMountPath.currentPath });
|
||||
} catch (e) {
|
||||
if (e.httpStatus === 404) {
|
||||
return { parentModel: this.modelFor('certificates') };
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model() {
|
||||
return this.store
|
||||
.query('pki/certificate', { backend: this.secretMountPath.currentPath })
|
||||
.then((certificateModel) => {
|
||||
return { certificateModel, parentModel: this.modelFor('certificates') };
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.httpStatus === 404) {
|
||||
return { parentModel: this.modelFor('certificates') };
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
return hash({
|
||||
hasConfig: this.hasConfig(),
|
||||
certificates: this.fetchCertificates(),
|
||||
parentModel: this.modelFor('certificates'),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import Route from '@ember/routing/route';
|
||||
import PkiOverviewRoute from '../overview';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { hash } from 'rsvp';
|
||||
|
||||
export default class PkiRolesIndexRoute extends Route {
|
||||
export default class PkiRolesIndexRoute extends PkiOverviewRoute {
|
||||
@service store;
|
||||
@service secretMountPath;
|
||||
@service pathHelp;
|
||||
@ -12,18 +13,23 @@ export default class PkiRolesIndexRoute extends Route {
|
||||
return this.pathHelp.getNewModel('pki/role', this.secretMountPath.currentPath);
|
||||
}
|
||||
|
||||
async fetchRoles() {
|
||||
try {
|
||||
return await this.store.query('pki/role', { backend: this.secretMountPath.currentPath });
|
||||
} catch (e) {
|
||||
if (e.httpStatus === 404) {
|
||||
return { parentModel: this.modelFor('roles') };
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model() {
|
||||
return this.store
|
||||
.query('pki/role', { backend: this.secretMountPath.currentPath })
|
||||
.then((roleModel) => {
|
||||
return { roleModel, parentModel: this.modelFor('roles') };
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.httpStatus === 404) {
|
||||
return { parentModel: this.modelFor('roles') };
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
return hash({
|
||||
hasConfig: this.hasConfig(),
|
||||
roles: this.fetchRoles(),
|
||||
parentModel: this.modelFor('roles'),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,14 +10,15 @@
|
||||
/>
|
||||
{{outlet}}
|
||||
<Toolbar>
|
||||
{{#if this.model.certificateModel.length}}
|
||||
{{#if this.model.certificates.length}}
|
||||
<ToolbarFilters>
|
||||
{{! ARG TODO glimmerize the NavigateInput and refactor so you can use it in an engine }}
|
||||
</ToolbarFilters>
|
||||
{{/if}}
|
||||
</Toolbar>
|
||||
{{#if this.model.certificateModel.length}}
|
||||
{{#each this.model.certificateModel as |pkiCertificate|}}
|
||||
|
||||
{{#if this.model.hasConfig}}
|
||||
{{#each this.model.certificates as |pkiCertificate|}}
|
||||
<LinkedBlock
|
||||
class="list-item-row"
|
||||
@params={{array "certificates.certificate.details" pkiCertificate.id}}
|
||||
@ -56,7 +57,7 @@
|
||||
{{else}}
|
||||
<EmptyState @title="PKI not configured" @message="This PKI mount hasn't yet been configured with a certificate issuer.">
|
||||
<LinkTo @route="configuration.create">
|
||||
{{! ARG TODO if configuration of engine not setup then direct toward setting that up otherwise replace with new design language }}
|
||||
Configure PKI
|
||||
</LinkTo>
|
||||
</EmptyState>
|
||||
{{/if}}
|
||||
@ -16,50 +16,58 @@
|
||||
</ToolbarActions>
|
||||
</Toolbar>
|
||||
|
||||
{{#if this.model.roleModel.length}}
|
||||
{{#each this.model.roleModel as |pkiRole|}}
|
||||
<LinkedBlock class="list-item-row" @params={{array "roles.role.details" pkiRole.id}} @linkPrefix={{this.mountPoint}}>
|
||||
<div class="level is-mobile">
|
||||
<div class="level-left">
|
||||
<div>
|
||||
<Icon @name="user" class="has-text-grey-light" />
|
||||
<span class="has-text-weight-semibold is-underline">
|
||||
{{pkiRole.id}}
|
||||
</span>
|
||||
{{#if this.model.hasConfig}}
|
||||
{{#if this.model.roles.length}}
|
||||
{{#each this.model.roles as |pkiRole|}}
|
||||
<LinkedBlock class="list-item-row" @params={{array "roles.role.details" pkiRole.id}} @linkPrefix={{this.mountPoint}}>
|
||||
<div class="level is-mobile">
|
||||
<div class="level-left">
|
||||
<div>
|
||||
<Icon @name="user" class="has-text-grey-light" />
|
||||
<span class="has-text-weight-semibold is-underline">
|
||||
{{pkiRole.id}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="level-right is-flex is-paddingless is-marginless">
|
||||
<div class="level-item">
|
||||
<PopupMenu>
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
<li>
|
||||
<LinkTo @route="roles.role.details" @model={{pkiRole.id}}>
|
||||
Details
|
||||
</LinkTo>
|
||||
</li>
|
||||
<li>
|
||||
<LinkTo @route="roles.role.edit" @model={{pkiRole.id}}>
|
||||
Edit
|
||||
</LinkTo>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</PopupMenu>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="level-right is-flex is-paddingless is-marginless">
|
||||
<div class="level-item">
|
||||
<PopupMenu>
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
<li>
|
||||
<LinkTo @route="roles.role.details" @model={{pkiRole.id}}>
|
||||
Details
|
||||
</LinkTo>
|
||||
</li>
|
||||
<li>
|
||||
<LinkTo @route="roles.role.edit" @model={{pkiRole.id}}>
|
||||
Edit
|
||||
</LinkTo>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</PopupMenu>
|
||||
</div>
|
||||
</LinkedBlock>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
<EmptyState @title="No roles yet">
|
||||
<div>
|
||||
<p>When created, roles will be listed here. Create a role to start generating certificates.</p>
|
||||
<div class="has-top-margin-m">
|
||||
<LinkTo @route="roles.create">
|
||||
Create role
|
||||
</LinkTo>
|
||||
</div>
|
||||
</div>
|
||||
</LinkedBlock>
|
||||
{{/each}}
|
||||
</EmptyState>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<EmptyState @title="No roles yet">
|
||||
<div>
|
||||
<p>When created, roles will be listed here. Create a role to start generating certificates.</p>
|
||||
<div class="has-top-margin-m">
|
||||
<LinkTo @route="roles.create">
|
||||
Create role
|
||||
</LinkTo>
|
||||
</div>
|
||||
</div>
|
||||
<EmptyState @title="PKI not configured" @message="This PKI mount hasn't yet been configured with a certificate issuer.">
|
||||
<LinkTo @route="configuration.create">
|
||||
Configure PKI
|
||||
</LinkTo>
|
||||
</EmptyState>
|
||||
{{/if}}
|
||||
@ -64,7 +64,7 @@ module('Acceptance | pki workflow', function (hooks) {
|
||||
});
|
||||
|
||||
test('empty state messages are correct when PKI not configured', async function (assert) {
|
||||
assert.expect(10);
|
||||
assert.expect(17);
|
||||
const assertEmptyState = (assert, resource) => {
|
||||
assert.strictEqual(currentURL(), `/vault/secrets/${this.mountPath}/pki/${resource}`);
|
||||
assert
|
||||
@ -73,6 +73,7 @@ module('Acceptance | pki workflow', function (hooks) {
|
||||
'PKI not configured',
|
||||
`${resource} index renders correct empty state title when PKI not configured`
|
||||
);
|
||||
assert.dom(SELECTORS.emptyStateLink).hasText('Configure PKI');
|
||||
assert
|
||||
.dom(SELECTORS.emptyStateMessage)
|
||||
.hasText(
|
||||
@ -84,9 +85,8 @@ module('Acceptance | pki workflow', function (hooks) {
|
||||
await visit(`/vault/secrets/${this.mountPath}/pki/overview`);
|
||||
assert.strictEqual(currentURL(), `/vault/secrets/${this.mountPath}/pki/overview`);
|
||||
|
||||
// TODO comment in when roles index empty state updated & update assert.expect() number
|
||||
// await click(SELECTORS.rolesTab);
|
||||
// assertEmptyState(assert, 'roles');
|
||||
await click(SELECTORS.rolesTab);
|
||||
assertEmptyState(assert, 'roles');
|
||||
|
||||
await click(SELECTORS.issuersTab);
|
||||
assertEmptyState(assert, 'issuers');
|
||||
@ -109,6 +109,7 @@ module('Acceptance | pki workflow', function (hooks) {
|
||||
allow_subdomains=true \
|
||||
max_ttl="720h"`,
|
||||
]);
|
||||
await runCommands([`write ${this.mountPath}/root/generate/internal common_name="Hashicorp Test"`]);
|
||||
const pki_admin_policy = adminPolicy(this.mountPath, 'roles');
|
||||
const pki_reader_policy = readerPolicy(this.mountPath, 'roles');
|
||||
const pki_editor_policy = updatePolicy(this.mountPath, 'roles');
|
||||
|
||||
@ -10,6 +10,7 @@ export const SELECTORS = {
|
||||
pageTitle: '[data-test-pki-role-page-title]',
|
||||
alertBanner: '[data-test-alert-banner="alert"]',
|
||||
emptyStateTitle: '[data-test-empty-state-title]',
|
||||
emptyStateLink: '.empty-state-actions a',
|
||||
emptyStateMessage: '[data-test-empty-state-message]',
|
||||
// TABS
|
||||
overviewTab: '[data-test-secret-list-tab="Overview"]',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user