fix: prevent deletion of scheduled messages that have been sent or failed (#212)
* fix: prevent deletion of scheduled messages that have been sent or failed * fix: update error message for deletion of processed scheduled messages
This commit is contained in:
parent
c24eba9180
commit
3c47ea3d43
@ -27,11 +27,13 @@ class Api::V1::Accounts::Conversations::ScheduledMessagesController < Api::V1::A
|
|||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
if @scheduled_message.sent? || @scheduled_message.failed?
|
||||||
|
return render json: { error: I18n.t('errors.scheduled_messages.cannot_delete_processed') }, status: :unprocessable_entity
|
||||||
|
end
|
||||||
|
|
||||||
scheduled_message = @scheduled_message
|
scheduled_message = @scheduled_message
|
||||||
scheduled_message.destroy!
|
scheduled_message.destroy!
|
||||||
dispatch_event(SCHEDULED_MESSAGE_DELETED, scheduled_message: scheduled_message)
|
dispatch_event(SCHEDULED_MESSAGE_DELETED, scheduled_message: scheduled_message)
|
||||||
rescue ActiveRecord::RecordNotDestroyed => e
|
|
||||||
render json: { errors: e.record.errors.full_messages }, status: :unprocessable_entity
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@ -51,7 +51,6 @@ class ScheduledMessage < ApplicationRecord
|
|||||||
enum status: { draft: 0, pending: 1, sent: 2, failed: 3 }
|
enum status: { draft: 0, pending: 1, sent: 2, failed: 3 }
|
||||||
|
|
||||||
before_validation :process_message_variables, if: :content_changed?
|
before_validation :process_message_variables, if: :content_changed?
|
||||||
before_destroy :prevent_destroy_if_processed
|
|
||||||
|
|
||||||
validates :scheduled_at, presence: true, unless: -> { status == 'draft' }
|
validates :scheduled_at, presence: true, unless: -> { status == 'draft' }
|
||||||
validates :content, presence: true, unless: :content_optional?
|
validates :content, presence: true, unless: :content_optional?
|
||||||
@ -121,13 +120,6 @@ class ScheduledMessage < ApplicationRecord
|
|||||||
changed_attributes.keys == ['status']
|
changed_attributes.keys == ['status']
|
||||||
end
|
end
|
||||||
|
|
||||||
def prevent_destroy_if_processed
|
|
||||||
return unless sent? || failed?
|
|
||||||
|
|
||||||
errors.add(:base, 'Cannot delete a scheduled message that has already been sent or failed')
|
|
||||||
throw(:abort)
|
|
||||||
end
|
|
||||||
|
|
||||||
def scheduled_at_must_be_in_future
|
def scheduled_at_must_be_in_future
|
||||||
return if scheduled_at.blank?
|
return if scheduled_at.blank?
|
||||||
return if scheduled_at > Time.current
|
return if scheduled_at > Time.current
|
||||||
|
|||||||
@ -68,6 +68,8 @@ en:
|
|||||||
scheduled_message:
|
scheduled_message:
|
||||||
delay_out_of_range: Delay must be between 1 minute and 999 days
|
delay_out_of_range: Delay must be between 1 minute and 999 days
|
||||||
content_attachment_or_template_required: Scheduled message must have content, attachment, or template
|
content_attachment_or_template_required: Scheduled message must have content, attachment, or template
|
||||||
|
scheduled_messages:
|
||||||
|
cannot_delete_processed: Cannot delete a scheduled message that has already been sent or failed
|
||||||
saml:
|
saml:
|
||||||
feature_not_enabled: SAML feature not enabled for this account
|
feature_not_enabled: SAML feature not enabled for this account
|
||||||
sso_not_enabled: SAML SSO is not enabled for this installation
|
sso_not_enabled: SAML SSO is not enabled for this installation
|
||||||
|
|||||||
@ -114,6 +114,19 @@ RSpec.describe 'Scheduled Messages API', type: :request do
|
|||||||
expect(ScheduledMessage.exists?(scheduled_message.id)).to be(false)
|
expect(ScheduledMessage.exists?(scheduled_message.id)).to be(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'deletes pending scheduled messages with attachments' do
|
||||||
|
scheduled_message.attachment.attach(
|
||||||
|
io: Rails.root.join('spec/assets/avatar.png').open,
|
||||||
|
filename: 'avatar.png',
|
||||||
|
content_type: 'image/png'
|
||||||
|
)
|
||||||
|
|
||||||
|
delete scheduled_message_url(scheduled_message), headers: agent.create_new_auth_token, as: :json
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
expect(ScheduledMessage.exists?(scheduled_message.id)).to be(false)
|
||||||
|
end
|
||||||
|
|
||||||
it 'rejects delete for sent messages' do
|
it 'rejects delete for sent messages' do
|
||||||
scheduled_message.update!(status: :sent)
|
scheduled_message.update!(status: :sent)
|
||||||
|
|
||||||
|
|||||||
@ -182,20 +182,52 @@ RSpec.describe ScheduledMessage, type: :model do
|
|||||||
expect { scheduled_message.destroy }.to change(described_class, :count).by(-1)
|
expect { scheduled_message.destroy }.to change(described_class, :count).by(-1)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not allow deleting sent messages' do
|
it 'allows deleting pending messages with attachments' do
|
||||||
|
scheduled_message = create_scheduled_message
|
||||||
|
scheduled_message.attachment.attach(
|
||||||
|
io: Rails.root.join('spec/assets/avatar.png').open,
|
||||||
|
filename: 'avatar.png',
|
||||||
|
content_type: 'image/png'
|
||||||
|
)
|
||||||
|
|
||||||
|
expect { scheduled_message.destroy! }.to change(described_class, :count).by(-1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'allows destroying conversation with pending scheduled messages with attachments' do
|
||||||
|
scheduled_message = create_scheduled_message
|
||||||
|
scheduled_message.attachment.attach(
|
||||||
|
io: Rails.root.join('spec/assets/avatar.png').open,
|
||||||
|
filename: 'avatar.png',
|
||||||
|
content_type: 'image/png'
|
||||||
|
)
|
||||||
|
|
||||||
|
expect { conversation.destroy! }.to change(described_class, :count).by(-1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'allows destroying conversation with sent scheduled messages with attachments' do
|
||||||
|
scheduled_message = create_scheduled_message
|
||||||
|
scheduled_message.attachment.attach(
|
||||||
|
io: Rails.root.join('spec/assets/avatar.png').open,
|
||||||
|
filename: 'avatar.png',
|
||||||
|
content_type: 'image/png'
|
||||||
|
)
|
||||||
|
scheduled_message.update!(status: :sent)
|
||||||
|
|
||||||
|
expect { conversation.destroy! }.to change(described_class, :count).by(-1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'allows deleting sent messages at model level (controller enforces restriction)' do
|
||||||
scheduled_message = create_scheduled_message
|
scheduled_message = create_scheduled_message
|
||||||
scheduled_message.update!(status: :sent)
|
scheduled_message.update!(status: :sent)
|
||||||
|
|
||||||
expect { scheduled_message.destroy }.not_to change(described_class, :count)
|
expect { scheduled_message.destroy! }.to change(described_class, :count).by(-1)
|
||||||
expect(scheduled_message.errors[:base]).to include('Cannot delete a scheduled message that has already been sent or failed')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not allow deleting failed messages' do
|
it 'allows deleting failed messages at model level (controller enforces restriction)' do
|
||||||
scheduled_message = create_scheduled_message
|
scheduled_message = create_scheduled_message
|
||||||
scheduled_message.update!(status: :failed)
|
scheduled_message.update!(status: :failed)
|
||||||
|
|
||||||
expect { scheduled_message.destroy }.not_to change(described_class, :count)
|
expect { scheduled_message.destroy! }.to change(described_class, :count).by(-1)
|
||||||
expect(scheduled_message.errors[:base]).to include('Cannot delete a scheduled message that has already been sent or failed')
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user