mirror of
https://github.com/hashicorp/vault.git
synced 2025-12-09 11:31:52 +01:00
UI: wrap client count card in permission conditional (#26848)
* consistent timestamp format * wrap client count card in permissions * add test * add changelog * move tests into module, add more! * final test cleanup, stub permissions manually without helper * use current_billing_period for dashboard, add tests * update mirage to handle new client param * Update ui/app/components/dashboard/client-count-card.js
This commit is contained in:
parent
57e6795c0c
commit
1e8eefade1
3
changelog/26848.txt
Normal file
3
changelog/26848.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
```release-note:improvement
|
||||||
|
ui: Hide dashboard client count card if user does not have permission to view clients.
|
||||||
|
```
|
||||||
@ -11,6 +11,11 @@ export default class ActivityAdapter extends ApplicationAdapter {
|
|||||||
// create date object from user's input using Date.UTC() then send to backend as unix
|
// create date object from user's input using Date.UTC() then send to backend as unix
|
||||||
// time params from the backend are formatted as a zulu timestamp
|
// time params from the backend are formatted as a zulu timestamp
|
||||||
formatQueryParams(queryParams) {
|
formatQueryParams(queryParams) {
|
||||||
|
if (queryParams?.current_billing_period) {
|
||||||
|
// { current_billing_period: true } automatically queries the activity log
|
||||||
|
// from the builtin license start timestamp to the current month
|
||||||
|
return queryParams;
|
||||||
|
}
|
||||||
let { start_time, end_time } = queryParams;
|
let { start_time, end_time } = queryParams;
|
||||||
start_time = start_time.timestamp || formatDateObject(start_time);
|
start_time = start_time.timestamp || formatDateObject(start_time);
|
||||||
end_time = end_time.timestamp || formatDateObject(end_time, true);
|
end_time = end_time.timestamp || formatDateObject(end_time, true);
|
||||||
|
|||||||
@ -14,11 +14,7 @@
|
|||||||
|
|
||||||
<hr class="has-background-gray-100" />
|
<hr class="has-background-gray-100" />
|
||||||
|
|
||||||
{{#if this.noActivityData}}
|
{{#if this.hasActivity}}
|
||||||
{{! This will likely not be show since the client activity api was changed to always return data. In the past it
|
|
||||||
would return no activity data. Adding this empty state here to match the current client count behavior }}
|
|
||||||
<Clients::NoData @config={{this.clientConfig}} />
|
|
||||||
{{else}}
|
|
||||||
{{#if this.fetchClientActivity.isRunning}}
|
{{#if this.fetchClientActivity.isRunning}}
|
||||||
<VaultLogoSpinner />
|
<VaultLogoSpinner />
|
||||||
{{else}}
|
{{else}}
|
||||||
@ -44,5 +40,9 @@
|
|||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
{{! This will likely never show since the clients activity api has changed to always return data. In the past it
|
||||||
|
would return no activity data. Adding this empty state here to match the current client count behavior }}
|
||||||
|
<Clients::NoData @config={{hash enabled="On"}} />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</Hds::Card::Container>
|
</Hds::Card::Container>
|
||||||
@ -9,27 +9,22 @@ import { task } from 'ember-concurrency';
|
|||||||
import { waitFor } from '@ember/test-waiters';
|
import { waitFor } from '@ember/test-waiters';
|
||||||
import { tracked } from '@glimmer/tracking';
|
import { tracked } from '@glimmer/tracking';
|
||||||
import { service } from '@ember/service';
|
import { service } from '@ember/service';
|
||||||
import { setStartTimeQuery } from 'core/utils/client-count-utils';
|
import { parseAPITimestamp } from 'core/utils/date-formatters';
|
||||||
import { dateFormat } from 'core/helpers/date-format';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @module DashboardClientCountCard
|
* @module DashboardClientCountCard
|
||||||
* DashboardClientCountCard component are used to display total and new client count information
|
* DashboardClientCountCard component are used to display total and new client count information
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
*
|
* <Dashboard::ClientCountCard />
|
||||||
* <Dashboard::ClientCountCard @isEnterprise={{@version.isEnterprise}} />
|
|
||||||
*
|
|
||||||
* @param {boolean} isEnterprise - used for setting the start time for the activity log query
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default class DashboardClientCountCard extends Component {
|
export default class DashboardClientCountCard extends Component {
|
||||||
@service store;
|
@service store;
|
||||||
|
|
||||||
clientConfig = null;
|
|
||||||
licenseStartTime = null;
|
|
||||||
@tracked activityData = null;
|
@tracked activityData = null;
|
||||||
@tracked updatedAt = timestamp.now().toISOString();
|
@tracked hasActivity = false;
|
||||||
|
@tracked updatedAt = null;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super(...arguments);
|
super(...arguments);
|
||||||
@ -41,12 +36,11 @@ export default class DashboardClientCountCard extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get statSubText() {
|
get statSubText() {
|
||||||
const format = (date) => dateFormat([date, 'MMM yyyy'], {});
|
const format = (date) => parseAPITimestamp(date, 'MMM yyyy');
|
||||||
return this.licenseStartTime
|
const { startTime, endTime } = this.activityData;
|
||||||
|
return startTime && endTime
|
||||||
? {
|
? {
|
||||||
total: `The number of clients in this billing period (${format(this.licenseStartTime)} - ${format(
|
total: `The number of clients in this billing period (${format(startTime)} - ${format(endTime)}).`,
|
||||||
this.updatedAt
|
|
||||||
)}).`,
|
|
||||||
new: 'The number of clients new to Vault in the current month.',
|
new: 'The number of clients new to Vault in the current month.',
|
||||||
}
|
}
|
||||||
: { total: 'No total client data available.', new: 'No new client data available.' };
|
: { total: 'No total client data available.', new: 'No new client data available.' };
|
||||||
@ -58,20 +52,11 @@ export default class DashboardClientCountCard extends Component {
|
|||||||
if (e) e.preventDefault();
|
if (e) e.preventDefault();
|
||||||
this.updatedAt = timestamp.now().toISOString();
|
this.updatedAt = timestamp.now().toISOString();
|
||||||
|
|
||||||
if (!this.clientConfig) {
|
|
||||||
// set config and license start time when component initializes
|
|
||||||
this.clientConfig = yield this.store.queryRecord('clients/config', {}).catch(() => {});
|
|
||||||
this.licenseStartTime = setStartTimeQuery(this.args.isEnterprise, this.clientConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
// only make the network request if we have a start_time
|
|
||||||
if (!this.licenseStartTime) return {};
|
|
||||||
try {
|
try {
|
||||||
this.activityData = yield this.store.queryRecord('clients/activity', {
|
this.activityData = yield this.store.queryRecord('clients/activity', {
|
||||||
start_time: { timestamp: this.licenseStartTime },
|
current_billing_period: true,
|
||||||
end_time: { timestamp: this.updatedAt },
|
|
||||||
});
|
});
|
||||||
this.noActivityData = this.activityData.activity.id === 'no-data' ? true : false;
|
this.hasActivity = this.activityData.id === 'no-data' ? false : true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.error = error;
|
this.error = error;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,10 +9,10 @@
|
|||||||
<div class="is-flex-row gap-24">
|
<div class="is-flex-row gap-24">
|
||||||
{{#if (and @version.isEnterprise @isRootNamespace)}}
|
{{#if (and @version.isEnterprise @isRootNamespace)}}
|
||||||
<div class="is-flex-column is-flex-1 gap-24">
|
<div class="is-flex-column is-flex-1 gap-24">
|
||||||
<Dashboard::ClientCountCard @isEnterprise={{@version.isEnterprise}} />
|
{{#if (has-permission "clients" routeParams="activity")}}
|
||||||
{{#if
|
<Dashboard::ClientCountCard />
|
||||||
(and @isRootNamespace (has-permission "status" routeParams="replication") (not (is-empty-value @replication)))
|
{{/if}}
|
||||||
}}
|
{{#if (and (has-permission "status" routeParams="replication") (not (is-empty-value @replication)))}}
|
||||||
<Dashboard::ReplicationCard
|
<Dashboard::ReplicationCard
|
||||||
@replication={{@replication}}
|
@replication={{@replication}}
|
||||||
@version={{@version}}
|
@version={{@version}}
|
||||||
|
|||||||
@ -79,7 +79,7 @@
|
|||||||
/>
|
/>
|
||||||
<small class="has-left-margin-xs has-text-grey">
|
<small class="has-left-margin-xs has-text-grey">
|
||||||
Updated
|
Updated
|
||||||
{{date-format @updatedAt "MMM dd, yyyy hh:mm:ss"}}
|
{{date-format @updatedAt "MMM d yyyy, h:mm:ss aaa" withTimeZone=true}}
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|||||||
@ -216,6 +216,12 @@ export default function (server) {
|
|||||||
|
|
||||||
server.get('/sys/internal/counters/activity', (schema, req) => {
|
server.get('/sys/internal/counters/activity', (schema, req) => {
|
||||||
let { start_time, end_time } = req.queryParams;
|
let { start_time, end_time } = req.queryParams;
|
||||||
|
if (req.queryParams.current_billing_period) {
|
||||||
|
// { current_billing_period: true } automatically queries the activity log
|
||||||
|
// from the builtin license start timestamp to the current month
|
||||||
|
start_time = LICENSE_START.toISOString();
|
||||||
|
end_time = STATIC_NOW.toISOString();
|
||||||
|
}
|
||||||
// backend returns a timestamp if given unix time, so first convert to timestamp string here
|
// backend returns a timestamp if given unix time, so first convert to timestamp string here
|
||||||
if (!start_time.includes('T')) start_time = fromUnixTime(start_time).toISOString();
|
if (!start_time.includes('T')) start_time = fromUnixTime(start_time).toISOString();
|
||||||
if (!end_time.includes('T')) end_time = fromUnixTime(end_time).toISOString();
|
if (!end_time.includes('T')) end_time = fromUnixTime(end_time).toISOString();
|
||||||
|
|||||||
@ -9,11 +9,12 @@ import { render, click } from '@ember/test-helpers';
|
|||||||
import { hbs } from 'ember-cli-htmlbars';
|
import { hbs } from 'ember-cli-htmlbars';
|
||||||
import { setupMirage } from 'ember-cli-mirage/test-support';
|
import { setupMirage } from 'ember-cli-mirage/test-support';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import { LICENSE_START, STATIC_NOW } from 'vault/mirage/handlers/clients';
|
import { STATIC_NOW } from 'vault/mirage/handlers/clients';
|
||||||
import timestamp from 'core/utils/timestamp';
|
import timestamp from 'core/utils/timestamp';
|
||||||
import { ACTIVITY_RESPONSE_STUB } from 'vault/tests/helpers/clients/client-count-helpers';
|
import { ACTIVITY_RESPONSE_STUB } from 'vault/tests/helpers/clients/client-count-helpers';
|
||||||
import { formatNumber } from 'core/helpers/format-number';
|
import { formatNumber } from 'core/helpers/format-number';
|
||||||
import { CLIENT_COUNT } from 'vault/tests/helpers/clients/client-count-selectors';
|
import { CLIENT_COUNT } from 'vault/tests/helpers/clients/client-count-selectors';
|
||||||
|
import { GENERAL } from 'vault/tests/helpers/general-selectors';
|
||||||
|
|
||||||
module('Integration | Component | dashboard/client-count-card', function (hooks) {
|
module('Integration | Component | dashboard/client-count-card', function (hooks) {
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
@ -21,37 +22,31 @@ module('Integration | Component | dashboard/client-count-card', function (hooks)
|
|||||||
|
|
||||||
test('it should display client count information', async function (assert) {
|
test('it should display client count information', async function (assert) {
|
||||||
sinon.replace(timestamp, 'now', sinon.fake.returns(STATIC_NOW));
|
sinon.replace(timestamp, 'now', sinon.fake.returns(STATIC_NOW));
|
||||||
assert.expect(6);
|
assert.expect(5);
|
||||||
const { months, total } = ACTIVITY_RESPONSE_STUB;
|
const { months, total } = ACTIVITY_RESPONSE_STUB;
|
||||||
const [latestMonth] = months.slice(-1);
|
const [latestMonth] = months.slice(-1);
|
||||||
this.server.get('sys/internal/counters/activity', () => {
|
this.server.get('sys/internal/counters/activity', (schema, req) => {
|
||||||
// this assertion should be hit twice, once initially and then again clicking 'refresh'
|
// this assertion should be hit twice, once initially and then again clicking 'refresh'
|
||||||
assert.true(true, 'makes request to sys/internal/counters/activity');
|
assert.propEqual(
|
||||||
|
req.queryParams,
|
||||||
|
{ current_billing_period: 'true' },
|
||||||
|
'it makes request to sys/internal/counters/activity with builtin license start time'
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
request_id: 'some-activity-id',
|
request_id: 'some-activity-id',
|
||||||
data: ACTIVITY_RESPONSE_STUB,
|
data: ACTIVITY_RESPONSE_STUB,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
this.server.get('sys/internal/counters/config', function () {
|
|
||||||
assert.true(true, 'sys/internal/counters/config');
|
|
||||||
return {
|
|
||||||
request_id: 'some-config-id',
|
|
||||||
data: {
|
|
||||||
billing_start_timestamp: LICENSE_START.toISOString(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
await render(hbs`<Dashboard::ClientCountCard @isEnterprise={{true}} />`);
|
await render(hbs`<Dashboard::ClientCountCard />`);
|
||||||
assert.dom('[data-test-client-count-title]').hasText('Client count');
|
assert.dom('[data-test-client-count-title]').hasText('Client count');
|
||||||
assert
|
assert
|
||||||
.dom(CLIENT_COUNT.statText('Total'))
|
.dom(CLIENT_COUNT.statText('Total'))
|
||||||
.hasText(
|
.hasText(
|
||||||
`Total The number of clients in this billing period (Jul 2023 - Jan 2024). ${formatNumber([
|
`Total The number of clients in this billing period (Aug 2023 - Sep 2023). ${formatNumber([
|
||||||
total.clients,
|
total.clients,
|
||||||
])}`
|
])}`
|
||||||
);
|
);
|
||||||
|
|
||||||
assert
|
assert
|
||||||
.dom(CLIENT_COUNT.statText('New'))
|
.dom(CLIENT_COUNT.statText('New'))
|
||||||
.hasText(
|
.hasText(
|
||||||
@ -64,30 +59,35 @@ module('Integration | Component | dashboard/client-count-card', function (hooks)
|
|||||||
await click('[data-test-refresh]');
|
await click('[data-test-refresh]');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('it does not query activity for community edition', async function (assert) {
|
test('it shows no data subtext if no start or end timestamp', async function (assert) {
|
||||||
assert.expect(3);
|
assert.expect(2);
|
||||||
// in the template this component is wrapped in an isEnterprise conditional so this
|
// as far as I know, responses will always have a start/end time
|
||||||
// state is currently not possible, adding a test to safeguard against introducing
|
// stubbing this unrealistic response just to test component subtext logic
|
||||||
// regressions during future refactors
|
this.server.get('sys/internal/counters/activity', () => {
|
||||||
this.server.get(
|
|
||||||
'sys/internal/counters/activity',
|
|
||||||
() => new Error('uh oh! a request was made to sys/internal/counters/activity')
|
|
||||||
);
|
|
||||||
this.server.get('sys/internal/counters/config', function () {
|
|
||||||
assert.true(true, 'sys/internal/counters/config');
|
|
||||||
return {
|
return {
|
||||||
request_id: 'some-config-id',
|
request_id: 'some-activity-id',
|
||||||
data: {
|
data: { by_namespace: [], months: [], total: {} },
|
||||||
billing_start_timestamp: '0001-01-01T00:00:00Z',
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
await render(hbs`<Dashboard::ClientCountCard @isEnterprise={{false}} />`);
|
await render(hbs`<Dashboard::ClientCountCard />`);
|
||||||
assert.dom(CLIENT_COUNT.statText('Total')).hasText('Total No total client data available. -');
|
assert.dom(CLIENT_COUNT.statText('Total')).hasText('Total No total client data available. -');
|
||||||
assert.dom(CLIENT_COUNT.statText('New')).hasText('New No new client data available. -');
|
assert.dom(CLIENT_COUNT.statText('New')).hasText('New No new client data available. -');
|
||||||
|
});
|
||||||
|
|
||||||
// attempt second request to /activity but component task should return instead of hitting endpoint
|
test('it shows empty state if no activity data', async function (assert) {
|
||||||
await click('[data-test-refresh]');
|
// the activity response has changed and now should ALWAYS return something
|
||||||
|
// but adding this test until we update the adapter to reflect that
|
||||||
|
assert.expect(3);
|
||||||
|
this.server.get('sys/internal/counters/activity', () => {
|
||||||
|
assert.true(true, 'makes request to sys/internal/counters/activity');
|
||||||
|
return { data: {} };
|
||||||
|
});
|
||||||
|
|
||||||
|
await render(hbs`<Dashboard::ClientCountCard />`);
|
||||||
|
assert.dom(GENERAL.emptyStateTitle).hasText('No data received');
|
||||||
|
assert
|
||||||
|
.dom(GENERAL.emptyStateMessage)
|
||||||
|
.hasText('Tracking is turned on and Vault is gathering data. It should appear here within 30 minutes.');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import { render } from '@ember/test-helpers';
|
|||||||
import { hbs } from 'ember-cli-htmlbars';
|
import { hbs } from 'ember-cli-htmlbars';
|
||||||
import { setupMirage } from 'ember-cli-mirage/test-support';
|
import { setupMirage } from 'ember-cli-mirage/test-support';
|
||||||
import { DASHBOARD } from 'vault/tests/helpers/components/dashboard/dashboard-selectors';
|
import { DASHBOARD } from 'vault/tests/helpers/components/dashboard/dashboard-selectors';
|
||||||
import { LICENSE_START } from 'vault/mirage/handlers/clients';
|
|
||||||
|
|
||||||
module('Integration | Component | dashboard/overview', function (hooks) {
|
module('Integration | Component | dashboard/overview', function (hooks) {
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
@ -17,7 +16,11 @@ module('Integration | Component | dashboard/overview', function (hooks) {
|
|||||||
|
|
||||||
hooks.beforeEach(function () {
|
hooks.beforeEach(function () {
|
||||||
this.store = this.owner.lookup('service:store');
|
this.store = this.owner.lookup('service:store');
|
||||||
|
this.permissions = this.owner.lookup('service:permissions');
|
||||||
|
this.version = this.owner.lookup('service:version');
|
||||||
|
this.version.version = '1.13.1+ent';
|
||||||
|
this.version.type = 'enterprise';
|
||||||
|
this.isRootNamespace = true;
|
||||||
this.replication = {
|
this.replication = {
|
||||||
dr: {
|
dr: {
|
||||||
clusterId: '123',
|
clusterId: '123',
|
||||||
@ -61,28 +64,29 @@ module('Integration | Component | dashboard/overview', function (hooks) {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
this.refreshModel = () => {};
|
this.refreshModel = () => {};
|
||||||
this.server.get('sys/internal/counters/config', function () {
|
this.renderComponent = async () => {
|
||||||
return {
|
return await render(
|
||||||
request_id: 'some-config-id',
|
hbs`
|
||||||
data: {
|
|
||||||
billing_start_timestamp: LICENSE_START.toISOString(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('it should show dashboard empty states', async function (assert) {
|
|
||||||
this.version = this.owner.lookup('service:version');
|
|
||||||
this.version.version = '1.13.1';
|
|
||||||
this.isRootNamespace = true;
|
|
||||||
await render(
|
|
||||||
hbs`
|
|
||||||
<Dashboard::Overview
|
<Dashboard::Overview
|
||||||
|
@secretsEngines={{this.secretsEngines}}
|
||||||
|
@vaultConfiguration={{this.vaultConfiguration}}
|
||||||
|
@replication={{this.replication}}
|
||||||
@version={{this.version}}
|
@version={{this.version}}
|
||||||
@isRootNamespace={{this.isRootNamespace}}
|
@isRootNamespace={{this.isRootNamespace}}
|
||||||
@refreshModel={{this.refreshModel}} />
|
@refreshModel={{this.refreshModel}}
|
||||||
|
@replicationUpdatedAt={{this.replicationUpdatedAt}}
|
||||||
|
/>
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it should show dashboard empty states in root namespace', async function (assert) {
|
||||||
|
this.version.version = '1.13.1';
|
||||||
|
this.secretsEngines = null;
|
||||||
|
this.replication = null;
|
||||||
|
this.vaultConfiguration = null;
|
||||||
|
await this.renderComponent();
|
||||||
assert.dom(DASHBOARD.cardHeader('Vault version')).exists();
|
assert.dom(DASHBOARD.cardHeader('Vault version')).exists();
|
||||||
assert.dom(DASHBOARD.cardName('secrets-engines')).exists();
|
assert.dom(DASHBOARD.cardName('secrets-engines')).exists();
|
||||||
assert.dom(DASHBOARD.emptyState('secrets-engines')).exists();
|
assert.dom(DASHBOARD.emptyState('secrets-engines')).exists();
|
||||||
@ -94,92 +98,123 @@ module('Integration | Component | dashboard/overview', function (hooks) {
|
|||||||
assert.dom(DASHBOARD.cardName('client-count')).doesNotExist();
|
assert.dom(DASHBOARD.cardName('client-count')).doesNotExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('it should hide client count and replication card on community', async function (assert) {
|
module('client count and replication card', function () {
|
||||||
this.version = this.owner.lookup('service:version');
|
test('it should hide cards on community in root namespace', async function (assert) {
|
||||||
this.version.version = '1.13.1';
|
this.version.version = '1.13.1';
|
||||||
this.isRootNamespace = true;
|
this.version.type = 'community';
|
||||||
|
this.server.get(
|
||||||
|
'sys/internal/counters/activity',
|
||||||
|
() => new Error('uh oh! a request was made to sys/internal/counters/activity')
|
||||||
|
);
|
||||||
|
await this.renderComponent();
|
||||||
|
|
||||||
await render(
|
assert.dom(DASHBOARD.cardHeader('Vault version')).exists();
|
||||||
hbs`
|
assert.dom(DASHBOARD.cardName('secrets-engines')).exists();
|
||||||
<Dashboard::Overview
|
assert.dom(DASHBOARD.cardName('learn-more')).exists();
|
||||||
@secretsEngines={{this.secretsEngines}}
|
assert.dom(DASHBOARD.cardName('quick-actions')).exists();
|
||||||
@vaultConfiguration={{this.vaultConfiguration}}
|
assert.dom(DASHBOARD.cardName('configuration-details')).exists();
|
||||||
@replication={{this.replication}}
|
assert.dom(DASHBOARD.cardName('replication')).doesNotExist();
|
||||||
@version={{this.version}}
|
assert.dom(DASHBOARD.cardName('client-count')).doesNotExist();
|
||||||
@isRootNamespace={{this.isRootNamespace}}
|
});
|
||||||
@refreshModel={{this.refreshModel}} />
|
|
||||||
`
|
|
||||||
);
|
|
||||||
|
|
||||||
assert.dom(DASHBOARD.cardHeader('Vault version')).exists();
|
test('it should hide cards on enterprise if permission but not in root namespace', async function (assert) {
|
||||||
assert.dom(DASHBOARD.cardName('secrets-engines')).exists();
|
this.permissions.exactPaths = {
|
||||||
assert.dom(DASHBOARD.cardName('learn-more')).exists();
|
'sys/internal/counters/activity': {
|
||||||
assert.dom(DASHBOARD.cardName('quick-actions')).exists();
|
capabilities: ['read'],
|
||||||
assert.dom(DASHBOARD.cardName('configuration-details')).exists();
|
},
|
||||||
assert.dom(DASHBOARD.cardName('replication')).doesNotExist();
|
'sys/replication/status': {
|
||||||
assert.dom(DASHBOARD.cardName('client-count')).doesNotExist();
|
capabilities: ['read'],
|
||||||
});
|
},
|
||||||
|
};
|
||||||
|
this.isRootNamespace = false;
|
||||||
|
await this.renderComponent();
|
||||||
|
assert.dom(DASHBOARD.cardName('client-count')).doesNotExist();
|
||||||
|
assert.dom(DASHBOARD.cardName('replication')).doesNotExist();
|
||||||
|
});
|
||||||
|
|
||||||
test('it should show client count on enterprise w/ license', async function (assert) {
|
test('it should show cards on enterprise if has permission and in root namespace', async function (assert) {
|
||||||
this.version = this.owner.lookup('service:version');
|
this.permissions.exactPaths = {
|
||||||
this.version.version = '1.13.1+ent';
|
'sys/internal/counters/activity': {
|
||||||
this.version.type = 'enterprise';
|
capabilities: ['read'],
|
||||||
this.license = {
|
},
|
||||||
autoloaded: {
|
'sys/replication/status': {
|
||||||
license_id: '7adbf1f4-56ef-35cd-3a6c-50ef2627865d',
|
capabilities: ['read'],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
await this.renderComponent();
|
||||||
|
assert.dom(DASHBOARD.cardHeader('Vault version')).exists();
|
||||||
|
assert.dom(DASHBOARD.cardName('secrets-engines')).exists();
|
||||||
|
assert.dom(DASHBOARD.cardName('learn-more')).exists();
|
||||||
|
assert.dom(DASHBOARD.cardName('quick-actions')).exists();
|
||||||
|
assert.dom(DASHBOARD.cardName('configuration-details')).exists();
|
||||||
|
assert.dom(DASHBOARD.cardName('client-count')).exists();
|
||||||
|
assert.dom(DASHBOARD.cardName('replication')).exists();
|
||||||
|
});
|
||||||
|
|
||||||
await render(
|
test('it should hide cards on enterprise in root namespace but no permission', async function (assert) {
|
||||||
hbs`
|
await this.renderComponent();
|
||||||
<Dashboard::Overview
|
assert.dom(DASHBOARD.cardName('client-count')).doesNotExist();
|
||||||
@secretsEngines={{this.secretsEngines}}
|
assert.dom(DASHBOARD.cardName('replication')).doesNotExist();
|
||||||
@vaultConfiguration={{this.vaultConfiguration}}
|
});
|
||||||
@replication={{this.replication}}
|
|
||||||
@version={{this.version}}
|
|
||||||
@isRootNamespace={{true}}
|
|
||||||
@refreshModel={{this.refreshModel}} />`
|
|
||||||
);
|
|
||||||
assert.dom(DASHBOARD.cardHeader('Vault version')).exists();
|
|
||||||
assert.dom(DASHBOARD.cardName('secrets-engines')).exists();
|
|
||||||
assert.dom(DASHBOARD.cardName('learn-more')).exists();
|
|
||||||
assert.dom(DASHBOARD.cardName('quick-actions')).exists();
|
|
||||||
assert.dom(DASHBOARD.cardName('configuration-details')).exists();
|
|
||||||
assert.dom(DASHBOARD.cardName('client-count')).exists();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('it should hide replication on enterprise not on root namespace', async function (assert) {
|
test('it should hide cards on enterprise if no permission and not in root namespace', async function (assert) {
|
||||||
this.version = this.owner.lookup('service:version');
|
this.isRootNamespace = false;
|
||||||
this.version.version = '1.13.1+ent';
|
await this.renderComponent();
|
||||||
this.version.type = 'enterprise';
|
assert.dom(DASHBOARD.cardName('client-count')).doesNotExist();
|
||||||
this.isRootNamespace = false;
|
assert.dom(DASHBOARD.cardName('replication')).doesNotExist();
|
||||||
|
});
|
||||||
|
|
||||||
await render(
|
test('it should hide client count on enterprise in root namespace if no activity permission', async function (assert) {
|
||||||
hbs`
|
this.permissions.exactPaths = {
|
||||||
<Dashboard::Overview
|
'sys/internal/counters/activity': {
|
||||||
@version={{this.version}}
|
capabilities: ['deny'],
|
||||||
@isRootNamespace={{this.isRootNamespace}}
|
},
|
||||||
@secretsEngines={{this.secretsEngines}}
|
'sys/replication/status': {
|
||||||
@vaultConfiguration={{this.vaultConfiguration}}
|
capabilities: ['read'],
|
||||||
@replication={{this.replication}}
|
},
|
||||||
@refreshModel={{this.refreshModel}} />`
|
};
|
||||||
);
|
|
||||||
|
|
||||||
assert.dom(DASHBOARD.cardHeader('Vault version')).exists();
|
await this.renderComponent();
|
||||||
assert.dom('[data-test-badge-namespace]').exists();
|
assert.dom(DASHBOARD.cardName('client-count')).doesNotExist();
|
||||||
assert.dom(DASHBOARD.cardName('secrets-engines')).exists();
|
assert.dom(DASHBOARD.cardName('replication')).exists();
|
||||||
assert.dom(DASHBOARD.cardName('learn-more')).exists();
|
});
|
||||||
assert.dom(DASHBOARD.cardName('quick-actions')).exists();
|
|
||||||
assert.dom(DASHBOARD.cardName('configuration-details')).exists();
|
test('it should hide replication on enterprise in root namespace if no replication status permission', async function (assert) {
|
||||||
assert.dom(DASHBOARD.cardName('replication')).doesNotExist();
|
this.permissions.exactPaths = {
|
||||||
assert.dom(DASHBOARD.cardName('client-count')).doesNotExist();
|
'sys/internal/counters/activity': {
|
||||||
|
capabilities: ['read'],
|
||||||
|
},
|
||||||
|
'sys/replication/status': {
|
||||||
|
capabilities: ['deny'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await this.renderComponent();
|
||||||
|
assert.dom(DASHBOARD.cardName('client-count')).exists();
|
||||||
|
assert.dom(DASHBOARD.cardName('replication')).doesNotExist();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it should hide replication on enterprise if has permission and in root namespace but is empty', async function (assert) {
|
||||||
|
this.permissions.exactPaths = {
|
||||||
|
'sys/internal/counters/activity': {
|
||||||
|
capabilities: ['read'],
|
||||||
|
},
|
||||||
|
'sys/replication/status': {
|
||||||
|
capabilities: ['read'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
this.replication = {};
|
||||||
|
await this.renderComponent();
|
||||||
|
assert.dom(DASHBOARD.cardName('client-count')).exists();
|
||||||
|
assert.dom(DASHBOARD.cardName('replication')).doesNotExist();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module('learn more card', function () {
|
module('learn more card', function () {
|
||||||
test('shows the learn more card on community', async function (assert) {
|
test('shows the learn more card on community', async function (assert) {
|
||||||
await render(
|
this.version.version = '1.13.1';
|
||||||
hbs`<Dashboard::Overview @secretsEngines={{this.secretsEngines}} @vaultConfiguration={{this.vaultConfiguration}} @replication={{this.replication}} @refreshModel={{this.refreshModel}} />`
|
this.version.type = 'community';
|
||||||
);
|
await this.renderComponent();
|
||||||
|
|
||||||
assert.dom('[data-test-learn-more-title]').hasText('Learn more');
|
assert.dom('[data-test-learn-more-title]').hasText('Learn more');
|
||||||
assert
|
assert
|
||||||
@ -193,32 +228,13 @@ module('Integration | Component | dashboard/overview', function (hooks) {
|
|||||||
.hasText("Don't see what you're looking for on this page? Let us know via our feedback form .");
|
.hasText("Don't see what you're looking for on this page? Let us know via our feedback form .");
|
||||||
});
|
});
|
||||||
test('shows the learn more card on enterprise', async function (assert) {
|
test('shows the learn more card on enterprise', async function (assert) {
|
||||||
this.version = this.owner.lookup('service:version');
|
|
||||||
this.version.version = '1.13.1+ent';
|
|
||||||
this.version.type = 'enterprise';
|
|
||||||
this.version.features = [
|
this.version.features = [
|
||||||
'Performance Replication',
|
'Performance Replication',
|
||||||
'DR Replication',
|
'DR Replication',
|
||||||
'Namespaces',
|
'Namespaces',
|
||||||
'Transform Secrets Engine',
|
'Transform Secrets Engine',
|
||||||
];
|
];
|
||||||
this.isRootNamespace = true;
|
await this.renderComponent();
|
||||||
this.license = {
|
|
||||||
autoloaded: {
|
|
||||||
license_id: '7adbf1f4-56ef-35cd-3a6c-50ef2627865d',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
await render(
|
|
||||||
hbs`
|
|
||||||
<Dashboard::Overview
|
|
||||||
@version={{this.version}}
|
|
||||||
@isRootNamespace={{this.isRootNamespace}}
|
|
||||||
@secretsEngines={{this.secretsEngines}}
|
|
||||||
@vaultConfiguration={{this.vaultConfiguration}}
|
|
||||||
@replication={{this.replication}}
|
|
||||||
@refreshModel={{this.refreshModel}} />
|
|
||||||
`
|
|
||||||
);
|
|
||||||
assert.dom('[data-test-learn-more-title]').hasText('Learn more');
|
assert.dom('[data-test-learn-more-title]').hasText('Learn more');
|
||||||
assert
|
assert
|
||||||
.dom('[data-test-learn-more-subtext]')
|
.dom('[data-test-learn-more-subtext]')
|
||||||
|
|||||||
@ -136,4 +136,18 @@ module('Unit | Adapter | clients activity', function (hooks) {
|
|||||||
|
|
||||||
this.store.queryRecord(this.modelName, queryParams);
|
this.store.queryRecord(this.modelName, queryParams);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('it sends current billing period boolean if provided', async function (assert) {
|
||||||
|
assert.expect(1);
|
||||||
|
|
||||||
|
this.server.get('sys/internal/counters/activity', (schema, req) => {
|
||||||
|
assert.propEqual(
|
||||||
|
req.queryParams,
|
||||||
|
{ current_billing_period: 'true' },
|
||||||
|
'it passes current_billing_period to query record'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.store.queryRecord(this.modelName, { current_billing_period: true });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user