2022-11-02 21:41:30 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
class Chat::ChatChannelsController < Chat::ChatBaseController
|
|
|
|
before_action :set_channel_and_chatable_with_access_check, except: %i[index create search]
|
|
|
|
|
|
|
|
def index
|
|
|
|
structured = Chat::ChatChannelFetcher.structured(guardian)
|
|
|
|
render_serialized(structured, ChatChannelIndexSerializer, root: false)
|
|
|
|
end
|
|
|
|
|
|
|
|
def show
|
|
|
|
render_serialized(
|
|
|
|
@chat_channel,
|
|
|
|
ChatChannelSerializer,
|
|
|
|
membership: @chat_channel.membership_for(current_user),
|
|
|
|
root: false,
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
def follow
|
|
|
|
membership = @chat_channel.add(current_user)
|
|
|
|
|
|
|
|
render_serialized(@chat_channel, ChatChannelSerializer, membership: membership, root: false)
|
|
|
|
end
|
|
|
|
|
|
|
|
def unfollow
|
|
|
|
membership = @chat_channel.remove(current_user)
|
|
|
|
|
|
|
|
render_serialized(@chat_channel, ChatChannelSerializer, membership: membership, root: false)
|
|
|
|
end
|
|
|
|
|
|
|
|
def create
|
|
|
|
params.require(%i[id name])
|
|
|
|
guardian.ensure_can_create_chat_channel!
|
|
|
|
if params[:name].length > SiteSetting.max_topic_title_length
|
|
|
|
raise Discourse::InvalidParameters.new(:name)
|
|
|
|
end
|
|
|
|
|
|
|
|
exists =
|
|
|
|
ChatChannel.exists?(chatable_type: "Category", chatable_id: params[:id], name: params[:name])
|
|
|
|
if exists
|
|
|
|
raise Discourse::InvalidParameters.new(I18n.t("chat.errors.channel_exists_for_category"))
|
|
|
|
end
|
|
|
|
|
|
|
|
chatable = Category.find_by(id: params[:id])
|
|
|
|
raise Discourse::NotFound unless chatable
|
|
|
|
|
|
|
|
auto_join_users = ActiveRecord::Type::Boolean.new.deserialize(params[:auto_join_users]) || false
|
|
|
|
|
|
|
|
chat_channel =
|
|
|
|
chatable.create_chat_channel!(
|
|
|
|
name: params[:name],
|
|
|
|
description: params[:description],
|
|
|
|
user_count: 1,
|
|
|
|
auto_join_users: auto_join_users,
|
|
|
|
)
|
|
|
|
chat_channel.user_chat_channel_memberships.create!(user: current_user, following: true)
|
|
|
|
|
|
|
|
if chat_channel.auto_join_users
|
|
|
|
Chat::ChatChannelMembershipManager.new(chat_channel).enforce_automatic_channel_memberships
|
|
|
|
end
|
|
|
|
|
|
|
|
render_serialized(
|
|
|
|
chat_channel,
|
|
|
|
ChatChannelSerializer,
|
|
|
|
membership: chat_channel.membership_for(current_user),
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
def edit
|
|
|
|
guardian.ensure_can_edit_chat_channel!
|
|
|
|
if (params[:name]&.length || 0) > SiteSetting.max_topic_title_length
|
|
|
|
raise Discourse::InvalidParameters.new(:name)
|
|
|
|
end
|
|
|
|
|
|
|
|
chat_channel = ChatChannel.find_by(id: params[:chat_channel_id])
|
|
|
|
raise Discourse::NotFound unless chat_channel
|
|
|
|
|
|
|
|
chat_channel.name = params[:name] if params[:name]
|
|
|
|
chat_channel.description = params[:description] if params[:description]
|
|
|
|
chat_channel.save!
|
|
|
|
|
|
|
|
ChatPublisher.publish_chat_channel_edit(chat_channel, current_user)
|
|
|
|
render_serialized(
|
|
|
|
chat_channel,
|
|
|
|
ChatChannelSerializer,
|
|
|
|
membership: chat_channel.membership_for(current_user),
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
def search
|
|
|
|
params.require(:filter)
|
|
|
|
filter = params[:filter]&.downcase
|
|
|
|
memberships = Chat::ChatChannelMembershipManager.all_for_user(current_user)
|
|
|
|
public_channels =
|
|
|
|
Chat::ChatChannelFetcher.secured_public_channels(
|
|
|
|
guardian,
|
|
|
|
memberships,
|
|
|
|
filter: filter,
|
|
|
|
status: :open,
|
|
|
|
)
|
|
|
|
|
|
|
|
users = User.joins(:user_option).where.not(id: current_user.id)
|
|
|
|
if !Chat.allowed_group_ids.include?(Group::AUTO_GROUPS[:everyone])
|
|
|
|
users =
|
|
|
|
users
|
|
|
|
.joins(:groups)
|
|
|
|
.where(groups: { id: Chat.allowed_group_ids })
|
|
|
|
.or(users.joins(:groups).staff)
|
|
|
|
end
|
|
|
|
|
|
|
|
users = users.where(user_option: { chat_enabled: true })
|
|
|
|
like_filter = "%#{filter}%"
|
|
|
|
if SiteSetting.prioritize_username_in_ux || !SiteSetting.enable_names
|
|
|
|
users = users.where("users.username_lower ILIKE ?", like_filter)
|
|
|
|
else
|
|
|
|
users =
|
|
|
|
users.where(
|
|
|
|
"LOWER(users.name) ILIKE ? OR users.username_lower ILIKE ?",
|
|
|
|
like_filter,
|
|
|
|
like_filter,
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
users = users.limit(25).uniq
|
|
|
|
|
|
|
|
direct_message_channels =
|
|
|
|
(
|
|
|
|
if users.count > 0
|
|
|
|
ChatChannel
|
|
|
|
.includes(chatable: :users)
|
2022-11-02 22:53:36 +08:00
|
|
|
.joins(direct_message: :direct_message_users)
|
2022-11-02 21:41:30 +08:00
|
|
|
.group(1)
|
|
|
|
.having(
|
|
|
|
"ARRAY[?] <@ ARRAY_AGG(user_id) AND ARRAY[?] && ARRAY_AGG(user_id)",
|
|
|
|
[current_user.id],
|
|
|
|
users.map(&:id),
|
|
|
|
)
|
|
|
|
else
|
|
|
|
[]
|
|
|
|
end
|
|
|
|
)
|
|
|
|
|
|
|
|
user_ids_with_channel = []
|
|
|
|
direct_message_channels.each do |dm_channel|
|
|
|
|
user_ids = dm_channel.chatable.users.map(&:id)
|
|
|
|
user_ids_with_channel.concat(user_ids) if user_ids.count < 3
|
|
|
|
end
|
|
|
|
|
|
|
|
users_without_channel = users.filter { |u| !user_ids_with_channel.include?(u.id) }
|
|
|
|
|
|
|
|
if current_user.username.downcase.start_with?(filter)
|
|
|
|
# We filtered out the current user for the query earlier, but check to see
|
|
|
|
# if they should be included, and add.
|
|
|
|
users_without_channel << current_user
|
|
|
|
end
|
|
|
|
|
|
|
|
render_serialized(
|
|
|
|
{
|
|
|
|
public_channels: public_channels,
|
|
|
|
direct_message_channels: direct_message_channels,
|
|
|
|
users: users_without_channel,
|
|
|
|
memberships: memberships,
|
|
|
|
},
|
|
|
|
ChatChannelSearchSerializer,
|
|
|
|
root: false,
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
def archive
|
|
|
|
params.require(:type)
|
|
|
|
|
|
|
|
if params[:type] == "newTopic" ? params[:title].blank? : params[:topic_id].blank?
|
|
|
|
raise Discourse::InvalidParameters
|
|
|
|
end
|
|
|
|
|
|
|
|
if !guardian.can_change_channel_status?(@chat_channel, :read_only)
|
|
|
|
raise Discourse::InvalidAccess.new(I18n.t("chat.errors.channel_cannot_be_archived"))
|
|
|
|
end
|
|
|
|
|
|
|
|
Chat::ChatChannelArchiveService.begin_archive_process(
|
|
|
|
chat_channel: @chat_channel,
|
|
|
|
acting_user: current_user,
|
|
|
|
topic_params: {
|
|
|
|
topic_id: params[:topic_id],
|
|
|
|
topic_title: params[:title],
|
|
|
|
category_id: params[:category_id],
|
|
|
|
tags: params[:tags],
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
render json: success_json
|
|
|
|
end
|
|
|
|
|
|
|
|
def retry_archive
|
|
|
|
guardian.ensure_can_change_channel_status!(@chat_channel, :archived)
|
|
|
|
|
|
|
|
archive = @chat_channel.chat_channel_archive
|
|
|
|
raise Discourse::NotFound if archive.blank?
|
|
|
|
raise Discourse::InvalidAccess if !archive.failed?
|
|
|
|
|
|
|
|
Chat::ChatChannelArchiveService.retry_archive_process(chat_channel: @chat_channel)
|
|
|
|
|
|
|
|
render json: success_json
|
|
|
|
end
|
|
|
|
|
|
|
|
def change_status
|
|
|
|
params.require(:status)
|
|
|
|
|
|
|
|
# we only want to use this endpoint for open/closed status changes,
|
|
|
|
# the others are more "special" and are handled by the archive endpoint
|
|
|
|
if !ChatChannel.statuses.keys.include?(params[:status]) || params[:status] == "read_only" ||
|
|
|
|
params[:status] == "archive"
|
|
|
|
raise Discourse::InvalidParameters
|
|
|
|
end
|
|
|
|
|
|
|
|
guardian.ensure_can_change_channel_status!(@chat_channel, params[:status].to_sym)
|
|
|
|
@chat_channel.public_send("#{params[:status]}!", current_user)
|
|
|
|
|
|
|
|
render json: success_json
|
|
|
|
end
|
|
|
|
|
|
|
|
def destroy
|
|
|
|
params.require(:channel_name_confirmation)
|
|
|
|
|
|
|
|
guardian.ensure_can_delete_chat_channel!
|
|
|
|
|
|
|
|
if @chat_channel.title(current_user).downcase != params[:channel_name_confirmation].downcase
|
|
|
|
raise Discourse::InvalidParameters.new(:channel_name_confirmation)
|
|
|
|
end
|
|
|
|
|
|
|
|
begin
|
|
|
|
ChatChannel.transaction do
|
|
|
|
@chat_channel.trash!(current_user)
|
|
|
|
StaffActionLogger.new(current_user).log_custom(
|
|
|
|
"chat_channel_delete",
|
|
|
|
{
|
|
|
|
chat_channel_id: @chat_channel.id,
|
|
|
|
chat_channel_name: @chat_channel.title(current_user),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
end
|
|
|
|
rescue ActiveRecord::Rollback
|
|
|
|
return render_json_error(I18n.t("chat.errors.delete_channel_failed"))
|
|
|
|
end
|
|
|
|
|
|
|
|
Jobs.enqueue(:chat_channel_delete, { chat_channel_id: @chat_channel.id })
|
|
|
|
render json: success_json
|
|
|
|
end
|
|
|
|
end
|