290 lines
12 KiB
Ruby
290 lines
12 KiB
Ruby
class ChatChannelMembershipsController < ApplicationController
|
|
before_action :authenticate_user!
|
|
after_action :verify_authorized, except: %w[join_channel request_details]
|
|
|
|
include MessagesHelper
|
|
|
|
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
|
|
rescue_from ActiveRecord::RecordNotFound, with: :record_not_found
|
|
|
|
def index
|
|
skip_authorization
|
|
memberships = current_user.chat_channel_memberships.includes(:chat_channel)
|
|
@pending_invites = memberships.filter_by_status("pending")
|
|
end
|
|
|
|
def find_by_chat_channel_id
|
|
@membership = ChatChannelMembership.where(chat_channel_id: params[:chat_channel_id],
|
|
user_id: current_user.id).first!
|
|
authorize @membership
|
|
render json: @membership.to_json(
|
|
only: %i[id status viewable_by chat_channel_id last_opened_at],
|
|
methods: %i[channel_text channel_last_message_at channel_status channel_username
|
|
channel_type channel_text channel_name channel_image channel_modified_slug channel_messages_count],
|
|
)
|
|
end
|
|
|
|
def chat_channel_info
|
|
@membership = ChatChannelMembership.find(params[:id])
|
|
authorize @membership
|
|
@channel = @membership.chat_channel
|
|
invite_cache_key = "chat-channel-invite-#{@channel.id}"
|
|
invitation_slug = Rails.cache.fetch(invite_cache_key, expires_in: 80.hours) do
|
|
"invitation-link-#{SecureRandom.hex(3)}"
|
|
end
|
|
@invitation_link = "/join_channel_invitation/#{@channel.slug}?invitation_slug=#{invitation_slug}"
|
|
end
|
|
|
|
def create_membership_request
|
|
chat_channel = ChatChannel.find_by(id: channel_membership_params[:chat_channel_id])
|
|
authorize chat_channel, :update?
|
|
usernames = channel_membership_params[:invitation_usernames].split(",").map do |username|
|
|
username.strip.delete("@")
|
|
end
|
|
users = User.where(username: usernames)
|
|
invitations_sent = chat_channel.invite_users(users: users, membership_role: "member", inviter: current_user)
|
|
message = if invitations_sent.zero?
|
|
"No invitations sent. Check for username typos."
|
|
else
|
|
"#{invitations_sent} #{'invitation'.pluralize(invitations_sent)} sent."
|
|
end
|
|
|
|
render json: { success: true, message: message, data: {} }, status: :ok
|
|
end
|
|
|
|
def join_channel
|
|
membership_params = params[:chat_channel_membership]
|
|
chat_channel = ChatChannel.find(membership_params[:chat_channel_id])
|
|
existing_membership = ChatChannelMembership.find_by(user_id: current_user.id, chat_channel_id: chat_channel.id)
|
|
if existing_membership.present? && %w[active joining_request].exclude?(existing_membership.status)
|
|
status = existing_membership.update(status: "joining_request", role: "member")
|
|
else
|
|
membership = ChatChannelMembership.new(user_id: current_user.id, chat_channel_id: chat_channel.id,
|
|
role: "member", status: "joining_request")
|
|
status = membership.save
|
|
end
|
|
if status
|
|
render json: { status: "success", message: "Request Sent" }, status: :ok
|
|
else
|
|
render json: { status: 400, message: "Unable to join channel" }, status: :bad_request
|
|
end
|
|
end
|
|
|
|
def remove_membership
|
|
@chat_channel = ChatChannel.find(params[:chat_channel_id])
|
|
authorize @chat_channel, :update?
|
|
@chat_channel_membership = @chat_channel.chat_channel_memberships.find(params[:membership_id])
|
|
if params[:status] == "pending"
|
|
@chat_channel_membership.destroy
|
|
message = "Invitation removed."
|
|
else
|
|
membership = @chat_channel_membership
|
|
message = "@#{current_user.username} removed @#{membership.user.username} from #{membership.channel_name}"
|
|
send_chat_action_message(
|
|
message, current_user, @chat_channel_membership.chat_channel_id, "removed_from_channel"
|
|
)
|
|
@chat_channel_membership.update(status: "removed_from_channel")
|
|
message = "Removed #{@chat_channel_membership.user.name}"
|
|
end
|
|
|
|
render json: { status: "success", message: message, success: true }, status: :ok
|
|
end
|
|
|
|
def add_membership
|
|
@chat_channel = ChatChannel.find(params[:chat_channel_id])
|
|
authorize @chat_channel, :update?
|
|
@chat_channel_membership = @chat_channel.chat_channel_memberships.find(params[:membership_id])
|
|
|
|
return unless permitted_params[:user_action].present? && @chat_channel_membership.status == "joining_request"
|
|
|
|
respond_to_invitation(@chat_channel_membership.status)
|
|
end
|
|
|
|
def update
|
|
@chat_channel_membership = ChatChannelMembership.find(params[:id])
|
|
authorize @chat_channel_membership
|
|
respond_to_invitation(@chat_channel_membership.status)
|
|
end
|
|
|
|
def update_membership
|
|
@chat_channel_membership = ChatChannelMembership.find(params[:id])
|
|
authorize @chat_channel_membership
|
|
@chat_channel_membership.update(permitted_params)
|
|
if @chat_channel_membership.errors.any?
|
|
render json: { success: false, errors: @chat_channel_membership.errors.full_messages,
|
|
message: "Failed to update settings." }, status: :bad_request
|
|
else
|
|
render json: { success: true, message: "Personal settings updated." }, status: :ok
|
|
end
|
|
end
|
|
|
|
def leave_membership
|
|
chat_channel_membership = ChatChannelMembership.find_by(id: params[:id])
|
|
authorize chat_channel_membership
|
|
channel_name = chat_channel_membership.chat_channel.channel_name
|
|
send_chat_action_message("@#{current_user.username} left #{chat_channel_membership.channel_name}", current_user,
|
|
chat_channel_membership.chat_channel_id, "left_channel")
|
|
chat_channel_membership.update(status: "left_channel")
|
|
message = "You have left the channel #{channel_name}. It may take a moment to be removed from your list."
|
|
if chat_channel_membership.errors.any?
|
|
render json: { success: false, message: "Failed to update membership",
|
|
errors: chat_channel_membership.errors.full_messages }, status: :bad_request
|
|
else
|
|
render json: { success: true, message: message }, status: :ok
|
|
end
|
|
end
|
|
|
|
def request_details
|
|
user_chat_channels = ChatChannel.includes(:chat_channel_memberships).where(
|
|
chat_channel_memberships: { user_id: current_user.id, role: "mod", status: "active" },
|
|
)
|
|
@memberships = user_chat_channels.map(&:requested_memberships).flatten
|
|
@user_invitations = ChatChannelMembership.where(
|
|
user_id: current_user.id,
|
|
status: %w[pending],
|
|
).order("created_at DESC")
|
|
end
|
|
|
|
def update_membership_role
|
|
@chat_channel = ChatChannel.find_by(id: params[:id])
|
|
authorize @chat_channel, :update?
|
|
membership = ChatChannelMembership.find_by(
|
|
id: channel_membership_params[:membership_id],
|
|
chat_channel_id: @chat_channel.id,
|
|
)
|
|
|
|
membership.update(role: channel_membership_params[:role])
|
|
if membership.errors.any?
|
|
render json: {
|
|
success: false,
|
|
message: "Failed to update membership",
|
|
errors: chat_channel_membership.errors.full_messages
|
|
}, status: :bad_request
|
|
else
|
|
role = membership.reload.role
|
|
send_chat_action_message(
|
|
"@#{membership.user.username} role is updated as #{role}",
|
|
current_user, @chat_channel.id,
|
|
"updated"
|
|
)
|
|
|
|
render json: { success: true, message: "User Membership is updated" }, status: :ok
|
|
end
|
|
end
|
|
|
|
def join_channel_invitation
|
|
@chat_channel = ChatChannel.find_by(slug: params[:channel_slug])
|
|
authorize @chat_channel
|
|
invite_cache_key = "chat-channel-invite-#{@chat_channel.id}"
|
|
invitation_slug = Rails.cache.read(invite_cache_key)
|
|
existing_membership = ChatChannelMembership.find_by(user_id: current_user.id, chat_channel_id: @chat_channel.id)
|
|
redirect_to connect_path(@chat_channel.slug) if existing_membership && existing_membership.status == "active"
|
|
@link_expired = true if invitation_slug != params[:invitation_slug]
|
|
end
|
|
|
|
def joining_invitation_response
|
|
chat_channel = ChatChannel.find_by(id: params[:chat_channel_id])
|
|
authorize chat_channel
|
|
if params[:user_action] == "accept"
|
|
membership = ChatChannelMembership.find_by(user_id: current_user.id, chat_channel_id: chat_channel.id)
|
|
if !membership
|
|
membership = ChatChannelMembership.new(user_id: current_user.id, chat_channel_id: chat_channel.id)
|
|
membership.save
|
|
unless membership&.errors&.any?
|
|
send_chat_action_message("@#{membership.user.username} join the channel", current_user, chat_channel.id,
|
|
"joined")
|
|
end
|
|
elsif membership.status != "active"
|
|
# This check checks if the user already has the chatChannelMembership with the status pending, joining_request
|
|
# Then update it to as active.
|
|
membership.update(role: "member", status: "active")
|
|
send_chat_action_message("@#{membership.user.username} join the channel", current_user,
|
|
membership.chat_channel_id, "joined")
|
|
end
|
|
|
|
if membership&.errors&.any?
|
|
flash[:settings_notice] = membership.errors.full_messages
|
|
redirect_to root_path
|
|
end
|
|
|
|
redirect_to connect_path(chat_channel.slug)
|
|
else
|
|
redirect_to root_path
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def permitted_params
|
|
params.require(:chat_channel_membership).permit(:user_action, :show_global_badge_notification)
|
|
end
|
|
|
|
def channel_membership_params
|
|
params.require(:chat_channel_membership).permit(:chat_channel_id, :invitation_usernames, :membership_id, :role)
|
|
end
|
|
|
|
def respond_to_invitation(previous_status)
|
|
if permitted_params[:user_action] == "accept"
|
|
@chat_channel_membership.update(status: "active")
|
|
channel_name = @chat_channel_membership.chat_channel.channel_name
|
|
|
|
if previous_status == "pending"
|
|
send_chat_action_message(
|
|
"@#{current_user.username} joined #{@chat_channel_membership.channel_name}",
|
|
current_user,
|
|
@chat_channel_membership.chat_channel_id,
|
|
"joined",
|
|
)
|
|
|
|
notice = "Invitation to #{channel_name} accepted. It may take a moment to show up in your list."
|
|
else
|
|
send_chat_action_message(
|
|
"@#{current_user.username} added @#{@chat_channel_membership.user.username}",
|
|
current_user,
|
|
@chat_channel_membership.chat_channel_id,
|
|
"joined",
|
|
)
|
|
|
|
NotifyMailer
|
|
.with(membership: @chat_channel_membership, inviter: @chat_channel_membership.user)
|
|
.channel_invite_email
|
|
.deliver_later
|
|
|
|
notice = "Accepted request of #{@chat_channel_membership.user.username} to join #{channel_name}."
|
|
end
|
|
else
|
|
@chat_channel_membership.update(status: "rejected")
|
|
notice = "Invitation rejected."
|
|
end
|
|
|
|
membership_user = helpers.format_membership(@chat_channel_membership)
|
|
flash[:settings_notice] = notice
|
|
|
|
respond_to do |format|
|
|
format.html { redirect_to chat_channel_memberships_path }
|
|
format.json do
|
|
render json: {
|
|
status: "success",
|
|
message: flash[:settings_notice],
|
|
success: true,
|
|
membership: membership_user
|
|
}, status: :ok
|
|
end
|
|
end
|
|
end
|
|
|
|
def send_chat_action_message(message, user, channel_id, action)
|
|
temp_message_id = (0...20).map { ("a".."z").to_a[rand(8)] }.join
|
|
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
|
|
|
|
def user_not_authorized
|
|
render json: { success: false, message: "User not authorized" }, status: :unauthorized
|
|
end
|
|
|
|
def record_not_found
|
|
render json: { success: false, message: "not found" }, status: :not_found
|
|
end
|
|
end
|