chore(refactor): Improve conversation permission filtering (#11166)
1. Add permission filter service to separate permission filtering logic from conversation queries 2. Implement hierarchical permissions with cleaner logic: - conversation_manage gives access to all conversations - conversation_unassigned_manage gives access to unassigned and user's conversations - conversation_participating_manage gives access only to user's conversations --------- Co-authored-by: Pranav <pranav@chatwoot.com>
This commit is contained in:
@@ -1,17 +1,21 @@
|
||||
class Api::V1::Accounts::Contacts::ConversationsController < Api::V1::Accounts::Contacts::BaseController
|
||||
def index
|
||||
@conversations = Current.account.conversations.includes(
|
||||
# Start with all conversations for this contact
|
||||
conversations = Current.account.conversations.includes(
|
||||
:assignee, :contact, :inbox, :taggings
|
||||
).where(inbox_id: inbox_ids, contact_id: @contact.id).order(last_activity_at: :desc).limit(20)
|
||||
end
|
||||
).where(contact_id: @contact.id)
|
||||
|
||||
private
|
||||
# Apply permission-based filtering using the existing service
|
||||
conversations = Conversations::PermissionFilterService.new(
|
||||
conversations,
|
||||
Current.user,
|
||||
Current.account
|
||||
).perform
|
||||
|
||||
def inbox_ids
|
||||
if Current.user.administrator? || Current.user.agent?
|
||||
Current.user.assigned_inboxes.pluck(:id)
|
||||
else
|
||||
[]
|
||||
end
|
||||
# Only allow conversations from inboxes the user has access to
|
||||
inbox_ids = Current.user.assigned_inboxes.pluck(:id)
|
||||
conversations = conversations.where(inbox_id: inbox_ids)
|
||||
|
||||
@conversations = conversations.order(last_activity_at: :desc).limit(20)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -48,7 +48,7 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro
|
||||
end
|
||||
|
||||
def filter
|
||||
result = ::Conversations::FilterService.new(params.permit!, current_user).perform
|
||||
result = ::Conversations::FilterService.new(params.permit!, current_user, current_account).perform
|
||||
@conversations = result[:conversations]
|
||||
@conversations_count = result[:count]
|
||||
rescue CustomExceptions::CustomFilter::InvalidAttribute,
|
||||
|
||||
@@ -93,6 +93,12 @@ class ConversationFinder
|
||||
|
||||
def find_all_conversations
|
||||
find_conversation_by_inbox
|
||||
# Apply permission-based filtering
|
||||
@conversations = Conversations::PermissionFilterService.new(
|
||||
@conversations,
|
||||
current_user,
|
||||
current_account
|
||||
).perform
|
||||
filter_by_conversation_type if params[:conversation_type]
|
||||
@conversations
|
||||
end
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
class Conversations::FilterService < FilterService
|
||||
ATTRIBUTE_MODEL = 'conversation_attribute'.freeze
|
||||
|
||||
def initialize(params, user, filter_account = nil)
|
||||
@account = filter_account || Current.account
|
||||
def initialize(params, user, account)
|
||||
@account = account
|
||||
super(params, user)
|
||||
end
|
||||
|
||||
@@ -24,9 +24,25 @@ class Conversations::FilterService < FilterService
|
||||
end
|
||||
|
||||
def base_relation
|
||||
@account.conversations.includes(
|
||||
conversations = @account.conversations.includes(
|
||||
:taggings, :inbox, { assignee: { avatar_attachment: [:blob] } }, { contact: { avatar_attachment: [:blob] } }, :team, :messages, :contact_inbox
|
||||
)
|
||||
|
||||
account_user = @account.account_users.find_by(user_id: @user.id)
|
||||
is_administrator = account_user&.role == 'administrator'
|
||||
|
||||
# Ensure we only include conversations from inboxes the user has access to
|
||||
unless is_administrator
|
||||
inbox_ids = @user.inboxes.where(account_id: @account.id).pluck(:id)
|
||||
conversations = conversations.where(inbox_id: inbox_ids)
|
||||
end
|
||||
|
||||
# Apply permission-based filtering
|
||||
Conversations::PermissionFilterService.new(
|
||||
conversations,
|
||||
@user,
|
||||
@account
|
||||
).perform
|
||||
end
|
||||
|
||||
def current_page
|
||||
|
||||
17
app/services/conversations/permission_filter_service.rb
Normal file
17
app/services/conversations/permission_filter_service.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
class Conversations::PermissionFilterService
|
||||
attr_reader :conversations, :user, :account
|
||||
|
||||
def initialize(conversations, user, account)
|
||||
@conversations = conversations
|
||||
@user = user
|
||||
@account = account
|
||||
end
|
||||
|
||||
def perform
|
||||
# The base implementation simply returns all conversations
|
||||
# Enterprise edition extends this with permission-based filtering
|
||||
conversations
|
||||
end
|
||||
end
|
||||
|
||||
Conversations::PermissionFilterService.prepend_mod_with('Conversations::PermissionFilterService')
|
||||
Reference in New Issue
Block a user