diff --git a/addons/core/translations/en-us.yaml b/addons/core/translations/en-us.yaml index a482f52fc..97bfa823d 100644 --- a/addons/core/translations/en-us.yaml +++ b/addons/core/translations/en-us.yaml @@ -43,6 +43,7 @@ descriptions: cluster-url-initialization: To get started, please enter your cluster URL create-but-not-list: You do not have permission to list {resource}, but you can create new instances. neither-list-nor-create: You do not have permission to list or create {resource}. + cannot-download: You do not have permission to download and playback {resource}. no-results: We found no matching records. choose-a-provider: There are several built-in plugins for the most common providers. You can choose from one of the included plugins or use a custom plugin. provider: This is the provider for this host catalog. The format of the host set filters are specific to each provider. diff --git a/addons/core/translations/resources/en-us.yaml b/addons/core/translations/resources/en-us.yaml index f20a64ec4..29a308b23 100644 --- a/addons/core/translations/resources/en-us.yaml +++ b/addons/core/translations/resources/en-us.yaml @@ -231,6 +231,13 @@ session-recording: title: Channel title_plural: Channels details: Channel details + messages: + none: + title: Channel Playback + missing: + title: We can't play back this channel because the file is missing + description: This likely means the connected storage bucket is misconfigured or the file was deleted. + link: Retrieving lost session recordings player: back-navigation: Back to channels session: diff --git a/ui/admin/app/routes/scopes/scope/session-recordings/session-recording/channels-by-connection/channel.js b/ui/admin/app/routes/scopes/scope/session-recordings/session-recording/channels-by-connection/channel.js index 611a762dc..287bddfb7 100644 --- a/ui/admin/app/routes/scopes/scope/session-recordings/session-recording/channels-by-connection/channel.js +++ b/ui/admin/app/routes/scopes/scope/session-recordings/session-recording/channels-by-connection/channel.js @@ -4,9 +4,11 @@ import { inject as service } from '@ember/service'; export default class ScopesScopeSessionRecordingsSessionRecordingChannelsByConnectionChannelRoute extends Route { // =services @service store; + @service can; // =methods async model({ channel_id }) { + let asciicast; const { sessionRecording, storageBucket } = await this.modelFor( 'scopes.scope.session-recordings.session-recording' ); @@ -14,7 +16,10 @@ export default class ScopesScopeSessionRecordingsSessionRecordingChannelsByConne 'channel-recording', channel_id ); - const asciicast = await channelRecording.getAsciicast(); + + if (this.can.can('getAsciicast channel-recording', channelRecording)) { + asciicast = await channelRecording.getAsciicast(); + } return { channelRecording, diff --git a/ui/admin/app/templates/scopes/scope/session-recordings/session-recording/channels-by-connection/channel.hbs b/ui/admin/app/templates/scopes/scope/session-recordings/session-recording/channels-by-connection/channel.hbs index 55c7ef3d1..364e2251f 100644 --- a/ui/admin/app/templates/scopes/scope/session-recordings/session-recording/channels-by-connection/channel.hbs +++ b/ui/admin/app/templates/scopes/scope/session-recordings/session-recording/channels-by-connection/channel.hbs @@ -13,11 +13,55 @@ - + {{#if @model.asciicast}} + + {{else}} + + {{#if + (can 'getAsciicast channel-recording' @model.channelRecording) + }} + {{! Was not able to downlaod asciicast }} + + + + + + {{else}} + {{! Not authorized to downlaod asciicast }} + + + {{/if}} + + {{/if}} diff --git a/ui/admin/tests/acceptance/session-recordings/session-recording/channels-by-connection/channel-test.js b/ui/admin/tests/acceptance/session-recordings/session-recording/channels-by-connection/channel-test.js index 3d0decb09..ac0beca3f 100644 --- a/ui/admin/tests/acceptance/session-recordings/session-recording/channels-by-connection/channel-test.js +++ b/ui/admin/tests/acceptance/session-recordings/session-recording/channels-by-connection/channel-test.js @@ -60,6 +60,41 @@ module( assert.strictEqual(currentURL(), urls.connectionRecording); }); + test('user can view recording with proper authorization', async function (assert) { + assert.expect(1); + + // Visit channel + await visit(urls.connectionRecording); + + // if authorized player will render + assert.dom('.session-recording-player').exists(); + }); + + test('user cannot view recording without proper authorization: channel mime_types', async function (assert) { + assert.expect(1); + instances.channelRecording.mime_types = []; + + // Visit channel + await visit(urls.connectionRecording); + + // if unauthorized player will not render + assert.dom('.session-recording-player').doesNotExist(); + }); + + test('user cannot view recording without proper authorization: session recording download action', async function (assert) { + assert.expect(1); + instances.sessionRecording.authorized_actions = + instances.sessionRecording.authorized_actions.filter( + (item) => item !== 'download' + ); + + // Visit channel + await visit(urls.connectionRecording); + + // if unauthorized player will not render + assert.dom('.session-recording-player').doesNotExist(); + }); + test('user can navigate back to session recording screen', async function (assert) { assert.expect(1); // Visit channel