mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-11-03 20:17:59 +00:00 
			
		
		
		
	UI: Redesign transit UX (#8304)
* 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
This commit is contained in:
		
							
								
								
									
										1
									
								
								ui/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								ui/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -17,6 +17,7 @@
 | 
			
		||||
/npm-debug.log*
 | 
			
		||||
/testem.log
 | 
			
		||||
/yarn-error.log
 | 
			
		||||
/.storybook/preview-head.html
 | 
			
		||||
 | 
			
		||||
# ember-try
 | 
			
		||||
/.node_modules.ember-try/
 | 
			
		||||
 
 | 
			
		||||
@@ -1,27 +0,0 @@
 | 
			
		||||
<meta name="vault/config/environment" content="%7B%22modulePrefix%22%3A%22vault%22%2C%22environment%22%3A%22development%22%2C%22rootURL%22%3A%22%2Fui%2F%22%2C%22locationType%22%3A%22auto%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%7D%2C%22_JQUERY_INTEGRATION%22%3Afalse%7D%2C%22APP%22%3A%7B%22POLLING_URLS%22%3A%5B%22sys%2Fhealth%22%2C%22sys%2Freplication%2Fstatus%22%2C%22sys%2Fseal-status%22%5D%2C%22NAMESPACE_ROOT_URLS%22%3A%5B%22sys%2Fhealth%22%2C%22sys%2Fseal-status%22%2C%22sys%2Flicense%2Ffeatures%22%5D%2C%22DEFAULT_PAGE_SIZE%22%3A15%2C%22LOG_TRANSITIONS%22%3Atrue%7D%2C%22flashMessageDefaults%22%3A%7B%22timeout%22%3A7000%2C%22sticky%22%3Afalse%7D%2C%22contentSecurityPolicyHeader%22%3A%22Content-Security-Policy%22%2C%22contentSecurityPolicyMeta%22%3Atrue%2C%22contentSecurityPolicy%22%3A%7B%22connect-src%22%3A%5B%22'self'%22%5D%2C%22img-src%22%3A%5B%22'self'%22%2C%22data%3A%22%5D%2C%22form-action%22%3A%5B%22'none'%22%5D%2C%22script-src%22%3A%5B%22'self'%22%5D%2C%22style-src%22%3A%5B%22'unsafe-inline'%22%2C%22'self'%22%5D%2C%22default-src%22%3A%5B%22'none'%22%5D%2C%22font-src%22%3A%5B%22'self'%22%5D%2C%22media-src%22%3A%5B%22'self'%22%5D%7D%2C%22exportApplicationGlobal%22%3Atrue%7D" />
 | 
			
		||||
<meta name="kmip/config/environment" content="%7B%22modulePrefix%22%3A%22kmip%22%2C%22environment%22%3A%22development%22%7D" />
 | 
			
		||||
<meta name="open-api-explorer/config/environment" content="%7B%22modulePrefix%22%3A%22open-api-explorer%22%2C%22environment%22%3A%22development%22%2C%22APP%22%3A%7B%22NAMESPACE_ROOT_URLS%22%3A%5B%22sys/health%22%2C%22sys/seal-status%22%2C%22sys/license/features%22%5D%7D%7D" />
 | 
			
		||||
<meta name="replication/config/environment" content="%7B%22modulePrefix%22%3A%22replication%22%2C%22environment%22%3A%22development%22%7D" />
 | 
			
		||||
<meta name="vault/config/asset-manifest"
 | 
			
		||||
  content="%7B%22bundles%22%3A%7B%22kmip%22%3A%7B%22assets%22%3A%5B%7B%22uri%22%3A%22/ui/engines-dist/kmip/assets/engine-vendor.js%22%2C%22type%22%3A%22js%22%7D%2C%7B%22uri%22%3A%22/ui/engines-dist/kmip/assets/engine.js%22%2C%22type%22%3A%22js%22%7D%5D%7D%2C%22open-api-explorer%22%3A%7B%22assets%22%3A%5B%7B%22uri%22%3A%22/ui/engines-dist/open-api-explorer/assets/engine-vendor.css%22%2C%22type%22%3A%22css%22%7D%2C%7B%22uri%22%3A%22/ui/engines-dist/open-api-explorer/assets/engine-vendor.js%22%2C%22type%22%3A%22js%22%7D%2C%7B%22uri%22%3A%22/ui/engines-dist/open-api-explorer/assets/engine.css%22%2C%22type%22%3A%22css%22%7D%2C%7B%22uri%22%3A%22/ui/engines-dist/open-api-explorer/assets/engine.js%22%2C%22type%22%3A%22js%22%7D%5D%7D%2C%22replication%22%3A%7B%22assets%22%3A%5B%7B%22uri%22%3A%22/ui/engines-dist/replication/assets/engine-vendor.js%22%2C%22type%22%3A%22js%22%7D%2C%7B%22uri%22%3A%22/ui/engines-dist/replication/assets/engine.js%22%2C%22type%22%3A%22js%22%7D%5D%7D%7D%7D" />
 | 
			
		||||
<link rel="stylesheet" href="/assets/vendor.css" />
 | 
			
		||||
<link rel="stylesheet" href="/assets/vault.css" />
 | 
			
		||||
<link rel="icon" href="/favicon.png" />
 | 
			
		||||
<script>
 | 
			
		||||
            (function() {
 | 
			
		||||
              var srcUrl = null;
 | 
			
		||||
              var host = location.hostname || 'localhost';
 | 
			
		||||
              var defaultPort = location.protocol === 'https:' ? 443 : 80;
 | 
			
		||||
              var port = 4200;
 | 
			
		||||
              var path = '';
 | 
			
		||||
              var prefixURL = '';
 | 
			
		||||
              var src = srcUrl || prefixURL + '/_lr/livereload.js?port=' + port + '&host=' + host + path;
 | 
			
		||||
              var script = document.createElement('script');
 | 
			
		||||
              script.type = 'text/javascript';
 | 
			
		||||
              script.src = location.protocol + '//' + host + ':4200' + src;
 | 
			
		||||
              document.getElementsByTagName('head')[0].appendChild(script);
 | 
			
		||||
            }());
 | 
			
		||||
          </script>
 | 
			
		||||
<script>runningTests = true;</script>
 | 
			
		||||
<script src="/assets/vendor.js"></script>
 | 
			
		||||
<script src="/assets/vault.js"></script>
 | 
			
		||||
							
								
								
									
										10
									
								
								ui/app/helpers/secret-query-params.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								ui/app/helpers/secret-query-params.js
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
			
		||||
@@ -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'),
 | 
			
		||||
//
 | 
			
		||||
 
 | 
			
		||||
@@ -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({
 | 
			
		||||
@@ -56,12 +80,14 @@ 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 };
 | 
			
		||||
      });
 | 
			
		||||
  }),
 | 
			
		||||
 | 
			
		||||
@@ -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'),
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										41
									
								
								ui/app/styles/components/transit-card.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								ui/app/styles/components/transit-card.scss
									
									
									
									
									
										Normal file
									
								
							@@ -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;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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';
 | 
			
		||||
 
 | 
			
		||||
@@ -20,5 +20,4 @@
 | 
			
		||||
    </h1>
 | 
			
		||||
  </p.levelLeft>
 | 
			
		||||
</PageHeader>
 | 
			
		||||
 | 
			
		||||
{{partial (concat 'partials/transit-form-' mode)}}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@
 | 
			
		||||
      data-test-transit-key-rotate="true"
 | 
			
		||||
    >
 | 
			
		||||
      Rotate encryption key
 | 
			
		||||
      <Chevron @isButton={{true}} />
 | 
			
		||||
    </ConfirmAction>
 | 
			
		||||
  {{/if}}
 | 
			
		||||
{{else}}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{{#linked-block
 | 
			
		||||
  (concat
 | 
			
		||||
    "vault.cluster.secrets.backend."
 | 
			
		||||
@@ -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)}}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -28,6 +40,7 @@
 | 
			
		||||
  </nav>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
{{#unless (eq tab 'actions')}}
 | 
			
		||||
  <Toolbar>
 | 
			
		||||
    <ToolbarActions>
 | 
			
		||||
      {{#if (eq tab 'versions')}}
 | 
			
		||||
@@ -48,18 +61,39 @@
 | 
			
		||||
            Edit encryption key
 | 
			
		||||
          </ToolbarSecretLink>
 | 
			
		||||
        {{/if}}
 | 
			
		||||
      <ToolbarSecretLink
 | 
			
		||||
        @secret={{key.id}}
 | 
			
		||||
        @mode="actions"
 | 
			
		||||
        @data-test-transit-key-actions-link=true
 | 
			
		||||
      >
 | 
			
		||||
        Key actions
 | 
			
		||||
      </ToolbarSecretLink>
 | 
			
		||||
      {{/if}}
 | 
			
		||||
    </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")
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +1,5 @@
 | 
			
		||||
<div class="columns">
 | 
			
		||||
  {{#menu-sidebar title="Transit Actions" class="is-2"}}
 | 
			
		||||
    {{#each model.supportedActions as |supportedAction|}}
 | 
			
		||||
      <li>
 | 
			
		||||
        {{#secret-link
 | 
			
		||||
          mode="actions"
 | 
			
		||||
          secret=model.id
 | 
			
		||||
          class=(if (eq supportedAction selectedAction) "is-active")
 | 
			
		||||
          queryParams=(query-params action=supportedAction)
 | 
			
		||||
          data-test-transit-action-link=supportedAction
 | 
			
		||||
        }}
 | 
			
		||||
          {{capitalize supportedAction}}
 | 
			
		||||
        {{/secret-link}}
 | 
			
		||||
      </li>
 | 
			
		||||
    {{/each}}
 | 
			
		||||
  {{/menu-sidebar}}
 | 
			
		||||
  <div class="column is-10">
 | 
			
		||||
  <div class="column">
 | 
			
		||||
    <PageHeader as |p|>
 | 
			
		||||
      <p.top>
 | 
			
		||||
        {{key-value-header
 | 
			
		||||
@@ -27,21 +12,39 @@
 | 
			
		||||
      </p.top>
 | 
			
		||||
      <p.levelLeft>
 | 
			
		||||
        <h1 class="title is-3">
 | 
			
		||||
          {{model.id}}
 | 
			
		||||
          {{#secret-link
 | 
			
		||||
            class="is-inline has-text-info"
 | 
			
		||||
            secret=model.id
 | 
			
		||||
            mode="show"
 | 
			
		||||
            replace=true
 | 
			
		||||
            queryParams=(query-params tab='actions')
 | 
			
		||||
            data-test-transit-link="actions"
 | 
			
		||||
            }}
 | 
			
		||||
            <Icon @glyph="arrow-left" />
 | 
			
		||||
          {{/secret-link}}
 | 
			
		||||
          Key Actions
 | 
			
		||||
        </h1>
 | 
			
		||||
      </p.levelLeft>
 | 
			
		||||
    </PageHeader>
 | 
			
		||||
 | 
			
		||||
    <Toolbar>
 | 
			
		||||
      <ToolbarActions>
 | 
			
		||||
        <ToolbarSecretLink
 | 
			
		||||
          @secret={{model.id}}
 | 
			
		||||
          @mode="show"
 | 
			
		||||
        >
 | 
			
		||||
          Details
 | 
			
		||||
        </ToolbarSecretLink>
 | 
			
		||||
      </ToolbarActions>
 | 
			
		||||
    </Toolbar>
 | 
			
		||||
    <div class="tabs-container box is-sideless is-fullwidth is-paddingless is-marginless">
 | 
			
		||||
      <nav class="tabs">
 | 
			
		||||
        <ul>
 | 
			
		||||
          {{#each model.supportedActions as |supportedAction|}}
 | 
			
		||||
            <li class="{{if (eq supportedAction.name selectedAction) 'is-active'}}">
 | 
			
		||||
              {{#secret-link
 | 
			
		||||
                  mode="actions"
 | 
			
		||||
                  secret=model.id
 | 
			
		||||
                  queryParams=(query-params action=supportedAction.name)
 | 
			
		||||
                  data-test-transit-action-link=supportedAction.name
 | 
			
		||||
                }}
 | 
			
		||||
                {{if (eq supportedAction.name 'export') 'Export Key' (humanize supportedAction.name)}}
 | 
			
		||||
              {{/secret-link}}
 | 
			
		||||
            </li>
 | 
			
		||||
          {{/each}}
 | 
			
		||||
        </ul>
 | 
			
		||||
      </nav>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <TransitKeyActions
 | 
			
		||||
      @selectedAction={{selectedAction}}
 | 
			
		||||
 
 | 
			
		||||
@@ -264,9 +264,21 @@ module('Acceptance | transit', function(hooks) {
 | 
			
		||||
      await click('[data-test-transit-key-actions-link]');
 | 
			
		||||
      await settled();
 | 
			
		||||
      assert.ok(
 | 
			
		||||
        currentURL().startsWith(`/vault/secrets/${path}/actions/${name}`),
 | 
			
		||||
        `${name}: navigates to tranist actions`
 | 
			
		||||
        currentURL().startsWith(`/vault/secrets/${path}/show/${name}?tab=actions`),
 | 
			
		||||
        `${name}: navigates to transit actions`
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      const keyAction = key.supportsEncryption ? 'encrypt' : 'sign';
 | 
			
		||||
      const actionTitle = find(`[data-test-transit-action-title=${keyAction}]`).innerText.toLowerCase();
 | 
			
		||||
 | 
			
		||||
      assert.equal(
 | 
			
		||||
        actionTitle.includes(keyAction),
 | 
			
		||||
        true,
 | 
			
		||||
        `shows a card with title that links to the ${name} transit action`
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      await click(`[data-test-transit-card=${keyAction}]`);
 | 
			
		||||
      await settled();
 | 
			
		||||
      assert.ok(
 | 
			
		||||
        find('[data-test-transit-key-version-select]'),
 | 
			
		||||
        `${name}: the rotated key allows you to select versions`
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ module('Unit | Model | transit key', function(hooks) {
 | 
			
		||||
      })
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let supportedActions = model.get('supportedActions');
 | 
			
		||||
    let supportedActions = model.get('supportedActions').map(k => k.name);
 | 
			
		||||
    assert.deepEqual(['encrypt', 'decrypt', 'datakey', 'rewrap', 'hmac', 'verify'], supportedActions);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1082,9 +1082,9 @@
 | 
			
		||||
    "@glimmer/util" "^0.41.4"
 | 
			
		||||
 | 
			
		||||
"@hashicorp/structure-icons@^1.3.0":
 | 
			
		||||
  version "1.3.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@hashicorp/structure-icons/-/structure-icons-1.3.0.tgz#1c7c1cb43a1c1aa92b073a7aa7956495ae14c3e0"
 | 
			
		||||
  integrity sha512-wTKpdaAPphEY2kg5QbQTSUlhqLTpBBR1+1dXp4LYTN0PtMSpetyDDDhcSyvKE8i4h2nwPJBRRfeFlE1snaHd7w==
 | 
			
		||||
  version "1.8.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@hashicorp/structure-icons/-/structure-icons-1.8.1.tgz#d29945df2b41dcb317b141e51a26bd4be796a164"
 | 
			
		||||
  integrity sha512-XFYdCIshmaR3Igc8eWpOZ2Gr3IR/0TogXZ4PQ9bz1E9cLzF3njBcs3tCpJUOwRwe/wMI5YTlL/sOGvcZ77AB/Q==
 | 
			
		||||
 | 
			
		||||
"@icons/material@^0.2.4":
 | 
			
		||||
  version "0.2.4"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user