Icu 5578 - introduce injected application credential on the api (#1269)
* chore: 🤖 include injected cred sources to the target model
This commit is contained in:
1 parent
bd0854b0f6
commit
2614b311a1
11 files changed
+395
-171
No files matched your search
@@ -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}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
],
|
||||
});
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -4,6 +4,4 @@ import { belongsTo, hasMany } from 'ember-cli-mirage';
|
||||
export default Model.extend({
|
||||
scope: belongsTo(),
|
||||
hostSets: hasMany(),
|
||||
credentialLibraries: hasMany(),
|
||||
credentials: hasMany(),
|
||||
});
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
},
|
||||
});
|
||||
@@ -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: {},
|
||||
},
|
||||
|
||||
@@ -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: {},
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+99
-79
@@ -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();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user