From 2614b311a19cbfc09654ecb39d6b1dbdf58d2d75 Mon Sep 17 00:00:00 2001 From: Dharini Jeeva Date: Thu, 1 Sep 2022 10:07:36 -0700 Subject: [PATCH] Icu 5578 - introduce injected application credential on the api (#1269) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 🤖 include injected cred sources to the target model --- addons/api/addon/models/target.js | 118 +++++++++++- addons/api/addon/serializers/target.js | 43 ++++- addons/api/mirage/config.js | 60 +----- addons/api/mirage/factories/target.js | 16 +- addons/api/mirage/models/target.js | 2 - addons/api/mirage/route-handlers/target.js | 99 ++++++++++ addons/api/mirage/serializers/target.js | 6 - .../unit/serializers/application-test.js | 1 + .../api/tests/unit/serializers/target-test.js | 38 +++- ui/admin/app/routes/scopes/scope/workers.js | 5 +- ...js => brokered-credential-sources-test.js} | 178 ++++++++++-------- 11 files changed, 395 insertions(+), 171 deletions(-) create mode 100644 addons/api/mirage/route-handlers/target.js rename ui/admin/tests/acceptance/targets/{credential-sources-test.js => brokered-credential-sources-test.js} (70%) diff --git a/addons/api/addon/models/target.js b/addons/api/addon/models/target.js index ae5a92716..a6f5f6ae3 100644 --- a/addons/api/addon/models/target.js +++ b/addons/api/addon/models/target.js @@ -20,7 +20,7 @@ export default class TargetModel extends GeneratedTargetModel { host_sources; /** - * Credential source ids are read only and can be + * Brokered Credential source ids are read only and can be * persisted via a dedicated call to `addBrokeredCredentialSources()`. */ @attr('string-array', { @@ -29,6 +29,16 @@ export default class TargetModel extends GeneratedTargetModel { }) brokered_credential_source_ids; + /** + * Injected Application Credential source ids are read only and can be + * persisted via a dedicated call to `addInjectedApplicationCredentialSources()`. + */ + @attr('string-array', { + readOnly: true, + emptyArrayIfMissing: true, + }) + injected_application_credential_source_ids; + /** * An array of resolved host set and host catalog instances. Model instances * must already be loaded into the store (this method will not load unloaded @@ -62,6 +72,24 @@ export default class TargetModel extends GeneratedTargetModel { .filter(Boolean); } + /** + * An array of resolved credential library and credential instances. Model instances + * must already be loaded into the store (this method will not load unloaded + * instances). Unresolvable instances are excluded from the array. + * @type {[CredentialLibraryModel, CredentialModel]} + */ + get injectedApplicationCredentialSources() { + return this.injected_application_credential_source_ids + .map((source) => { + if (source.value.startsWith('cred')) { + return this.store.peekRecord('credential', source.value); + } else { + return this.store.peekRecord('credential-library', source.value); + } + }) + .filter(Boolean); + } + /** * Sessions associated with this target (but only already loaded sessions). * @type {SessionModel[]} @@ -152,18 +180,44 @@ export default class TargetModel extends GeneratedTargetModel { /** * Adds credential sources via the `add-credential-sources` method. * See serializer and adapter for more information. - * @param {[string]} credentialSourceIDs + * @param {[string]} brokeredCredentialSourceIDs * @param {object} options * @param {object} options.adapterOptions * @return {Promise} */ addBrokeredCredentialSources( - credentialSourceIDs, + brokeredCredentialSourceIDs, options = { adapterOptions: {} } ) { const defaultAdapterOptions = { method: 'add-credential-sources', - credentialSourceIDs, + brokeredCredentialSourceIDs, + }; + // There is no "deep merge" in ES. + return this.save({ + ...options, + adapterOptions: { + ...defaultAdapterOptions, + ...options.adapterOptions, + }, + }); + } + + /** + * Adds credential sources via the `add-credential-sources` method. + * See serializer and adapter for more information. + * @param {[string]} injectedApplicationCredentialSourceIDs + * @param {object} options + * @param {object} options.adapterOptions + * @return {Promise} + */ + addInjectedApplicationCredentialSources( + injectedApplicationCredentialSourceIDs, + options = { adapterOptions: {} } + ) { + const defaultAdapterOptions = { + method: 'add-credential-sources', + injectedApplicationCredentialSourceIDs, }; // There is no "deep merge" in ES. return this.save({ @@ -178,18 +232,18 @@ export default class TargetModel extends GeneratedTargetModel { /** * Delete credential libraries and credentials via the `remove-credential-sources` method. * See serializer and adapter for more information. - * @param {[string]} credentialSourceIDs + * @param {[string]} brokeredCredentialSourceIDs * @param {object} options * @param {object} options.adapterOptions * @return {Promise} */ removeBrokeredCredentialSources( - credentialSourceIDs, + brokeredCredentialSourceIDs, options = { adapterOptions: {} } ) { const defaultAdapterOptions = { method: 'remove-credential-sources', - credentialSourceIDs, + brokeredCredentialSourceIDs, }; // There is no "deep merge" in ES. return this.save({ @@ -203,14 +257,58 @@ export default class TargetModel extends GeneratedTargetModel { /** * Delete a single credential library/credential set via the `remove-credential-sources` method. - * @param {number} credentialSourceID + * @param {number} brokeredCredentialSourceID * @param {object} options * @return {Promise} */ - removeBrokeredCredentialSource(credentialSourceID, options) { - return this.removeBrokeredCredentialSources([credentialSourceID], options); + removeBrokeredCredentialSource(brokeredCredentialSourceID, options) { + return this.removeBrokeredCredentialSources( + [brokeredCredentialSourceID], + options + ); } + /** + * Delete credential libraries and credentials via the `remove-credential-sources` method. + * See serializer and adapter for more information. + * @param {[string]} injectedApplicationCredentialSourceIDs + * @param {object} options + * @param {object} options.adapterOptions + * @return {Promise} + */ + removeInjectedApplicationCredentialSources( + injectedApplicationCredentialSourceIDs, + options = { adapterOptions: {} } + ) { + const defaultAdapterOptions = { + method: 'remove-credential-sources', + injectedApplicationCredentialSourceIDs, + }; + // There is no "deep merge" in ES. + return this.save({ + ...options, + adapterOptions: { + ...defaultAdapterOptions, + ...options.adapterOptions, + }, + }); + } + + /** + * Delete a single credential library/credential set via the `remove-credential-sources` method. + * @param {number} injectedApplicationCredentialSourceID + * @param {object} options + * @return {Promise} + */ + removeInjectedApplicationCredentialSource( + injectedApplicationCredentialSourceID, + options + ) { + return this.removeInjectedApplicationCredentialSources( + [injectedApplicationCredentialSourceID], + options + ); + } /** * True if the target type is tcp. * @type {boolean} diff --git a/addons/api/addon/serializers/target.js b/addons/api/addon/serializers/target.js index 074ad33e0..443a705eb 100644 --- a/addons/api/addon/serializers/target.js +++ b/addons/api/addon/serializers/target.js @@ -21,11 +21,20 @@ export default class TargetSerializer extends ApplicationSerializer { if (hostSourceIDs) { serialized = this.serializeWithHostSources(snapshot, hostSourceIDs); } - const credentialSourceIDs = snapshot?.adapterOptions?.credentialSourceIDs; - if (credentialSourceIDs) - serialized = this.serializeWithCredentialSources( + const brokeredCredentialSourceIDs = + snapshot?.adapterOptions?.brokeredCredentialSourceIDs; + const injectedApplicationCredentialSourceIDs = + snapshot?.adapterOptions?.injectedApplicationCredentialSourceIDs; + + if (brokeredCredentialSourceIDs) + serialized = this.serializeWithBrokeredCredentialSources( snapshot, - credentialSourceIDs + brokeredCredentialSourceIDs + ); + if (injectedApplicationCredentialSourceIDs) + serialized = this.serializeWithInjectedApplicationCredentialSources( + snapshot, + injectedApplicationCredentialSourceIDs ); return serialized; } @@ -48,13 +57,33 @@ export default class TargetSerializer extends ApplicationSerializer { * Returns a payload containing only version and an array of passed IDs, * rather than existing instances on the model. * @param {Snapshot} snapshot - * @param {[string]} credentialSourceIDs + * @param {[string]} brokered_credential_source_ids * @return {object} */ - serializeWithCredentialSources(snapshot, credentialSourceIDs) { + serializeWithBrokeredCredentialSources( + snapshot, + brokered_credential_source_ids + ) { return { version: snapshot.attr('version'), - brokered_credential_source_ids: credentialSourceIDs, + brokered_credential_source_ids, + }; + } + + /** + * Returns a payload containing only version and an array of passed IDs, + * rather than existing instances on the model. + * @param {Snapshot} snapshot + * @param {[string]} injected_application_credential_source_ids + * @return {object} + */ + serializeWithInjectedApplicationCredentialSources( + snapshot, + injected_application_credential_source_ids + ) { + return { + version: snapshot.attr('version'), + injected_application_credential_source_ids, }; } } diff --git a/addons/api/mirage/config.js b/addons/api/mirage/config.js index a200b4260..24818894c 100644 --- a/addons/api/mirage/config.js +++ b/addons/api/mirage/config.js @@ -1,5 +1,6 @@ import config from '../config/environment'; import { authHandler, deauthHandler } from './route-handlers/auth'; +import { targetHandler } from './route-handlers/target'; import { pickRandomStatusString } from './factories/session'; import { Response } from 'miragejs'; import initializeMockIPC from './scenarios/ipc'; @@ -435,64 +436,7 @@ export default function () { this.get('/targets/:id'); this.patch('/targets/:id'); this.del('/targets/:id'); - this.post( - '/targets/:idMethod', - function ({ targets }, { params: { idMethod } }) { - const attrs = this.normalizedRequestAttrs(); - const id = idMethod.split(':')[0]; - const method = idMethod.split(':')[1]; - const target = targets.find(id); - const updatedAttrs = { - version: attrs.version, - }; - // If adding host sources, push them into the array - if (method === 'add-host-sources') { - updatedAttrs.hostSetIds = target.hostSetIds; - attrs.hostSourceIds.forEach((id) => { - if (!updatedAttrs.hostSetIds.includes(id)) { - updatedAttrs.hostSetIds.push(id); - } - }); - } - // If deleting host sources, filter them out of the array - if (method === 'remove-host-sources') { - updatedAttrs.hostSetIds = target.hostSetIds; - updatedAttrs.hostSetIds = updatedAttrs.hostSetIds.filter((id) => { - return !attrs.hostSourceIds.includes(id); - }); - } - // If adding brokered credential sources, push them into the array - if (method === 'add-credential-sources') { - updatedAttrs.credentialLibraryIds = target.credentialLibraryIds; - updatedAttrs.credentialIds = target.credentialIds; - attrs.brokeredCredentialSourceIds.forEach((id) => { - if ( - !updatedAttrs.credentialLibraryIds.includes(id) || - !updatedAttrs.credentialIds.includes(id) - ) { - if (id.startsWith('cred')) { - updatedAttrs.credentialIds.push(id); - } else { - updatedAttrs.credentialLibraryIds.push(id); - } - } - }); - } - // If deleting brokered credential sources, filter them out of the array - if (method === 'remove-credential-sources') { - updatedAttrs.credentialLibraryIds = target.credentialLibraryIds; - updatedAttrs.credentialIds = target.credentialIds; - updatedAttrs.credentialLibraryIds = - updatedAttrs.credentialLibraryIds.filter((id) => { - return !attrs.brokeredCredentialSourceIds.includes(id); - }); - updatedAttrs.credentialIds = updatedAttrs.credentialIds.filter((id) => { - return !attrs.brokeredCredentialSourceIds.includes(id); - }); - } - return target.update(updatedAttrs); - } - ); + this.post('/targets/:idMethod', targetHandler); // session diff --git a/addons/api/mirage/factories/target.js b/addons/api/mirage/factories/target.js index 3b344b3ed..9ea10477e 100644 --- a/addons/api/mirage/factories/target.js +++ b/addons/api/mirage/factories/target.js @@ -65,14 +65,22 @@ export default factory.extend({ .where( (credentialLibrary) => credentialLibrary.scopeId === target.scope.id ) - .models.filter(() => randomBoolean()); + .models.filter(() => randomBoolean()) + .map((cred) => cred.id); randomlySelectedCredentials = server.schema.credentials .where((credential) => credential.scopeId === target.scope.id) - .models.filter(() => randomBoolean()); + .models.filter(() => randomBoolean()) + .map((cred) => cred.id); target.update({ hostSets: randomlySelectedHostSets, - credentialLibraries: randomlySelectedCredentialLibraries, - credentials: randomlySelectedCredentials, + brokeredCredentialSourceIds: [ + ...randomlySelectedCredentialLibraries, + ...randomlySelectedCredentials, + ], + injectedApplicationCredentialSourceIds: [ + ...randomlySelectedCredentialLibraries, + ...randomlySelectedCredentials, + ], }); }, }), diff --git a/addons/api/mirage/models/target.js b/addons/api/mirage/models/target.js index b7a6a36b2..e4413f20d 100644 --- a/addons/api/mirage/models/target.js +++ b/addons/api/mirage/models/target.js @@ -4,6 +4,4 @@ import { belongsTo, hasMany } from 'ember-cli-mirage'; export default Model.extend({ scope: belongsTo(), hostSets: hasMany(), - credentialLibraries: hasMany(), - credentials: hasMany(), }); diff --git a/addons/api/mirage/route-handlers/target.js b/addons/api/mirage/route-handlers/target.js new file mode 100644 index 000000000..af4ec1aab --- /dev/null +++ b/addons/api/mirage/route-handlers/target.js @@ -0,0 +1,99 @@ +export function targetHandler({ targets }, { params: { idMethod } }) { + const attrs = this.normalizedRequestAttrs(); + const id = idMethod.split(':')[0]; + const method = idMethod.split(':')[1]; + const target = targets.find(id); + const { + brokeredCredentialSourceIds: originalBrokeredCredentials, + injectedApplicationCredentialSourceIds: originalInjectedCredentials, + } = target; + const selectedBrokeredCredentials = attrs.brokeredCredentialSourceIds; + const selectedInjectedCredentials = + attrs.injectedApplicationCredentialSourceIds; + const selectedHostSourceIds = attrs.hostSourceIds; + const originHostSetIds = target.hostSetIds; + + const updatedAttrs = { + version: attrs.version, + }; + + const addToSourcesList = (originalSourceIds, selectedSourceIds) => { + const sourceIds = new Set([...originalSourceIds, ...selectedSourceIds]); + return [...sourceIds]; + }; + + const removeFromSourcesList = (originalSourceIds, selectedSourceIds) => { + const sourceIds = new Set(originalSourceIds); + for (const elem of selectedSourceIds) { + sourceIds.delete(elem); + } + return [...sourceIds]; + }; + + // If adding host sources, push them into the array + if (method === 'add-host-sources') { + if (selectedHostSourceIds) { + const listOfHostSources = addToSourcesList( + originHostSetIds, + selectedHostSourceIds + ); + if (listOfHostSources?.length) { + updatedAttrs.hostSetIds = listOfHostSources; + } + } + } + // If deleting host sources, filter them out of the array + if (method === 'remove-host-sources') { + if (selectedHostSourceIds) { + const removedHostSources = removeFromSourcesList( + originHostSetIds, + selectedHostSourceIds + ); + updatedAttrs.hostSetIds = removedHostSources; + } + } + // If adding brokered or injected application cred sources, push them into the array + if (method === 'add-credential-sources') { + if (selectedBrokeredCredentials) { + const listOfBrokeredCredentialSources = addToSourcesList( + originalBrokeredCredentials, + selectedBrokeredCredentials + ); + if (listOfBrokeredCredentialSources?.length) { + updatedAttrs.brokeredCredentialSourceIds = + listOfBrokeredCredentialSources; + } + } + + if (selectedInjectedCredentials) { + const listOfInjectedCredentialSources = addToSourcesList( + originalInjectedCredentials, + selectedInjectedCredentials + ); + if (listOfInjectedCredentialSources?.length) { + updatedAttrs.injectedApplicationCredentialSourceIds = + listOfInjectedCredentialSources; + } + } + } + // If deleting brokered or injected application cred sources, filter them out of the array + if (method === 'remove-credential-sources') { + if (selectedBrokeredCredentials) { + const removedCredentialSources = removeFromSourcesList( + originalBrokeredCredentials, + selectedBrokeredCredentials + ); + updatedAttrs.brokeredCredentialSourceIds = removedCredentialSources; + } + + if (selectedInjectedCredentials) { + const removedCredentialSources = removeFromSourcesList( + originalInjectedCredentials, + selectedInjectedCredentials + ); + updatedAttrs.injectedApplicationCredentialSourceIds = + removedCredentialSources; + } + } + return target.update(updatedAttrs); +} diff --git a/addons/api/mirage/serializers/target.js b/addons/api/mirage/serializers/target.js index 9f01d5287..01d8db299 100644 --- a/addons/api/mirage/serializers/target.js +++ b/addons/api/mirage/serializers/target.js @@ -23,12 +23,6 @@ export default ApplicationSerializer.extend({ return { id: host_set_id, host_catalog_id }; }); } - if (model.credentialLibraryIds?.length || model.credentialIds?.length) { - json.brokered_credential_source_ids = [ - ...model.credentialLibraryIds, - ...model.credentialIds, - ]; - } return json; }, }); diff --git a/addons/api/tests/unit/serializers/application-test.js b/addons/api/tests/unit/serializers/application-test.js index ff50169d6..545a8377c 100644 --- a/addons/api/tests/unit/serializers/application-test.js +++ b/addons/api/tests/unit/serializers/application-test.js @@ -215,6 +215,7 @@ module('Unit | Serializer | application', function (hooks) { scope: { id: 'o_123', scope_id: 'o_123' }, host_sources: [], brokered_credential_source_ids: [], + injected_application_credential_source_ids: [], }, relationships: {}, }, diff --git a/addons/api/tests/unit/serializers/target-test.js b/addons/api/tests/unit/serializers/target-test.js index 6ec23edf9..fde87e20d 100644 --- a/addons/api/tests/unit/serializers/target-test.js +++ b/addons/api/tests/unit/serializers/target-test.js @@ -16,6 +16,10 @@ module('Unit | Serializer | target', function (hooks) { { host_source_id: '3', host_catalog_id: '4' }, ], brokered_credential_source_ids: [{ value: '1' }, { value: '2' }], + injected_application_credential_source_ids: [ + { value: '4' }, + { value: '5' }, + ], scope: { scope_id: 'org_1', type: 'org', @@ -66,7 +70,7 @@ module('Unit | Serializer | target', function (hooks) { }); }); - test('it serializes only credential sources and version when an `adapterOptions.credentialSourceIDs` array is passed', function (assert) { + test('it serializes only credential sources and version when an `adapterOptions.brokeredCredentialSourceIDs` array is passed', function (assert) { assert.expect(1); const store = this.owner.lookup('service:store'); const serializer = store.serializerFor('target'); @@ -78,15 +82,40 @@ module('Unit | Serializer | target', function (hooks) { }); const snapshot = record._createSnapshot(); snapshot.adapterOptions = { - credentialSourceIDs: ['4', '5'], + brokeredCredentialSourceIDs: ['4', '5'], }; const serializedRecord = serializer.serialize(snapshot); + assert.deepEqual(serializedRecord, { brokered_credential_source_ids: ['4', '5'], version: 1, }); }); + test('it serializes only credential sources and version when an `adapterOptions.injectedApplicationCredentialSourceIDs` array is passed', function (assert) { + assert.expect(1); + const store = this.owner.lookup('service:store'); + const serializer = store.serializerFor('target'); + const record = store.createRecord('target', { + name: 'User', + description: 'Description', + injected_application_credential_source_ids: [ + { value: '1' }, + { value: '2' }, + ], + version: 1, + }); + const snapshot = record._createSnapshot(); + snapshot.adapterOptions = { + injectedApplicationCredentialSourceIDs: ['4', '5'], + }; + const serializedRecord = serializer.serialize(snapshot); + + assert.deepEqual(serializedRecord, { + injected_application_credential_source_ids: ['4', '5'], + version: 1, + }); + }); test('it serializes the worker_filter attribute if present', function (assert) { assert.expect(1); const store = this.owner.lookup('service:store'); @@ -132,6 +161,7 @@ module('Unit | Serializer | target', function (hooks) { { host_source_id: '3', host_catalog_id: '4' }, ], brokered_credential_source_ids: ['1'], + injected_application_credential_source_ids: ['3'], }; const normalized = serializer.normalizeSingleResponse( store, @@ -151,6 +181,7 @@ module('Unit | Serializer | target', function (hooks) { { host_source_id: '3', host_catalog_id: '4' }, ], brokered_credential_source_ids: [{ value: '1' }], + injected_application_credential_source_ids: [{ value: '3' }], }, relationships: {}, }, @@ -181,6 +212,7 @@ module('Unit | Serializer | target', function (hooks) { type: 'target', attributes: { brokered_credential_source_ids: [], + injected_application_credential_source_ids: [], authorized_actions: [], host_sources: [], name: 'Target 1', @@ -217,6 +249,7 @@ module('Unit | Serializer | target', function (hooks) { scope: { id: 'o_123', scope_id: 'o_123' }, host_sources: [], brokered_credential_source_ids: [], + injected_application_credential_source_ids: [], }, relationships: {}, }, @@ -248,6 +281,7 @@ module('Unit | Serializer | target', function (hooks) { name: 'Target 1', host_sources: [], brokered_credential_source_ids: [], + injected_application_credential_source_ids: [], worker_filter: 'worker', }, relationships: {}, diff --git a/ui/admin/app/routes/scopes/scope/workers.js b/ui/admin/app/routes/scopes/scope/workers.js index afba82223..159609af7 100644 --- a/ui/admin/app/routes/scopes/scope/workers.js +++ b/ui/admin/app/routes/scopes/scope/workers.js @@ -5,11 +5,10 @@ import { loading } from 'ember-loading'; import { confirm } from 'core/decorators/confirm'; import { notifySuccess, notifyError } from 'core/decorators/notify'; - export default class ScopesScopeWorkersRoute extends Route { // =services - - @service can + + @service can; @service session; @service router; diff --git a/ui/admin/tests/acceptance/targets/credential-sources-test.js b/ui/admin/tests/acceptance/targets/brokered-credential-sources-test.js similarity index 70% rename from ui/admin/tests/acceptance/targets/credential-sources-test.js rename to ui/admin/tests/acceptance/targets/brokered-credential-sources-test.js index 6dc1c74a6..54bb7c2c7 100644 --- a/ui/admin/tests/acceptance/targets/credential-sources-test.js +++ b/ui/admin/tests/acceptance/targets/brokered-credential-sources-test.js @@ -4,20 +4,17 @@ import { setupApplicationTest } from 'ember-qunit'; import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; import { Response } from 'miragejs'; import a11yAudit from 'ember-a11y-testing/test-support/audit'; -import { - authenticateSession, - // These are left here intentionally for future reference. - //currentSession, - //invalidateSession, -} from 'ember-simple-auth/test-support'; +import { authenticateSession } from 'ember-simple-auth/test-support'; -module('Acceptance | targets | credential sources', function (hooks) { +module('Acceptance | targets | brokered credential sources', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); let getCredentialLibraryCount; let getCredentialCount; let credentialSourceCount; + let randomlySelectedCredentialLibraries; + let randomlySelectedCredentials; const instances = { scopes: { @@ -41,6 +38,7 @@ module('Acceptance | targets | credential sources', function (hooks) { credentialLibraries: null, credentialLibrary: null, addBrokeredCredentialSources: null, + brokeredCredentialSources: null, }; hooks.beforeEach(function () { @@ -78,38 +76,54 @@ module('Acceptance | targets | credential sources', function (hooks) { instances.credential = instances.credentials[0]; instances.target = this.server.create('target', { scope: instances.scopes.project, - credentialLibraries: instances.credentialLibraries, }); + + randomlySelectedCredentials = this.server.schema.credentials + .all() + .models.filter(Boolean) + .map((cred) => cred.id); + randomlySelectedCredentialLibraries = this.server.schema.credentialLibraries + .all() + .models.filter(Boolean) + .map((cred) => cred.id); + + instances.target.update({ + brokeredCredentialSourceIds: [ + ...randomlySelectedCredentialLibraries, + ...randomlySelectedCredentials, + ], + }); + // Generate route URLs for resources urls.globalScope = `/scopes/global/scopes`; urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`; urls.projectScope = `/scopes/${instances.scopes.project.id}`; urls.targets = `${urls.projectScope}/targets`; urls.target = `${urls.targets}/${instances.target.id}`; - urls.credentialSources = `${urls.target}/brokered-credential-sources`; + urls.brokeredCredentialSources = `${urls.target}/brokered-credential-sources`; urls.credentialLibrary = `${urls.projectScope}/credential-stores/${instances.credentialLibrary.credentialStoreId}/credential-libraries/${instances.credentialLibrary.id}`; urls.credential = `${urls.projectScope}/credential-stores/${instances.credential.credentialStoreId}/credentials/${instances.credential.id}`; urls.addBrokeredCredentialSources = `${urls.target}/add-brokered-credential-sources`; - // Generate resource counter getCredentialLibraryCount = () => this.server.schema.credentialLibraries.all().models.length; getCredentialCount = () => this.server.schema.credentials.all().models.length; credentialSourceCount = getCredentialLibraryCount() + getCredentialCount(); + authenticateSession({}); }); - test('visiting target credential sources', async function (assert) { + test('visiting target brokered credential sources', async function (assert) { assert.expect(2); - await visit(urls.credentialSources); + await visit(urls.brokeredCredentialSources); await a11yAudit(); - assert.strictEqual(currentURL(), urls.credentialSources); - assert.strictEqual(findAll('tbody tr').length, getCredentialLibraryCount()); + assert.strictEqual(currentURL(), urls.brokeredCredentialSources); + assert.strictEqual(findAll('tbody tr').length, credentialSourceCount); }); test('can navigate to a vault type credential library', async function (assert) { assert.expect(1); - await visit(urls.credentialSources); + await visit(urls.brokeredCredentialSources); await click('main tbody .rose-table-header-cell:nth-child(1) a'); await a11yAudit(); assert.strictEqual(currentURL(), urls.credentialLibrary); @@ -118,51 +132,43 @@ module('Acceptance | targets | credential sources', function (hooks) { test('can navigate to a username & password type credential', async function (assert) { assert.expect(1); instances.target.update({ - credentialLibraries: [], - credentials: instances.credentials, + brokeredCredentialSourceIds: [...randomlySelectedCredentials], }); - await visit(urls.credentialSources); + await visit(urls.brokeredCredentialSources); await click('main tbody .rose-table-header-cell:nth-child(1) a'); await a11yAudit(); assert.strictEqual(currentURL(), urls.credential); }); - test('visiting add credential sources', async function (assert) { + test('visiting add brokered credential sources', async function (assert) { assert.expect(1); await visit(urls.addBrokeredCredentialSources); await a11yAudit(); assert.strictEqual(currentURL(), urls.addBrokeredCredentialSources); }); - test('displays list of all credential source types available', async function (assert) { + test('displays list of all brokered credential source types available', async function (assert) { assert.expect(2); - instances.target.update({ credentialLibraries: [] }); + instances.target.update({ + brokeredCredentialSourceIds: [], + }); await visit(urls.addBrokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, credentialSourceCount); - assert.notOk(find('.rose-message-title')); + assert.dom('.rose-message-title').doesNotExist(); }); - test('displays list of credential sources with only credential libraries available', async function (assert) { + test('displays list of brokered credential sources with only credential libraries available', async function (assert) { assert.expect(2); - instances.target.update({ credentialLibraries: [] }); - this.server.db.credentials.remove(); + instances.target.update({ + brokeredCredentialSourceIds: [...randomlySelectedCredentialLibraries], + }); await visit(urls.addBrokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, getCredentialLibraryCount()); - assert.notOk(find('.rose-message-title')); + assert.dom('.rose-message-title').doesNotExist(); }); - test('displays list of credential sources with only credentials available', async function (assert) { - assert.expect(2); - await visit(urls.addBrokeredCredentialSources); - assert.strictEqual(findAll('tbody tr').length, getCredentialCount()); - assert.notOk(find('.rose-message-title')); - }); - - test('displays no credential sources message when none available', async function (assert) { + test('displays no brokered credential sources message when none available', async function (assert) { assert.expect(1); - instances.target.update({ credentialLibraries: [] }); - this.server.db.credentialLibraries.remove(); - this.server.db.credentials.remove(); await visit(urls.addBrokeredCredentialSources); assert.strictEqual( find('.rose-message-title').textContent.trim(), @@ -170,53 +176,59 @@ module('Acceptance | targets | credential sources', function (hooks) { ); }); - test('when no credential sources available, button routes to credential sources', async function (assert) { + test('when no brokered credential sources available, button routes to add brokered credential sources', async function (assert) { assert.expect(1); - instances.target.update({ credentialLibraries: [] }); - this.server.db.credentialLibraries.remove(); - this.server.db.credentials.remove(); - await visit(urls.addBrokeredCredentialSources); + instances.target.update({ + brokeredCredentialSourceIds: [], + }); + await visit(urls.brokeredCredentialSources); await click(find('.rose-message-link')); - assert.strictEqual(currentURL(), urls.credentialSources); + assert.strictEqual(currentURL(), urls.addBrokeredCredentialSources); }); test('can select and save a vault type credential library to add', async function (assert) { assert.expect(4); - instances.target.update({ credentialLibraries: [] }); - await visit(urls.credentialSources); + instances.target.update({ + brokeredCredentialSourceIds: [], + }); + await visit(urls.brokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, 0); await visit(urls.addBrokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, credentialSourceCount); await click('tbody tr:first-child label'); await click('form [type="submit"]'); - assert.strictEqual(currentURL(), urls.credentialSources); + assert.strictEqual(currentURL(), urls.brokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, 1); }); test('can select and save a username & password type credential to add', async function (assert) { assert.expect(4); - instances.target.update({ credentialLibraries: [] }); - await visit(urls.credentialSources); + instances.target.update({ + brokeredCredentialSourceIds: [], + }); + await visit(urls.brokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, 0); await visit(urls.addBrokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, credentialSourceCount); await click('tbody tr:last-child label'); await click('form [type="submit"]'); - assert.strictEqual(currentURL(), urls.credentialSources); + assert.strictEqual(currentURL(), urls.brokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, 1); }); test('can select and save both a credential-library and a credential to add', async function (assert) { assert.expect(4); - instances.target.update({ credentialLibraries: [] }); - await visit(urls.credentialSources); + instances.target.update({ + brokeredCredentialSourceIds: [], + }); + await visit(urls.brokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, 0); await visit(urls.addBrokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, credentialSourceCount); await click('tbody tr:last-child label'); await click('tbody tr:first-child label'); await click('form [type="submit"]'); - assert.strictEqual(currentURL(), urls.credentialSources); + assert.strictEqual(currentURL(), urls.brokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, 2); }); @@ -226,34 +238,38 @@ module('Acceptance | targets | credential sources', function (hooks) { instances.target.authorized_actions.filter( (item) => item !== 'add-credential-sources' ); - await visit(urls.credentialSources); - assert.notOk(find(`[href="${urls.addBrokeredCredentialSources}"]`)); + await visit(urls.brokeredCredentialSources); + assert.dom(`[href="${urls.addBrokeredCredentialSources}"]`).doesNotExist(); }); test('can select and cancel credential sources to add', async function (assert) { assert.expect(4); - instances.target.update({ credentialLibraries: [] }); - await visit(urls.credentialSources); + instances.target.update({ + brokeredCredentialSourceIds: [], + }); + await visit(urls.brokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, 0); await visit(urls.addBrokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, credentialSourceCount); await click('tbody label'); await click('form [type="button"]'); - assert.strictEqual(currentURL(), urls.credentialSources); + assert.strictEqual(currentURL(), urls.brokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, 0); }); - test('can select multiple credential sources to add and cancel', async function (assert) { + test('can select multiple brokered credential sources to add and cancel', async function (assert) { assert.expect(4); - instances.target.update({ credentialLibraries: [] }); - await visit(urls.credentialSources); + instances.target.update({ + brokeredCredentialSourceIds: [], + }); + await visit(urls.brokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, 0); await visit(urls.addBrokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, credentialSourceCount); await click('tbody tr:last-child label'); await click('tbody tr:first-child label'); await click('form [type="button"]'); - assert.strictEqual(currentURL(), urls.credentialSources); + assert.strictEqual(currentURL(), urls.brokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, 0); }); @@ -271,40 +287,42 @@ module('Acceptance | targets | credential sources', function (hooks) { } ); }); - instances.target.update({ credentialLibraries: [] }); + instances.target.update({ + brokeredCredentialSourceIds: [], + }); await visit(urls.addBrokeredCredentialSources); await click('tbody tr:last-child label'); await click('tbody tr:first-child label'); await click('form [type="submit"]'); - assert.ok(find('[role="alert"]')); + assert.dom('[role="alert"]').isVisible(); }); test('can remove a vault type credential library', async function (assert) { assert.expect(3); + instances.target.update({ + brokeredCredentialSourceIds: [...randomlySelectedCredentialLibraries], + }); const credentialLibraryCount = getCredentialLibraryCount(); - const credentialCount = getCredentialCount(); - await visit(urls.credentialSources); + await visit(urls.brokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, credentialLibraryCount); await click('tbody tr .rose-dropdown-button-danger'); assert.strictEqual(findAll('tbody tr').length, credentialLibraryCount - 1); await visit(urls.addBrokeredCredentialSources); - assert.strictEqual(findAll('tbody tr').length, credentialCount + 1); + assert.strictEqual(findAll('tbody tr').length, credentialLibraryCount + 1); }); test('can remove a username & password type credential', async function (assert) { assert.expect(3); instances.target.update({ - credentialLibraries: [], - credentials: instances.credentials, + brokeredCredentialSourceIds: [...randomlySelectedCredentials], }); const credentialCount = getCredentialCount(); - const credentialLibraryCount = getCredentialLibraryCount(); - await visit(urls.credentialSources); + await visit(urls.brokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, credentialCount); await click('tbody tr .rose-dropdown-button-danger'); assert.strictEqual(findAll('tbody tr').length, credentialCount - 1); await visit(urls.addBrokeredCredentialSources); - assert.strictEqual(findAll('tbody tr').length, credentialLibraryCount + 1); + assert.strictEqual(findAll('tbody tr').length, credentialCount + 1); }); test('cannot remove credential libraries without proper authorization', async function (assert) { @@ -313,12 +331,15 @@ module('Acceptance | targets | credential sources', function (hooks) { instances.target.authorized_actions.filter( (item) => item !== 'remove-credential-sources' ); - await visit(urls.credentialSources); - assert.notOk(find('tbody tr .rose-dropdown-button-danger')); + await visit(urls.brokeredCredentialSources); + assert.dom('tbody tr .rose-dropdown-button-danger').doesNotExist(); }); test('removing a target credential library which errors displays error messages', async function (assert) { assert.expect(2); + instances.target.update({ + brokeredCredentialSourceIds: [...randomlySelectedCredentialLibraries], + }); this.server.post('/targets/:idMethod', () => { return new Response( 400, @@ -332,17 +353,16 @@ module('Acceptance | targets | credential sources', function (hooks) { ); }); const count = getCredentialLibraryCount(); - await visit(urls.credentialSources); + await visit(urls.brokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, count); await click('tbody tr .rose-dropdown-button-danger'); - assert.ok(find('[role="alert"]')); + assert.dom('[role="alert"]').isVisible(); }); test('removing a target credential which errors displays error messages', async function (assert) { assert.expect(2); instances.target.update({ - credentialLibraries: [], - credentials: instances.credentials, + brokeredCredentialSourceIds: [...randomlySelectedCredentials], }); this.server.post('/targets/:idMethod', () => { return new Response( @@ -357,9 +377,9 @@ module('Acceptance | targets | credential sources', function (hooks) { ); }); const count = getCredentialCount(); - await visit(urls.credentialSources); + await visit(urls.brokeredCredentialSources); assert.strictEqual(findAll('tbody tr').length, count); await click('tbody tr .rose-dropdown-button-danger'); - assert.ok(find('[role="alert"]')); + assert.dom('[role="alert"]').isVisible(); }); });