diff --git a/ui/app/controllers/vault/cluster/auth.js b/ui/app/controllers/vault/cluster/auth.js index 7156ade999..93b267bf33 100644 --- a/ui/app/controllers/vault/cluster/auth.js +++ b/ui/app/controllers/vault/cluster/auth.js @@ -7,6 +7,7 @@ import { inject as service } from '@ember/service'; import { alias } from '@ember/object/computed'; import Controller, { inject as controller } from '@ember/controller'; import { task, timeout } from 'ember-concurrency'; +import { sanitizePath } from 'core/utils/sanitize-path'; export default Controller.extend({ flashMessages: service(), @@ -24,30 +25,34 @@ export default Controller.extend({ authMethod: '', oidcProvider: '', - get managedNamespaceChild() { - const fullParam = this.namespaceQueryParam; - const split = fullParam.split('/'); - if (split.length > 1) { - split.shift(); - return `/${split.join('/')}`; + get namespaceInput() { + const namespaceQP = this.clusterController.namespaceQueryParam; + if (this.managedNamespaceRoot) { + // When managed, the user isn't allowed to edit the prefix `admin/` for their nested namespace + const split = namespaceQP.split('/'); + if (split.length > 1) { + split.shift(); + return `/${split.join('/')}`; + } + return ''; } - return ''; + return namespaceQP; }, - updateManagedNamespace: task(function* (value) { - // debounce - yield timeout(500); - // TODO: Move this to shared fn - const newNamespace = `${this.managedNamespaceRoot}${value}`; - this.namespaceService.setNamespace(newNamespace, true); - this.set('namespaceQueryParam', newNamespace); - }).restartable(), + fullNamespaceFromInput(value) { + const strippedNs = sanitizePath(value); + if (this.managedNamespaceRoot) { + return `${this.managedNamespaceRoot}/${strippedNs}`; + } + return strippedNs; + }, updateNamespace: task(function* (value) { // debounce yield timeout(500); - this.namespaceService.setNamespace(value, true); - this.set('namespaceQueryParam', value); + const ns = this.fullNamespaceFromInput(value); + this.namespaceService.setNamespace(ns, true); + this.set('namespaceQueryParam', ns); }).restartable(), authSuccess({ isRoot, namespace }) { diff --git a/ui/app/services/console.js b/ui/app/services/console.js index 49680e3af8..8e8d91c91e 100644 --- a/ui/app/services/console.js +++ b/ui/app/services/console.js @@ -13,14 +13,7 @@ import { getOwner } from '@ember/application'; import { computed } from '@ember/object'; import { shiftCommandIndex } from 'vault/lib/console-helpers'; import { encodePath } from 'vault/utils/path-encoding-helpers'; - -export function sanitizePath(path) { - //remove whitespace + remove trailing and leading slashes - return path.trim().replace(/^\/+|\/+$/g, ''); -} -export function ensureTrailingSlash(path) { - return path.replace(/(\w+[^/]$)/g, '$1/'); -} +import { sanitizePath, ensureTrailingSlash } from 'core/utils/sanitize-path'; const VERBS = { read: 'GET', diff --git a/ui/app/services/path-help.js b/ui/app/services/path-help.js index 78d617448a..14695f5522 100644 --- a/ui/app/services/path-help.js +++ b/ui/app/services/path-help.js @@ -23,10 +23,7 @@ import { singularize } from 'ember-inflector'; import { withModelValidations } from 'vault/decorators/model-validations'; import generatedItemAdapter from 'vault/adapters/generated-item-list'; -export function sanitizePath(path) { - // remove whitespace + remove trailing and leading slashes - return path.trim().replace(/^\/+|\/+$/g, ''); -} +import { sanitizePath } from 'core/utils/sanitize-path'; export default Service.extend({ attrs: null, diff --git a/ui/app/templates/vault/cluster/auth.hbs b/ui/app/templates/vault/cluster/auth.hbs index 2192c4390c..95e5e8d30c 100644 --- a/ui/app/templates/vault/cluster/auth.hbs +++ b/ui/app/templates/vault/cluster/auth.hbs @@ -49,52 +49,25 @@ {{/if}} {{#unless this.mfaAuthData}} - {{#if this.managedNamespaceRoot}} - - - - - - Namespace - - - /{{this.managedNamespaceRoot}} - - - - - - - - - - - - - {{else if (has-feature "Namespaces")}} + {{#if (has-feature "Namespaces")}} Namespace + {{#if this.managedNamespaceRoot}} + + /{{this.managedNamespaceRoot}} + + {{/if}}