* Attempt number 1 * Fix rack_attack specs * Fix users_searches_users spec * Fix display_users_search_spec * Fix comment typo * Remove search:destroy task from cypress * Remove port 9300 from gitpod * Stub response in attack_spec
268 lines
9.4 KiB
Ruby
268 lines
9.4 KiB
Ruby
class ChatChannelsController < ApplicationController
|
|
before_action :authenticate_user!, only: %i[moderate]
|
|
before_action :set_channel, only: %i[show update update_channel open moderate]
|
|
after_action :verify_authorized
|
|
|
|
include MessagesHelper
|
|
include ChatChannelsHelper
|
|
|
|
CHANNEL_ATTRIBUTES_FOR_SERIALIZATION = %i[id description channel_name].freeze
|
|
private_constant :CHANNEL_ATTRIBUTES_FOR_SERIALIZATION
|
|
|
|
def index
|
|
case params[:state]
|
|
when "unopened"
|
|
authorize ChatChannel
|
|
@chat_channels_memberships = unopened_json_response
|
|
render "index", formats: :json
|
|
when "unopened_ids"
|
|
authorize ChatChannel
|
|
@unopened_ids = unopened_ids_response
|
|
render json: { unopened_ids: @unopened_ids }
|
|
when "pending"
|
|
authorize ChatChannel
|
|
@chat_channels_memberships = pending_json_response
|
|
render "index", formats: :json
|
|
when "joining_request"
|
|
authorize ChatChannel
|
|
@chat_channels_memberships = joining_request_json_response
|
|
render "index", formats: :json
|
|
else
|
|
skip_authorization
|
|
render_channels_html
|
|
end
|
|
end
|
|
|
|
def show
|
|
@chat_messages = @chat_channel.messages
|
|
.includes(:user)
|
|
.order(created_at: :desc)
|
|
.offset(params[:message_offset])
|
|
.limit(50)
|
|
end
|
|
|
|
def create
|
|
authorize ChatChannel
|
|
@chat_channel = current_user.chat_channels.create(
|
|
channel_type: "invite_only",
|
|
channel_name: chat_channel_params[:channel_name],
|
|
slug: chat_channel_params[:slug],
|
|
)
|
|
render_chat_channel
|
|
end
|
|
|
|
def update
|
|
chat_channel = ChatChannels::UpdateChannel.call(@chat_channel, chat_channel_params)
|
|
if chat_channel.errors.any?
|
|
flash[:error] = chat_channel.errors.full_messages.to_sentence
|
|
else
|
|
if chat_channel_params[:discoverable].to_i.zero?
|
|
ChatChannelMembership.create(user_id: Settings::Mascot.mascot_user_id, chat_channel_id: chat_channel.id,
|
|
role: "member", status: "active")
|
|
else
|
|
ChatChannelMembership.find_by(user_id: Settings::Mascot.mascot_user_id)&.destroy
|
|
end
|
|
flash[:settings_notice] = "Channel settings updated."
|
|
end
|
|
current_user_membership = @chat_channel.mod_memberships.find_by!(user: current_user)
|
|
|
|
redirect_to edit_chat_channel_membership_path(current_user_membership)
|
|
end
|
|
|
|
def update_channel
|
|
@chat_channel.update(chat_channel_params)
|
|
if @chat_channel.errors.any?
|
|
render json: { success: false, errors: @chat_channel.errors.full_messages,
|
|
message: "Channel settings updation failed. Try again later." }, success: :bad_request
|
|
else
|
|
if chat_channel_params[:discoverable]
|
|
ChatChannelMembership.create(user_id: Settings::Mascot.mascot_user_id, chat_channel_id: @chat_channel.id,
|
|
role: "member", status: "active")
|
|
else
|
|
ChatChannelMembership.find_by(user_id: Settings::Mascot.mascot_user_id)&.destroy
|
|
end
|
|
render json: { success: true, message: "Channel settings updated.", data: {} }, success: :ok
|
|
end
|
|
end
|
|
|
|
def open
|
|
membership = @chat_channel.chat_channel_memberships.where(user_id: current_user.id).first
|
|
membership.update(last_opened_at: 1.second.from_now, has_unopened_messages: false)
|
|
send_open_notification
|
|
render json: { status: "success", channel: params[:id] }, status: :ok
|
|
end
|
|
|
|
def moderate
|
|
chat_channel = ChatChannel.find_by(id: params[:id])
|
|
authorize chat_channel
|
|
command, username = chat_channel_params[:command].split
|
|
case command
|
|
when "/ban"
|
|
user = User.find_by(username: username)
|
|
membership = user&.chat_channel_memberships&.find_by(chat_channel: chat_channel)
|
|
if user && membership
|
|
user.add_role(:suspended)
|
|
user.messages.where(chat_channel: chat_channel).delete_all
|
|
membership.update(status: "removed_from_channel")
|
|
Pusher.trigger(chat_channel.pusher_channels, "user-banned", { userId: user.id }.to_json)
|
|
render json: { status: "moderation-success", message: "#{username} was suspended.", userId: user.id,
|
|
chatChannelId: chat_channel.id }, status: :ok
|
|
else
|
|
render json: {
|
|
status: "error",
|
|
message: "Suspend failed. user with username '#{username}' not found in this channel."
|
|
}, status: :bad_request
|
|
end
|
|
when "/unban"
|
|
user = User.find_by(username: username)
|
|
if user
|
|
user.remove_role(:suspended)
|
|
render json: { status: "moderation-success", message: "#{username} was unsuspended." }, status: :ok
|
|
else
|
|
render json: {
|
|
status: "error",
|
|
message: "Unsuspend failed. User with username '#{username}' not found in this channel."
|
|
}, status: :bad_request
|
|
end
|
|
when "/clearchannel"
|
|
@chat_channel.clear_channel
|
|
render json: { status: "success", message: "cleared!" }, status: :ok
|
|
else
|
|
render json: { status: "error", message: "invalid command" }, status: :bad_request
|
|
end
|
|
end
|
|
|
|
def create_chat
|
|
chat_recipient = User.find(params[:user_id])
|
|
valid_listing = Listing.where(user_id: params[:user_id], contact_via_connect: true).limit(1)
|
|
authorize ChatChannel
|
|
|
|
if chat_recipient.inbox_type == "open" || valid_listing.length == 1
|
|
chat = ChatChannels::CreateWithUsers.call(users: [current_user, chat_recipient], channel_type: "direct")
|
|
message_markdown = params[:message]
|
|
message = Message.new(
|
|
chat_channel: chat,
|
|
message_markdown: message_markdown,
|
|
user: current_user,
|
|
)
|
|
chat.messages.append(message)
|
|
render json: { status: "success", message: "chat channel created!" }, status: :ok
|
|
else
|
|
render json: { status: "error", message: "not allowed!" }, status: :bad_request
|
|
end
|
|
rescue StandardError => e
|
|
render json: { status: "error", message: e.message }, status: :bad_request
|
|
end
|
|
|
|
def block_chat
|
|
chat_channel = ChatChannel.find(params[:chat_id])
|
|
authorize chat_channel
|
|
chat_channel.status = "blocked"
|
|
chat_channel.save
|
|
render json: { status: "success", message: "chat channel blocked" }, status: :ok
|
|
end
|
|
|
|
# NOTE: this is part of an effort of moving some things from the external to
|
|
# the internal API. No behavior was changes as part of this refactoring, so
|
|
# this action is a bit unusual.
|
|
def channel_info
|
|
skip_authorization
|
|
|
|
@chat_channel =
|
|
ChatChannel
|
|
.select(CHANNEL_ATTRIBUTES_FOR_SERIALIZATION)
|
|
.find_by(id: params[:id])
|
|
|
|
return if @chat_channel&.has_member?(current_user)
|
|
|
|
render json: { error: "not found", status: 404 }, status: :not_found
|
|
end
|
|
|
|
def create_channel
|
|
chat_channel_params = params[:chat_channel]
|
|
chat_channel_name = chat_channel_params[:channel_name].split.join("-")
|
|
chat_channel = ChatChannel.new(
|
|
channel_type: "invite_only",
|
|
channel_name: chat_channel_params[:channel_name],
|
|
slug: "#{chat_channel_name}-#{SecureRandom.hex(5)}",
|
|
)
|
|
authorize chat_channel
|
|
chat_channel.save
|
|
membership = chat_channel.chat_channel_memberships.new(user_id: current_user.id, role: "mod")
|
|
if membership.save
|
|
message = ChatChannels::SendInvitation.call(
|
|
chat_channel_params[:invitation_usernames],
|
|
current_user,
|
|
chat_channel,
|
|
)
|
|
|
|
send_chat_action_message(
|
|
"channel is created by #{current_user.username}",
|
|
current_user, membership.chat_channel_id,
|
|
"chat channel is created"
|
|
)
|
|
render json: {
|
|
success: true,
|
|
message: "Channel is created #{message ? "& #{message}" : nil}"
|
|
}, status: :ok
|
|
else
|
|
render json: {
|
|
success: false,
|
|
message: membership.errors_as_sentence
|
|
}, status: 445
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def set_channel
|
|
@chat_channel = ChatChannel.find_by(id: params[:id]) || not_found
|
|
authorize @chat_channel
|
|
end
|
|
|
|
def chat_channel_params
|
|
params.require(:chat_channel).permit(policy(ChatChannel).permitted_attributes)
|
|
end
|
|
|
|
def render_channels_html
|
|
return unless current_user && params[:slug]
|
|
|
|
slug = if params[:slug]&.start_with?("@")
|
|
[current_user.username, params[:slug].delete("@")].sort.join("/")
|
|
else
|
|
params[:slug]
|
|
end
|
|
chat_channel = ChatChannel.find_by(slug: slug)
|
|
return unless chat_channel
|
|
|
|
membership = chat_channel.chat_channel_memberships.find_by(user_id: current_user.id)
|
|
@active_channel = membership&.status == "active" ? chat_channel : nil
|
|
end
|
|
|
|
def render_chat_channel
|
|
if @chat_channel.valid?
|
|
render json: { status: "success",
|
|
chat_channel: @chat_channel.to_json(only: %i[channel_name slug]) },
|
|
status: :ok
|
|
else
|
|
render json: { errors: @chat_channel.errors.full_messages }
|
|
end
|
|
end
|
|
|
|
def send_open_notification
|
|
adjusted_slug = if @chat_channel.group?
|
|
@chat_channel.adjusted_slug
|
|
else
|
|
@chat_channel.adjusted_slug(current_user)
|
|
end
|
|
payload = { channel_type: @chat_channel.channel_type, adjusted_slug: adjusted_slug }.to_json
|
|
Pusher.trigger(ChatChannel.pm_notifications_channel(session_current_user_id), "message-opened", payload)
|
|
end
|
|
|
|
def send_chat_action_message(message, user, channel_id, action)
|
|
temp_message_id = SecureRandom.hex(20)
|
|
message = Message.create(message_markdown: message, user_id: user.id, chat_channel_id: channel_id,
|
|
chat_action: action)
|
|
pusher_message_created(false, message, temp_message_id)
|
|
end
|
|
end
|