Skip to content

Commit

Permalink
UI: Redesign transit UX (#8304)
Browse files Browse the repository at this point in the history
* add placeholder for Key actions tab

* navigate to key items by default

* add placeholder key actions list page

* remove extra whitespace from component blueprint

* add SelectableCard

* move key actions from side nav to top nav

* make tabs active

* remove toolbar from key actions pages

* add divs to link to each key action on key actions page

* move preview-head to gitignore

* use selectable card css

* remove key actions

* use css grid

* update selectable card styling

* update Key Actions page header

* make cards clickable

* refactor supportedActions to include glyph

* make header black on hover

* rename selectable-card transit card and update styling

* add description and glyph for other key types

* use human readable titles for key action names

* update tests; still need to fix failing ones

* use datakey instead of data-key

* fix some failing tests

* fix more tests

* remove extra chevron from rotate button

* remove whitespace

* remove pauseTest

* use rename export to export key in the template instead of the model

* fix last few failing tests

* WIP

* link to key actions page by default

* test for transit action title

* only add query params when viewing a transit secret

* update structure icons

* add missing structure icons

* resolve merge conflicts from rebase

* use filter and map for supported actions

* only add query params for transit secrets
  • Loading branch information
Noelle Daley authored Feb 14, 2020
1 parent 78496d6 commit cbda9da
Show file tree
Hide file tree
Showing 17 changed files with 217 additions and 116 deletions.
1 change: 1 addition & 0 deletions ui/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
/npm-debug.log*
/testem.log
/yarn-error.log
/.storybook/preview-head.html

# ember-try
/.node_modules.ember-try/
Expand Down
27 changes: 0 additions & 27 deletions ui/.storybook/preview-head.html

This file was deleted.

10 changes: 10 additions & 0 deletions ui/app/helpers/secret-query-params.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { helper } from '@ember/component/helper';

export function secretQueryParams([backendType]) {
if (backendType === 'transit') {
return { tab: 'actions' };
}
return;
}

export default helper(secretQueryParams);
2 changes: 1 addition & 1 deletion ui/app/macros/lazy-capabilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//
// export default DS.Model.extend({
// //pass the template string as the first arg, and be sure to use '' around the
// //paramerters that get interpolated in the string - that's how the template function
// //parameters that get interpolated in the string - that's how the template function
// //knows where to put each value
// zeroAddressPath: lazyCapabilities(apiPath`${'id'}/config/zeroaddress`, 'id'),
//
Expand Down
60 changes: 42 additions & 18 deletions ui/app/models/transit-key.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,38 @@ import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities';
const { attr } = DS;

const ACTION_VALUES = {
encrypt: 'supportsEncryption',
decrypt: 'supportsDecryption',
datakey: 'supportsEncryption',
rewrap: 'supportsEncryption',
sign: 'supportsSigning',
hmac: true,
verify: true,
export: 'exportable',
encrypt: {
isSupported: 'supportsEncryption',
description: 'Looks up wrapping properties for the given token',
glyph: 'lock-closed',
},
decrypt: {
isSupported: 'supportsDecryption',
description: 'Decrypts the provided ciphertext using this key',
glyph: 'envelope-unsealed--outline',
},
datakey: {
isSupported: 'supportsEncryption',
description: 'Generates a new key and value encrypted with this key',
glyph: 'key',
},
rewrap: {
isSupported: 'supportsEncryption',
description: 'Rewraps the ciphertext using the latest version of the named key',
glyph: 'refresh-default',
},
sign: {
isSupported: 'supportsSigning',
description: 'Get the cryptographic signature of the given data',
glyph: 'edit',
},
hmac: { isSupported: true, description: 'Generate a data digest using a hash algorithm', glyph: 'remix' },
verify: {
isSupported: true,
description: 'Validate the provided signature for the given data',
glyph: 'check-circle-outline',
},
export: { isSupported: 'exportable', description: 'Get the named key', glyph: 'exit' },
};

export default DS.Model.extend({
Expand Down Expand Up @@ -56,13 +80,15 @@ export default DS.Model.extend({
},

supportedActions: computed('type', function() {
return Object.keys(ACTION_VALUES).filter(name => {
const isSupported = ACTION_VALUES[name];
if (typeof isSupported === 'boolean') {
return isSupported;
}
return get(this, isSupported);
});
return Object.keys(ACTION_VALUES)
.filter(name => {
const { isSupported } = ACTION_VALUES[name];
return typeof isSupported === 'boolean' || get(this, isSupported);
})
.map(name => {
const { description, glyph } = ACTION_VALUES[name];
return { name, description, glyph };
});
}),

canDelete: computed('deletionAllowed', 'lastLoadTS', function() {
Expand Down Expand Up @@ -116,9 +142,7 @@ export default DS.Model.extend({
return types;
}),

backend: attr('string', {
readOnly: true,
}),
backend: attr('string'),

rotatePath: lazyCapabilities(apiPath`${'backend'}/keys/${'id'}/rotate`, 'backend', 'id'),
canRotate: alias('rotatePath.canUpdate'),
Expand Down
41 changes: 41 additions & 0 deletions ui/app/styles/components/transit-card.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
.transit-card-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 0.2fr));
grid-template-rows: 1fr;
align-content: start;
grid-gap: 2rem;
margin-top: $spacing-l;
}

.transit-card {
border-radius: $radius;
box-shadow: 0 0 0 1px rgba($grey-dark, 0.3), $box-shadow-middle;
display: grid;
grid-template-columns: 0.45fr 2fr;
padding: $spacing-m;

.transit-icon {
justify-self: center;
}

.transit-action-description {
font-family: $family-sans;
font-size: $size-8;
color: $grey;
}

.title {
color: $grey;
font-size: $size-7;
margin-bottom: $spacing-xxs;
}

&:hover {
box-shadow: 0 0 0 1px $blue-500, $box-shadow-middle;
background: $blue-010;

.title {
color: initial;
}
}
}
1 change: 1 addition & 0 deletions ui/app/styles/core.scss
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
@import './components/token-expire-warning';
@import './components/toolbar';
@import './components/tool-tip';
@import './components/transit-card';
@import './components/unseal-warning';
@import './components/ui-wizard';
@import './components/vault-loading';
Expand Down
4 changes: 2 additions & 2 deletions ui/app/templates/components/selectable-card.hbs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{{!-- conditional to check if SelectableCard is apart of a CSS Grid, if yes return grid item class --}}
{{#if gridContainer}}
<div class="selectable-card is-rounded is-grid-container">
<div class="selectable-card-title">
<div class="selectable-card-title">
<h2 class="title-number">{{format-number total}}</h2>
<h3 class="title is-5" data-test-selectable-card-title={{formattedCardTitle}}>{{formattedCardTitle}}</h3>
<p class="has-text-grey is-size-8">{{subText}}</p>
Expand All @@ -10,7 +10,7 @@
</div>
{{else}}
<div class="selectable-card is-rounded">
<div>
<div>
<h2 class="title-number">{{format-number total}}</h2>
<h3 class="title is-5" data-test-selectable-card-title={{formattedCardTitle}}>{{formattedCardTitle}}</h3>
<p class="has-text-grey is-size-8">{{subText}}</p>
Expand Down
1 change: 0 additions & 1 deletion ui/app/templates/components/transit-edit.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,4 @@
</h1>
</p.levelLeft>
</PageHeader>

{{partial (concat 'partials/transit-form-' mode)}}
1 change: 0 additions & 1 deletion ui/app/templates/components/transit-key-actions.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
data-test-transit-key-rotate="true"
>
Rotate encryption key
<Chevron @isButton={{true}} />
</ConfirmAction>
{{/if}}
{{else}}
Expand Down
4 changes: 4 additions & 0 deletions ui/app/templates/partials/secret-list/item.hbs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@


{{#linked-block
(concat
"vault.cluster.secrets.backend."
Expand All @@ -8,12 +10,14 @@
class="list-item-row"
data-test-secret-link=item.id
encode=true
queryParams=(secret-query-params backendModel.type)
}}
<div class="columns is-mobile">
<div class="column is-10">
<SecretLink
@mode={{if item.isFolder "list" "show" }}
@secret={{item.id}}
@queryParams={{if (eq backendModel.type "transit") (query-params tab="actions") ""}}
@class="has-text-black has-text-weight-semibold"><Icon
@glyph={{if item.isFolder 'folder-outline' 'file-outline' }}
@class="has-text-grey-light"/>{{if (eq item.id ' ') '(self)' (or item.keyWithoutParent item.id)}}
Expand Down
98 changes: 66 additions & 32 deletions ui/app/templates/partials/transit-form-show.hbs
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
<div class="tabs-container box is-sideless is-fullwidth is-paddingless is-marginless">
<nav class="tabs">
<ul>
<li class="{{if (eq tab '') 'is-active'}}">
<li class="{{if (eq tab 'actions') 'is-active'}}">
{{#secret-link
secret=key.id
mode="show"
replace=true
queryParams=(query-params tab='')
queryParams=(query-params tab='actions')
data-test-transit-key-actions-link=true
}}
Key Actions
{{/secret-link}}
</li>

<li class="{{if (eq tab 'details') 'is-active'}}">
{{#secret-link
secret=key.id
mode="show"
replace=true
queryParams=(query-params tab='details')
data-test-transit-link="details"
}}
Details
Expand All @@ -28,38 +40,60 @@
</nav>
</div>

<Toolbar>
<ToolbarActions>
{{#if (eq tab 'versions')}}
<TransitKeyActions
@key={{key}}
@selectedAction="rotate"
@capabilities={{capabilities}}
@onRefresh={{action "refresh"}}
/>
{{/if}}
{{#if (eq mode "show") }}
{{#if (or capabilities.canUpdate capabilities.canDelete)}}
<ToolbarSecretLink
@secret={{key.id}}
@mode="edit"
replace=true
>
Edit encryption key
</ToolbarSecretLink>
{{#unless (eq tab 'actions')}}
<Toolbar>
<ToolbarActions>
{{#if (eq tab 'versions')}}
<TransitKeyActions
@key={{key}}
@selectedAction="rotate"
@capabilities={{capabilities}}
@onRefresh={{action "refresh"}}
/>
{{/if}}
{{#if (eq mode "show") }}
{{#if (or capabilities.canUpdate capabilities.canDelete)}}
<ToolbarSecretLink
@secret={{key.id}}
@mode="edit"
replace=true
>
Edit encryption key
</ToolbarSecretLink>
{{/if}}
{{/if}}
<ToolbarSecretLink
@secret={{key.id}}
@mode="actions"
@data-test-transit-key-actions-link=true
>
Key actions
</ToolbarSecretLink>
{{/if}}
</ToolbarActions>
</Toolbar>
</ToolbarActions>
</Toolbar>
{{/unless}}

{{#if (eq tab 'versions')}}

{{#if (eq tab 'actions')}}
<div class="transit-card-container">
{{#each model.supportedActions as |supportedAction|}}
{{#linked-block
"vault.cluster.secrets.backend.actions"
model.id
queryParams=(hash action=supportedAction.name)
class="transit-card"
data-test-transit-card=supportedAction.name
}}
<div class="transit-icon">
<Icon
@glyph={{supportedAction.glyph}}
@size="l"
class="has-text-grey auto-width"
aria-label={{concat backend.path " options"}} />
</div>
<div class="transit-description">
<h2 class="title is-6" data-test-transit-action-title={{supportedAction.name}}>
{{if (eq supportedAction.name 'export') 'Export Key' (humanize supportedAction.name)}}
</h2>
<p class="transit-action-description">{{supportedAction.description}}</p>
</div>
{{/linked-block}}
{{/each}}
</div>
{{else if (eq tab 'versions')}}
{{#if (or
(eq key.type "aes256-gcm96")
(eq key.type "chacha20-poly1305")
Expand Down
Loading

0 comments on commit cbda9da

Please sign in to comment.