From bd50c4f78c2f9adf126e29783ff763769808ab14 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Thu, 8 Jul 2021 11:38:41 -0400 Subject: [PATCH 01/15] feat: Add credential library api --- .../generated/models/credential-library.js | 42 ++++++++++++ .../generated/models/credential-store.js | 2 +- addons/api/addon/models/credential-library.js | 23 +++++++ .../fragment-credential-library-attributes.js | 23 +++++++ .../addon/serializers/credential-library.js | 3 + .../fragment-credential-library-attributes.js | 27 ++++++++ addons/api/app/models/credential-library.js | 1 + .../fragment-credential-library-attributes.js | 1 + .../api/app/serializers/credential-library.js | 1 + .../fragment-credential-library-attributes.js | 1 + .../unit/models/credential-library-test.js | 13 ++++ ...ment-credential-library-attributes-test.js | 19 ++++++ .../serializers/credential-library-test.js | 67 +++++++++++++++++++ ...ment-credential-library-attributes-test.js | 59 ++++++++++++++++ 14 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 addons/api/addon/generated/models/credential-library.js create mode 100644 addons/api/addon/models/credential-library.js create mode 100644 addons/api/addon/models/fragment-credential-library-attributes.js create mode 100644 addons/api/addon/serializers/credential-library.js create mode 100644 addons/api/addon/serializers/fragment-credential-library-attributes.js create mode 100644 addons/api/app/models/credential-library.js create mode 100644 addons/api/app/models/fragment-credential-library-attributes.js create mode 100644 addons/api/app/serializers/credential-library.js create mode 100644 addons/api/app/serializers/fragment-credential-library-attributes.js create mode 100644 addons/api/tests/unit/models/credential-library-test.js create mode 100644 addons/api/tests/unit/models/fragment-credential-library-attributes-test.js create mode 100644 addons/api/tests/unit/serializers/credential-library-test.js create mode 100644 addons/api/tests/unit/serializers/fragment-credential-library-attributes-test.js diff --git a/addons/api/addon/generated/models/credential-library.js b/addons/api/addon/generated/models/credential-library.js new file mode 100644 index 000000000..895c467f9 --- /dev/null +++ b/addons/api/addon/generated/models/credential-library.js @@ -0,0 +1,42 @@ +import BaseModel from '../../models/base'; +import { attr } from '@ember-data/model'; + +/** + * A credential library is a resource that can generate and retrieve + * credentials. + */ +export default class GeneratedCredentialLibraryModel extends BaseModel { + // =attributes + + @attr('string', { + description: 'The owning credential store ID.', + }) + credential_store_id; + + @attr('string', { + description: 'Optional name for identification purposes', + }) + name; + + @attr('string', { + description: 'Optional user-set description for identification purposes', + }) + description; + + @attr('date', { + description: 'The time this resource was created\nOutput only.', + readOnly: true, + }) + created_time; + + @attr('date', { + description: 'The time this resource was last updated\nOutput only.', + readOnly: true, + }) + updated_time; + + @attr('number', { + description: 'Current version number of this resource.', + }) + version; +} diff --git a/addons/api/addon/generated/models/credential-store.js b/addons/api/addon/generated/models/credential-store.js index 78834dc51..51dd4af87 100644 --- a/addons/api/addon/generated/models/credential-store.js +++ b/addons/api/addon/generated/models/credential-store.js @@ -5,7 +5,7 @@ import { attr } from '@ember-data/model'; * A credential store is a resource that can retrieve, store, and potentially * generate credentials. */ -export default class GeneratedAccountModel extends BaseModel { +export default class GeneratedCredentialStoreModel extends BaseModel { // =attributes @attr('string', { diff --git a/addons/api/addon/models/credential-library.js b/addons/api/addon/models/credential-library.js new file mode 100644 index 000000000..c95b9f73e --- /dev/null +++ b/addons/api/addon/models/credential-library.js @@ -0,0 +1,23 @@ +import GeneratedCredentialLibraryModel from '../generated/models/credential-library'; +import { attr } from '@ember-data/model'; +import { fragment } from 'ember-data-model-fragments/attributes'; + +export default class CredentialLibraryModel extends GeneratedCredentialLibraryModel { + // =error attributes + // These attributes exist solely to capture errors on nested fields. + // See the application adapter's error normalization method for + // more information. + + @attr('string', { readOnly: true }) attributes_http_method; + @attr('string', { readOnly: true }) attributes_http_request_body; + @attr('string', { readOnly: true }) attributes_path; + + // =attributes + + /** + * Attributes of this resource, if any, represented as a JSON fragment. + * @type {FragmentCredentialLibraryAttributesModel} + */ + @fragment('fragment-credential-library-attributes', { defaultValue: {} }) + attributes; +} diff --git a/addons/api/addon/models/fragment-credential-library-attributes.js b/addons/api/addon/models/fragment-credential-library-attributes.js new file mode 100644 index 000000000..dd6138199 --- /dev/null +++ b/addons/api/addon/models/fragment-credential-library-attributes.js @@ -0,0 +1,23 @@ +import Fragment from 'ember-data-model-fragments/fragment'; +import { attr } from '@ember-data/model'; + +export default class FragmentCredentialLibraryAttributesModel extends Fragment { + //= attributes (vault) + + @attr('string', { + description: + 'The HTTP method the library uses when requesting credentials from Vault.', + }) + http_method; + + @attr('string', { + description: + 'The body of the HTTP request the library sends to Vault when requesting credentials. Only valid if `http_method` is set to `POST`.', + }) + http_request_body; + + @attr('string', { + description: 'The path in Vault to request credentials from.', + }) + path; +} diff --git a/addons/api/addon/serializers/credential-library.js b/addons/api/addon/serializers/credential-library.js new file mode 100644 index 000000000..d1ced9a2b --- /dev/null +++ b/addons/api/addon/serializers/credential-library.js @@ -0,0 +1,3 @@ +import ApplicationSerializer from './application'; + +export default class CredentialLibrarySerializer extends ApplicationSerializer {} diff --git a/addons/api/addon/serializers/fragment-credential-library-attributes.js b/addons/api/addon/serializers/fragment-credential-library-attributes.js new file mode 100644 index 000000000..8d52b101f --- /dev/null +++ b/addons/api/addon/serializers/fragment-credential-library-attributes.js @@ -0,0 +1,27 @@ +import JSONSerializer from '@ember-data/serializer/json'; + +export default class FragmentCredentialLibraryAttributesSerializer extends JSONSerializer { + /** + * If an attribute is annotated as readOnly in the model, don't serialize it. + * Otherwise delegate to default attribute serializer. + * Only serialize http_request_body when `http_method` is set to `POST`. + * @override + * @method serializeAttribute + * @param {Snapshot} snapshot + * @param {Object} json + * @param {String} key + * @param {Object} attribute + */ + serializeAttribute(snapshot, json, key, attribute) { + const { type, options } = attribute; + let value = super.serializeAttribute(...arguments); + // Convert empty strings to null. + if (type === 'string' && json[key] === '') json[key] = null; + // Do not serialize read-only attributes. + if (options.readOnly) delete json[key]; + // Do not serialize http_request_body unless http_method is POST + if (key === 'http_request_body' && !json['http_method']?.match(/post/i)) + delete json[key]; + return value; + } +} diff --git a/addons/api/app/models/credential-library.js b/addons/api/app/models/credential-library.js new file mode 100644 index 000000000..b9f39e29d --- /dev/null +++ b/addons/api/app/models/credential-library.js @@ -0,0 +1 @@ +export { default } from 'api/models/credential-library'; diff --git a/addons/api/app/models/fragment-credential-library-attributes.js b/addons/api/app/models/fragment-credential-library-attributes.js new file mode 100644 index 000000000..04d8f2597 --- /dev/null +++ b/addons/api/app/models/fragment-credential-library-attributes.js @@ -0,0 +1 @@ +export { default } from 'api/models/fragment-credential-library-attributes'; diff --git a/addons/api/app/serializers/credential-library.js b/addons/api/app/serializers/credential-library.js new file mode 100644 index 000000000..2a76b7b03 --- /dev/null +++ b/addons/api/app/serializers/credential-library.js @@ -0,0 +1 @@ +export { default } from 'api/serializers/credential-library'; diff --git a/addons/api/app/serializers/fragment-credential-library-attributes.js b/addons/api/app/serializers/fragment-credential-library-attributes.js new file mode 100644 index 000000000..d16c81e21 --- /dev/null +++ b/addons/api/app/serializers/fragment-credential-library-attributes.js @@ -0,0 +1 @@ +export { default } from 'api/serializers/fragment-credential-library-attributes'; diff --git a/addons/api/tests/unit/models/credential-library-test.js b/addons/api/tests/unit/models/credential-library-test.js new file mode 100644 index 000000000..4cd00ab05 --- /dev/null +++ b/addons/api/tests/unit/models/credential-library-test.js @@ -0,0 +1,13 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Model | credential library', function (hooks) { + setupTest(hooks); + + // Replace this with your real tests. + test('it exists', function (assert) { + let store = this.owner.lookup('service:store'); + let model = store.createRecord('credential-library', {}); + assert.ok(model); + }); +}); diff --git a/addons/api/tests/unit/models/fragment-credential-library-attributes-test.js b/addons/api/tests/unit/models/fragment-credential-library-attributes-test.js new file mode 100644 index 000000000..01f649c1e --- /dev/null +++ b/addons/api/tests/unit/models/fragment-credential-library-attributes-test.js @@ -0,0 +1,19 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module( + 'Unit | Model | fragment credential library attributes', + function (hooks) { + setupTest(hooks); + + // Replace this with your real tests. + test('it exists', function (assert) { + let store = this.owner.lookup('service:store'); + let model = store.createRecord( + 'fragment-credential-library-attributes', + {} + ); + assert.ok(model); + }); + } +); diff --git a/addons/api/tests/unit/serializers/credential-library-test.js b/addons/api/tests/unit/serializers/credential-library-test.js new file mode 100644 index 000000000..4be3c76f2 --- /dev/null +++ b/addons/api/tests/unit/serializers/credential-library-test.js @@ -0,0 +1,67 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Serializer | credential library', function (hooks) { + setupTest(hooks); + + test('it serializes correctly on create', function (assert) { + assert.expect(1); + const store = this.owner.lookup('service:store'); + const serializer = store.serializerFor('credential-library'); + const record = store.createRecord('credential-library', { + name: 'Name', + description: 'Description', + attributes: { + path: '/vault/path', + http_method: 'GET', + }, + version: 1, + }); + const snapshot = record._createSnapshot(); + const serializedRecord = serializer.serialize(snapshot); + assert.deepEqual(serializedRecord, { + credential_store_id: null, + name: 'Name', + description: 'Description', + version: 1, + attributes: { + path: '/vault/path', + http_method: 'GET', + }, + }); + }); + + test('it serializes correctly on update', function (assert) { + assert.expect(1); + const store = this.owner.lookup('service:store'); + const serializer = store.serializerFor('credential-library'); + store.push({ + data: { + id: '1', + type: 'credential-library', + attributes: { + name: 'Name', + description: 'Description', + attributes: { + path: '/vault/path', + http_method: 'GET', + }, + version: 1, + }, + }, + }); + const record = store.peekRecord('credential-library', '1'); + const snapshot = record._createSnapshot(); + const serializedRecord = serializer.serialize(snapshot); + assert.deepEqual(serializedRecord, { + credential_store_id: null, + name: 'Name', + description: 'Description', + attributes: { + path: '/vault/path', + http_method: 'GET', + }, + version: 1, + }); + }); +}); diff --git a/addons/api/tests/unit/serializers/fragment-credential-library-attributes-test.js b/addons/api/tests/unit/serializers/fragment-credential-library-attributes-test.js new file mode 100644 index 000000000..72818936c --- /dev/null +++ b/addons/api/tests/unit/serializers/fragment-credential-library-attributes-test.js @@ -0,0 +1,59 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module( + 'Unit | Serializer | fragment credential library attributes', + function (hooks) { + setupTest(hooks); + + test('it serializes empty strings to null', function (assert) { + assert.expect(1); + const store = this.owner.lookup('service:store'); + const record = store.createRecord( + 'fragment-credential-library-attributes', + { + http_method: '', + path: null, + } + ); + let serializedRecord = record.serialize(); + assert.deepEqual(serializedRecord, { + http_method: null, + path: null, + }); + }); + + test('it does not serialize http_request_body unless http_method is set to POST', function (assert) { + assert.expect(2); + const store = this.owner.lookup('service:store'); + const record = store.createRecord( + 'fragment-credential-library-attributes', + { + http_method: 'GET', + http_request_body: 'body', + } + ); + let serializedRecord = record.serialize(); + assert.deepEqual( + serializedRecord, + { + http_method: 'GET', + path: null, + }, + 'http_request_body attribute is not expected' + ); + + record.http_method = 'POST'; + serializedRecord = record.serialize(); + assert.deepEqual( + serializedRecord, + { + http_method: 'POST', + http_request_body: 'body', + path: null, + }, + 'http_request_body attribute is expected' + ); + }); + } +); From 1fb41665e55d62573bcd63a560b6a2bc0b035626 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Mon, 12 Jul 2021 16:03:06 -0400 Subject: [PATCH 02/15] feat: Mock credential library in api addon --- addons/api/mirage/config.js | 14 ++++++++++++++ addons/api/mirage/factories/credential-library.js | 14 ++++++++++++++ addons/api/mirage/factories/credential-store.js | 11 +++++++++++ .../generated/factories/credential-library.js | 12 ++++++++++++ .../mirage/generated/factories/credential-store.js | 2 +- addons/api/mirage/models/credential-library.js | 6 ++++++ addons/api/mirage/scenarios/default.js | 2 +- .../api/mirage/serializers/credential-library.js | 14 ++++++++++++++ 8 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 addons/api/mirage/factories/credential-library.js create mode 100644 addons/api/mirage/generated/factories/credential-library.js create mode 100644 addons/api/mirage/models/credential-library.js create mode 100644 addons/api/mirage/serializers/credential-library.js diff --git a/addons/api/mirage/config.js b/addons/api/mirage/config.js index 1b495c0b2..6e598b47d 100644 --- a/addons/api/mirage/config.js +++ b/addons/api/mirage/config.js @@ -464,6 +464,20 @@ export default function () { credentialStores.where({ scopeId }) ); + // credential-libraries + + this.get( + '/credential-libraries', + ( + { credentialLibraries }, + { queryParams: { credential_store_id: credentialStoreId } } + ) => credentialLibraries.where({ credentialStoreId }) + ); + this.get('/credential-libraries/:id'); + this.post('/credential-libraries/:id'); + this.del('/credential-libraries/:id'); + this.patch('/credential-libraries/:id'); + /* Uncomment the following line and the Response import above * Then change the response code to simulate error responses. * this.get('/scopes', () => new Response(505)); diff --git a/addons/api/mirage/factories/credential-library.js b/addons/api/mirage/factories/credential-library.js new file mode 100644 index 000000000..f1127d5ef --- /dev/null +++ b/addons/api/mirage/factories/credential-library.js @@ -0,0 +1,14 @@ +import factory from '../generated/factories/credential-library'; +import { random, system } from 'faker'; + +export default factory.extend({ + id: (i) => `credential-library-id-${i}`, + + attributes() { + return { + http_method: 'GET', + http_request_body: random.word(), + path: system.directoryPath(), + }; + }, +}); diff --git a/addons/api/mirage/factories/credential-store.js b/addons/api/mirage/factories/credential-store.js index e143b5906..d1b037c7d 100644 --- a/addons/api/mirage/factories/credential-store.js +++ b/addons/api/mirage/factories/credential-store.js @@ -1,5 +1,6 @@ import factory from '../generated/factories/credential-store'; import { random, internet, datatype } from 'faker'; +import { trait } from 'ember-cli-mirage'; const types = ['vault']; @@ -22,4 +23,14 @@ export default factory.extend({ }; } }, + + withAssociations: trait({ + afterCreate(credentialStore, server) { + const { scope } = credentialStore; + server.createList('credential-library', 2, { + scope, + credentialStore, + }); + }, + }), }); diff --git a/addons/api/mirage/generated/factories/credential-library.js b/addons/api/mirage/generated/factories/credential-library.js new file mode 100644 index 000000000..b2e001493 --- /dev/null +++ b/addons/api/mirage/generated/factories/credential-library.js @@ -0,0 +1,12 @@ +import { Factory } from 'ember-cli-mirage'; +import { random, date } from 'faker'; + +/** + * GeneratedCredentialLibraryModelFactory + */ +export default Factory.extend({ + name: () => random.words(), + description: () => random.words(), + created_time: () => date.recent(), + updated_time: () => date.recent(), +}); diff --git a/addons/api/mirage/generated/factories/credential-store.js b/addons/api/mirage/generated/factories/credential-store.js index 1fb24e39e..2b8a86dd2 100644 --- a/addons/api/mirage/generated/factories/credential-store.js +++ b/addons/api/mirage/generated/factories/credential-store.js @@ -2,7 +2,7 @@ import { Factory } from 'ember-cli-mirage'; import { random, date } from 'faker'; /** - * GeneratedAuthMethodModelFactory + * GeneratedCredentialStoreModelFactory */ export default Factory.extend({ name: () => random.words(), diff --git a/addons/api/mirage/models/credential-library.js b/addons/api/mirage/models/credential-library.js new file mode 100644 index 000000000..921a63182 --- /dev/null +++ b/addons/api/mirage/models/credential-library.js @@ -0,0 +1,6 @@ +import { Model, belongsTo } from 'ember-cli-mirage'; + +export default Model.extend({ + scope: belongsTo(), + credentialStore: belongsTo(), +}); diff --git a/addons/api/mirage/scenarios/default.js b/addons/api/mirage/scenarios/default.js index 12adb6c5d..fc5931908 100644 --- a/addons/api/mirage/scenarios/default.js +++ b/addons/api/mirage/scenarios/default.js @@ -49,6 +49,6 @@ export default function (server) { server.createList('host-catalog', 2, { scope }, 'withChildren'); server.createList('target', 2, { scope }, 'withRandomHostSets'); server.createList('session', 4, { scope }, 'withAssociations'); - server.createList('credential-store', 3, { scope }); + server.createList('credential-store', 3, { scope }, 'withAssociations'); }); } diff --git a/addons/api/mirage/serializers/credential-library.js b/addons/api/mirage/serializers/credential-library.js new file mode 100644 index 000000000..fd65fc743 --- /dev/null +++ b/addons/api/mirage/serializers/credential-library.js @@ -0,0 +1,14 @@ +import ApplicationSerializer from './application'; + +export default ApplicationSerializer.extend({ + modelName: 'credential-library', + + _hashForModel(model) { + const json = ApplicationSerializer.prototype._hashForModel.apply( + this, + arguments + ); + json.credential_store_id = model.credentialStoreId; + return json; + }, +}); From 885ce5ebf53305e0b467fcf5fe9c63011ff09cf1 Mon Sep 17 00:00:00 2001 From: Carlos Alcaide Date: Wed, 14 Jul 2021 07:59:15 -0700 Subject: [PATCH 03/15] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Adding=20credentia?= =?UTF-8?q?l=20store=20edit=20form?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add credential-store mirage config. Add edit credential store form. Add credential store route. Add credential store template. --- addons/api/mirage/config.js | 3 ++ .../form/credential-store/index.hbs | 37 +++++++++++++++++++ ui/admin/app/router.js | 6 ++- .../routes/scopes/scope/credential-stores.js | 16 ++++++++ .../credential-stores/credential-store.js | 20 +++++++++- .../credential-stores/credential-store.hbs | 26 ++++++++++++- .../credential-store/-header.hbs | 3 ++ .../credential-store/-navigation.hbs | 5 +++ .../credential-store/index.hbs | 4 ++ 9 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 ui/admin/app/components/form/credential-store/index.hbs create mode 100644 ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs create mode 100644 ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-navigation.hbs create mode 100644 ui/admin/app/templates/scopes/scope/credential-stores/credential-store/index.hbs diff --git a/addons/api/mirage/config.js b/addons/api/mirage/config.js index 6e598b47d..4564352a6 100644 --- a/addons/api/mirage/config.js +++ b/addons/api/mirage/config.js @@ -464,6 +464,9 @@ export default function () { credentialStores.where({ scopeId }) ); + this.get('/credential-stores/:id'); + this.patch('/credential-stores/:id'); + // credential-libraries this.get( diff --git a/ui/admin/app/components/form/credential-store/index.hbs b/ui/admin/app/components/form/credential-store/index.hbs new file mode 100644 index 000000000..312dce672 --- /dev/null +++ b/ui/admin/app/components/form/credential-store/index.hbs @@ -0,0 +1,37 @@ + + + + + + + + + \ No newline at end of file diff --git a/ui/admin/app/router.js b/ui/admin/app/router.js index 4d723cab8..21a7859c7 100644 --- a/ui/admin/app/router.js +++ b/ui/admin/app/router.js @@ -87,7 +87,11 @@ Router.map(function () { }); }); this.route('credential-stores', function () { - this.route('credential-store', { path: ':credential_store_id' }); + this.route( + 'credential-store', + { path: ':credential_store_id' }, + function () {} + ); }); }); }); diff --git a/ui/admin/app/routes/scopes/scope/credential-stores.js b/ui/admin/app/routes/scopes/scope/credential-stores.js index 7f75dd4fa..d08a6402a 100644 --- a/ui/admin/app/routes/scopes/scope/credential-stores.js +++ b/ui/admin/app/routes/scopes/scope/credential-stores.js @@ -1,4 +1,7 @@ import Route from '@ember/routing/route'; +import { action } from '@ember/object'; +import loading from 'ember-loading/decorator'; +import { notifySuccess, notifyError } from 'core/decorators/notify'; export default class ScopesScopeCredentialStoresRoute extends Route { /** @@ -9,4 +12,17 @@ export default class ScopesScopeCredentialStoresRoute extends Route { const { id: scope_id } = this.modelFor('scopes.scope'); return this.store.query('credential-store', { scope_id }); } + + @action + @loading + @notifyError(({ message }) => message) + @notifySuccess('notifications.save-success') + async save(credentialStore) { + await credentialStore.save(); + await this.transitionTo( + 'scopes.scope.credential-stores.credential-store', + credentialStore + ); + this.refresh(); + } } diff --git a/ui/admin/app/routes/scopes/scope/credential-stores/credential-store.js b/ui/admin/app/routes/scopes/scope/credential-stores/credential-store.js index 82fa9d62c..307c11079 100644 --- a/ui/admin/app/routes/scopes/scope/credential-stores/credential-store.js +++ b/ui/admin/app/routes/scopes/scope/credential-stores/credential-store.js @@ -6,6 +6,24 @@ export default class ScopesScopeCredentialStoresCredentialStoreRoute extends Rou * @return {Promise[CredentialStoreModel]} */ async model({ credential_store_id }) { - return this.route.findRecord('credential-store', credential_store_id); + return this.store.findRecord('credential-store', credential_store_id); + } + + /** + * Render credential store header and navigation page sections. + * @override + */ + renderTemplate() { + super.renderTemplate(...arguments); + + this.render('scopes/scope/credential-stores/credential-store/-header', { + into: 'scopes/scope/credential-stores/credential-store', + outlet: 'header', + }); + + this.render('scopes/scope/credential-stores/credential-store/-navigation', { + into: 'scopes/scope/credential-stores/credential-store', + outlet: 'navigation', + }); } } diff --git a/ui/admin/app/templates/scopes/scope/credential-stores/credential-store.hbs b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store.hbs index 637b45528..a6ecd7f81 100644 --- a/ui/admin/app/templates/scopes/scope/credential-stores/credential-store.hbs +++ b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store.hbs @@ -1,2 +1,24 @@ -{{page-title 'CredentialStore'}} -{{outlet}} \ No newline at end of file +{{page-title @model.displayName}} + + + + + + + + + {{outlet 'header'}} + + + + {{outlet 'navigation'}} + + + + {{!-- {{outlet 'actions'}} --}} + + + + {{outlet}} + + \ No newline at end of file diff --git a/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs new file mode 100644 index 000000000..d9df667e2 --- /dev/null +++ b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs @@ -0,0 +1,3 @@ +

{{@model.displayName}}

+

{{@model.description}}

+{{@model.id}} \ No newline at end of file diff --git a/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-navigation.hbs b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-navigation.hbs new file mode 100644 index 000000000..86b9cf585 --- /dev/null +++ b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-navigation.hbs @@ -0,0 +1,5 @@ + + + {{t 'titles.details'}} + + \ No newline at end of file diff --git a/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/index.hbs b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/index.hbs new file mode 100644 index 000000000..860476547 --- /dev/null +++ b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/index.hbs @@ -0,0 +1,4 @@ + \ No newline at end of file From b9c5ed0de3599cf798881656d68ab981c1e25760 Mon Sep 17 00:00:00 2001 From: Carlos Alcaide Date: Wed, 14 Jul 2021 10:15:21 -0700 Subject: [PATCH 04/15] Add cancel action when editing a credential-store. Add breadcrumb feature on the credential store controller. --- .../components/form/credential-store/index.hbs | 1 + .../scope/credential-stores/credential-store.js | 13 +++++++++++++ .../routes/scopes/scope/credential-stores.js | 11 +++++++++++ .../credential-store/-header.hbs | 8 +++++++- .../credential-store/index.hbs | 1 + .../credential-stores/credential-store-test.js | 17 +++++++++++++++++ 6 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 ui/admin/app/controllers/scopes/scope/credential-stores/credential-store.js create mode 100644 ui/admin/tests/unit/controllers/scopes/scope/credential-stores/credential-store-test.js diff --git a/ui/admin/app/components/form/credential-store/index.hbs b/ui/admin/app/components/form/credential-store/index.hbs index 312dce672..f972854c1 100644 --- a/ui/admin/app/components/form/credential-store/index.hbs +++ b/ui/admin/app/components/form/credential-store/index.hbs @@ -1,5 +1,6 @@ message) @@ -25,4 +29,11 @@ export default class ScopesScopeCredentialStoresRoute extends Route { ); this.refresh(); } + + @action + cancel(credentialStore) { + const { isNew } = credentialStore; + credentialStore.rollbackAttributes(); + if (isNew) this.transitionTo('scopes.scope.credential-stores'); + } } diff --git a/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs index d9df667e2..9bdf844ae 100644 --- a/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs +++ b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs @@ -1,3 +1,9 @@

{{@model.displayName}}

{{@model.description}}

-{{@model.id}} \ No newline at end of file + + {{@model.id}} + \ No newline at end of file diff --git a/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/index.hbs b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/index.hbs index 860476547..aaa14a18c 100644 --- a/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/index.hbs +++ b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/index.hbs @@ -1,4 +1,5 @@ \ No newline at end of file diff --git a/ui/admin/tests/unit/controllers/scopes/scope/credential-stores/credential-store-test.js b/ui/admin/tests/unit/controllers/scopes/scope/credential-stores/credential-store-test.js new file mode 100644 index 000000000..5736858ff --- /dev/null +++ b/ui/admin/tests/unit/controllers/scopes/scope/credential-stores/credential-store-test.js @@ -0,0 +1,17 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module( + 'Unit | Controller | scopes/scope/credential-stores/credential-store', + function (hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function (assert) { + let controller = this.owner.lookup( + 'controller:scopes/scope/credential-stores/credential-store' + ); + assert.ok(controller); + }); + } +); From c82a8be1ed6f4f66d1ced1cc8128a0994e083692 Mon Sep 17 00:00:00 2001 From: Carlos Alcaide Date: Wed, 14 Jul 2021 11:29:45 -0700 Subject: [PATCH 05/15] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Stop=20using=20mod?= =?UTF-8?q?el=20on=20template?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stop using model on template, so no more updating template while editing the form. Add link to documentation --- .../.watchman-cookie-ccorvo-C02FJ2P9Q05P-810-234 | 0 .../credential-stores/credential-store/index.js | 3 +++ .../credential-store/-header.hbs | 4 ++-- .../scopes/scope/credential-stores/index.hbs | 5 ++++- ui/admin/config/environment.js | 1 + .../credential-store/index-test.js | 16 ++++++++++++++++ 6 files changed, 26 insertions(+), 3 deletions(-) create mode 100755 addons/rose/.watchman-cookie-ccorvo-C02FJ2P9Q05P-810-234 create mode 100644 ui/admin/app/routes/scopes/scope/credential-stores/credential-store/index.js create mode 100644 ui/admin/tests/unit/routes/scopes/scope/credential-stores/credential-store/index-test.js diff --git a/addons/rose/.watchman-cookie-ccorvo-C02FJ2P9Q05P-810-234 b/addons/rose/.watchman-cookie-ccorvo-C02FJ2P9Q05P-810-234 new file mode 100755 index 000000000..e69de29bb diff --git a/ui/admin/app/routes/scopes/scope/credential-stores/credential-store/index.js b/ui/admin/app/routes/scopes/scope/credential-stores/credential-store/index.js new file mode 100644 index 000000000..7e61beb34 --- /dev/null +++ b/ui/admin/app/routes/scopes/scope/credential-stores/credential-store/index.js @@ -0,0 +1,3 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeCredentialStoresCredentialStoreIndexRoute extends Route {} diff --git a/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs index 9bdf844ae..0ff5c81bc 100644 --- a/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs +++ b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs @@ -1,5 +1,5 @@ -

{{@model.displayName}}

-

{{@model.description}}

+

{{t 'resources.credential-store.title'}}

+

{{t 'resources.credential-store.description'}}

{{t 'resources.credential-store.title_plural'}} +

- {{t 'resources.credential-store.description'}} + {{#if @model}} +

{{t 'resources.credential-store.description'}}

+ {{/if}} {{!-- diff --git a/ui/admin/config/environment.js b/ui/admin/config/environment.js index 7464ea022..fca0dab92 100644 --- a/ui/admin/config/environment.js +++ b/ui/admin/config/environment.js @@ -55,6 +55,7 @@ module.exports = function (environment) { 'host-set': '/host-sets', 'host-set.new': '/host-sets/new', 'host-set.add-hosts': '/host-sets/add-hosts', + 'credential-stores': '/credential-stores', host: '/hosts', 'host.new': '/hosts/new', role: '/roles', diff --git a/ui/admin/tests/unit/routes/scopes/scope/credential-stores/credential-store/index-test.js b/ui/admin/tests/unit/routes/scopes/scope/credential-stores/credential-store/index-test.js new file mode 100644 index 000000000..a08a9fff6 --- /dev/null +++ b/ui/admin/tests/unit/routes/scopes/scope/credential-stores/credential-store/index-test.js @@ -0,0 +1,16 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module( + 'Unit | Route | scopes/scope/credential-stores/credential-store/index', + function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let route = this.owner.lookup( + 'route:scopes/scope/credential-stores/credential-store/index' + ); + assert.ok(route); + }); + } +); From cf377ad3dc07ad493b6e085946247cd4cb923c68 Mon Sep 17 00:00:00 2001 From: Carlos Alcaide Date: Fri, 16 Jul 2021 08:36:57 -0700 Subject: [PATCH 06/15] Delete model check --- .../app/templates/scopes/scope/credential-stores/index.hbs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ui/admin/app/templates/scopes/scope/credential-stores/index.hbs b/ui/admin/app/templates/scopes/scope/credential-stores/index.hbs index 765371017..0e2177ff1 100644 --- a/ui/admin/app/templates/scopes/scope/credential-stores/index.hbs +++ b/ui/admin/app/templates/scopes/scope/credential-stores/index.hbs @@ -8,9 +8,7 @@ {{t 'resources.credential-store.title_plural'}} - {{#if @model}} -

{{t 'resources.credential-store.description'}}

- {{/if}} +

{{t 'resources.credential-store.description'}}

{{!-- From 1a46a6b183204fe26544a823efe4845808f6d2c1 Mon Sep 17 00:00:00 2001 From: Carlos Alcaide Date: Fri, 16 Jul 2021 08:52:18 -0700 Subject: [PATCH 07/15] Add .watchman-cookie to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 80cb94003..f8f2ec1c2 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ testem.log yarn-error.log storybook-static **/.storybook/*.html +addons/rose/.watchman-cookie* # ember-try .node_modules.ember-try From e4a0150ee79fed9fb9579a73ff81be04ba1c590a Mon Sep 17 00:00:00 2001 From: Carlos Alcaide Date: Fri, 16 Jul 2021 08:53:37 -0700 Subject: [PATCH 08/15] Delete watchman cookie file --- addons/rose/.watchman-cookie-ccorvo-C02FJ2P9Q05P-810-234 | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 addons/rose/.watchman-cookie-ccorvo-C02FJ2P9Q05P-810-234 diff --git a/addons/rose/.watchman-cookie-ccorvo-C02FJ2P9Q05P-810-234 b/addons/rose/.watchman-cookie-ccorvo-C02FJ2P9Q05P-810-234 deleted file mode 100755 index e69de29bb..000000000 From cf72af400404ca6b708ee5168b50e7e204b8f780 Mon Sep 17 00:00:00 2001 From: Carlos Alcaide Date: Fri, 16 Jul 2021 09:05:36 -0700 Subject: [PATCH 09/15] Add comments to route functions --- .gitignore | 2 +- ui/admin/app/routes/scopes/scope/credential-stores.js | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f8f2ec1c2..95852e8ad 100644 --- a/.gitignore +++ b/.gitignore @@ -22,7 +22,7 @@ testem.log yarn-error.log storybook-static **/.storybook/*.html -addons/rose/.watchman-cookie* +.watchman-cookie* # ember-try .node_modules.ember-try diff --git a/ui/admin/app/routes/scopes/scope/credential-stores.js b/ui/admin/app/routes/scopes/scope/credential-stores.js index 6dc7128e5..4bac020b1 100644 --- a/ui/admin/app/routes/scopes/scope/credential-stores.js +++ b/ui/admin/app/routes/scopes/scope/credential-stores.js @@ -17,6 +17,10 @@ export default class ScopesScopeCredentialStoresRoute extends Route { // =actions + /** + * Handle save + * @param {CredentialStoreModel} credentialStore + */ @action @loading @notifyError(({ message }) => message) @@ -30,6 +34,10 @@ export default class ScopesScopeCredentialStoresRoute extends Route { this.refresh(); } + /** + * Rollback changes on credential stores. + * @param {CredentialStoreModel} credentialStore + */ @action cancel(credentialStore) { const { isNew } = credentialStore; From 03187e2e2e1aa66d6444afa7e5094f4a639ea80d Mon Sep 17 00:00:00 2001 From: Carlos Alcaide Date: Fri, 16 Jul 2021 09:07:53 -0700 Subject: [PATCH 10/15] Fix typo in comment --- .../scopes/scope/credential-stores/credential-store.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/admin/app/controllers/scopes/scope/credential-stores/credential-store.js b/ui/admin/app/controllers/scopes/scope/credential-stores/credential-store.js index 2b799746b..67b0b2c33 100644 --- a/ui/admin/app/controllers/scopes/scope/credential-stores/credential-store.js +++ b/ui/admin/app/controllers/scopes/scope/credential-stores/credential-store.js @@ -4,7 +4,7 @@ export default class ScopesScopeCredentialStoresCredentialStoreController extend // =attributes /** - * A role breadcrumb + * A credential store breadcrumb * @type {string} */ get breadCrumb() { From 221748232909a9aa414c92aeb7883e818c70b7a3 Mon Sep 17 00:00:00 2001 From: Carlos Alcaide Date: Wed, 14 Jul 2021 07:59:15 -0700 Subject: [PATCH 11/15] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Adding=20credentia?= =?UTF-8?q?l=20store=20edit=20form?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add credential-store mirage config. Add edit credential store form. Add credential store route. Add credential store template. --- ui/admin/app/components/form/credential-store/index.hbs | 3 +++ .../scope/credential-stores/credential-store/-header.hbs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ui/admin/app/components/form/credential-store/index.hbs b/ui/admin/app/components/form/credential-store/index.hbs index f972854c1..446ac598a 100644 --- a/ui/admin/app/components/form/credential-store/index.hbs +++ b/ui/admin/app/components/form/credential-store/index.hbs @@ -1,6 +1,9 @@ >>>>>> 9bf653f8 (feat: 🎸 Adding credential store edit form) @disabled={{@model.isSaving}} @showEditToggle={{if @model.isNew false true}} as |form| diff --git a/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs index 0ff5c81bc..c3db9fd05 100644 --- a/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs +++ b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs @@ -6,4 +6,4 @@ @acknowledgeText={{t 'states.copied'}} > {{@model.id}} -
\ No newline at end of file + From 3b4bb24eb7d13efb811829ceb7daa957518a0eed Mon Sep 17 00:00:00 2001 From: Carlos Alcaide Date: Thu, 15 Jul 2021 09:36:32 -0700 Subject: [PATCH 12/15] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Add=20credential?= =?UTF-8?q?=20store?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add screen to create new credential store --- ui/admin/app/router.js | 1 + .../scopes/scope/credential-stores/new.js | 14 +++++++++++++ .../scopes/scope/credential-stores/index.hbs | 4 ++-- .../scopes/scope/credential-stores/new.hbs | 20 +++++++++++++++++++ .../scope/credential-stores/new-test.js | 11 ++++++++++ 5 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 ui/admin/app/routes/scopes/scope/credential-stores/new.js create mode 100644 ui/admin/app/templates/scopes/scope/credential-stores/new.hbs create mode 100644 ui/admin/tests/unit/routes/scopes/scope/credential-stores/new-test.js diff --git a/ui/admin/app/router.js b/ui/admin/app/router.js index 21a7859c7..665582957 100644 --- a/ui/admin/app/router.js +++ b/ui/admin/app/router.js @@ -92,6 +92,7 @@ Router.map(function () { { path: ':credential_store_id' }, function () {} ); + this.route('new'); }); }); }); diff --git a/ui/admin/app/routes/scopes/scope/credential-stores/new.js b/ui/admin/app/routes/scopes/scope/credential-stores/new.js new file mode 100644 index 000000000..fecb9bb9b --- /dev/null +++ b/ui/admin/app/routes/scopes/scope/credential-stores/new.js @@ -0,0 +1,14 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeCredentialStoresNewRoute extends Route { + // =methods + /** + * Creates a new unsaved credential-store + */ + model() { + const scopeModel = this.modelFor('scopes.scope'); + return this.store.createRecord('credential-store', { + scopeModel, + }); + } +} diff --git a/ui/admin/app/templates/scopes/scope/credential-stores/index.hbs b/ui/admin/app/templates/scopes/scope/credential-stores/index.hbs index 0e2177ff1..c8ff3b098 100644 --- a/ui/admin/app/templates/scopes/scope/credential-stores/index.hbs +++ b/ui/admin/app/templates/scopes/scope/credential-stores/index.hbs @@ -11,7 +11,7 @@

{{t 'resources.credential-store.description'}}

- {{!-- + {{#if @model}} {{/if}} - --}} + {{#if @model}} diff --git a/ui/admin/app/templates/scopes/scope/credential-stores/new.hbs b/ui/admin/app/templates/scopes/scope/credential-stores/new.hbs new file mode 100644 index 000000000..cb38701d9 --- /dev/null +++ b/ui/admin/app/templates/scopes/scope/credential-stores/new.hbs @@ -0,0 +1,20 @@ +{{page-title (t 'titles.new')}} + + + + + + + +

{{t 'titles.new'}}

+
+ + + + + +
\ No newline at end of file diff --git a/ui/admin/tests/unit/routes/scopes/scope/credential-stores/new-test.js b/ui/admin/tests/unit/routes/scopes/scope/credential-stores/new-test.js new file mode 100644 index 000000000..ea136c333 --- /dev/null +++ b/ui/admin/tests/unit/routes/scopes/scope/credential-stores/new-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/credential-stores/new', function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let route = this.owner.lookup('route:scopes/scope/credential-stores/new'); + assert.ok(route); + }); +}); From d6129a7dfcc4a2488ee31a42a3a15c86de77afcb Mon Sep 17 00:00:00 2001 From: Carlos Alcaide Date: Fri, 16 Jul 2021 09:41:41 -0700 Subject: [PATCH 13/15] Fix lint issues --- ui/admin/app/components/form/credential-store/index.hbs | 3 --- .../scope/credential-stores/credential-store/-header.hbs | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/ui/admin/app/components/form/credential-store/index.hbs b/ui/admin/app/components/form/credential-store/index.hbs index 446ac598a..f972854c1 100644 --- a/ui/admin/app/components/form/credential-store/index.hbs +++ b/ui/admin/app/components/form/credential-store/index.hbs @@ -1,9 +1,6 @@ >>>>>> 9bf653f8 (feat: 🎸 Adding credential store edit form) @disabled={{@model.isSaving}} @showEditToggle={{if @model.isNew false true}} as |form| diff --git a/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs index c3db9fd05..0ff5c81bc 100644 --- a/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs +++ b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/-header.hbs @@ -6,4 +6,4 @@ @acknowledgeText={{t 'states.copied'}} > {{@model.id}} - + \ No newline at end of file From 90675580822bab226b3e87a40370face7ab1ea73 Mon Sep 17 00:00:00 2001 From: Carlos Alcaide Date: Fri, 16 Jul 2021 10:28:31 -0700 Subject: [PATCH 14/15] Add type to credential store creation --- ui/admin/app/routes/scopes/scope/credential-stores/new.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/admin/app/routes/scopes/scope/credential-stores/new.js b/ui/admin/app/routes/scopes/scope/credential-stores/new.js index fecb9bb9b..e8bc7e431 100644 --- a/ui/admin/app/routes/scopes/scope/credential-stores/new.js +++ b/ui/admin/app/routes/scopes/scope/credential-stores/new.js @@ -8,6 +8,7 @@ export default class ScopesScopeCredentialStoresNewRoute extends Route { model() { const scopeModel = this.modelFor('scopes.scope'); return this.store.createRecord('credential-store', { + type: 'vault', scopeModel, }); } From 816b50eb1b620ccd373d68a0d539d7158654eb86 Mon Sep 17 00:00:00 2001 From: Carlos Alcaide Date: Fri, 16 Jul 2021 10:41:04 -0700 Subject: [PATCH 15/15] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Fix=20creation=20t?= =?UTF-8?q?ype=20issue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix credential store creation type issue --- addons/api/mirage/config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/api/mirage/config.js b/addons/api/mirage/config.js index 4564352a6..1fd364182 100644 --- a/addons/api/mirage/config.js +++ b/addons/api/mirage/config.js @@ -465,6 +465,7 @@ export default function () { ); this.get('/credential-stores/:id'); + this.post('/credential-stores'); this.patch('/credential-stores/:id'); // credential-libraries