From 8d883073e12a18f64502733d164507975276a8fb Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Mon, 22 May 2023 08:49:30 -0700 Subject: [PATCH] =?UTF-8?q?fix:=20=F0=9F=90=9B=20fix=20mismtach=20between?= =?UTF-8?q?=20fe/be=20feature=20flag=20strings=20(#264)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 🐛 fix mismtach between fe/be feature flag strings * chore: 🤖 add development can helper to recompute on flags --- ui/admin/app/abilities/scope.js | 8 +++- ui/admin/app/abilities/session-recording.js | 4 +- ui/admin/app/abilities/storage-bucket.js | 8 ++-- ui/admin/app/helpers/can.js | 48 +++++++++++++++++++ ui/admin/app/templates/scopes/scope.hbs | 34 +++++++------ .../scopes/scope/targets/target/index.hbs | 2 +- ui/admin/config/features.js | 2 +- .../session-recordings/list-test.js | 8 +++- .../session-recordings/read-test.js | 8 ++-- .../acceptance/storage-buckets/create-test.js | 2 +- .../acceptance/storage-buckets/delete-test.js | 2 +- .../acceptance/storage-buckets/list-test.js | 12 ++--- .../acceptance/storage-buckets/read-test.js | 2 +- .../acceptance/storage-buckets/update-test.js | 2 +- .../targets/enable-session-recording-test.js | 20 ++++---- .../tests/integration/helpers/can-test.js | 42 ++++++++++++++++ .../unit/abilities/session-recording-test.js | 11 +++-- .../unit/abilities/storage-bucket-test.js | 24 ++++++++-- 18 files changed, 180 insertions(+), 59 deletions(-) create mode 100644 ui/admin/app/helpers/can.js create mode 100644 ui/admin/tests/integration/helpers/can-test.js diff --git a/ui/admin/app/abilities/scope.js b/ui/admin/app/abilities/scope.js index f4d269d77..736a72cf0 100644 --- a/ui/admin/app/abilities/scope.js +++ b/ui/admin/app/abilities/scope.js @@ -21,7 +21,9 @@ export default class OverrideScopeAbility extends OverrideModelAbility { get canCreate() { switch (this.collection) { case 'storage-buckets': - return this.features.isEnabled('session-recording') && super.canCreate; + return ( + this.features.isEnabled('ssh-session-recording') && super.canCreate + ); default: return super.canCreate; } @@ -36,7 +38,9 @@ export default class OverrideScopeAbility extends OverrideModelAbility { switch (this.collection) { case 'session-recordings': case 'storage-buckets': - return this.features.isEnabled('session-recording') && super.canList; + return ( + this.features.isEnabled('ssh-session-recording') && super.canList + ); default: return super.canList; } diff --git a/ui/admin/app/abilities/session-recording.js b/ui/admin/app/abilities/session-recording.js index 60664eb26..6f5164444 100644 --- a/ui/admin/app/abilities/session-recording.js +++ b/ui/admin/app/abilities/session-recording.js @@ -15,6 +15,8 @@ export default class OverrideSessionRecordingAbility extends SessionRecordingAbi * session-recording feature flag is enabled. */ get canRead() { - return this.features.isEnabled('session-recording') ? super.canRead : false; + return this.features.isEnabled('ssh-session-recording') + ? super.canRead + : false; } } diff --git a/ui/admin/app/abilities/storage-bucket.js b/ui/admin/app/abilities/storage-bucket.js index fb2ed3530..a63292148 100644 --- a/ui/admin/app/abilities/storage-bucket.js +++ b/ui/admin/app/abilities/storage-bucket.js @@ -15,7 +15,9 @@ export default class OverrideStorageBucketAbility extends StorageBucketAbility { * session-recording feature flag is enabled. */ get canRead() { - return this.features.isEnabled('session-recording') ? super.canRead : false; + return this.features.isEnabled('ssh-session-recording') + ? super.canRead + : false; } /** @@ -23,7 +25,7 @@ export default class OverrideStorageBucketAbility extends StorageBucketAbility { * session-recording feature flag is enabled. */ get canUpdate() { - return this.features.isEnabled('session-recording') + return this.features.isEnabled('ssh-session-recording') ? super.canUpdate : false; } @@ -33,7 +35,7 @@ export default class OverrideStorageBucketAbility extends StorageBucketAbility { * session-recording feature flag is enabled. */ get canDelete() { - return this.features.isEnabled('session-recording') + return this.features.isEnabled('ssh-session-recording') ? super.canDelete : false; } diff --git a/ui/admin/app/helpers/can.js b/ui/admin/app/helpers/can.js new file mode 100644 index 000000000..b4d745383 --- /dev/null +++ b/ui/admin/app/helpers/can.js @@ -0,0 +1,48 @@ +import CanHelper from 'ember-can/helpers/can'; +import { inject as service } from '@ember/service'; +import config from 'admin/config/environment'; + +const isDevelopment = config.environment === 'development'; + +/** + * Normally, abilities that access tracked values are not recomputed on change. + * This helper overrides the Ember Can helper to trigger recompute whenever + * a feature flag changes. This functionality is available only in the + * development environment, since feature flags may be toggled in the UI, and + * also for performance reasons as this effectively recomputes _all_ `can` + * helpers on any feature flag change. + */ +class DevelopmentCanHelper extends CanHelper { + // =services + + @service features; + + // =methods + + constructor() { + super(...arguments); + this.observeAllFlags(); + } + + willDestroy() { + this.removeAllFlags(); + super.willDestroy(); + } + + observeAllFlags() { + this.features.flags.forEach((flag) => + /* eslint-disable-next-line ember/no-observers */ + this.features.addObserver(flag, this, 'recompute') + ); + } + + removeAllFlags() { + this.features.flags.forEach((flag) => + /* eslint-disable-next-line ember/no-observers */ + this.features.removeObserver(flag, this, 'recompute') + ); + } +} + +// In development, export the development helper, otherwise the original. +export default isDevelopment ? DevelopmentCanHelper : CanHelper; diff --git a/ui/admin/app/templates/scopes/scope.hbs b/ui/admin/app/templates/scopes/scope.hbs index e2e9cd27a..cfe44e607 100644 --- a/ui/admin/app/templates/scopes/scope.hbs +++ b/ui/admin/app/templates/scopes/scope.hbs @@ -26,25 +26,23 @@ {{t 'resources.org.title_plural'}} - {{#if (feature-flag 'session-recording')}} - {{#if - (can 'navigate scope' @model collection='session-recordings') - }} - - - {{t 'resources.session-recording.title_plural'}} - - {{/if}} - {{#if (can 'navigate scope' @model collection='storage-buckets')}} - - - {{t 'resources.storage-bucket.title_plural'}} - - {{/if}} + + {{#if (can 'navigate scope' @model collection='session-recordings')}} + + + {{t 'resources.session-recording.title_plural'}} + {{/if}} + {{#if (can 'navigate scope' @model collection='storage-buckets')}} + + + {{t 'resources.storage-bucket.title_plural'}} + + {{/if}} + {{#if (and (can 'navigate worker' @model collection='workers') 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 96d43b530..1a5687aac 100644 --- a/ui/admin/app/templates/scopes/scope/targets/target/index.hbs +++ b/ui/admin/app/templates/scopes/scope/targets/target/index.hbs @@ -33,7 +33,7 @@ {{#if (and (can 'setStorageBucket target' @model) - (feature-flag 'session-recording') + (feature-flag 'ssh-session-recording') ) }} diff --git a/ui/admin/config/features.js b/ui/admin/config/features.js index 8338943fa..33197c0c9 100644 --- a/ui/admin/config/features.js +++ b/ui/admin/config/features.js @@ -13,7 +13,7 @@ const devFeatures = { const licensedFeatures = { 'multi-hop-sessions': false, 'ssh-target': false, - 'session-recording': false, + 'ssh-session-recording': false, }; // Base edition declares available features, disabled by default. const baseEdition = { diff --git a/ui/admin/tests/acceptance/session-recordings/list-test.js b/ui/admin/tests/acceptance/session-recordings/list-test.js index 68e6bd06a..84876c190 100644 --- a/ui/admin/tests/acceptance/session-recordings/list-test.js +++ b/ui/admin/tests/acceptance/session-recordings/list-test.js @@ -3,12 +3,13 @@ import { visit, currentURL, click } from '@ember/test-helpers'; import { setupApplicationTest } from 'admin/tests/helpers'; import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; import { authenticateSession } from 'ember-simple-auth/test-support'; -import { enableFeature } from 'ember-feature-flags/test-support'; module('Acceptance | session recordings | list', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); + let featuresService; + // Selectors const SESSION_RECORDING_TITLE = 'Session Recordings'; @@ -45,7 +46,10 @@ module('Acceptance | session recordings | list', function (hooks) { urls.globalScope = `/scopes/global`; urls.sessionRecordings = `${urls.globalScope}/session-recordings`; urls.sessionRecording = `${urls.sessionRecordings}/${instances.sessionRecording.id}`; - enableFeature('session-recording'); + + featuresService = this.owner.lookup('service:features'); + featuresService.enable('ssh-session-recording'); + authenticateSession({}); }); diff --git a/ui/admin/tests/acceptance/session-recordings/read-test.js b/ui/admin/tests/acceptance/session-recordings/read-test.js index 9916a4a71..4e22ab1e5 100644 --- a/ui/admin/tests/acceptance/session-recordings/read-test.js +++ b/ui/admin/tests/acceptance/session-recordings/read-test.js @@ -64,7 +64,7 @@ module('Acceptance | session recordings | read', function (hooks) { test('visiting a session recording', async function (assert) { assert.expect(1); - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); // Visit session recordings await visit(urls.sessionRecordings); await a11yAudit(); @@ -76,7 +76,7 @@ module('Acceptance | session recordings | read', function (hooks) { test('user can navigate to a session recording with proper authorization', async function (assert) { assert.expect(3); - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); // Visit session recordings await visit(urls.sessionRecordings); assert.true(instances.sessionRecording.authorized_actions.includes('read')); @@ -88,7 +88,7 @@ module('Acceptance | session recordings | read', function (hooks) { test('user cannot navigate to a session recording without the read action', async function (assert) { assert.expect(1); - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); instances.sessionRecording.authorized_actions = instances.sessionRecording.authorized_actions.filter( (item) => item !== 'read' @@ -100,7 +100,7 @@ module('Acceptance | session recordings | read', function (hooks) { test('user can navigate to a channel recording', async function (assert) { assert.expect(2); - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); // Visit session recording await visit(urls.sessionRecording); assert.dom('table').hasClass('hds-table'); diff --git a/ui/admin/tests/acceptance/storage-buckets/create-test.js b/ui/admin/tests/acceptance/storage-buckets/create-test.js index edfcd044d..2457dd6ad 100644 --- a/ui/admin/tests/acceptance/storage-buckets/create-test.js +++ b/ui/admin/tests/acceptance/storage-buckets/create-test.js @@ -46,7 +46,7 @@ module('Acceptance | storage-buckets | create', function (hooks) { this.server.schema.storageBuckets.all().models.length; features = this.owner.lookup('service:features'); - features.enable('session-recording'); + features.enable('ssh-session-recording'); authenticateSession({}); }); diff --git a/ui/admin/tests/acceptance/storage-buckets/delete-test.js b/ui/admin/tests/acceptance/storage-buckets/delete-test.js index 395913591..5dbc65ad5 100644 --- a/ui/admin/tests/acceptance/storage-buckets/delete-test.js +++ b/ui/admin/tests/acceptance/storage-buckets/delete-test.js @@ -57,7 +57,7 @@ module('Acceptance | storage-buckets | delete', function (hooks) { authenticateSession({}); intl = this.owner.lookup('service:intl'); features = this.owner.lookup('service:features'); - features.enable('session-recording'); + features.enable('ssh-session-recording'); }); test('user can delete a storage bucket', async function (assert) { diff --git a/ui/admin/tests/acceptance/storage-buckets/list-test.js b/ui/admin/tests/acceptance/storage-buckets/list-test.js index 9a810afa8..9d220e24d 100644 --- a/ui/admin/tests/acceptance/storage-buckets/list-test.js +++ b/ui/admin/tests/acceptance/storage-buckets/list-test.js @@ -53,7 +53,7 @@ module('Acceptance | storage-buckets | list', function (hooks) { test('users can navigate to storage-buckets with proper authorization', async function (assert) { assert.expect(5); - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); await visit(urls.globalScope); assert.true( @@ -80,7 +80,7 @@ module('Acceptance | storage-buckets | list', function (hooks) { test('user cannot navigate to index without either list or create actions', async function (assert) { assert.expect(5); featuresService.enable('byow'); - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); instances.scopes.global.authorized_collection_actions['storage-buckets'] = []; @@ -114,7 +114,7 @@ module('Acceptance | storage-buckets | list', function (hooks) { test('user can navigate to index with only create action', async function (assert) { assert.expect(5); - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); instances.scopes.global.authorized_collection_actions['storage-buckets'] = instances.scopes.global.authorized_collection_actions[ @@ -148,7 +148,7 @@ module('Acceptance | storage-buckets | list', function (hooks) { test('user can navigate to index with only list action', async function (assert) { assert.expect(5); - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); instances.scopes.global.authorized_collection_actions['storage-buckets'] = instances.scopes.global.authorized_collection_actions[ @@ -182,7 +182,7 @@ module('Acceptance | storage-buckets | list', function (hooks) { assert.expect(2); featuresService.enable('byow'); await visit(urls.globalScope); - assert.false(featuresService.isEnabled('session-recording')); + assert.false(featuresService.isEnabled('ssh-session-recording')); assert .dom('[title="General"] a:nth-of-type(2)') .doesNotIncludeText(STORAGE_BUCKET_TITLE); @@ -190,7 +190,7 @@ module('Acceptance | storage-buckets | list', function (hooks) { test('edit action in table directs user to appropriate page', async function (assert) { assert.expect(3); - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); await visit(urls.globalScope); instances.storageBucket = this.server.create('storage-bucket', { scope: instances.scopes.global, diff --git a/ui/admin/tests/acceptance/storage-buckets/read-test.js b/ui/admin/tests/acceptance/storage-buckets/read-test.js index b0aa243d9..bf09e6f38 100644 --- a/ui/admin/tests/acceptance/storage-buckets/read-test.js +++ b/ui/admin/tests/acceptance/storage-buckets/read-test.js @@ -49,7 +49,7 @@ module('Acceptance | storage-buckets | read', function (hooks) { urls.unknownStorageBucket = `${urls.storageBuckets}/foo`; features = this.owner.lookup('service:features'); - features.enable('session-recording'); + features.enable('ssh-session-recording'); authenticateSession({}); }); diff --git a/ui/admin/tests/acceptance/storage-buckets/update-test.js b/ui/admin/tests/acceptance/storage-buckets/update-test.js index b1f774839..959df68e3 100644 --- a/ui/admin/tests/acceptance/storage-buckets/update-test.js +++ b/ui/admin/tests/acceptance/storage-buckets/update-test.js @@ -52,7 +52,7 @@ module('Acceptance | storage-buckets | update', function (hooks) { urls.storageBucket = `${urls.storageBuckets}/${instances.storageBucket.id}`; features = this.owner.lookup('service:features'); - features.enable('session-recording'); + features.enable('ssh-session-recording'); authenticateSession({}); }); diff --git a/ui/admin/tests/acceptance/targets/enable-session-recording-test.js b/ui/admin/tests/acceptance/targets/enable-session-recording-test.js index e294c1c3c..1580a267f 100644 --- a/ui/admin/tests/acceptance/targets/enable-session-recording-test.js +++ b/ui/admin/tests/acceptance/targets/enable-session-recording-test.js @@ -93,14 +93,14 @@ module('Acceptance | targets | enable session recording', function (hooks) { test('cannot enable session recording for a target without proper authorization', async function (assert) { assert.expect(2); - assert.false(featuresService.isEnabled('session-recording')); + assert.false(featuresService.isEnabled('ssh-session-recording')); await visit(urls.target); await a11yAudit(); assert.dom('.target-sidebar a').doesNotExist(); }); test('users can click on enable-recording button in target session-recording sidebar and it takes them to enable session recording', async function (assert) { - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); assert.expect(2); await visit(urls.target); assert.dom(SETTINGS_LINK_SELECTOR).doesNotExist(); @@ -109,7 +109,7 @@ module('Acceptance | targets | enable session recording', function (hooks) { }); test('users can click on settings link in target session-recording sidebar and it takes them to enable session recording', async function (assert) { - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); assert.expect(1); instances.target.update({ storageBucketId: storageBucketOne.id, @@ -120,7 +120,7 @@ module('Acceptance | targets | enable session recording', function (hooks) { }); test('users can click on associated storage bucket card on an ssh target', async function (assert) { - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); assert.expect(1); instances.target.update({ storageBucketId: storageBucketOne.id }); await visit(urls.target); @@ -129,7 +129,7 @@ module('Acceptance | targets | enable session recording', function (hooks) { }); test('toggle should be enabled and storage buckets list should be shown when enable session recording button is clicked', async function (assert) { - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); assert.expect(3); await visit(urls.target); await click(ENABLE_BUTTON_SELECTOR); @@ -139,7 +139,7 @@ module('Acceptance | targets | enable session recording', function (hooks) { }); test('storage buckets list is hidden when toggle is disabled', async function (assert) { - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); assert.expect(4); await visit(urls.target); await click(ENABLE_BUTTON_SELECTOR); @@ -151,7 +151,7 @@ module('Acceptance | targets | enable session recording', function (hooks) { }); test('link to add new storage bucket should be displayed and redirect to new storage buckets form', async function (assert) { - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); assert.expect(3); await visit(urls.target); await click(ENABLE_BUTTON_SELECTOR); @@ -162,7 +162,7 @@ module('Acceptance | targets | enable session recording', function (hooks) { }); test('retain last selected dropdown list value when the toggle is off', async function (assert) { - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); assert.expect(3); instances.target.update({ storageBucketId: storageBucketOne.id, @@ -184,7 +184,7 @@ module('Acceptance | targets | enable session recording', function (hooks) { }); test('can assign a storage bucket for the target', async function (assert) { - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); assert.expect(5); await visit(urls.target); await click(ENABLE_BUTTON_SELECTOR); @@ -205,7 +205,7 @@ module('Acceptance | targets | enable session recording', function (hooks) { }); test('can cancel changes to an exisiting storage bucket selection', async function (assert) { - featuresService.enable('session-recording'); + featuresService.enable('ssh-session-recording'); assert.expect(3); instances.target.update({ storageBucketId: storageBucketOne.id, diff --git a/ui/admin/tests/integration/helpers/can-test.js b/ui/admin/tests/integration/helpers/can-test.js new file mode 100644 index 000000000..3da065d55 --- /dev/null +++ b/ui/admin/tests/integration/helpers/can-test.js @@ -0,0 +1,42 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'admin/tests/helpers'; +import { render } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +/** + * The can helper override in admin is exported only in a development + * environment, never in tests or production. This is a simple smoke test + * to ensure that it still functions as intended. + */ +module('Integration | Helper | can', function (hooks) { + setupRenderingTest(hooks); + + test('it renders', async function (assert) { + assert.expect(2); + + const model = { + authorized_actions: ['read'], + authorized_collection_actions: { + resource: ['list'], + }, + }; + + this.set('model', model); + + await render(hbs` + {{#if (can 'read model' this.model)}} + Read + {{/if}} + `); + + assert.dom(this.element).hasText('Read'); + + await render(hbs` + {{#if (can 'list model' this.model collection='resource')}} + List + {{/if}} + `); + + assert.dom(this.element).hasText('List'); + }); +}); diff --git a/ui/admin/tests/unit/abilities/session-recording-test.js b/ui/admin/tests/unit/abilities/session-recording-test.js index 7116cb21b..226ffb651 100644 --- a/ui/admin/tests/unit/abilities/session-recording-test.js +++ b/ui/admin/tests/unit/abilities/session-recording-test.js @@ -16,7 +16,6 @@ module('Unit | Abilities | session-recording', function (hooks) { hooks.beforeEach(function () { features = this.owner.lookup('service:features'); - features.enable('session-recording'); canService = this.owner.lookup('service:can'); store = this.owner.lookup('service:store'); }); @@ -24,6 +23,8 @@ module('Unit | Abilities | session-recording', function (hooks) { test('can read session recording feature is enabled', function (assert) { assert.expect(2); + features.enable('ssh-session-recording'); + const recordingWithAuthorizedAction = store.createRecord( 'session-recording', { @@ -49,7 +50,6 @@ module('Unit | Abilities | session-recording', function (hooks) { test('cannot read session recording when feature is disabled', function (assert) { assert.expect(2); - features.disable('session-recording'); const recordingWithAuthorizedAction = store.createRecord( 'session-recording', @@ -77,6 +77,8 @@ module('Unit | Abilities | session-recording', function (hooks) { test('can list session recording when in global scope', function (assert) { assert.expect(2); + features.enable('ssh-session-recording'); + const scopeModelWithAuthorizedAction = store.createRecord('scope', { authorized_collection_actions: { ['session-recordings']: ['list'] }, type: 'global', @@ -103,6 +105,8 @@ module('Unit | Abilities | session-recording', function (hooks) { test('can list session recording when in org scope when authorized', function (assert) { assert.expect(2); + features.enable('ssh-session-recording'); + const scopeModelWithAuthorizedAction = store.createRecord('scope', { authorized_collection_actions: { ['session-recordings']: ['list'] }, type: 'org', @@ -129,6 +133,8 @@ module('Unit | Abilities | session-recording', function (hooks) { test('can navigate to session recording when feature is enabled', function (assert) { assert.expect(2); + features.enable('ssh-session-recording'); + const scopeModelWithAuthorizedAction = store.createRecord('scope', { authorized_collection_actions: { ['session-recordings']: ['list'] }, type: 'global', @@ -154,7 +160,6 @@ module('Unit | Abilities | session-recording', function (hooks) { test('cannot navigate to session recording when feature is disabled', function (assert) { assert.expect(2); - features.disable('session-recording'); const scopeModelWithAuthorizedAction = store.createRecord('scope', { authorized_collection_actions: { ['session-recordings']: ['list'] }, diff --git a/ui/admin/tests/unit/abilities/storage-bucket-test.js b/ui/admin/tests/unit/abilities/storage-bucket-test.js index 2eb8d49c4..43dd6c811 100644 --- a/ui/admin/tests/unit/abilities/storage-bucket-test.js +++ b/ui/admin/tests/unit/abilities/storage-bucket-test.js @@ -21,12 +21,13 @@ module('Unit | Abilities | storage-bucket', function (hooks) { store = this.owner.lookup('service:store'); canService = this.owner.lookup('service:can'); features = this.owner.lookup('service:features'); - features.enable('session-recording'); }); test('can read storage bucket when authorized and feature is enabled', function (assert) { assert.expect(1); + features.enable('ssh-session-recording'); + const storageBucket = store.createRecord('storage-bucket', { authorized_actions: ['read'], type: TYPE_STORAGE_BUCKET_PLUGIN, @@ -39,6 +40,8 @@ module('Unit | Abilities | storage-bucket', function (hooks) { test('cannot read storage bucket when unauthorized and feature is enabled', function (assert) { assert.expect(1); + features.enable('ssh-session-recording'); + const storageBucket = store.createRecord('storage-bucket', { authorized_actions: [], type: TYPE_STORAGE_BUCKET_PLUGIN, @@ -50,7 +53,6 @@ module('Unit | Abilities | storage-bucket', function (hooks) { test('cannot read storage bucket when authorized and feature is disabled', function (assert) { assert.expect(1); - features.disable('session-recording'); const storageBucket = store.createRecord('storage-bucket', { authorized_actions: ['read'], @@ -63,7 +65,6 @@ module('Unit | Abilities | storage-bucket', function (hooks) { test('cannot read storage bucket when unauthorized and feature is disabled', function (assert) { assert.expect(1); - features.disable('session-recording'); const storageBucket = store.createRecord('storage-bucket', { authorized_actions: [], @@ -77,6 +78,8 @@ module('Unit | Abilities | storage-bucket', function (hooks) { test('can list storage bucket when authorized and in global scope', function (assert) { assert.expect(1); + features.enable('ssh-session-recording'); + const scopeModel = store.createRecord('scope', { authorized_collection_actions: { 'storage-buckets': ['list'] }, type: 'global', @@ -93,6 +96,8 @@ module('Unit | Abilities | storage-bucket', function (hooks) { test('cannot list storage bucket when unauthorized and in global scope', function (assert) { assert.expect(1); + features.enable('ssh-session-recording'); + const scopeModel = store.createRecord('scope', { authorized_collection_actions: { 'storage-buckets': [] }, type: 'global', @@ -109,6 +114,8 @@ module('Unit | Abilities | storage-bucket', function (hooks) { test('can list storage bucket when authorized and in org scope', function (assert) { assert.expect(1); + features.enable('ssh-session-recording'); + const scopeModel = store.createRecord('scope', { authorized_collection_actions: { 'storage-buckets': ['list'] }, type: 'org', @@ -125,6 +132,8 @@ module('Unit | Abilities | storage-bucket', function (hooks) { test('can create storage bucket when authorized and in global scope', function (assert) { assert.expect(1); + features.enable('ssh-session-recording'); + const scopeModel = store.createRecord('scope', { authorized_collection_actions: { 'storage-buckets': ['create'] }, type: 'global', @@ -141,6 +150,8 @@ module('Unit | Abilities | storage-bucket', function (hooks) { test('can create storage bucket when authorized and in org scope', function (assert) { assert.expect(1); + features.enable('ssh-session-recording'); + const scopeModel = store.createRecord('scope', { authorized_collection_actions: { 'storage-buckets': ['create'] }, type: 'org', @@ -157,6 +168,8 @@ module('Unit | Abilities | storage-bucket', function (hooks) { test('can create storage bucket when authorized and in project scope', function (assert) { assert.expect(1); + features.enable('ssh-session-recording'); + const scopeModel = store.createRecord('scope', { authorized_collection_actions: { 'storage-buckets': ['create'] }, type: 'project', @@ -173,6 +186,8 @@ module('Unit | Abilities | storage-bucket', function (hooks) { test('cannot create storage bucket when unauthorized', function (assert) { assert.expect(1); + features.enable('ssh-session-recording'); + const scopeModel = store.createRecord('scope', { authorized_collection_actions: { 'storage-buckets': [] }, type: 'global', @@ -189,6 +204,8 @@ module('Unit | Abilities | storage-bucket', function (hooks) { test('can navigate to storage bucket when authorized', function (assert) { assert.expect(1); + features.enable('ssh-session-recording'); + const scopeModel = store.createRecord('scope', { authorized_collection_actions: { 'storage-buckets': ['create'] }, type: 'global', @@ -204,7 +221,6 @@ module('Unit | Abilities | storage-bucket', function (hooks) { test('cannot navigate to storage bucket when authorized and feature is disabled', function (assert) { assert.expect(1); - features.disable('session-recording'); const scopeModel = store.createRecord('scope', { authorized_collection_actions: { 'storage-buckets': ['create'] },