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:
Sojan Jose
2025-03-31 19:30:02 -07:00
committed by GitHub
parent f20a18b03f
commit ca83a27e95
12 changed files with 759 additions and 260 deletions

View File

@@ -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

View 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')