fix: 🐛 reapply storage policy errors out after a failed delete (#2674)

* fix: 🐛 reapply storage policy errors out after a failed delete

* refactor: 💡 hide delete button when policy is retain forever

* refactor: 💡 pr feedback (move check to model)
This commit is contained in:
Lisbet Alvarez authored and GitHub committed 2025-02-04 14:09:10 -08:00
1 parent 570ed61edb
commit c9a74f2800
7 files changed
+93 -16

No files matched your search

+1 -1
View File
@@ -163,7 +163,7 @@ export default class ApplicationAdapter extends RESTAdapter.extend(
}
/**
* Overrides default ajax method by rewritting PUT requests as PATCH.
* Overrides default ajax method by rewriting PUT requests as PATCH.
* PATCH is the request method used by our API for updates.
*
* @override
+2 -2
View File
@@ -6,7 +6,7 @@
import Mixin from '@ember/object/mixin';
/**
* Overrides URL-building methods in an adpater for greater flexibility.
* Overrides URL-building methods in an adapter for greater flexibility.
* Specifically enhances calls to `urlPrefix` with `modelName`, `id`, and
* `snapshot`, which aren't normally passed. And adds support for a
* `urlSuffix` method, the return value of which is appended to the end of
@@ -22,7 +22,7 @@ export default Mixin.create({
/**
* This override behaves identically to the default method by default.
* It exists only to document the additional paramters to the method.
* It exists only to document the additional parameters to the method.
* @override
* @param {string} path
* @param {string} parentURL
+9 -1
View File
@@ -71,7 +71,15 @@ export default class SessionRecordingModel extends GeneratedSessionRecordingMode
}
/**
* Reapply policy dates via the `reapply-staorage-policy` method.
* Returns true if retention of session-recording is forever.
* @type {boolean}
*/
get retainForever() {
return this.retain_until?.toISOString() === '9999-12-31T23:23:23.999Z';
}
/**
* Reapply policy dates via the `reapply-storage-policy` method.
* @param {object} options
* @param {object} options.adapterOptions
* @return {Promise}
+3 -2
View File
@@ -32,10 +32,11 @@ export default class OverrideSessionRecordingAbility extends SessionRecordingAbi
/**
* This override ensures that session recordings may be deleted only if the
* session-recording feature flag is enabled.
* session-recording feature flag is enabled and policy allows deletion.
*/
get canDelete() {
return this.features.isEnabled('ssh-session-recording')
return this.features.isEnabled('ssh-session-recording') &&
!this.model.retainForever
? super.canDelete
: false;
}
@@ -78,8 +78,13 @@ export default class ScopesScopeSessionRecordingsSessionRecordingChannelsByConne
@notifyError(({ message }) => message, { catch: true })
@notifySuccess('notifications.delete-success')
async delete(sessionRecording) {
await sessionRecording.destroyRecord();
this.router.replaceWith('scopes.scope.session-recordings');
this.router.refresh();
try {
await sessionRecording.destroyRecord();
this.router.replaceWith('scopes.scope.session-recordings');
await this.router.refresh('scopes.scope.session-recordings');
} catch (e) {
sessionRecording.rollbackAttributes();
throw new Error(e);
}
}
}
@@ -260,12 +260,7 @@
@model.sessionRecording.retain_until
}}
>
{{#if
(eq
(format-date-iso @model.sessionRecording.retain_until)
'9999-12-31T23:23:23.999Z'
)
}}
{{#if @model.sessionRecording.retainForever}}
{{t 'resources.policy.titles.forever'}}
{{else}}
{{format-date-iso @model.sessionRecording.retain_until}}
@@ -5,7 +5,11 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import { TYPE_SESSION_RECORDING_SSH } from 'api/models/session-recording';
import {
TYPE_SESSION_RECORDING_SSH,
STATE_SESSION_RECORDING_AVAILABLE,
} from 'api/models/session-recording';
import { faker } from '@faker-js/faker';
module('Unit | Abilities | session-recording', function (hooks) {
setupTest(hooks);
@@ -177,4 +181,68 @@ module('Unit | Abilities | session-recording', function (hooks) {
}),
);
});
test('can delete session recording when feature is enabled', async function (assert) {
features.enable('ssh-session-recording');
const recordingWithAuthorizedAction = await store.createRecord(
'session-recording',
{
authorized_actions: ['delete'],
type: TYPE_SESSION_RECORDING_SSH,
state: STATE_SESSION_RECORDING_AVAILABLE,
retain_until: faker.date.recent(),
},
);
const recordingWithoutAuthorizedAction = store.createRecord(
'session-recording',
{
authorized_actions: [],
type: TYPE_SESSION_RECORDING_SSH,
state: STATE_SESSION_RECORDING_AVAILABLE,
retain_until: faker.date.recent(),
},
);
assert.true(
canService.can('delete session-recording', recordingWithAuthorizedAction),
);
assert.false(
canService.can(
'delete session-recording',
recordingWithoutAuthorizedAction,
),
);
});
test('cannot delete session recording when feature is enabled but retain policy is forever', async function (assert) {
features.enable('ssh-session-recording');
const recordingWithAuthorizedAction = await store.createRecord(
'session-recording',
{
authorized_actions: ['delete'],
type: TYPE_SESSION_RECORDING_SSH,
state: STATE_SESSION_RECORDING_AVAILABLE,
retain_until: new Date('9999-12-31T23:23:23.999Z'),
},
);
const recordingWithoutAuthorizedAction = store.createRecord(
'session-recording',
{
authorized_actions: [],
type: TYPE_SESSION_RECORDING_SSH,
state: STATE_SESSION_RECORDING_AVAILABLE,
retain_until: new Date('9999-12-31T23:23:23.999Z'),
},
);
assert.false(
canService.can('delete session-recording', recordingWithAuthorizedAction),
);
assert.false(
canService.can(
'delete session-recording',
recordingWithoutAuthorizedAction,
),
);
});
});