From 2c3160cfee7cdeff1106691a1a3dcdc8ed13c689 Mon Sep 17 00:00:00 2001 From: Muhsin Keloth Date: Fri, 12 May 2023 15:48:06 +0530 Subject: [PATCH] feat: API to list all attachments for a conversation (#7059) Fixes: https://linear.app/chatwoot/issue/CW-1678/api-to-list-all-attachments-for-a-conversation --- .../v1/accounts/conversations_controller.rb | 4 ++ app/models/conversation.rb | 1 + .../conversations/attachments.json.jbuilder | 1 + config/routes.rb | 1 + .../accounts/conversations_controller_spec.rb | 49 +++++++++++++++++++ spec/factories/messages.rb | 7 +++ 6 files changed, 63 insertions(+) create mode 100644 app/views/api/v1/accounts/conversations/attachments.json.jbuilder diff --git a/app/controllers/api/v1/accounts/conversations_controller.rb b/app/controllers/api/v1/accounts/conversations_controller.rb index 6e580a497..ebd673d6f 100644 --- a/app/controllers/api/v1/accounts/conversations_controller.rb +++ b/app/controllers/api/v1/accounts/conversations_controller.rb @@ -22,6 +22,10 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro @conversations_count = result[:count] end + def attachments + @attachments = @conversation.attachments + end + def create ActiveRecord::Base.transaction do @conversation = ConversationBuilder.new(params: params, contact_inbox: @contact_inbox).perform diff --git a/app/models/conversation.rb b/app/models/conversation.rb index e01fb3863..becb0a639 100644 --- a/app/models/conversation.rb +++ b/app/models/conversation.rb @@ -95,6 +95,7 @@ class Conversation < ApplicationRecord has_one :csat_survey_response, dependent: :destroy_async has_many :conversation_participants, dependent: :destroy_async has_many :notifications, as: :primary_actor, dependent: :destroy_async + has_many :attachments, through: :messages before_save :ensure_snooze_until_reset before_create :mark_conversation_pending_if_bot diff --git a/app/views/api/v1/accounts/conversations/attachments.json.jbuilder b/app/views/api/v1/accounts/conversations/attachments.json.jbuilder new file mode 100644 index 000000000..e31980ea2 --- /dev/null +++ b/app/views/api/v1/accounts/conversations/attachments.json.jbuilder @@ -0,0 +1 @@ +json.payload @attachments.map(&:push_event_data) diff --git a/config/routes.rb b/config/routes.rb index bdad7c1bf..650f8a64c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -97,6 +97,7 @@ Rails.application.routes.draw do post :update_last_seen post :unread post :custom_attributes + get :attachments end end diff --git a/spec/controllers/api/v1/accounts/conversations_controller_spec.rb b/spec/controllers/api/v1/accounts/conversations_controller_spec.rb index 9689bdd4d..bf73cd0ce 100644 --- a/spec/controllers/api/v1/accounts/conversations_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/conversations_controller_spec.rb @@ -731,4 +731,53 @@ RSpec.describe 'Conversations API', type: :request do end end end + + describe 'GET /api/v1/accounts/{account.id}/conversations/:id/attachments' do + let(:conversation) { create(:conversation, account: account) } + + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/attachments" + + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + let(:agent) { create(:user, account: account, role: :agent) } + let(:administrator) { create(:user, account: account, role: :administrator) } + + before do + create(:message, :with_attachment, conversation: conversation, account: account, inbox: conversation.inbox, message_type: 'incoming') + end + + it 'does not return the attachments if you do not have access to it' do + get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/attachments", + headers: agent.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:unauthorized) + end + + it 'return the attachments if you are an administrator' do + get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/attachments", + headers: administrator.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + response_body = JSON.parse(response.body) + expect(response_body['payload'].first['file_type']).to eq('image') + end + + it 'return the attachments if you are an agent with access to inbox' do + get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/attachments", + headers: administrator.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + response_body = JSON.parse(response.body) + expect(response_body['payload'].length).to eq(1) + end + end + end end diff --git a/spec/factories/messages.rb b/spec/factories/messages.rb index e14a8000d..3e51f2b35 100644 --- a/spec/factories/messages.rb +++ b/spec/factories/messages.rb @@ -20,6 +20,13 @@ FactoryBot.define do end end + trait :with_attachment do + after(:build) do |message| + attachment = message.attachments.new(account_id: message.account_id, file_type: :image) + attachment.file.attach(io: File.open(Rails.root.join('spec/assets/avatar.png')), filename: 'avatar.png', content_type: 'image/png') + end + end + after(:build) do |message| message.sender ||= message.outgoing? ? create(:user, account: message.account) : create(:contact, account: message.account) message.inbox ||= message.conversation&.inbox || create(:inbox, account: message.account)