mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 02:28:09 +00:00 
			
		
		
		
	UI: Add PKI role attribute no_store_metadata (#27251)
* Add noStoreMetadata attribute to pki/role model and details component * update tests * Make noStoreMetadata enterprise only * update tests * Cleanup tests * Address PR comments
This commit is contained in:
		| @@ -5,7 +5,7 @@ | |||||||
|  |  | ||||||
| import { expandAttributeMeta } from 'vault/utils/field-to-attrs'; | import { expandAttributeMeta } from 'vault/utils/field-to-attrs'; | ||||||
| import Model from '@ember-data/model'; | import Model from '@ember-data/model'; | ||||||
| import { assert } from '@ember/debug'; | import { debug } from '@ember/debug'; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * sets allByKey properties on model class. These are all the attributes on the model |  * sets allByKey properties on model class. These are all the attributes on the model | ||||||
| @@ -41,10 +41,9 @@ export function withExpandedAttributes() { | |||||||
|           const [key, stringArray] = Object.entries(obj)[0]; |           const [key, stringArray] = Object.entries(obj)[0]; | ||||||
|           const expanded = stringArray.map((fieldName) => this.allByKey[fieldName]).filter((f) => !!f); |           const expanded = stringArray.map((fieldName) => this.allByKey[fieldName]).filter((f) => !!f); | ||||||
|           // if this fails, it might mean there are missing fields in the model or the model must be hydrated via OpenAPI |           // if this fails, it might mean there are missing fields in the model or the model must be hydrated via OpenAPI | ||||||
|           assert( |           if (expanded.length !== stringArray.length) { | ||||||
|             `all model fields found in allByKey for group ${key}`, |             debug(`not all model fields found in allByKey for group "${key}"`); | ||||||
|             expanded.length === stringArray.length |           } | ||||||
|           ); |  | ||||||
|           return { [key]: expanded }; |           return { [key]: expanded }; | ||||||
|         }); |         }); | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -4,17 +4,32 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| import Model, { attr } from '@ember-data/model'; | import Model, { attr } from '@ember-data/model'; | ||||||
|  | import { service } from '@ember/service'; | ||||||
| import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities'; | import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities'; | ||||||
| import { withModelValidations } from 'vault/decorators/model-validations'; | import { withModelValidations } from 'vault/decorators/model-validations'; | ||||||
| import { withFormFields } from 'vault/decorators/model-form-fields'; | import { withExpandedAttributes } from 'vault/decorators/model-expanded-attributes'; | ||||||
|  |  | ||||||
| const validations = { | const validations = { | ||||||
|   name: [{ type: 'presence', message: 'Name is required.' }], |   name: [{ type: 'presence', message: 'Name is required.' }], | ||||||
| }; | }; | ||||||
|  |  | ||||||
| const fieldGroups = [ | @withExpandedAttributes() | ||||||
|   { | @withModelValidations(validations) | ||||||
|     default: [ | export default class PkiRoleModel extends Model { | ||||||
|  |   @service version; // noStoreMetadata is enterprise-only, so we need this available | ||||||
|  |  | ||||||
|  |   get useOpenAPI() { | ||||||
|  |     // must be a getter so it can be accessed in path-help.js | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  |   getHelpUrl(backend) { | ||||||
|  |     return `/v1/${backend}/roles/example?help=1`; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @attr('string', { readOnly: true }) backend; | ||||||
|  |  | ||||||
|  |   get formFieldGroups() { | ||||||
|  |     let defaultArray = [ | ||||||
|       'name', |       'name', | ||||||
|       'issuerRef', |       'issuerRef', | ||||||
|       'customTtl', |       'customTtl', | ||||||
| @@ -22,8 +37,16 @@ const fieldGroups = [ | |||||||
|       'maxTtl', |       'maxTtl', | ||||||
|       'generateLease', |       'generateLease', | ||||||
|       'noStore', |       'noStore', | ||||||
|  |       'noStoreMetadata', | ||||||
|       'addBasicConstraints', |       'addBasicConstraints', | ||||||
|     ], |     ]; | ||||||
|  |     if (this.version.isCommunity) { | ||||||
|  |       const entFields = ['noStoreMetadata']; | ||||||
|  |       defaultArray = defaultArray.filter((field) => !entFields.includes(field)); | ||||||
|  |     } | ||||||
|  |     return this._expandGroups([ | ||||||
|  |       { | ||||||
|  |         default: defaultArray, | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         'Domain handling': [ |         'Domain handling': [ | ||||||
| @@ -69,20 +92,8 @@ const fieldGroups = [ | |||||||
|           'postalCode', |           'postalCode', | ||||||
|         ], |         ], | ||||||
|       }, |       }, | ||||||
| ]; |     ]); | ||||||
|  |  | ||||||
| @withFormFields(null, fieldGroups) |  | ||||||
| @withModelValidations(validations) |  | ||||||
| export default class PkiRoleModel extends Model { |  | ||||||
|   get useOpenAPI() { |  | ||||||
|     // must be a getter so it can be accessed in path-help.js |  | ||||||
|     return true; |  | ||||||
|   } |   } | ||||||
|   getHelpUrl(backend) { |  | ||||||
|     return `/v1/${backend}/roles/example?help=1`; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   @attr('string', { readOnly: true }) backend; |  | ||||||
|  |  | ||||||
|   /* Overriding OpenApi default options */ |   /* Overriding OpenApi default options */ | ||||||
|   @attr('string', { |   @attr('string', { | ||||||
| @@ -146,6 +157,14 @@ export default class PkiRoleModel extends Model { | |||||||
|   }) |   }) | ||||||
|   noStore; |   noStore; | ||||||
|  |  | ||||||
|  |   @attr('boolean', { | ||||||
|  |     label: 'Do not store certificate metadata in storage backend', | ||||||
|  |     detailsLabel: 'Store metadata in storage backend', // template reverses value | ||||||
|  |     subText: | ||||||
|  |       'We don’t recommend storing metadata, since this information creates overhead in storage, and requires clean up.', | ||||||
|  |   }) | ||||||
|  |   noStoreMetadata; | ||||||
|  |  | ||||||
|   @attr('boolean', { |   @attr('boolean', { | ||||||
|     label: 'Basic constraints valid for non-CA', |     label: 'Basic constraints valid for non-CA', | ||||||
|     detailsLabel: 'Add basic constraints', |     detailsLabel: 'Add basic constraints', | ||||||
|   | |||||||
| @@ -72,7 +72,7 @@ | |||||||
|             @value={{val}} |             @value={{val}} | ||||||
|             @alwaysRender={{true}} |             @alwaysRender={{true}} | ||||||
|           /> |           /> | ||||||
|         {{else if (eq attr.name "noStore")}} |         {{else if (includes attr.name (array "noStore" "noStoreMetadata"))}} | ||||||
|           <InfoTableRow |           <InfoTableRow | ||||||
|             @label={{capitalize (or attr.options.detailsLabel attr.options.label (humanize (dasherize attr.name)))}} |             @label={{capitalize (or attr.options.detailsLabel attr.options.label (humanize (dasherize attr.name)))}} | ||||||
|             @value={{not val}} |             @value={{not val}} | ||||||
|   | |||||||
| @@ -191,6 +191,7 @@ export const PKI_KEYS = { | |||||||
| export const PKI_ROLE_DETAILS = { | export const PKI_ROLE_DETAILS = { | ||||||
|   issuerLabel: '[data-test-row-label="Issuer"]', |   issuerLabel: '[data-test-row-label="Issuer"]', | ||||||
|   noStoreValue: '[data-test-value-div="Store in storage backend"]', |   noStoreValue: '[data-test-value-div="Store in storage backend"]', | ||||||
|  |   noStoreMetadataValue: '[data-test-value-div="Store metadata in storage backend"]', | ||||||
|   keyUsageValue: '[data-test-value-div="Key usage"]', |   keyUsageValue: '[data-test-value-div="Key usage"]', | ||||||
|   extKeyUsageValue: '[data-test-value-div="Ext key usage"]', |   extKeyUsageValue: '[data-test-value-div="Ext key usage"]', | ||||||
|   customTtlValue: '[data-test-value-div="Issued certificates expire after"]', |   customTtlValue: '[data-test-value-div="Issued certificates expire after"]', | ||||||
|   | |||||||
| @@ -20,6 +20,7 @@ module('Integration | Component | pki role details page', function (hooks) { | |||||||
|       name: 'Foobar', |       name: 'Foobar', | ||||||
|       backend: 'pki', |       backend: 'pki', | ||||||
|       noStore: false, |       noStore: false, | ||||||
|  |       noStoreMetadata: true, | ||||||
|       keyUsage: [], |       keyUsage: [], | ||||||
|       extKeyUsage: ['bar', 'baz'], |       extKeyUsage: ['bar', 'baz'], | ||||||
|       ttl: 600, |       ttl: 600, | ||||||
| @@ -27,7 +28,6 @@ module('Integration | Component | pki role details page', function (hooks) { | |||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   test('it should render the page component', async function (assert) { |   test('it should render the page component', async function (assert) { | ||||||
|     assert.expect(5); |  | ||||||
|     await render( |     await render( | ||||||
|       hbs` |       hbs` | ||||||
|       <Page::PkiRoleDetails @role={{this.model}} /> |       <Page::PkiRoleDetails @role={{this.model}} /> | ||||||
| @@ -44,9 +44,26 @@ module('Integration | Component | pki role details page', function (hooks) { | |||||||
|     assert |     assert | ||||||
|       .dom(PKI_ROLE_DETAILS.noStoreValue) |       .dom(PKI_ROLE_DETAILS.noStoreValue) | ||||||
|       .containsText('Yes', 'noStore shows opposite of what the value is'); |       .containsText('Yes', 'noStore shows opposite of what the value is'); | ||||||
|  |     assert | ||||||
|  |       .dom(PKI_ROLE_DETAILS.noStoreMetadataValue) | ||||||
|  |       .doesNotExist('does not render value for enterprise-only field'); | ||||||
|     assert.dom(PKI_ROLE_DETAILS.customTtlValue).containsText('10 minutes', 'TTL shown as duration'); |     assert.dom(PKI_ROLE_DETAILS.customTtlValue).containsText('10 minutes', 'TTL shown as duration'); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|  |   test('it should render the enterprise-only values in enterprise edition', async function (assert) { | ||||||
|  |     const version = this.owner.lookup('service:version'); | ||||||
|  |     version.type = 'enterprise'; | ||||||
|  |     await render( | ||||||
|  |       hbs` | ||||||
|  |       <Page::PkiRoleDetails @role={{this.model}} /> | ||||||
|  |   `, | ||||||
|  |       { owner: this.engine } | ||||||
|  |     ); | ||||||
|  |     assert | ||||||
|  |       .dom(PKI_ROLE_DETAILS.noStoreMetadataValue) | ||||||
|  |       .containsText('No', 'noStoreMetadata shows opposite of what the value is'); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|   test('it should render the notAfter date if present', async function (assert) { |   test('it should render the notAfter date if present', async function (assert) { | ||||||
|     assert.expect(1); |     assert.expect(1); | ||||||
|     this.model = this.store.createRecord('pki/role', { |     this.model = this.store.createRecord('pki/role', { | ||||||
|   | |||||||
| @@ -37,7 +37,6 @@ module('Integration | Component | pki-role-form', function (hooks) { | |||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   test('it should render default fields and toggle groups', async function (assert) { |   test('it should render default fields and toggle groups', async function (assert) { | ||||||
|     assert.expect(13); |  | ||||||
|     await render( |     await render( | ||||||
|       hbs` |       hbs` | ||||||
|       <PkiRoleForm |       <PkiRoleForm | ||||||
| @@ -55,6 +54,9 @@ module('Integration | Component | pki-role-form', function (hooks) { | |||||||
|     assert.dom(GENERAL.ttl.toggle('Max TTL')).exists(); |     assert.dom(GENERAL.ttl.toggle('Max TTL')).exists(); | ||||||
|     assert.dom(GENERAL.fieldByAttr('generateLease')).exists(); |     assert.dom(GENERAL.fieldByAttr('generateLease')).exists(); | ||||||
|     assert.dom(GENERAL.fieldByAttr('noStore')).exists(); |     assert.dom(GENERAL.fieldByAttr('noStore')).exists(); | ||||||
|  |     assert | ||||||
|  |       .dom(GENERAL.fieldByAttr('noStoreMetadata')) | ||||||
|  |       .doesNotExist('noStoreMetadata is not shown b/c not enterprise'); | ||||||
|     assert.dom(GENERAL.inputByAttr('addBasicConstraints')).exists(); |     assert.dom(GENERAL.inputByAttr('addBasicConstraints')).exists(); | ||||||
|     assert.dom(PKI_ROLE_FORM.domainHandling).exists('shows form-field group add domain handling'); |     assert.dom(PKI_ROLE_FORM.domainHandling).exists('shows form-field group add domain handling'); | ||||||
|     assert.dom(PKI_ROLE_FORM.keyParams).exists('shows form-field group key params'); |     assert.dom(PKI_ROLE_FORM.keyParams).exists('shows form-field group key params'); | ||||||
| @@ -66,6 +68,23 @@ module('Integration | Component | pki-role-form', function (hooks) { | |||||||
|       .exists('shows form-field group additional subject fields'); |       .exists('shows form-field group additional subject fields'); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|  |   test('it renders enterprise-only values in enterprise edition', async function (assert) { | ||||||
|  |     const version = this.owner.lookup('service:version'); | ||||||
|  |     version.type = 'enterprise'; | ||||||
|  |     await render( | ||||||
|  |       hbs` | ||||||
|  |       <PkiRoleForm | ||||||
|  |          @role={{this.role}} | ||||||
|  |          @issuers={{this.issuers}} | ||||||
|  |          @onCancel={{this.onCancel}} | ||||||
|  |          @onSave={{this.onSave}} | ||||||
|  |        /> | ||||||
|  |   `, | ||||||
|  |       { owner: this.engine } | ||||||
|  |     ); | ||||||
|  |     assert.dom(GENERAL.fieldByAttr('noStoreMetadata')).exists(); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|   test('it should save a new pki role with various options selected', async function (assert) { |   test('it should save a new pki role with various options selected', async function (assert) { | ||||||
|     // Key usage, Key params and Not valid after options are tested in their respective component tests |     // Key usage, Key params and Not valid after options are tested in their respective component tests | ||||||
|     assert.expect(8); |     assert.expect(8); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Chelsea Shaw
					Chelsea Shaw