UI namespace additions (#5150)

* add switch link on namespace link page if user has access to the namespace
* refresh list when you delete, only show manage if you can list
* fix bug where disconnected namespaces wouldn't show the picker properly
* namespaces list should end in a slash
* end full namespace paths with a /
* shorten pop up menu link
This commit is contained in:
Matthew Irish 2018-08-22 11:13:28 -05:00 committed by GitHub
parent 62eae43c07
commit d6ab7bcd54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 61 additions and 9 deletions

View File

@ -9,11 +9,12 @@ export default Ember.Component.extend({
componentName: null,
hasMenu: false,
callMethod: task(function*(method, model, successMessage, failureMessage) {
callMethod: task(function*(method, model, successMessage, failureMessage, successCallback = () => {}) {
let flash = this.get('flashMessages');
try {
yield model[method]();
flash.success(successMessage);
successCallback();
} catch (e) {
let errString = e.errors.join(' ');
flash.danger(failureMessage + errString);

View File

@ -0,0 +1,14 @@
import Ember from 'ember';
const { computed, inject, Controller } = Ember;
export default Controller.extend({
namespaceService: inject.service('namespace'),
accessibleNamespaces: computed.alias('namespaceService.accessibleNamespaces'),
currentNamespace: computed.alias('namespaceService.path'),
actions: {
refreshNamespaceList() {
// fetch new namespaces for the namespace picker
this.get('namespaceService.findNamespacesForUser').perform();
},
},
});

View File

@ -1,5 +1,6 @@
import Ember from 'ember';
import { task } from 'ember-concurrency';
import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities';
const { Service, computed, inject } = Ember;
const ROOT_NAMESPACE = '';
@ -18,6 +19,8 @@ export default Service.extend({
setNamespace(path) {
this.set('path', path);
},
listPath: lazyCapabilities(apiPath`sys/namespaces/`, 'path'),
canList: computed.alias('listPath.canList'),
findNamespacesForUser: task(function*() {
// uses the adapter and the raw response here since
@ -25,14 +28,28 @@ export default Service.extend({
// want to keep track of these separately
let store = this.get('store');
let adapter = store.adapterFor('namespace');
let userRoot = this.get('auth.authData.userRootNamespace');
try {
let ns = yield adapter.findAll(store, 'namespace', null, {
adapterOptions: {
forUser: true,
namespace: this.get('userRootNamespace'),
namespace: userRoot,
},
});
this.set('accessibleNamespaces', ns.data.keys.map(n => n.replace(/\/$/, '')));
this.set(
'accessibleNamespaces',
ns.data.keys.map(n => {
let fullNS = n;
// if the user's root isn't '', then we need to construct
// the paths so they connect to the user root to the list
// otherwise using the current ns to grab the correct leaf
// node in the graph doesn't work
if (userRoot) {
fullNS = `${userRoot}/${n}`;
}
return fullNS.replace(/\/$/, '');
})
);
} catch (e) {
//do nothing here
}

View File

@ -33,15 +33,17 @@
{{/if}}
</div>
<div class="level-right">
{{#link-to "vault.cluster.access.namespaces" class="namespace-manage-link"}}
Manage
{{/link-to}}
{{#if namespaceService.canList}}
{{#link-to "vault.cluster.access.namespaces" class="namespace-manage-link"}}
Manage
{{/link-to}}
{{/if}}
</div>
</div>
<header class="current-namespace">
<h5 class="namespace-header">Current namespace</h5>
<div class="level is-mobile namespace-link">
<span class="level-left">{{or namespacePath "root"}}</span>
<span class="level-left">{{if namespacePath (concat namespacePath "/") "root"}}</span>
<ICon @glyph="checkmark-circled-outline" @size="16" @class="has-text-success level-right" />
</div>
</header>

View File

@ -1,5 +1,5 @@
{{#if showMessage}}
<p class="namespace-reminder">
This {{noun}} will be {{modeVerb}} in the <span class="tag">{{namespace.path}}</span>namespace.
This {{noun}} will be {{modeVerb}} in the <span class="tag">{{namespace.path}}/</span>namespace.
</p>
{{/if}}

View File

@ -18,12 +18,30 @@
{{list.item.id}}
</Item.content>
<Item.menu>
{{#with (concat currentNamespace (if currentNamespace "/") list.item.id) as |targetNamespace|}}
{{#if (contains targetNamespace accessibleNamespaces)}}
<li class="action">
{{#link-to "vault.cluster.secrets" (query-params namespace=targetNamespace) class="is-block"}}
Switch to namespace
{{/link-to}}
</li>
{{/if}}
{{/with}}
<li class="action">
<ConfirmAction
@confirmButtonClasses="button is-primary"
@confirmButtonText="Remove"
@buttonClasses="link is-destroy"
@onConfirmAction={{action (perform Item.callMethod "destroyRecord" list.item (concat "Successfully deleted namespace: " list.item.id) "There was an error deleting this namespace: ") }}
@onConfirmAction={{action
(perform
Item.callMethod
"destroyRecord"
list.item
(concat "Successfully deleted namespace: " list.item.id)
"There was an error deleting this namespace: "
(action "refreshNamespaceList")
)
}}
@confirmMessage={{concat "Are you sure you want to delete " list.item.id "?"}}
@showConfirm={{get this (concat "shouldDelete-" list.item.id)}}
@class={{if (get this (concat "shouldDelete-" list.item.id)) "message is-block is-warning is-outline"}}