diff --git a/ui/app/adapters/cluster.js b/ui/app/adapters/cluster.js index 131d143e84..19f7682f71 100644 --- a/ui/app/adapters/cluster.js +++ b/ui/app/adapters/cluster.js @@ -61,6 +61,12 @@ export default ApplicationAdapter.extend({ } if (replicationStatus && replicationStatus instanceof AdapterError === false) { ret = Object.assign(ret, replicationStatus.data); + } else if ( + replicationStatus instanceof AdapterError && + replicationStatus?.errors.find((err) => err === 'disabled path') + ) { + // set redacted if result is an error which only happens when redacted + ret = Object.assign(ret, { replication_redacted: true }); } return resolve(ret); }); diff --git a/ui/app/components/sidebar/nav/cluster.hbs b/ui/app/components/sidebar/nav/cluster.hbs index 6668bade2e..bb3c142de0 100644 --- a/ui/app/components/sidebar/nav/cluster.hbs +++ b/ui/app/components/sidebar/nav/cluster.hbs @@ -52,7 +52,14 @@ }} Monitoring {{/if}} - {{#if (and this.version.isEnterprise this.namespace.inRootNamespace (has-permission "status" routeParams="replication"))}} + {{#if + (and + this.version.isEnterprise + this.namespace.inRootNamespace + (not this.cluster.replicationRedacted) + (has-permission "status" routeParams="replication") + ) + }} {{/if}} - {{#if (and @isRootNamespace (has-permission "status" routeParams="replication"))}} + {{#if + (and @isRootNamespace (has-permission "status" routeParams="replication") (not (is-empty-value @replication))) + }} { return this._super(...arguments); }); diff --git a/ui/mirage/handlers/reduced-disclosure.js b/ui/mirage/handlers/reduced-disclosure.js index c0be1b072b..73fc189d36 100644 --- a/ui/mirage/handlers/reduced-disclosure.js +++ b/ui/mirage/handlers/reduced-disclosure.js @@ -4,6 +4,7 @@ */ import modifyPassthroughResponse from '../helpers/modify-passthrough-response'; +import { Response } from 'miragejs'; export default function (server) { server.get('/sys/health', (schema, req) => @@ -12,7 +13,10 @@ export default function (server) { server.get('/sys/seal-status', (schema, req) => modifyPassthroughResponse(req, { version: '', cluster_name: '', build_date: '' }) ); - server.get('sys/replication/status', () => new Response(404)); - server.get('sys/replication/dr/status', () => new Response(404)); - server.get('sys/replication/performance/status', () => new Response(404)); + server.get('sys/replication/status', () => new Response(404, {}, { errors: ['disabled path'] })); + server.get('sys/replication/dr/status', () => new Response(404, {}, { errors: ['disabled path'] })); + server.get( + 'sys/replication/performance/status', + () => new Response(404, {}, { errors: ['disabled path'] }) + ); } diff --git a/ui/tests/acceptance/enterprise-reduced-disclosure-test.js b/ui/tests/acceptance/enterprise-reduced-disclosure-test.js index 93976d204d..ad5b8c332a 100644 --- a/ui/tests/acceptance/enterprise-reduced-disclosure-test.js +++ b/ui/tests/acceptance/enterprise-reduced-disclosure-test.js @@ -134,4 +134,17 @@ module('Acceptance | Enterprise | reduced disclosure test', function (hooks) { .dom('[data-test-footer-version]') .hasText(`Vault ${versionSvc.version}`, 'Version is shown after login'); }); + + test('does not allow access to replication pages', async function (assert) { + await authPage.login(); + assert.dom('[data-test-sidebar-nav-link="Replication"]').doesNotExist('hides replication nav item'); + + await visit(`/vault/replication/dr`); + assert.strictEqual( + currentRouteName(), + 'vault.cluster.dashboard', + 'redirects to dashboard if replication access attempted' + ); + assert.dom('[data-test-card="replication"]').doesNotExist('hides replication card on dashboard'); + }); });