feat: reapply storage policies to session recording (#2095)

* refactor: 💡 add global settings link

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12257

* fix: 🐛 route

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12257

* fix: 🐛 comment

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12257

* feat: 🎸 add reapply sp to session recording page

* fix: 🐛 normalize

* feat: 🎸 upates

* fix: 🐛 logs

* fix: 🐛 comment

* test: 💍 add tests

* fix: 🐛 normalizer, style

* fix: 🐛 normalize

* fix: 🐛 normalizw

* fix: 🐛 normalize

* test: 💍 add tests for serializer n normalizer

* fix: 🐛 name

* fix: 🐛 do not delete, send null

* fix: 🐛 return

---------

Co-authored-by: Lisbet Alvarez <lisbet.alvarez@hashicorp.com>
This commit is contained in:
Dharini JeevaandLisbet Alvarez authored and GitHub committed 2024-01-17 14:37:54 -05:00
1 parent 9e0467cbf0
commit fb9a080d2e
19 files changed
+314 -3

No files matched your search

@@ -19,4 +19,14 @@ export default class OverrideSessionRecordingAbility extends SessionRecordingAbi
? super.canRead
: false;
}
/**
* Reapplying policy is allowed only if the feature flag is enabled
* @type {boolean}
*/
get canReapplyStoragePolicy() {
return this.features.isEnabled('ssh-session-recording')
? this.hasAuthorizedAction('reapply-storage-policy')
: false;
}
}
@@ -0,0 +1,31 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: MPL-2.0
}}
{{page-title (t 'titles.new')}}
<Breadcrumbs::Item
@text={{t 'resources.policy.titles.new'}}
@route='scopes.scope.add-storage-policy.create'
/>
<Rose::Layout::Page as |page|>
<page.breadcrumbs>
<Breadcrumbs::Container />
</page.breadcrumbs>
<page.header>
<Hds::Text::Display @tag='h2'>
{{t 'resources.policy.titles.new'}}
</Hds::Text::Display>
</page.header>
<page.body>
<Form::Policy
@model={{@model}}
@submit={{route-action 'save' @model}}
@cancel={{route-action 'cancel' @model}}
/>
</page.body>
</Rose::Layout::Page>
@@ -5,6 +5,8 @@
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 orderBy from 'lodash/orderBy';
export default class ScopesScopeSessionRecordingsRoute extends Route {
@@ -68,4 +70,16 @@ export default class ScopesScopeSessionRecordingsRoute extends Route {
};
}
}
/**
* Reapplies storage policy dates to session recording
* @param {SessionRecordingModel}
*/
@action
@notifyError(({ message }) => message, { catch: true })
@notifySuccess('resources.policy.messages.reapply')
async reapplyStoragepolicy(sessionRecording) {
await sessionRecording.reapplyStoragePolicy();
super.refresh(...arguments);
}
}
@@ -12,6 +12,24 @@
<h2>{{t 'resources.session-recording.session.title'}}</h2>
</page.header>
<page.actions>
{{#if
(can 'reapplyStoragePolicy session-recording' @model.sessionRecording)
}}
<Hds::Dropdown data-test-manage-dropdown as |dd|>
<dd.ToggleButton @text={{t 'actions.manage'}} @color='secondary' />
<dd.Interactive
@text={{t 'resources.policy.actions.update'}}
{{on
'click'
(route-action 'reapplyStoragepolicy' @model.sessionRecording)
}}
/>
</Hds::Dropdown>
{{/if}}
</page.actions>
<page.body>
<div class='channels-by-connection'>
<Rose::Layout::BodyContent as |bc|>
@@ -223,6 +241,35 @@
}}
</list.Item>
{{/if}}
{{! Policy info}}
{{#if @model.sessionRecording.retain_until}}
<list.Item @icon='hourglass' @color='faint'>
{{t 'resources.policy.titles.retain_until'}}
<time
data-test-retain-until
datetime={{format-date-iso
@model.sessionRecording.retain_until
}}
>
{{format-date-iso @model.sessionRecording.retain_until}}
</time>
</list.Item>
{{/if}}
{{#if @model.sessionRecording.delete_after}}
<list.Item @icon='hourglass' @color='faint'>
{{t 'resources.policy.titles.delete_after'}}
<time
data-test-delete-after
datetime={{format-date-iso
@model.sessionRecording.delete_after
}}
>
{{format-date-iso @model.sessionRecording.delete_after}}
</time>
</list.Item>
{{/if}}
</Rose::MetadataList>
</div>
@@ -146,5 +146,39 @@ module(
assert.notEqual(currentURL(), incorrectUrl);
assert.strictEqual(currentURL(), urls.channelRecording);
});
test('user cannot view manage dropdown without proper authorization', async function (assert) {
// Visit channel
featuresService.enable('ssh-session-recording');
instances.sessionRecording.authorized_actions =
instances.sessionRecording.authorized_actions.filter(
(item) => item !== 'reapply-storage-policy',
);
await visit(urls.sessionRecording);
assert.dom('[data-test-manage-dropdown]').doesNotExist();
});
test('user can view manage dropdown with proper authorization', async function (assert) {
// Visit channel
featuresService.enable('ssh-session-recording');
await visit(urls.sessionRecording);
assert.dom('[data-test-manage-dropdown]').isVisible();
});
test('both retain until and delete after can be seen with proper authorization', async function (assert) {
// Visit channel
featuresService.enable('ssh-session-recording');
await visit(urls.sessionRecording);
assert.dom('.hds-dropdown-toggle-button__text').isVisible();
assert.dom('[data-test-retain-until]').isVisible();
assert.dom('[data-test-delete-after]').isVisible();
});
},
);