diff --git a/addons/api/mirage/route-handlers/target.js b/addons/api/mirage/route-handlers/target.js index f6590c15a..5750e69d1 100644 --- a/addons/api/mirage/route-handlers/target.js +++ b/addons/api/mirage/route-handlers/target.js @@ -9,8 +9,8 @@ export function targetHandler({ targets }, { params: { idMethod } }) { const method = idMethod.split(':')[1]; const target = targets.find(id); const { - brokeredCredentialSourceIds: originalBrokeredCredentials, - injectedApplicationCredentialSourceIds: originalInjectedCredentials, + brokeredCredentialSourceIds: originalBrokeredCredentials = [], + injectedApplicationCredentialSourceIds: originalInjectedCredentials = [], } = target; const selectedBrokeredCredentials = attrs.brokeredCredentialSourceIds; const selectedInjectedCredentials = diff --git a/ui/admin/app/components/targets/target/actions/index.hbs b/ui/admin/app/components/targets/target/actions/index.hbs index 9eacbd237..77897b69c 100644 --- a/ui/admin/app/components/targets/target/actions/index.hbs +++ b/ui/admin/app/components/targets/target/actions/index.hbs @@ -37,7 +37,7 @@ {{t 'resources.target.actions.delete'}} diff --git a/ui/admin/app/controllers/scopes/scope/targets/index.js b/ui/admin/app/controllers/scopes/scope/targets/index.js index 9411915a9..25923c3e7 100644 --- a/ui/admin/app/controllers/scopes/scope/targets/index.js +++ b/ui/admin/app/controllers/scopes/scope/targets/index.js @@ -6,14 +6,20 @@ import Controller from '@ember/controller'; import { inject as service } from '@ember/service'; import { tracked } from '@glimmer/tracking'; -import { TYPES_TARGET } from 'api/models/target'; import { action } from '@ember/object'; import { debounce } from 'core/decorators/debounce'; +import { loading } from 'ember-loading'; +import { confirm } from 'core/decorators/confirm'; +import { notifySuccess, notifyError } from 'core/decorators/notify'; +import { TYPES_TARGET } from 'api/models/target'; export default class ScopesScopeTargetsIndexController extends Controller { // =services @service intl; + @service can; + @service router; + @service confirm; // =attributes @@ -66,7 +72,7 @@ export default class ScopesScopeTargetsIndexController extends Controller { })); } - // =methods + // =actions /** * Handles input on each keystroke and the search queryParam @@ -91,4 +97,223 @@ export default class ScopesScopeTargetsIndexController extends Controller { this[paramKey] = [...selectedItems]; this.page = 1; } + + /** + * Rollback changes on a target. + * @param {TargetModel} target + */ + @action + cancel(target) { + const { isNew } = target; + target.rollbackAttributes(); + if (isNew) this.router.transitionTo('scopes.scope.targets'); + } + + /** + * Saves the target and refreshes the list. + * @param {TargetModel} target + */ + @action + @loading + @notifyError(({ message }) => message) + @notifySuccess(({ isNew }) => + isNew ? 'notifications.create-success' : 'notifications.save-success', + ) + async save(target) { + await target.save(); + if (this.can.can('read model', target)) { + await this.router.transitionTo('scopes.scope.targets.target', target); + } else { + await this.router.transitionTo('scopes.scope.targets'); + } + await this.router.refresh(); + } + + /** + * Targets may have either an `address` _or_ host sources, but not both. + * + * In order to save a target with an `address`, any existing host sources + * must first be removed. Once host sources are removed, the target with + * `address` may be saved via the standard `save` action. + * + * If `address` and host sources are both present, the user is asked to + * confirm that they wish to remove all host sources. If the user declines, + * no changes are persisted; the form remains editable and unsaved. + * + * If `address` is set and the target has no host sources, the save proceeds + * as normal. + * + * If neither `address` nor host sources are set, the save proceeds as normal. + * + * @param {TargetModel} target + */ + @action + async saveWithAddress(target) { + if (target.address) { + const { address } = target; + // Remove host sources if necessary. This is cancelable by the user. + await this.removeHostSources(target); + // After removing host sources, the model is reset to an empty address, + // so we need to update the address with the previous value. + target.address = address; + } + + // Proceed with standard save. + await this.save(target); + } + + /** + * If the passed target has host sources: + * - Request confirmation from the user for host source removal. + * - Persist removal of all host sources. + * @param {TargetModel} target + */ + @action + @loading + @notifyError(({ message }) => message) + async removeHostSources(target) { + const hostSourceCount = target.host_sources?.length; + + if (hostSourceCount) { + const hostSourceIDs = target.host_sources.map( + ({ host_source_id }) => host_source_id, + ); + const confirmMessage = this.intl.t( + 'resources.target.questions.delete-host-sources.message', + { hostSourceCount }, + ); + + // Ask for confirmation + await this.confirm.confirm(confirmMessage, { + title: 'resources.target.questions.delete-host-sources.title', + confirm: 'actions.remove-resources', + }); + // Remove host sources. This step is reached only if the user accepts. + await target.removeHostSources(hostSourceIDs); + } + } + + /** + * Deletes a target and redirects to targets index. + * @param {TargetModel} target + */ + @action + @loading + @confirm('questions.delete-confirm') + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.delete-success') + async delete(target) { + await target.destroyRecord(); + this.router.replaceWith('scopes.scope.targets'); + await this.router.refresh(); + } + + /** + * Update type of target + * @param {string} type + */ + @action + changeType(type) { + this.router.replaceWith({ queryParams: { type } }); + } + + /** + * Remove a credential source from the current target. + * @param {TargetModel} target + * @param {CredentialLibraryModel, credentialModel} credentialSource + */ + @action + @loading + @confirm('questions.remove-confirm') + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.remove-success') + async removeInjectedApplicationCredentialSource(target, credentialSource) { + await target.removeInjectedApplicationCredentialSource(credentialSource.id); + await this.router.refresh(); + } + + /** + * Remove a credential source from the current target. + * @param {TargetModel} target + * @param {CredentialLibraryModel, credentialModel} credentialSource + */ + @action + @loading + @confirm('questions.remove-confirm') + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.remove-success') + async removeBrokeredCredentialSource(target, credentialSource) { + await target.removeBrokeredCredentialSource(credentialSource.id); + await this.router.refresh(); + } + + /** + * Removes a host set from the current target and redirects to index. + * @param {TargetModel} target + * @param {HostSetModel} hostSet + */ + @action + @loading + @confirm('questions.remove-confirm') + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.remove-success') + async removeHostSource(target, hostSet) { + await target.removeHostSource(hostSet.id); + await this.router.refresh(); + } + + /** + * Delete an alias + * @param {AliasModel} alias + */ + @action + @loading + @confirm('resources.alias.messages.delete') + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.delete-success') + async deleteAlias(alias) { + await alias.destroyRecord(); + await this.router.transitionTo('scopes.scope.targets.target'); + await this.router.refresh('scopes.scope.targets.target'); + } + + /** + * Remove destaination_id from alias + * @param {AliasModel} alias + */ + @action + @loading + @confirm('questions.clear-confirm') + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.clear-success') + async clearAlias(alias) { + alias.destination_id = ''; + await alias.save(); + await this.router.transitionTo('scopes.scope.targets.target'); + await this.router.refresh('scopes.scope.targets.target'); + } + + /** + * Handle save + * @param {AliasModel} alias + */ + @action + @loading + @notifyError(({ message }) => message) + @notifySuccess('notifications.save-success') + async saveAlias(alias) { + await alias.save(); + await this.router.transitionTo('scopes.scope.targets.target'); + await this.router.refresh(); + } + + /** + * Rollback changes on alias. + * @param {AliasModel} alias + */ + @action + async cancelAlias(alias) { + alias.rollbackAttributes(); + await this.router.transitionTo('scopes.scope.targets.target'); + } } diff --git a/ui/admin/app/controllers/scopes/scope/targets/new.js b/ui/admin/app/controllers/scopes/scope/targets/new.js index 247f56be4..ff9d5d53b 100644 --- a/ui/admin/app/controllers/scopes/scope/targets/new.js +++ b/ui/admin/app/controllers/scopes/scope/targets/new.js @@ -3,10 +3,10 @@ * SPDX-License-Identifier: BUSL-1.1 */ -import Controller from '@ember/controller'; +import Controller, { inject as controller } from '@ember/controller'; export default class ScopesScopeTargetsNewController extends Controller { - // =services + @controller('scopes/scope/targets/index') targets; // =attributes diff --git a/ui/admin/app/controllers/scopes/scope/targets/target/add-brokered-credential-sources.js b/ui/admin/app/controllers/scopes/scope/targets/target/add-brokered-credential-sources.js index 63d0dfb7f..f7d673d66 100644 --- a/ui/admin/app/controllers/scopes/scope/targets/target/add-brokered-credential-sources.js +++ b/ui/admin/app/controllers/scopes/scope/targets/target/add-brokered-credential-sources.js @@ -4,10 +4,16 @@ */ import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import { loading } from 'ember-loading'; +import { notifySuccess, notifyError } from 'core/decorators/notify'; export default class ScopesScopeTargetsTargetAddBrokeredCredentialSourcesController extends Controller { // =services + @service router; + // =attributes /** @@ -38,4 +44,32 @@ export default class ScopesScopeTargetsTargetAddBrokeredCredentialSourcesControl ); return [...notAddedCredentialLibraries, ...notAddedCredentials]; } + + // =actions + + /** + * Add credential libraries to current target + * @param {TargetModel} target + * @param {[string]} credentialLibraryIDs + */ + @action + @loading + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.add-success') + async save(target, credentialLibraryIDs) { + await target.addBrokeredCredentialSources(credentialLibraryIDs); + this.router.replaceWith( + 'scopes.scope.targets.target.brokered-credential-sources', + ); + } + + /** + * Redirect to target credential sources as if nothing ever happened. + */ + @action + cancel() { + this.router.replaceWith( + 'scopes.scope.targets.target.brokered-credential-sources', + ); + } } diff --git a/ui/admin/app/controllers/scopes/scope/targets/target/add-host-sources.js b/ui/admin/app/controllers/scopes/scope/targets/target/add-host-sources.js new file mode 100644 index 000000000..8c81d9c40 --- /dev/null +++ b/ui/admin/app/controllers/scopes/scope/targets/target/add-host-sources.js @@ -0,0 +1,30 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import { loading } from 'ember-loading'; +import { notifySuccess, notifyError } from 'core/decorators/notify'; + +export default class ScopesScopeTargetsTargetAddHostSourcesController extends Controller { + // =services + + @service router; + + // =actions + + @action + @loading + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.add-success') + async save(target, hostSetIDs) { + await target.addHostSources(hostSetIDs); + this.router.replaceWith('scopes.scope.targets.target.host-sources'); + } + + /** + * Redirect to target host sources as if nothing ever happened. + */ + @action + cancel() { + this.router.replaceWith('scopes.scope.targets.target.host-sources'); + } +} diff --git a/ui/admin/app/controllers/scopes/scope/targets/target/add-injected-application-credential-sources.js b/ui/admin/app/controllers/scopes/scope/targets/target/add-injected-application-credential-sources.js index 814f41d0b..747be566c 100644 --- a/ui/admin/app/controllers/scopes/scope/targets/target/add-injected-application-credential-sources.js +++ b/ui/admin/app/controllers/scopes/scope/targets/target/add-injected-application-credential-sources.js @@ -4,10 +4,16 @@ */ import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import { loading } from 'ember-loading'; +import { notifySuccess, notifyError } from 'core/decorators/notify'; export default class ScopesScopeTargetsTargetAddInjectedApplicationCredentialSourcesController extends Controller { // =services + @service router; + // =attributes /** @@ -37,4 +43,32 @@ export default class ScopesScopeTargetsTargetAddInjectedApplicationCredentialSou ); return [...notAddedCredentialLibraries, ...notAddedCredentials]; } + + // =actions + + /** + * Add credential libraries to current target + * @param {TargetModel} target + * @param {[string]} credentialLibraryIDs + */ + @action + @loading + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.add-success') + async save(target, credentialLibraryIDs) { + await target.addInjectedApplicationCredentialSources(credentialLibraryIDs); + this.router.replaceWith( + 'scopes.scope.targets.target.injected-application-credential-sources', + ); + } + + /** + * Redirect to target credential sources as if nothing ever happened. + */ + @action + cancel() { + this.router.replaceWith( + 'scopes.scope.targets.target.injected-application-credential-sources', + ); + } } diff --git a/ui/admin/app/controllers/scopes/scope/targets/target/brokered-credential-sources.js b/ui/admin/app/controllers/scopes/scope/targets/target/brokered-credential-sources.js new file mode 100644 index 000000000..4a77290ff --- /dev/null +++ b/ui/admin/app/controllers/scopes/scope/targets/target/brokered-credential-sources.js @@ -0,0 +1,5 @@ +import Controller, { inject as controller } from '@ember/controller'; + +export default class ScopesScopeTargetsTargetBrokeredCredentialSourcesController extends Controller { + @controller('scopes/scope/targets/index') targets; +} diff --git a/ui/admin/app/controllers/scopes/scope/targets/target/create-alias.js b/ui/admin/app/controllers/scopes/scope/targets/target/create-alias.js new file mode 100644 index 000000000..c07f80c26 --- /dev/null +++ b/ui/admin/app/controllers/scopes/scope/targets/target/create-alias.js @@ -0,0 +1,5 @@ +import Controller, { inject as controller } from '@ember/controller'; + +export default class ScopesScopeTargetsTargetCreateAliasController extends Controller { + @controller('scopes/scope/targets/index') targets; +} diff --git a/ui/admin/app/controllers/scopes/scope/targets/target/enable-session-recording/create-storage-bucket.js b/ui/admin/app/controllers/scopes/scope/targets/target/enable-session-recording/create-storage-bucket.js index b4761cb68..78bbfd464 100644 --- a/ui/admin/app/controllers/scopes/scope/targets/target/enable-session-recording/create-storage-bucket.js +++ b/ui/admin/app/controllers/scopes/scope/targets/target/enable-session-recording/create-storage-bucket.js @@ -4,8 +4,46 @@ */ import Controller, { inject as controller } from '@ember/controller'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import { notifySuccess, notifyError } from 'core/decorators/notify'; +import { loading } from 'ember-loading'; export default class ScopesScopeTargetsTargetEnableSessionRecordingCreateStorageBucketController extends Controller { @controller('scopes/scope/storage-buckets/index') storageBuckets; + + // =services + + @service router; + + // =actions + + /** + * Handle save + * @param {StorageBucketModel} storageBucket + */ + @action + @loading + @notifyError(({ message }) => message) + @notifySuccess('notifications.save-success') + async save(storageBucket) { + await storageBucket.save(); + await this.router.transitionTo( + 'scopes.scope.targets.target.enable-session-recording', + ); + await this.router.refresh(); + } + + /** + * Rollback changes on storage buckets. + * @param {StorageBucketModel} storageBucket + */ + @action + cancel(storageBucket) { + storageBucket.rollbackAttributes(); + this.router.transitionTo( + 'scopes.scope.targets.target.enable-session-recording', + ); + } } diff --git a/ui/admin/app/controllers/scopes/scope/targets/target/enable-session-recording/index.js b/ui/admin/app/controllers/scopes/scope/targets/target/enable-session-recording/index.js new file mode 100644 index 000000000..4592035f6 --- /dev/null +++ b/ui/admin/app/controllers/scopes/scope/targets/target/enable-session-recording/index.js @@ -0,0 +1,24 @@ +import Controller, { inject as controller } from '@ember/controller'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; + +export default class ScopesScopeTargetsTargetEnableSessionRecordingIndexController extends Controller { + @controller('scopes/scope/targets/index') targets; + + // =services + + @service router; + + // =actions + + /** + * Reset the selected storage bucket and redirect to target + * @param {TargetModel} target + */ + @action + cancel(target) { + const { id } = target; + target.rollbackAttributes(); + this.router.transitionTo('scopes.scope.targets.target', id); + } +} diff --git a/ui/admin/app/controllers/scopes/scope/targets/target/host-sources.js b/ui/admin/app/controllers/scopes/scope/targets/target/host-sources.js new file mode 100644 index 000000000..a2bc8918b --- /dev/null +++ b/ui/admin/app/controllers/scopes/scope/targets/target/host-sources.js @@ -0,0 +1,5 @@ +import Controller, { inject as controller } from '@ember/controller'; + +export default class ScopesScopeTargetsTargetHostSourcesController extends Controller { + @controller('scopes/scope/targets/index') targets; +} diff --git a/ui/admin/app/controllers/scopes/scope/targets/target/index.js b/ui/admin/app/controllers/scopes/scope/targets/target/index.js index 73c493a1c..96f11e673 100644 --- a/ui/admin/app/controllers/scopes/scope/targets/target/index.js +++ b/ui/admin/app/controllers/scopes/scope/targets/target/index.js @@ -9,7 +9,7 @@ import { inject as service } from '@ember/service'; import { tracked } from '@glimmer/tracking'; export default class ScopesScopeTargetsTargetIndexController extends Controller { - @controller('scopes/scope/targets/target/index') targets; + @controller('scopes/scope/targets/index') targets; // =services @@ -17,6 +17,7 @@ export default class ScopesScopeTargetsTargetIndexController extends Controller @service router; // =attributes + @tracked showFlyout = false; // =actions diff --git a/ui/admin/app/controllers/scopes/scope/targets/target/injected-application-credential-sources.js b/ui/admin/app/controllers/scopes/scope/targets/target/injected-application-credential-sources.js new file mode 100644 index 000000000..b230b2d51 --- /dev/null +++ b/ui/admin/app/controllers/scopes/scope/targets/target/injected-application-credential-sources.js @@ -0,0 +1,5 @@ +import Controller, { inject as controller } from '@ember/controller'; + +export default class ScopesScopeTargetsTargetInjectedApplicationCredentialSourcesController extends Controller { + @controller('scopes/scope/targets/index') targets; +} diff --git a/ui/admin/app/controllers/scopes/scope/targets/target/manage-alias.js b/ui/admin/app/controllers/scopes/scope/targets/target/manage-alias.js new file mode 100644 index 000000000..9b83e2b90 --- /dev/null +++ b/ui/admin/app/controllers/scopes/scope/targets/target/manage-alias.js @@ -0,0 +1,5 @@ +import Controller, { inject as controller } from '@ember/controller'; + +export default class ScopesScopeTargetsTargetManageAliasController extends Controller { + @controller('scopes/scope/targets/index') targets; +} diff --git a/ui/admin/app/routes/scopes/scope/targets.js b/ui/admin/app/routes/scopes/scope/targets.js index 71519197c..791e681ca 100644 --- a/ui/admin/app/routes/scopes/scope/targets.js +++ b/ui/admin/app/routes/scopes/scope/targets.js @@ -5,19 +5,12 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import { loading } from 'ember-loading'; -import { confirm } from 'core/decorators/confirm'; -import { notifySuccess, notifyError } from 'core/decorators/notify'; export default class ScopesScopeTargetsRoute extends Route { // =services - @service intl; @service session; - @service can; @service router; - @service confirm; // =methods @@ -27,148 +20,4 @@ export default class ScopesScopeTargetsRoute extends Route { beforeModel() { if (!this.session.isAuthenticated) this.router.transitionTo('index'); } - - // =actions - - /** - * Rollback changes on a target. - * @param {TargetModel} target - */ - @action - cancel(target) { - const { isNew } = target; - target.rollbackAttributes(); - if (isNew) this.router.transitionTo('scopes.scope.targets'); - } - - /** - * Saves the target and refreshes the list. - * @param {TargetModel} target - */ - @action - @loading - @notifyError(({ message }) => message) - @notifySuccess(({ isNew }) => - isNew ? 'notifications.create-success' : 'notifications.save-success', - ) - async save(target) { - await target.save(); - if (this.can.can('read model', target)) { - await this.router.transitionTo('scopes.scope.targets.target', target); - } else { - await this.router.transitionTo('scopes.scope.targets'); - } - this.refresh(); - } - - /** - * Targets may have either an `address` _or_ host sources, but not both. - * - * In order to save a target with an `address`, any existing host sources - * must first be removed. Once host sources are removed, the target with - * `address` may be saved via the standard `save` action. - * - * If `address` and host sources are both present, the user is asked to - * confirm that they wish to remove all host sources. If the user declines, - * no changes are persisted; the form remains editable and unsaved. - * - * If `address` is set and the target has no host sources, the save proceeds - * as normal. - * - * If neither `address` nor host sources are set, the save proceeds as normal. - * - * @param {TargetModel} target - */ - @action - async saveWithAddress(target) { - if (target.address) { - const { address } = target; - // Remove host sources if necessary. This is cancelable by the user. - await this.removeHostSources(target); - // After removing host sources, the model is reset to an empty address, - // so we need to update the address with the previous value. - target.address = address; - } - - // Proceed with standard save. - await this.save(target); - } - - /** - * If the passed target has host sources: - * - Request confirmation from the user for host source removal. - * - Persist removal of all host sources. - * @param {TargetModel} target - */ - @action - @loading - @notifyError(({ message }) => message) - async removeHostSources(target) { - const hostSourceCount = target.host_sources?.length; - - if (hostSourceCount) { - const hostSourceIDs = target.host_sources.map( - ({ host_source_id }) => host_source_id, - ); - const confirmMessage = this.intl.t( - 'resources.target.questions.delete-host-sources.message', - { hostSourceCount }, - ); - - // Ask for confirmation - await this.confirm.confirm(confirmMessage, { - title: 'resources.target.questions.delete-host-sources.title', - confirm: 'actions.remove-resources', - }); - // Remove host sources. This step is reached only if the user accepts. - await target.removeHostSources(hostSourceIDs); - } - } - - /** - * Deletes a target and redirects to targets index. - * @param {TargetModel} target - */ - @action - @loading - @confirm('questions.delete-confirm') - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.delete-success') - async delete(target) { - await target.destroyRecord(); - // awaiting this transition causes a transitionAborted error to bubble up - this.router.replaceWith('scopes.scope.targets'); - this.refresh(); - } - - /** - * Delete an alias - * @param {AliasModel} alias - */ - @action - @loading - @confirm('resources.alias.messages.delete') - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.delete-success') - async deleteAlias(alias) { - await alias.destroyRecord(); - this.router.refresh('scopes.scope.targets.target'); - await this.router.transitionTo('scopes.scope.targets.target'); - } - - /** - * Remove destaination_id from alias - * @param {AliasModel} alias - */ - @action - @loading - @confirm('questions.clear-confirm') - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.clear-success') - async clearAlias(alias) { - alias.destination_id = ''; - await alias.save(); - this.router.refresh('scopes.scope.targets.target'); - await this.router.transitionTo('scopes.scope.targets.target'); - } } diff --git a/ui/admin/app/routes/scopes/scope/targets/new.js b/ui/admin/app/routes/scopes/scope/targets/new.js index 13fae3d8c..c25a8bb96 100644 --- a/ui/admin/app/routes/scopes/scope/targets/new.js +++ b/ui/admin/app/routes/scopes/scope/targets/new.js @@ -4,7 +4,6 @@ */ import Route from '@ember/routing/route'; -import { action } from '@ember/object'; import { inject as service } from '@ember/service'; import { TYPE_TARGET_TCP, TYPE_TARGET_SSH } from 'api/models/target'; @@ -77,12 +76,4 @@ export default class ScopesScopeTargetsNewRoute extends Route { const globalScope = await this.store.peekRecord('scope', 'global'); controller.set('globalScope', globalScope); } - /** - * Update type of target - * @param {string} type - */ - @action - changeType(type) { - this.router.replaceWith({ queryParams: { type } }); - } } diff --git a/ui/admin/app/routes/scopes/scope/targets/target/add-brokered-credential-sources.js b/ui/admin/app/routes/scopes/scope/targets/target/add-brokered-credential-sources.js index 61e6eca3a..fed6dbb73 100644 --- a/ui/admin/app/routes/scopes/scope/targets/target/add-brokered-credential-sources.js +++ b/ui/admin/app/routes/scopes/scope/targets/target/add-brokered-credential-sources.js @@ -5,16 +5,11 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import { loading } from 'ember-loading'; -import { notifySuccess, notifyError } from 'core/decorators/notify'; export default class ScopesScopeTargetsTargetAddBrokeredCredentialSourcesRoute extends Route { // =services @service store; - @service intl; - @service router; // =methods @@ -65,32 +60,4 @@ export default class ScopesScopeTargetsTargetAddBrokeredCredentialSourcesRoute e credentials, }; } - - // =actions - - /** - * Add credential libraries to current target - * @param {TargetModel} target - * @param {[string]} credentialLibraryIDs - */ - @action - @loading - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.add-success') - async save(target, credentialLibraryIDs) { - await target.addBrokeredCredentialSources(credentialLibraryIDs); - this.router.replaceWith( - 'scopes.scope.targets.target.brokered-credential-sources', - ); - } - - /** - * Redirect to target credential sources as if nothing ever happened. - */ - @action - cancel() { - this.router.replaceWith( - 'scopes.scope.targets.target.brokered-credential-sources', - ); - } } diff --git a/ui/admin/app/routes/scopes/scope/targets/target/add-host-sources.js b/ui/admin/app/routes/scopes/scope/targets/target/add-host-sources.js index f1e319406..e3010541b 100644 --- a/ui/admin/app/routes/scopes/scope/targets/target/add-host-sources.js +++ b/ui/admin/app/routes/scopes/scope/targets/target/add-host-sources.js @@ -5,16 +5,11 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import { loading } from 'ember-loading'; -import { notifySuccess, notifyError } from 'core/decorators/notify'; export default class ScopesScopeTargetsTargetAddHostSourcesRoute extends Route { // =services @service store; - @service intl; - @service router; // =methods @@ -54,23 +49,4 @@ export default class ScopesScopeTargetsTargetAddHostSourcesRoute extends Route { hostSets, }; } - - // =actions - - @action - @loading - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.add-success') - async save(target, hostSetIDs) { - await target.addHostSources(hostSetIDs); - this.router.replaceWith('scopes.scope.targets.target.host-sources'); - } - - /** - * Redirect to target host sources as if nothing ever happened. - */ - @action - cancel() { - this.router.replaceWith('scopes.scope.targets.target.host-sources'); - } } diff --git a/ui/admin/app/routes/scopes/scope/targets/target/add-injected-application-credential-sources.js b/ui/admin/app/routes/scopes/scope/targets/target/add-injected-application-credential-sources.js index a5c20928e..940b42f24 100644 --- a/ui/admin/app/routes/scopes/scope/targets/target/add-injected-application-credential-sources.js +++ b/ui/admin/app/routes/scopes/scope/targets/target/add-injected-application-credential-sources.js @@ -5,16 +5,11 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import { loading } from 'ember-loading'; -import { notifySuccess, notifyError } from 'core/decorators/notify'; export default class ScopesScopeTargetsTargetAddInjectedApplicationCredentialSourcesRoute extends Route { // =services @service store; - @service intl; - @service router; // =methods @@ -64,32 +59,4 @@ export default class ScopesScopeTargetsTargetAddInjectedApplicationCredentialSou credentials, }; } - - // =actions - - /** - * Add credential libraries to current target - * @param {TargetModel} target - * @param {[string]} credentialLibraryIDs - */ - @action - @loading - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.add-success') - async save(target, credentialLibraryIDs) { - await target.addInjectedApplicationCredentialSources(credentialLibraryIDs); - this.router.replaceWith( - 'scopes.scope.targets.target.injected-application-credential-sources', - ); - } - - /** - * Redirect to target credential sources as if nothing ever happened. - */ - @action - cancel() { - this.router.replaceWith( - 'scopes.scope.targets.target.injected-application-credential-sources', - ); - } } diff --git a/ui/admin/app/routes/scopes/scope/targets/target/brokered-credential-sources.js b/ui/admin/app/routes/scopes/scope/targets/target/brokered-credential-sources.js index 9b7757b29..7dd442ace 100644 --- a/ui/admin/app/routes/scopes/scope/targets/target/brokered-credential-sources.js +++ b/ui/admin/app/routes/scopes/scope/targets/target/brokered-credential-sources.js @@ -5,10 +5,6 @@ import Route from '@ember/routing/route'; import { all } from 'rsvp'; -import { action } from '@ember/object'; -import { loading } from 'ember-loading'; -import { confirm } from 'core/decorators/confirm'; -import { notifySuccess, notifyError } from 'core/decorators/notify'; import { inject as service } from '@ember/service'; export default class ScopesScopeTargetsTargetBrokeredCredentialSourcesRoute extends Route { @@ -49,21 +45,4 @@ export default class ScopesScopeTargetsTargetBrokeredCredentialSourcesRoute exte model() { return this.modelFor('scopes.scope.targets.target'); } - - // =actions - - /** - * Remove a credential source from the current target. - * @param {TargetModel} target - * @param {CredentialLibraryModel, credentialModel} credentialSource - */ - @action - @loading - @confirm('questions.remove-confirm') - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.remove-success') - async removeBrokeredCredentialSource(target, credentialSource) { - await target.removeBrokeredCredentialSource(credentialSource.id); - this.refresh(); - } } diff --git a/ui/admin/app/routes/scopes/scope/targets/target/create-alias.js b/ui/admin/app/routes/scopes/scope/targets/target/create-alias.js index f3bcf5ea4..d712c93ed 100644 --- a/ui/admin/app/routes/scopes/scope/targets/target/create-alias.js +++ b/ui/admin/app/routes/scopes/scope/targets/target/create-alias.js @@ -5,16 +5,13 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import { notifySuccess, notifyError } from 'core/decorators/notify'; -import { loading } from 'ember-loading'; import { TYPE_ALIAS_TARGET } from 'api/models/alias'; export default class ScopesScopeTargetsTargetCreateAliasRoute extends Route { // =services @service store; - @service router; + // =methods /** @@ -31,30 +28,4 @@ export default class ScopesScopeTargetsTargetCreateAliasRoute extends Route { record.scopeModel = scopeModel; return record; } - - // =actions - - /** - * Handle save - * @param {AliasModel} alias - */ - @action - @loading - @notifyError(({ message }) => message) - @notifySuccess('notifications.save-success') - async save(alias) { - await alias.save(); - await this.router.transitionTo('scopes.scope.targets.target'); - this.router.refresh(); - } - - /** - * Rollback changes on alias. - * @param {AliasModel} alias - */ - @action - cancel(alias) { - alias.rollbackAttributes(); - this.router.transitionTo('scopes.scope.targets.target'); - } } diff --git a/ui/admin/app/routes/scopes/scope/targets/target/enable-session-recording.js b/ui/admin/app/routes/scopes/scope/targets/target/enable-session-recording.js index 823eea6c5..76532536a 100644 --- a/ui/admin/app/routes/scopes/scope/targets/target/enable-session-recording.js +++ b/ui/admin/app/routes/scopes/scope/targets/target/enable-session-recording.js @@ -4,14 +4,8 @@ */ import Route from '@ember/routing/route'; -import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; export default class ScopesScopeTargetsTargetEnableSessionRecordingRoute extends Route { - // =services - @service store; - @service router; - // =methods /** @@ -22,16 +16,4 @@ export default class ScopesScopeTargetsTargetEnableSessionRecordingRoute extends model() { return this.modelFor('scopes.scope.targets.target'); } - - // =actions - /** - * Reset the selected storage bucket and redirect to target - * @param {TargetModel} target - */ - @action - cancel(target) { - const { id } = target; - target.rollbackAttributes(); - this.router.replaceWith('scopes.scope.targets.target', id); - } } diff --git a/ui/admin/app/routes/scopes/scope/targets/target/enable-session-recording/create-storage-bucket.js b/ui/admin/app/routes/scopes/scope/targets/target/enable-session-recording/create-storage-bucket.js index fa45d2950..d3aead918 100644 --- a/ui/admin/app/routes/scopes/scope/targets/target/enable-session-recording/create-storage-bucket.js +++ b/ui/admin/app/routes/scopes/scope/targets/target/enable-session-recording/create-storage-bucket.js @@ -5,9 +5,6 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import { notifySuccess, notifyError } from 'core/decorators/notify'; -import { loading } from 'ember-loading'; import { TYPE_STORAGE_BUCKET_PLUGIN, TYPE_STORAGE_BUCKET_PLUGIN_AWS_S3, @@ -17,7 +14,7 @@ export default class ScopesScopeTargetsTargetEnableSessionRecordingCreateStorage // =services @service store; - @service router; + // =methods /** @@ -57,34 +54,4 @@ export default class ScopesScopeTargetsTargetEnableSessionRecordingCreateStorage super.setupController(...arguments); controller.set('scopes', this.scopes); } - - // =actions - - /** - * Handle save - * @param {StorageBucketModel} storageBucket - */ - @action - @loading - @notifyError(({ message }) => message) - @notifySuccess('notifications.save-success') - async save(storageBucket) { - await storageBucket.save(); - await this.router.transitionTo( - 'scopes.scope.targets.target.enable-session-recording', - ); - this.refresh(); - } - - /** - * Rollback changes on storage buckets. - * @param {StorageBucketModel} storageBucket - */ - @action - cancel(storageBucket) { - storageBucket.rollbackAttributes(); - this.router.transitionTo( - 'scopes.scope.targets.target.enable-session-recording', - ); - } } diff --git a/ui/admin/app/routes/scopes/scope/targets/target/enable-session-recording/index.js b/ui/admin/app/routes/scopes/scope/targets/target/enable-session-recording/index.js index 9d32abc31..ffc7659d8 100644 --- a/ui/admin/app/routes/scopes/scope/targets/target/enable-session-recording/index.js +++ b/ui/admin/app/routes/scopes/scope/targets/target/enable-session-recording/index.js @@ -8,8 +8,8 @@ import { inject as service } from '@ember/service'; export default class ScopesScopeTargetsTargetEnableSessionRecordingIndexRoute extends Route { // =services + @service store; - @service router; // =methods diff --git a/ui/admin/app/routes/scopes/scope/targets/target/host-sources.js b/ui/admin/app/routes/scopes/scope/targets/target/host-sources.js index 9b58cc2e0..9b88939b2 100644 --- a/ui/admin/app/routes/scopes/scope/targets/target/host-sources.js +++ b/ui/admin/app/routes/scopes/scope/targets/target/host-sources.js @@ -5,17 +5,12 @@ import Route from '@ember/routing/route'; import { all, hash } from 'rsvp'; -import { action } from '@ember/object'; import { inject as service } from '@ember/service'; -import { loading } from 'ember-loading'; -import { confirm } from 'core/decorators/confirm'; -import { notifySuccess, notifyError } from 'core/decorators/notify'; export default class ScopesScopeTargetsTargetHostSourcesRoute extends Route { // =services @service store; - @service intl; // =methods @@ -52,21 +47,4 @@ export default class ScopesScopeTargetsTargetHostSourcesRoute extends Route { model() { return this.modelFor('scopes.scope.targets.target'); } - - // =actions - - /** - * Removes a host set from the current target and redirects to index. - * @param {TargetModel} target - * @param {HostSetModel} hostSet - */ - @action - @loading - @confirm('questions.remove-confirm') - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.remove-success') - async removeHostSource(target, hostSet) { - await target.removeHostSource(hostSet.id); - this.refresh(); - } } diff --git a/ui/admin/app/routes/scopes/scope/targets/target/injected-application-credential-sources.js b/ui/admin/app/routes/scopes/scope/targets/target/injected-application-credential-sources.js index 9d9ede62b..3c39495c0 100644 --- a/ui/admin/app/routes/scopes/scope/targets/target/injected-application-credential-sources.js +++ b/ui/admin/app/routes/scopes/scope/targets/target/injected-application-credential-sources.js @@ -5,10 +5,6 @@ import Route from '@ember/routing/route'; import { all } from 'rsvp'; -import { action } from '@ember/object'; -import { loading } from 'ember-loading'; -import { confirm } from 'core/decorators/confirm'; -import { notifySuccess, notifyError } from 'core/decorators/notify'; import { inject as service } from '@ember/service'; export default class ScopesScopeTargetsTargetInjectedApplicationCredentialSourcesRoute extends Route { @@ -48,21 +44,4 @@ export default class ScopesScopeTargetsTargetInjectedApplicationCredentialSource model() { return this.modelFor('scopes.scope.targets.target'); } - - // =actions - - /** - * Remove a credential source from the current target. - * @param {TargetModel} target - * @param {CredentialLibraryModel, credentialModel} credentialSource - */ - @action - @loading - @confirm('questions.remove-confirm') - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.remove-success') - async removeInjectedApplicationCredentialSource(target, credentialSource) { - await target.removeInjectedApplicationCredentialSource(credentialSource.id); - this.refresh(); - } } diff --git a/ui/admin/app/routes/scopes/scope/targets/target/manage-alias.js b/ui/admin/app/routes/scopes/scope/targets/target/manage-alias.js index 1436faa3c..d4e936cfc 100644 --- a/ui/admin/app/routes/scopes/scope/targets/target/manage-alias.js +++ b/ui/admin/app/routes/scopes/scope/targets/target/manage-alias.js @@ -5,15 +5,12 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import { notifySuccess, notifyError } from 'core/decorators/notify'; -import { loading } from 'ember-loading'; export default class ScopesScopeTargetsTargetManageAliasRoute extends Route { // =services @service store; - @service router; + // =methods /** @@ -25,30 +22,4 @@ export default class ScopesScopeTargetsTargetManageAliasRoute extends Route { reload: true, }); } - - // =actions - - /** - * Handle save - * @param {AliasModel} alias - */ - @action - @loading - @notifyError(({ message }) => message) - @notifySuccess('notifications.save-success') - async save(alias) { - await alias.save(); - await this.router.refresh('scopes.scope.targets.target'); - this.router.transitionTo('scopes.scope.targets.target'); - } - - /** - * Rollback changes on alias. - * @param {AliasModel} alias - */ - @action - async cancel(alias) { - alias.rollbackAttributes(); - await this.router.transitionTo('scopes.scope.targets.target'); - } } diff --git a/ui/admin/app/templates/scopes/scope/targets/new.hbs b/ui/admin/app/templates/scopes/scope/targets/new.hbs index f8f79edc2..c7dc33f02 100644 --- a/ui/admin/app/templates/scopes/scope/targets/new.hbs +++ b/ui/admin/app/templates/scopes/scope/targets/new.hbs @@ -26,9 +26,9 @@ diff --git a/ui/admin/app/templates/scopes/scope/targets/target/add-brokered-credential-sources.hbs b/ui/admin/app/templates/scopes/scope/targets/target/add-brokered-credential-sources.hbs index 246456cdc..842293b66 100644 --- a/ui/admin/app/templates/scopes/scope/targets/target/add-brokered-credential-sources.hbs +++ b/ui/admin/app/templates/scopes/scope/targets/target/add-brokered-credential-sources.hbs @@ -29,8 +29,8 @@ {{/if}} diff --git a/ui/admin/app/templates/scopes/scope/targets/target/add-host-sources.hbs b/ui/admin/app/templates/scopes/scope/targets/target/add-host-sources.hbs index 47ca5a1e2..6f5114fd2 100644 --- a/ui/admin/app/templates/scopes/scope/targets/target/add-host-sources.hbs +++ b/ui/admin/app/templates/scopes/scope/targets/target/add-host-sources.hbs @@ -29,8 +29,8 @@ @model={{@model.target}} @hostCatalogs={{@model.hostCatalogs}} @hostSets={{@model.hostSets}} - @submit={{route-action 'save' @model.target}} - @cancel={{route-action 'cancel'}} + @submit={{fn this.save @model.target}} + @cancel={{this.cancel}} /> {{/if}} diff --git a/ui/admin/app/templates/scopes/scope/targets/target/add-injected-application-credential-sources.hbs b/ui/admin/app/templates/scopes/scope/targets/target/add-injected-application-credential-sources.hbs index b9ec9a9cf..5e0c12f69 100644 --- a/ui/admin/app/templates/scopes/scope/targets/target/add-injected-application-credential-sources.hbs +++ b/ui/admin/app/templates/scopes/scope/targets/target/add-injected-application-credential-sources.hbs @@ -34,8 +34,8 @@ {{/if}} diff --git a/ui/admin/app/templates/scopes/scope/targets/target/brokered-credential-sources.hbs b/ui/admin/app/templates/scopes/scope/targets/target/brokered-credential-sources.hbs index ace980af0..a0e4f18fd 100644 --- a/ui/admin/app/templates/scopes/scope/targets/target/brokered-credential-sources.hbs +++ b/ui/admin/app/templates/scopes/scope/targets/target/brokered-credential-sources.hbs @@ -24,7 +24,10 @@ - + @@ -87,8 +90,10 @@ @text={{t 'actions.remove'}} {{on 'click' - (route-action - 'removeBrokeredCredentialSource' @model B.data + (fn + this.targets.removeBrokeredCredentialSource + @model + B.data ) }} /> diff --git a/ui/admin/app/templates/scopes/scope/targets/target/create-alias.hbs b/ui/admin/app/templates/scopes/scope/targets/target/create-alias.hbs index 58b63e263..8ce97779c 100644 --- a/ui/admin/app/templates/scopes/scope/targets/target/create-alias.hbs +++ b/ui/admin/app/templates/scopes/scope/targets/target/create-alias.hbs @@ -26,8 +26,8 @@ \ No newline at end of file diff --git a/ui/admin/app/templates/scopes/scope/targets/target/enable-session-recording/create-storage-bucket.hbs b/ui/admin/app/templates/scopes/scope/targets/target/enable-session-recording/create-storage-bucket.hbs index 1b04bb945..e36a4e135 100644 --- a/ui/admin/app/templates/scopes/scope/targets/target/enable-session-recording/create-storage-bucket.hbs +++ b/ui/admin/app/templates/scopes/scope/targets/target/enable-session-recording/create-storage-bucket.hbs @@ -24,8 +24,8 @@ diff --git a/ui/admin/app/templates/scopes/scope/targets/target/host-sources.hbs b/ui/admin/app/templates/scopes/scope/targets/target/host-sources.hbs index 9dc89c5bb..08e669d00 100644 --- a/ui/admin/app/templates/scopes/scope/targets/target/host-sources.hbs +++ b/ui/admin/app/templates/scopes/scope/targets/target/host-sources.hbs @@ -24,7 +24,10 @@ - + @@ -77,7 +80,7 @@ @text={{t 'actions.remove'}} {{on 'click' - (route-action 'removeHostSource' @model B.data.model) + (fn this.targets.removeHostSource @model B.data.model) }} /> diff --git a/ui/admin/app/templates/scopes/scope/targets/target/index.hbs b/ui/admin/app/templates/scopes/scope/targets/target/index.hbs index 99a18d899..1f9ba5359 100644 --- a/ui/admin/app/templates/scopes/scope/targets/target/index.hbs +++ b/ui/admin/app/templates/scopes/scope/targets/target/index.hbs @@ -18,7 +18,10 @@ - + @@ -26,8 +29,8 @@ @@ -54,7 +57,7 @@ data-test-view-more @text={{t 'resources.target.actions.view-more-aliases'}} @color='secondary' - {{on 'click' this.targets.toggleFlyout}} + {{on 'click' this.toggleFlyout}} /> {{/if}} {{#if this.showFlyOutComponent}} diff --git a/ui/admin/app/templates/scopes/scope/targets/target/injected-application-credential-sources.hbs b/ui/admin/app/templates/scopes/scope/targets/target/injected-application-credential-sources.hbs index 21fea8df0..9c63210ce 100644 --- a/ui/admin/app/templates/scopes/scope/targets/target/injected-application-credential-sources.hbs +++ b/ui/admin/app/templates/scopes/scope/targets/target/injected-application-credential-sources.hbs @@ -28,7 +28,10 @@ - + @@ -91,8 +94,8 @@ @text={{t 'actions.remove'}} {{on 'click' - (route-action - 'removeInjectedApplicationCredentialSource' + (fn + this.targets.removeInjectedApplicationCredentialSource @model B.data ) diff --git a/ui/admin/app/templates/scopes/scope/targets/target/manage-alias.hbs b/ui/admin/app/templates/scopes/scope/targets/target/manage-alias.hbs index 96ebbd35a..92ec2e451 100644 --- a/ui/admin/app/templates/scopes/scope/targets/target/manage-alias.hbs +++ b/ui/admin/app/templates/scopes/scope/targets/target/manage-alias.hbs @@ -3,6 +3,11 @@ SPDX-License-Identifier: BUSL-1.1 }} + + @@ -41,14 +46,14 @@ {{#if (and perms.canUpdate @model.destination_id)}} {{/if}} {{#if perms.canDelete}} {{/if}} @@ -59,8 +64,8 @@ \ No newline at end of file diff --git a/ui/admin/tests/unit/controllers/scopes/scope/targets/index-test.js b/ui/admin/tests/unit/controllers/scopes/scope/targets/index-test.js index 0ad10be78..d7e43d7d7 100644 --- a/ui/admin/tests/unit/controllers/scopes/scope/targets/index-test.js +++ b/ui/admin/tests/unit/controllers/scopes/scope/targets/index-test.js @@ -5,14 +5,76 @@ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; -import { waitUntil } from '@ember/test-helpers'; +import { waitUntil, visit } from '@ember/test-helpers'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { setupIndexedDb } from 'api/test-support/helpers/indexed-db'; +import { authenticateSession } from 'ember-simple-auth/test-support'; import { TYPE_TARGET_TCP, TYPE_TARGET_SSH } from 'api/models/target'; module('Unit | Controller | scopes/scope/targets/index', function (hooks) { setupTest(hooks); + setupMirage(hooks); + setupIndexedDb(hooks); + + let store; + let controller; + let getTargetCount; + let getAliasCount; + + const instances = { + scopes: { + global: null, + org: null, + project: null, + }, + target: null, + hostSet: null, + credential: null, + alias: null, + }; + + const urls = { + projectScope: null, + targets: null, + alias: null, + }; + + hooks.beforeEach(function () { + authenticateSession({}); + store = this.owner.lookup('service:store'); + controller = this.owner.lookup('controller:scopes/scope/targets/index'); + + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: 'org' }, + }); + instances.target = this.server.create('target', { + scope: instances.scopes.project, + }); + instances.hostSet = this.server.create('host-set', { + scope: instances.scopes.project, + }); + instances.credential = this.server.create('credential', { + scope: instances.scopes.project, + }); + instances.alias = this.server.create('alias', { + scope: instances.scopes.global, + }); + + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.targets = `${urls.projectScope}/targets`; + urls.alias = `${urls.projectScope}/targets/${instances.target.id}/${instances.alias.id}`; + + getTargetCount = () => this.server.schema.targets.all().models.length; + getAliasCount = () => this.server.schema.aliases.all().models.length; + }); test('it exists', function (assert) { - let controller = this.owner.lookup('controller:scopes/scope/targets/index'); assert.ok(controller); }); @@ -56,4 +118,146 @@ module('Unit | Controller | scopes/scope/targets/index', function (hooks) { assert.strictEqual(controller.page, 1); assert.deepEqual(controller.availableSessions, selectedItems); }); + + test('cancel action rolls-back changes on the specified model', async function (assert) { + await visit(urls.targets); + const target = await store.findRecord('target', instances.target.id); + target.name = 'test'; + + assert.strictEqual(target.name, 'test'); + + await controller.cancel(target); + + assert.notEqual(target.name, 'test'); + }); + + test('save action saves changes on the specified model', async function (assert) { + await visit(urls.targets); + const target = await store.findRecord('target', instances.target.id); + target.name = 'test'; + + await controller.save(target); + + assert.strictEqual(target.name, 'test'); + }); + + test('saveWithAddress action saves address and removes host sources on the specified model', async function (assert) { + await visit(urls.targets); + const target = await store.findRecord('target', instances.target.id); + await target.addHostSources([instances.hostSet.id]); + target.address = '127.0.0.1'; + + assert.deepEqual(target.host_sources, [ + { host_source_id: instances.hostSet.id }, + ]); + + await controller.saveWithAddress(target); + + assert.deepEqual(target.host_sources, []); + assert.strictEqual(target.address, '127.0.0.1'); + }); + + test('delete action destroys specified model', async function (assert) { + await visit(urls.projectScope); + const target = await store.findRecord('target', instances.target.id); + const targetCount = getTargetCount(); + + await controller.delete(target); + + assert.strictEqual(getTargetCount(), targetCount - 1); + }); + + test('removeHostSource action removes specified host-set from model', async function (assert) { + await visit(urls.targets); + const target = await store.findRecord('target', instances.target.id); + await target.addHostSources([instances.hostSet.id]); + + assert.deepEqual(target.host_sources, [ + { host_source_id: instances.hostSet.id }, + ]); + + await controller.removeHostSource(target, instances.hostSet); + + assert.deepEqual(target.host_sources, []); + }); + + test('removeInjectedApplicationCredentialSource action removes specified credential from model', async function (assert) { + await visit(urls.targets); + const target = await store.findRecord('target', instances.target.id); + await target.addInjectedApplicationCredentialSources([ + instances.credential.id, + ]); + + assert.deepEqual(target.injected_application_credential_source_ids, [ + { value: instances.credential.id }, + ]); + + await controller.removeInjectedApplicationCredentialSource( + target, + instances.credential, + ); + + assert.deepEqual(target.injected_application_credential_source_ids, []); + }); + + test('removeBrokeredCredentialSource action removes specified credential from model', async function (assert) { + await visit(urls.targets); + const target = await store.findRecord('target', instances.target.id); + await target.addBrokeredCredentialSources([instances.credential.id]); + + assert.deepEqual(target.brokered_credential_source_ids, [ + { value: instances.credential.id }, + ]); + + await controller.removeBrokeredCredentialSource( + target, + instances.credential, + ); + + assert.deepEqual(target.brokered_credential_source_ids, []); + }); + + test('deleteAlias action destroys specified model', async function (assert) { + await visit(urls.targets); + const alias = await store.findRecord('alias', instances.alias.id); + const aliasCount = getAliasCount(); + + await controller.deleteAlias(alias); + + assert.strictEqual(getAliasCount(), aliasCount - 1); + }); + + test('clearAlias action removes destination_id from model', async function (assert) { + await visit(urls.alias); + const alias = await store.findRecord('alias', instances.alias.id); + alias.destination_id = 'www.test.com'; + + assert.strictEqual(alias.destination_id, 'www.test.com'); + + await controller.clearAlias(alias); + + assert.notOk(alias.destination_id); + }); + + test('saveAlias action saves changes on the specified model', async function (assert) { + await visit(urls.alias); + const alias = await store.findRecord('alias', instances.alias.id); + alias.name = 'test'; + + await controller.saveAlias(alias); + + assert.strictEqual(alias.name, 'test'); + }); + + test('cancelAlias action rolls-back changes on the specified model', async function (assert) { + await visit(urls.alias); + const alias = await store.findRecord('alias', instances.alias.id); + alias.name = 'test'; + + assert.strictEqual(alias.name, 'test'); + + await controller.cancelAlias(alias); + + assert.notEqual(alias.name, 'test'); + }); }); diff --git a/ui/admin/tests/unit/controllers/scopes/scope/targets/target/add-brokered-credential-sources-test.js b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/add-brokered-credential-sources-test.js index d1e44aa71..ef1c0e57e 100644 --- a/ui/admin/tests/unit/controllers/scopes/scope/targets/target/add-brokered-credential-sources-test.js +++ b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/add-brokered-credential-sources-test.js @@ -5,25 +5,68 @@ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; +import { currentURL, visit } from '@ember/test-helpers'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { authenticateSession } from 'ember-simple-auth/test-support'; module( 'Unit | Controller | scopes/scope/targets/target/add-brokered-credential-sources', function (hooks) { setupTest(hooks); + setupMirage(hooks); - test('it exists', function (assert) { - const controller = this.owner.lookup( + let store; + let controller; + + const instances = { + scopes: { + global: null, + org: null, + project: null, + }, + target: null, + credential: null, + }; + + const urls = { + projectScope: null, + addCredentialSources: null, + credentialSources: null, + }; + + hooks.beforeEach(function () { + authenticateSession({}); + store = this.owner.lookup('service:store'); + controller = this.owner.lookup( 'controller:scopes/scope/targets/target/add-brokered-credential-sources', ); + + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: 'org' }, + }); + instances.target = this.server.create('target', { + scope: instances.scopes.project, + }); + instances.credential = this.server.create('credential', { + scope: instances.scopes.project, + }); + + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.addCredentialSources = `${urls.projectScope}/targets/${instances.target.id}/add-brokered-credential-sources`; + urls.credentialSources = `${urls.projectScope}/targets/${instances.target.id}/brokered-credential-sources`; + }); + + test('it exists', function (assert) { assert.ok(controller); }); test('hasAvailableBrokeredCredentialSources returns true if target has available credentials', function (assert) { - const store = this.owner.lookup('service:store'); - const controller = this.owner.lookup( - 'controller:scopes/scope/targets/target/add-brokered-credential-sources', - ); - const target = store.createRecord('target', { brokered_credential_source_ids: [{ value: 'cred_123' }], }); @@ -37,11 +80,6 @@ module( }); test('hasAvailableBrokeredCredentialSources returns false if target has no available credentials', function (assert) { - const store = this.owner.lookup('service:store'); - const controller = this.owner.lookup( - 'controller:scopes/scope/targets/target/add-brokered-credential-sources', - ); - const target = store.createRecord('target', { brokered_credential_source_ids: [{ value: 'cred_123' }], }); @@ -53,5 +91,26 @@ module( assert.false(controller.hasAvailableBrokeredCredentialSources); }); + + test('save action saves credential sources on the specified model', async function (assert) { + await visit(urls.addCredentialSources); + const target = await store.findRecord('target', instances.target.id); + + assert.deepEqual(target.brokered_credential_source_ids, []); + + await controller.save(target, [instances.credential.id]); + + assert.deepEqual(target.brokered_credential_source_ids, [ + { value: instances.credential.id }, + ]); + }); + + test('cancel action causes transition to expected route', async function (assert) { + await visit(urls.addCredentialSources); + + await controller.cancel(); + + assert.strictEqual(currentURL(), urls.credentialSources); + }); }, ); diff --git a/ui/admin/tests/unit/controllers/scopes/scope/targets/target/add-host-sources-test.js b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/add-host-sources-test.js new file mode 100644 index 000000000..8d38b72f9 --- /dev/null +++ b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/add-host-sources-test.js @@ -0,0 +1,85 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; +import { currentURL, visit } from '@ember/test-helpers'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { authenticateSession } from 'ember-simple-auth/test-support'; + +module( + 'Unit | Controller | scopes/scope/targets/target/add-host-sources', + function (hooks) { + setupTest(hooks); + setupMirage(hooks); + + let store; + let controller; + + const instances = { + scopes: { + global: null, + org: null, + project: null, + }, + target: null, + hostSet: null, + }; + + const urls = { + projectScope: null, + addHostSources: null, + hostSources: null, + }; + + hooks.beforeEach(function () { + authenticateSession({}); + store = this.owner.lookup('service:store'); + controller = this.owner.lookup( + 'controller:scopes/scope/targets/target/add-host-sources', + ); + + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: 'org' }, + }); + instances.target = this.server.create('target', { + scope: instances.scopes.project, + }); + instances.hostSet = this.server.create('host-set', { + scope: instances.scopes.project, + }); + + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.addHostSources = `${urls.projectScope}/targets/${instances.target.id}/add-host-sources`; + urls.hostSources = `${urls.projectScope}/targets/${instances.target.id}/host-sources`; + }); + + test('it exists', function (assert) { + assert.ok(controller); + }); + + test('save action saves host sources on the specified model', async function (assert) { + await visit(urls.addHostSources); + const target = await store.findRecord('target', instances.target.id); + + assert.deepEqual(target.host_sources, []); + + await controller.save(target, [instances.hostSet.id]); + + assert.deepEqual(target.host_sources, [ + { host_source_id: instances.hostSet.id }, + ]); + }); + + test('cancel action causes transition to expected route', async function (assert) { + await visit(urls.addHostSources); + + await controller.cancel(); + + assert.strictEqual(currentURL(), urls.hostSources); + }); + }, +); diff --git a/ui/admin/tests/unit/controllers/scopes/scope/targets/target/add-injected-application-credential-sources-test.js b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/add-injected-application-credential-sources-test.js index 1c294ed47..623f27c11 100644 --- a/ui/admin/tests/unit/controllers/scopes/scope/targets/target/add-injected-application-credential-sources-test.js +++ b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/add-injected-application-credential-sources-test.js @@ -5,25 +5,68 @@ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; +import { currentURL, visit } from '@ember/test-helpers'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { authenticateSession } from 'ember-simple-auth/test-support'; module( 'Unit | Controller | scopes/scope/targets/target/add-injected-application-credential-sources', function (hooks) { setupTest(hooks); + setupMirage(hooks); - test('it exists', function (assert) { - const controller = this.owner.lookup( + let store; + let controller; + + const instances = { + scopes: { + global: null, + org: null, + project: null, + }, + target: null, + credential: null, + }; + + const urls = { + projectScope: null, + addCredentialSources: null, + credentialSources: null, + }; + + hooks.beforeEach(function () { + authenticateSession({}); + store = this.owner.lookup('service:store'); + controller = this.owner.lookup( 'controller:scopes/scope/targets/target/add-injected-application-credential-sources', ); + + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: 'org' }, + }); + instances.target = this.server.create('target', { + scope: instances.scopes.project, + }); + instances.credential = this.server.create('credential', { + scope: instances.scopes.project, + }); + + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.addCredentialSources = `${urls.projectScope}/targets/${instances.target.id}/add-injected-application-credential-sources`; + urls.credentialSources = `${urls.projectScope}/targets/${instances.target.id}/injected-application-credential-sources`; + }); + + test('it exists', function (assert) { assert.ok(controller); }); test('hasAvailableInjectedApplicationCredentialSources returns true if target has available credentials', function (assert) { - const store = this.owner.lookup('service:store'); - const controller = this.owner.lookup( - 'controller:scopes/scope/targets/target/add-injected-application-credential-sources', - ); - const target = store.createRecord('target', { injected_application_credential_source_ids: [{ value: 'cred_123' }], }); @@ -37,11 +80,6 @@ module( }); test('hasAvailableInjectedApplicationCredentialSources returns false if target has no available credentials', function (assert) { - const store = this.owner.lookup('service:store'); - const controller = this.owner.lookup( - 'controller:scopes/scope/targets/target/add-injected-application-credential-sources', - ); - const target = store.createRecord('target', { injected_application_credential_source_ids: [{ value: 'cred_123' }], }); @@ -53,5 +91,26 @@ module( assert.false(controller.hasAvailableInjectedApplicationCredentialSources); }); + + test('save action saves credential sources on the specified model', async function (assert) { + await visit(urls.addCredentialSources); + const target = await store.findRecord('target', instances.target.id); + + assert.deepEqual(target.injected_application_credential_source_ids, []); + + await controller.save(target, [instances.credential.id]); + + assert.deepEqual(target.injected_application_credential_source_ids, [ + { value: instances.credential.id }, + ]); + }); + + test('cancel action causes transition to expected route', async function (assert) { + await visit(urls.addCredentialSources); + + await controller.cancel(); + + assert.strictEqual(currentURL(), urls.credentialSources); + }); }, ); diff --git a/ui/admin/tests/unit/controllers/scopes/scope/targets/target/brokered-credential-sources-test.js b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/brokered-credential-sources-test.js new file mode 100644 index 000000000..16f14070e --- /dev/null +++ b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/brokered-credential-sources-test.js @@ -0,0 +1,16 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module( + 'Unit | Controller | scopes/scope/targets/target/brokered-credential-sources', + function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let controller = this.owner.lookup( + 'controller:scopes/scope/targets/target/brokered-credential-sources', + ); + assert.ok(controller); + }); + }, +); diff --git a/ui/admin/tests/unit/controllers/scopes/scope/targets/target/create-alias-test.js b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/create-alias-test.js new file mode 100644 index 000000000..d0f67b049 --- /dev/null +++ b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/create-alias-test.js @@ -0,0 +1,16 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module( + 'Unit | Controller | scopes/scope/targets/target/create-alias', + function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let controller = this.owner.lookup( + 'controller:scopes/scope/targets/target/create-alias', + ); + assert.ok(controller); + }); + }, +); diff --git a/ui/admin/tests/unit/controllers/scopes/scope/targets/target/enable-session-recording/create-storage-bucket-test.js b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/enable-session-recording/create-storage-bucket-test.js index e6d27e3eb..12f480987 100644 --- a/ui/admin/tests/unit/controllers/scopes/scope/targets/target/enable-session-recording/create-storage-bucket-test.js +++ b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/enable-session-recording/create-storage-bucket-test.js @@ -4,19 +4,92 @@ */ import { module, test } from 'qunit'; -import { setupTest } from 'admin/tests/helpers'; +import { setupTest } from 'ember-qunit'; +import { visit } from '@ember/test-helpers'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { authenticateSession } from 'ember-simple-auth/test-support'; module( 'Unit | Controller | scopes/scope/targets/target/enable-session-recording/create-storage-bucket', function (hooks) { setupTest(hooks); + setupMirage(hooks); - // TODO: Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup( + let store; + let controller; + + const instances = { + scopes: { + global: null, + org: null, + project: null, + }, + target: null, + storageBucket: null, + }; + + const urls = { + projectScope: null, + createStorageBucket: null, + }; + + hooks.beforeEach(function () { + authenticateSession({}); + store = this.owner.lookup('service:store'); + controller = this.owner.lookup( 'controller:scopes/scope/targets/target/enable-session-recording/create-storage-bucket', ); + + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: 'org' }, + }); + instances.target = this.server.create('target', { + scope: instances.scopes.project, + }); + instances.storageBucket = this.server.create('storage-bucket', { + scope: instances.scopes.org, + }); + + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.createStorageBucket = `${urls.projectScope}/targets/${instances.target.id}/enable-session-recording`; + }); + + test('it exists', function (assert) { assert.ok(controller); }); + + test('cancel action rolls-back changes on the specified model', async function (assert) { + await visit(urls.createStorageBucket); + const storageBucket = await store.findRecord( + 'storage-bucket', + instances.storageBucket.id, + ); + storageBucket.name = 'test'; + + assert.strictEqual(storageBucket.name, 'test'); + + await controller.cancel(storageBucket); + + assert.notEqual(storageBucket.name, 'test'); + }); + + test('save action saves changes on the specified model', async function (assert) { + await visit(urls.createStorageBucket); + const storageBucket = await store.findRecord( + 'storage-bucket', + instances.storageBucket.id, + ); + storageBucket.name = 'test'; + + await controller.save(storageBucket); + + assert.strictEqual(storageBucket.name, 'test'); + }); }, ); diff --git a/ui/admin/tests/unit/controllers/scopes/scope/targets/target/enable-session-recording/index-test.js b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/enable-session-recording/index-test.js new file mode 100644 index 000000000..0fb43b0d3 --- /dev/null +++ b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/enable-session-recording/index-test.js @@ -0,0 +1,70 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; +import { visit } from '@ember/test-helpers'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { authenticateSession } from 'ember-simple-auth/test-support'; + +module( + 'Unit | Controller | scopes/scope/targets/target/enable-session-recording/index', + function (hooks) { + setupTest(hooks); + setupMirage(hooks); + + let store; + let controller; + + const instances = { + scopes: { + global: null, + org: null, + project: null, + }, + target: null, + }; + + const urls = { + projectScope: null, + enableSessionRecording: null, + }; + + hooks.beforeEach(function () { + authenticateSession({}); + store = this.owner.lookup('service:store'); + controller = this.owner.lookup( + 'controller:scopes/scope/targets/target/enable-session-recording/index', + ); + + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: 'org' }, + }); + instances.target = this.server.create('target', { + scope: instances.scopes.project, + }); + + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.enableSessionRecording = `${urls.projectScope}/targets/${instances.target.id}/enable-session-recording`; + }); + + test('it exists', function (assert) { + assert.ok(controller); + }); + + test('cancel action rolls-back changes on the specified model', async function (assert) { + await visit(urls.enableSessionRecording); + const target = await store.findRecord('target', instances.target.id); + target.enable_session_recording = 'true'; + + assert.strictEqual(target.enable_session_recording, 'true'); + + await controller.cancel(target); + + assert.notEqual(target.enable_session_recording, 'true'); + }); + }, +); diff --git a/ui/admin/tests/unit/controllers/scopes/scope/targets/target/host-sources-test.js b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/host-sources-test.js new file mode 100644 index 000000000..a7f68e006 --- /dev/null +++ b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/host-sources-test.js @@ -0,0 +1,16 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module( + 'Unit | Controller | scopes/scope/targets/target/host-sources', + function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let controller = this.owner.lookup( + 'controller:scopes/scope/targets/target/host-sources', + ); + assert.ok(controller); + }); + }, +); diff --git a/ui/admin/tests/unit/controllers/scopes/scope/targets/target/injected-application-credential-sources-test.js b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/injected-application-credential-sources-test.js new file mode 100644 index 000000000..9f5a03091 --- /dev/null +++ b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/injected-application-credential-sources-test.js @@ -0,0 +1,16 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module( + 'Unit | Controller | scopes/scope/targets/target/injected-application-credential-sources', + function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let controller = this.owner.lookup( + 'controller:scopes/scope/targets/target/injected-application-credential-sources', + ); + assert.ok(controller); + }); + }, +); diff --git a/ui/admin/tests/unit/controllers/scopes/scope/targets/target/manage-alias-test.js b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/manage-alias-test.js new file mode 100644 index 000000000..52b4a857f --- /dev/null +++ b/ui/admin/tests/unit/controllers/scopes/scope/targets/target/manage-alias-test.js @@ -0,0 +1,16 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module( + 'Unit | Controller | scopes/scope/targets/target/manage-alias', + function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let controller = this.owner.lookup( + 'controller:scopes/scope/targets/target/manage-alias', + ); + assert.ok(controller); + }); + }, +);