mirror of
https://github.com/discourse/discourse.git
synced 2025-01-31 08:01:01 +08:00
766bcbc684
This commit adds last_editor_id to ChatMessage for parity with Post in core, as well as adding user_id to the ChatMessageRevision record since we need to know who is making edits and revisions to messages, in case in future we want to allow more than just the current user to edit chat messages. The backfill for data here simply uses the record's creating user ID, but in future if we allow other people to edit the messages it will use their ID.
101 lines
2.9 KiB
Ruby
101 lines
2.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class Chat::ChatMessageUpdater
|
|
attr_reader :error
|
|
|
|
def self.update(opts)
|
|
instance = new(**opts)
|
|
instance.update
|
|
instance
|
|
end
|
|
|
|
def initialize(guardian:, chat_message:, new_content:, upload_ids: nil)
|
|
@guardian = guardian
|
|
@user = guardian.user
|
|
@chat_message = chat_message
|
|
@old_message_content = chat_message.message
|
|
@chat_channel = @chat_message.chat_channel
|
|
@user = @chat_message.user
|
|
@guardian = Guardian.new(@user)
|
|
@new_content = new_content
|
|
@upload_ids = upload_ids
|
|
@error = nil
|
|
end
|
|
|
|
def update
|
|
begin
|
|
validate_channel_status!
|
|
@chat_message.message = @new_content
|
|
@chat_message.last_editor_id = @user.id
|
|
upload_info = get_upload_info
|
|
validate_message!(has_uploads: upload_info[:uploads].any?)
|
|
@chat_message.cook
|
|
@chat_message.save!
|
|
update_uploads(upload_info)
|
|
revision = save_revision!
|
|
ChatPublisher.publish_edit!(@chat_channel, @chat_message)
|
|
Jobs.enqueue(:process_chat_message, { chat_message_id: @chat_message.id })
|
|
Chat::ChatNotifier.notify_edit(chat_message: @chat_message, timestamp: revision.created_at)
|
|
rescue => error
|
|
@error = error
|
|
end
|
|
end
|
|
|
|
def failed?
|
|
@error.present?
|
|
end
|
|
|
|
private
|
|
|
|
# TODO (martin) Since we have guardian here now we should move
|
|
# guardian.ensure_can_edit_chat!(@message) from the controller into
|
|
# this class.
|
|
|
|
def validate_channel_status!
|
|
return if @guardian.can_modify_channel_message?(@chat_channel)
|
|
raise StandardError.new(
|
|
I18n.t(
|
|
"chat.errors.channel_modify_message_disallowed",
|
|
status: @chat_channel.status_name,
|
|
),
|
|
)
|
|
end
|
|
|
|
def validate_message!(has_uploads:)
|
|
@chat_message.validate_message(has_uploads: has_uploads)
|
|
if @chat_message.errors.present?
|
|
raise StandardError.new(@chat_message.errors.map(&:full_message).join(", "))
|
|
end
|
|
end
|
|
|
|
def get_upload_info
|
|
return { uploads: [] } if @upload_ids.nil? || !SiteSetting.chat_allow_uploads
|
|
|
|
uploads = Upload.where(id: @upload_ids, user_id: @user.id)
|
|
if uploads.count != @upload_ids.count
|
|
# User is passing upload_ids for uploads that they don't own. Don't change anything.
|
|
return { uploads: @chat_message.uploads, changed: false }
|
|
end
|
|
|
|
new_upload_ids = uploads.map(&:id)
|
|
existing_upload_ids = @chat_message.upload_ids
|
|
difference = (existing_upload_ids + new_upload_ids) - (existing_upload_ids & new_upload_ids)
|
|
{ uploads: uploads, changed: difference.any? }
|
|
end
|
|
|
|
def update_uploads(upload_info)
|
|
return unless upload_info[:changed]
|
|
|
|
ChatUpload.where(chat_message: @chat_message).destroy_all
|
|
@chat_message.attach_uploads(upload_info[:uploads])
|
|
end
|
|
|
|
def save_revision!
|
|
@chat_message.revisions.create!(
|
|
old_message: @old_message_content,
|
|
new_message: @chat_message.message,
|
|
user_id: @user.id,
|
|
)
|
|
end
|
|
end
|