mirror of
https://github.com/discourse/discourse.git
synced 2024-12-13 11:03:43 +08:00
7212a2ad51
There must have been a small loophole that allowed setting the channel slug in the DB which has led to conflicts in some cases. This commit fixes the conflicting chat channel slugs and then changes the channel slug index to a unique one in the DB.
150 lines
4.2 KiB
Ruby
150 lines
4.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class ChatChannel < ActiveRecord::Base
|
|
include Trashable
|
|
|
|
belongs_to :chatable, polymorphic: true
|
|
belongs_to :direct_message,
|
|
-> { where(chat_channels: { chatable_type: "DirectMessage" }) },
|
|
foreign_key: "chatable_id"
|
|
|
|
has_many :chat_messages
|
|
has_many :user_chat_channel_memberships
|
|
|
|
has_one :chat_channel_archive
|
|
|
|
enum :status, { open: 0, read_only: 1, closed: 2, archived: 3 }, scopes: false
|
|
|
|
validates :name,
|
|
length: {
|
|
maximum: Proc.new { SiteSetting.max_topic_title_length },
|
|
},
|
|
presence: true,
|
|
allow_nil: true
|
|
validate :ensure_slug_ok
|
|
before_validation :generate_auto_slug
|
|
|
|
scope :public_channels,
|
|
-> {
|
|
where(chatable_type: public_channel_chatable_types).where(
|
|
"categories.id IS NOT NULL",
|
|
).joins(
|
|
"LEFT JOIN categories ON categories.id = chat_channels.chatable_id AND chat_channels.chatable_type = 'Category'",
|
|
)
|
|
}
|
|
|
|
delegate :empty?, to: :chat_messages, prefix: true
|
|
|
|
class << self
|
|
def public_channel_chatable_types
|
|
["Category"]
|
|
end
|
|
|
|
def chatable_types
|
|
public_channel_chatable_types << "DirectMessage"
|
|
end
|
|
end
|
|
|
|
statuses.keys.each do |status|
|
|
define_method("#{status}!") { |acting_user| change_status(acting_user, status.to_sym) }
|
|
end
|
|
|
|
%i[
|
|
category_channel?
|
|
direct_message_channel?
|
|
public_channel?
|
|
chatable_has_custom_fields?
|
|
read_restricted?
|
|
].each { |name| define_method(name) { false } }
|
|
|
|
%i[allowed_user_ids allowed_group_ids chatable_url].each { |name| define_method(name) { nil } }
|
|
|
|
def membership_for(user)
|
|
user_chat_channel_memberships.find_by(user: user)
|
|
end
|
|
|
|
def add(user)
|
|
Chat::ChatChannelMembershipManager.new(self).follow(user)
|
|
end
|
|
|
|
def remove(user)
|
|
Chat::ChatChannelMembershipManager.new(self).unfollow(user)
|
|
end
|
|
|
|
def status_name
|
|
I18n.t("chat.channel.statuses.#{self.status}")
|
|
end
|
|
|
|
def url
|
|
"#{Discourse.base_url}/chat/channel/#{self.id}/#{self.slug || "-"}"
|
|
end
|
|
|
|
def relative_url
|
|
"#{Discourse.base_path}/chat/channel/#{self.id}/#{self.slug || "-"}"
|
|
end
|
|
|
|
private
|
|
|
|
def change_status(acting_user, target_status)
|
|
return if !Guardian.new(acting_user).can_change_channel_status?(self, target_status)
|
|
self.update!(status: target_status)
|
|
log_channel_status_change(acting_user: acting_user)
|
|
end
|
|
|
|
def log_channel_status_change(acting_user:)
|
|
DiscourseEvent.trigger(
|
|
:chat_channel_status_change,
|
|
channel: self,
|
|
old_status: status_previously_was,
|
|
new_status: status,
|
|
)
|
|
|
|
StaffActionLogger.new(acting_user).log_custom(
|
|
"chat_channel_status_change",
|
|
{
|
|
chat_channel_id: self.id,
|
|
chat_channel_name: self.name,
|
|
previous_value: status_previously_was,
|
|
new_value: status,
|
|
},
|
|
)
|
|
|
|
ChatPublisher.publish_channel_status(self)
|
|
end
|
|
|
|
def duplicate_slug?
|
|
ChatChannel.where(slug: self.slug).where.not(id: self.id).any?
|
|
end
|
|
end
|
|
|
|
# == Schema Information
|
|
#
|
|
# Table name: chat_channels
|
|
#
|
|
# id :bigint not null, primary key
|
|
# chatable_id :integer not null
|
|
# deleted_at :datetime
|
|
# deleted_by_id :integer
|
|
# featured_in_category_id :integer
|
|
# delete_after_seconds :integer
|
|
# chatable_type :string not null
|
|
# created_at :datetime not null
|
|
# updated_at :datetime not null
|
|
# name :string
|
|
# description :text
|
|
# status :integer default("open"), not null
|
|
# user_count :integer default(0), not null
|
|
# last_message_sent_at :datetime not null
|
|
# auto_join_users :boolean default(FALSE), not null
|
|
# user_count_stale :boolean default(FALSE), not null
|
|
# slug :string
|
|
# type :string
|
|
#
|
|
# Indexes
|
|
#
|
|
# index_chat_channels_on_chatable_id (chatable_id)
|
|
# index_chat_channels_on_chatable_id_and_chatable_type (chatable_id,chatable_type)
|
|
# index_chat_channels_on_slug (slug) UNIQUE
|
|
# index_chat_channels_on_status (status)
|
|
#
|