Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI - identity details #4502

Merged
merged 27 commits into from
May 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4637e10
add popup to entity / group list
meirish Apr 11, 2018
efba180
add alias popover menu
meirish Apr 20, 2018
e6362c2
add metadata popover
meirish Apr 24, 2018
d247f37
more metadata popups
meirish Apr 24, 2018
173d532
use base popup component and convert identity popups to use it
meirish Apr 25, 2018
2cc75f5
add group members popup
meirish Apr 26, 2018
12d35f4
add ability to disable entity and banner when entity is disabled
meirish Apr 30, 2018
73bc868
re-add alias-popup template
meirish Apr 30, 2018
855043e
add accpetance tests for creating entities
meirish Apr 30, 2018
00ac6ee
add more entity creation acceptance tests
meirish Apr 30, 2018
bc98ae1
add delete to edit-form
meirish May 1, 2018
e3a251c
add more identity tests and associated selectors
meirish May 2, 2018
bf748cc
add onSuccess hook and use UnloadModel route mixins
meirish May 2, 2018
02a0cae
add ability to toggle entity disabling from the popover
meirish May 2, 2018
b546c7a
fix store list cache because unloadAll isn't synchronous
meirish May 2, 2018
3da2e1d
fill out tests for identity items and aliases
meirish May 2, 2018
700bfe7
add ability to enable entity from the detail page
meirish May 2, 2018
c660e07
toArray on the peekAll
meirish May 2, 2018
07811f2
fix other tests/behavior that relied on a RecordArray
meirish May 3, 2018
f290211
adjust layout for disabled entity and label for disabling an entity o…
meirish May 3, 2018
e9314ca
add item-details integration tests
meirish May 3, 2018
6b531b3
move disable field on the entity form
meirish May 3, 2018
b050f5f
use ghost buttons for delete in identity and policy edit forms
meirish May 8, 2018
f317154
review feedback
meirish May 23, 2018
feba7a9
adding computed macros for lazy capability fetching and using them in…
meirish May 23, 2018
d195251
prettier
meirish May 24, 2018
8c5aefd
Merge branch 'master' into ui-identity-details
meirish May 24, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ui/app/components/confirm-action.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default Ember.Component.extend({
class={{buttonClasses}}
type="button"
disabled={{disabled}}
data-test-confirm-action-trigger=true

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was there a particular motivation for assigning true rather than assigning it nothing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh ha, just habit from components 😬

{{action 'toggleConfirm'}}
>
{{yield}}
Expand Down
40 changes: 40 additions & 0 deletions ui/app/components/identity/_popup-base.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import Ember from 'ember';
const { assert, inject, Component } = Ember;

export default Component.extend({
tagName: '',
flashMessages: inject.service(),
params: null,
successMessage() {
return 'Save was successful';
},
errorMessage() {
return 'There was an error saving';
},
onError(model) {
if (model && model.rollbackAttributes) {
model.rollbackAttributes();
}
},
onSuccess(){},
// override and return a promise
transaction() {
assert('override transaction call in an extension of popup-base', false);
},

actions: {
performTransaction() {
let args = [...arguments];
let messageArgs = this.messageArgs(...args);
return this.transaction(...args)
.then(() => {
this.get('onSuccess')();
this.get('flashMessages').success(this.successMessage(...messageArgs));
})
.catch(e => {
this.onError(...messageArgs);
this.get('flashMessages').success(this.errorMessage(e, ...messageArgs));
});
},
},
});
35 changes: 26 additions & 9 deletions ui/app/components/identity/edit-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@ import Ember from 'ember';
import { task } from 'ember-concurrency';
import { humanize } from 'vault/helpers/humanize';

const { computed } = Ember;
const { computed, inject } = Ember;
export default Ember.Component.extend({
flashMessages: inject.service(),
'data-test-component': 'identity-edit-form',
model: null,

// 'create', 'edit', 'merge'
mode: 'create',
/*
* @param Function
* @public
*
* Optional param to call a function upon successfully mounting a backend
*
* Optional param to call a function upon successfully saving an entity
*/
onSave: () => {},

cancelLink: computed('mode', 'model', function() {
cancelLink: computed('mode', 'model.identityType', function() {
let { model, mode } = this.getProperties('model', 'mode');
let key = `${mode}-${model.get('identityType')}`;
let routes = {
Expand All @@ -33,16 +36,17 @@ export default Ember.Component.extend({
return routes[key];
}),

getMessage(model) {
getMessage(model, isDelete = false) {
let mode = this.get('mode');
let typeDisplay = humanize([model.get('identityType')]);
let action = isDelete ? 'deleted' : 'saved';
if (mode === 'merge') {
return 'Successfully merged entities';
}
if (model.get('id')) {
return `Successfully saved ${typeDisplay} ${model.id}.`;
return `Successfully ${action} ${typeDisplay} ${model.id}.`;
}
return `Successfully saved ${typeDisplay}.`;
return `Successfully ${action} ${typeDisplay}.`;
},

save: task(function*() {
Expand All @@ -56,13 +60,26 @@ export default Ember.Component.extend({
return;
}
this.get('flashMessages').success(message);
yield this.get('onSave')(model);
yield this.get('onSave')({saveType: 'save', model});
}).drop(),

willDestroy() {
let model = this.get('model');
if (!model.isDestroyed || !model.isDestroying) {
if ((model.get('isDirty') && !model.isDestroyed) || !model.isDestroying) {
model.rollbackAttributes();
}
},

actions: {
deleteItem(model) {
let message = this.getMessage(model, true);
let flash = this.get('flashMessages');
model
.destroyRecord()
.then(() => {
flash.success(message);
return this.get('onSave')({saveType: 'delete', model});
});
},
},
});
23 changes: 23 additions & 0 deletions ui/app/components/identity/item-details.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Ember from 'ember';

const { inject } = Ember;

export default Ember.Component.extend({
flashMessages: inject.service(),

actions: {
enable(model) {
model.set('disabled', false);

model.save().
then(() => {
this.get('flashMessages').success(`Successfully enabled entity: ${model.id}`);
})
.catch(e => {
this.get('flashMessages').success(
`There was a problem enabling the entity: ${model.id} - ${e.error.join(' ') || e.message}`
);
});
}
}
});
22 changes: 22 additions & 0 deletions ui/app/components/identity/popup-alias.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import Base from './_popup-base';

export default Base.extend({
messageArgs(model) {
let type = model.get('identityType');
let id = model.id;
return [type, id];
},

successMessage(type, id) {
return `Successfully deleted ${type}: ${id}`;
},

errorMessage(e, type, id) {
let error = e.errors ? e.errors.join(' ') : e.message;
return `There was a problem deleting ${type}: ${id} - ${error}`;
},

transaction(model) {
return model.destroyRecord();
},
});
34 changes: 34 additions & 0 deletions ui/app/components/identity/popup-members.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import Base from './_popup-base';
import Ember from 'ember';
const { computed } = Ember;

export default Base.extend({
model: computed.alias('params.firstObject'),

groupArray: computed('params', function() {
return this.get('params').objectAt(1);
}),

memberId: computed('params', function() {
return this.get('params').objectAt(2);
}),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the event that params is not an ember array (most likely null) this will blow up.


messageArgs(/*model, groupArray, memberId*/) {
return [...arguments];
},

successMessage(model, groupArray, memberId) {
return `Successfully removed '${memberId}' from the group`;
},

errorMessage(e, model, groupArray, memberId) {
let error = e.errors ? e.errors.join(' ') : e.message;
return `There was a problem removing '${memberId}' from the group - ${error}`;
},

transaction(model, groupArray, memberId) {
let members = model.get(groupArray);
model.set(groupArray, members.without(memberId));
return model.save();
},
});
29 changes: 29 additions & 0 deletions ui/app/components/identity/popup-metadata.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Base from './_popup-base';
import Ember from 'ember';
const { computed } = Ember;

export default Base.extend({
model: computed.alias('params.firstObject'),
key: computed('params', function() {
return this.get('params').objectAt(1);
}),

messageArgs(model, key) {
return [model, key];
},

successMessage(model, key) {
return `Successfully removed '${key}' from metadata`;
},
errorMessage(e, model, key) {
let error = e.errors ? e.errors.join(' ') : e.message;
return `There was a problem removing '${key}' from the metadata - ${error}`;
},

transaction(model, key) {
let metadata = model.get('metadata');
delete metadata[key];
model.set('metadata', { ...metadata });
return model.save();
},
});
29 changes: 29 additions & 0 deletions ui/app/components/identity/popup-policy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Base from './_popup-base';
import Ember from 'ember';
const { computed } = Ember;

export default Base.extend({
model: computed.alias('params.firstObject'),
policyName: computed('params', function() {
return this.get('params').objectAt(1);
}),

messageArgs(model, policyName) {
return [model, policyName];
},

successMessage(model, policyName) {
return `Successfully removed '${policyName}' policy from ${model.id} `;
},

errorMessage(e, model, policyName) {
let error = e.errors ? e.errors.join(' ') : e.message;
return `There was a problem removing '${policyName}' policy - ${error}`;
},

transaction(model, policyName) {
let policies = model.get('policies');
model.set('policies', policies.without(policyName));
return model.save();
},
});
1 change: 1 addition & 0 deletions ui/app/components/info-table-row.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Ember from 'ember';

export default Ember.Component.extend({
'data-test-component': 'info-table-row',
classNames: ['info-table-row'],
isVisible: Ember.computed.or('alwaysRender', 'value'),

Expand Down
2 changes: 2 additions & 0 deletions ui/app/components/message-in-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const { computed } = Ember;
export default Ember.Component.extend({
type: null,

yieldWithoutColumn: false,

classNameBindings: ['containerClass'],

containerClass: computed('type', function() {
Expand Down
2 changes: 0 additions & 2 deletions ui/app/components/secret-list-header.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,4 @@ export default Ember.Component.extend({
baseKey: null,
backendCrumb: null,
model: null,


});
2 changes: 1 addition & 1 deletion ui/app/components/tool-actions-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export default Ember.Component.extend(DEFAULTS, {

handleSuccess(resp, action) {
let props = {};
let secret = resp && resp.data || resp.auth;
let secret = (resp && resp.data) || resp.auth;
if (secret && action === 'unwrap') {
props = Ember.assign({}, props, { unwrap_data: secret });
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import Ember from 'ember';
import ListController from 'vault/mixins/list-controller';

export default Ember.Controller.extend(ListController);
export default Ember.Controller.extend(ListController, {
actions: {
onDelete() {
this.send('reload');
}
}
});
23 changes: 21 additions & 2 deletions ui/app/controllers/vault/cluster/access/identity/create.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,26 @@ import { task } from 'ember-concurrency';
export default Ember.Controller.extend({
showRoute: 'vault.cluster.access.identity.show',
showTab: 'details',
navToShow: task(function*(model) {
yield this.transitionToRoute(this.get('showRoute'), model.id, this.get('showTab'));
navAfterSave: task(function*({saveType, model}) {
let isDelete = saveType === 'delete';
let type = model.get('identityType');
let listRoutes= {
'entity-alias': 'vault.cluster.access.identity.aliases.index',
'group-alias': 'vault.cluster.access.identity.aliases.index',
'group': 'vault.cluster.access.identity.index',
'entity': 'vault.cluster.access.identity.index',
};
let routeName = listRoutes[type]
if (!isDelete) {
yield this.transitionToRoute(
this.get('showRoute'),
model.id,
this.get('showTab')
);
return;
}
yield this.transitionToRoute(
routeName
);
}),
});
44 changes: 43 additions & 1 deletion ui/app/controllers/vault/cluster/access/identity/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,46 @@
import Ember from 'ember';
import ListController from 'vault/mixins/list-controller';

export default Ember.Controller.extend(ListController);
const { inject } = Ember;

export default Ember.Controller.extend(ListController, {
flashMessages: inject.service(),

actions: {
delete(model) {
let type = model.get('identityType');
let id = model.id;
return model
.destroyRecord()
.then(() => {
this.send('reload');
this.get('flashMessages').success(`Successfully deleted ${type}: ${id}`);
})
.catch(e => {
this.get('flashMessages').success(
`There was a problem deleting ${type}: ${id} - ${e.error.join(' ') || e.message}`
);
});
},

toggleDisabled(model) {
let action = model.get('disabled') ? ['enabled', 'enabling'] : ['disabled', 'disabling'];
let type = model.get('identityType');
let id = model.id;
model.toggleProperty('disabled');

model.save().
then(() => {
this.get('flashMessages').success(`Successfully ${action[0]} ${type}: ${id}`);
})
.catch(e => {
this.get('flashMessages').success(
`There was a problem ${action[1]} ${type}: ${id} - ${e.error.join(' ') || e.message}`
);
});
},
reloadRecord(model) {
model.reload();
},
},
});
Loading