mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-31 19:17:48 +00:00 
			
		
		
		
	chore: Add Additional Contact APIs (#1130)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
This commit is contained in:
		| @@ -31,7 +31,7 @@ class Messages::MessageBuilder | ||||
|   private | ||||
|  | ||||
|   def message_type | ||||
|     if @conversation.inbox.channel.class != Channel::Api && @message_type == 'incoming' | ||||
|     if @conversation.inbox.channel_type != 'Channel::Api' && @message_type == 'incoming' | ||||
|       raise StandardError, 'Incoming messages are only allowed in Api inboxes' | ||||
|     end | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,26 @@ | ||||
| class Api::V1::Accounts::Contacts::ContactInboxesController < Api::V1::Accounts::BaseController | ||||
|   before_action :ensure_contact | ||||
|   before_action :ensure_inbox, only: [:create] | ||||
|   before_action :validate_channel_type | ||||
|  | ||||
|   def create | ||||
|     source_id = params[:source_id] || SecureRandom.uuid | ||||
|     @contact_inbox = ContactInbox.create(contact: @contact, inbox: @inbox, source_id: source_id) | ||||
|   end | ||||
|  | ||||
|   private | ||||
|  | ||||
|   def validate_channel_type | ||||
|     return if @inbox.channel_type == 'Channel::Api' | ||||
|  | ||||
|     render json: { error: 'Contact Inbox creation is only allowed in API inboxes' }, status: :unprocessable_entity | ||||
|   end | ||||
|  | ||||
|   def ensure_inbox | ||||
|     @inbox = Current.account.inboxes.find(params[:inbox_id]) | ||||
|   end | ||||
|  | ||||
|   def ensure_contact | ||||
|     @contact = Current.account.contacts.find(params[:contact_id]) | ||||
|   end | ||||
| end | ||||
| @@ -22,6 +22,12 @@ class Api::V1::Accounts::ContactsController < Api::V1::Accounts::BaseController | ||||
|     @contact.update!(contact_params) | ||||
|   end | ||||
|  | ||||
|   def search | ||||
|     render json: { error: 'Specify search string with parameter q' }, status: :unprocessable_entity if params[:q].blank? && return | ||||
|  | ||||
|     @contacts = Current.account.contacts.where('name LIKE :search OR email LIKE :search', search: "%#{params[:q]}%") | ||||
|   end | ||||
|  | ||||
|   private | ||||
|  | ||||
|   def check_authorization | ||||
| @@ -31,7 +37,7 @@ class Api::V1::Accounts::ContactsController < Api::V1::Accounts::BaseController | ||||
|   def build_contact_inbox | ||||
|     return if params[:inbox_id].blank? | ||||
|  | ||||
|     inbox = Inbox.find(params[:inbox_id]) | ||||
|     inbox = Current.account.inboxes.find(params[:inbox_id]) | ||||
|     source_id = params[:source_id] || SecureRandom.uuid | ||||
|     ContactInbox.create(contact: @contact, inbox: inbox, source_id: source_id) | ||||
|   end | ||||
|   | ||||
| @@ -3,6 +3,10 @@ class ContactPolicy < ApplicationPolicy | ||||
|     true | ||||
|   end | ||||
|  | ||||
|   def search? | ||||
|     true | ||||
|   end | ||||
|  | ||||
|   def update? | ||||
|     true | ||||
|   end | ||||
|   | ||||
| @@ -0,0 +1 @@ | ||||
| json.partial! 'api/v1/models/contact_inbox.json.jbuilder', resource: @contact_inbox | ||||
							
								
								
									
										5
									
								
								app/views/api/v1/accounts/contacts/search.json.jbuilder
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/views/api/v1/accounts/contacts/search.json.jbuilder
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| json.payload do | ||||
|   json.array! @contacts do |contact| | ||||
|     json.partial! 'api/v1/models/contact.json.jbuilder', resource: contact | ||||
|   end | ||||
| end | ||||
| @@ -5,3 +5,8 @@ json.id resource.id | ||||
| json.name resource.name | ||||
| json.phone_number resource.phone_number | ||||
| json.thumbnail resource.avatar_url | ||||
| json.contact_inboxes do | ||||
|   json.array! resource.contact_inboxes do |contact_inbox| | ||||
|     json.partial! 'api/v1/models/contact_inbox.json.jbuilder', resource: contact_inbox | ||||
|   end | ||||
| end | ||||
|   | ||||
							
								
								
									
										2
									
								
								app/views/api/v1/models/_contact_inbox.json.jbuilder
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								app/views/api/v1/models/_contact_inbox.json.jbuilder
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| json.source_id resource.source_id | ||||
| json.inbox resource.inbox | ||||
| @@ -61,8 +61,12 @@ Rails.application.routes.draw do | ||||
|           end | ||||
|  | ||||
|           resources :contacts, only: [:index, :show, :update, :create] do | ||||
|             collection do | ||||
|               get :search | ||||
|             end | ||||
|             scope module: :contacts do | ||||
|               resources :conversations, only: [:index] | ||||
|               resources :contact_inboxes, only: [:create] | ||||
|             end | ||||
|           end | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,43 @@ | ||||
| require 'rails_helper' | ||||
|  | ||||
| RSpec.describe '/api/v1/accounts/{account.id}/contacts/:id/contact_inboxes', type: :request do | ||||
|   let(:account) { create(:account) } | ||||
|   let(:contact) { create(:contact, account: account) } | ||||
|   let(:inbox_1) { create(:inbox, account: account) } | ||||
|   let(:channel_api) { create(:channel_api, account: account) } | ||||
|   let(:user) { create(:user, account: account) } | ||||
|  | ||||
|   describe 'GET /api/v1/accounts/{account.id}/contacts/:id/contact_inboxes' do | ||||
|     context 'when unauthenticated user' do | ||||
|       it 'returns unauthorized' do | ||||
|         post "/api/v1/accounts/#{account.id}/contacts/#{contact.id}/contact_inboxes" | ||||
|         expect(response).to have_http_status(:unauthorized) | ||||
|       end | ||||
|     end | ||||
|  | ||||
|     context 'when user is logged in' do | ||||
|       it 'creates a contact inbox' do | ||||
|         expect do | ||||
|           post "/api/v1/accounts/#{account.id}/contacts/#{contact.id}/contact_inboxes", | ||||
|                params: { inbox_id: channel_api.inbox.id }, | ||||
|                headers: user.create_new_auth_token, | ||||
|                as: :json | ||||
|         end.to change(ContactInbox, :count).by(1) | ||||
|  | ||||
|         expect(response).to have_http_status(:success) | ||||
|         expect(contact.reload.contact_inboxes.map(&:inbox_id)).to include(channel_api.inbox.id) | ||||
|       end | ||||
|  | ||||
|       it 'throws error when its not an api inbox' do | ||||
|         expect do | ||||
|           post "/api/v1/accounts/#{account.id}/contacts/#{contact.id}/contact_inboxes", | ||||
|                params: { inbox_id: inbox_1.id }, | ||||
|                headers: user.create_new_auth_token, | ||||
|                as: :json | ||||
|         end.to change(ContactInbox, :count).by(0) | ||||
|  | ||||
|         expect(response).to have_http_status(:unprocessable_entity) | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| end | ||||
| @@ -15,14 +15,44 @@ RSpec.describe 'Contacts API', type: :request do | ||||
|     context 'when it is an authenticated user' do | ||||
|       let(:admin) { create(:user, account: account, role: :administrator) } | ||||
|       let!(:contact) { create(:contact, account: account) } | ||||
|       let!(:contact_inbox) { create(:contact_inbox, contact: contact) } | ||||
|  | ||||
|       it 'returns all contacts' do | ||||
|       it 'returns all contacts with contact inboxes' do | ||||
|         get "/api/v1/accounts/#{account.id}/contacts", | ||||
|             headers: admin.create_new_auth_token, | ||||
|             as: :json | ||||
|  | ||||
|         expect(response).to have_http_status(:success) | ||||
|         expect(response.body).to include(contact.email) | ||||
|         expect(response.body).to include(contact_inbox.source_id) | ||||
|         expect(response.body).to include(contact_inbox.inbox.name) | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   describe 'GET /api/v1/accounts/{account.id}/contacts/search' do | ||||
|     context 'when it is an unauthenticated user' do | ||||
|       it 'returns unauthorized' do | ||||
|         get "/api/v1/accounts/#{account.id}/contacts/search" | ||||
|  | ||||
|         expect(response).to have_http_status(:unauthorized) | ||||
|       end | ||||
|     end | ||||
|  | ||||
|     context 'when it is an authenticated user' do | ||||
|       let(:admin) { create(:user, account: account, role: :administrator) } | ||||
|       let!(:contact1) { create(:contact, account: account) } | ||||
|       let!(:contact2) { create(:contact, account: account, email: 'test@test.com') } | ||||
|  | ||||
|       it 'returns all contacts with contact inboxes' do | ||||
|         get "/api/v1/accounts/#{account.id}/contacts/search", | ||||
|             params: { q: contact2.email }, | ||||
|             headers: admin.create_new_auth_token, | ||||
|             as: :json | ||||
|  | ||||
|         expect(response).to have_http_status(:success) | ||||
|         expect(response.body).to include(contact2.email) | ||||
|         expect(response.body).not_to include(contact1.email) | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Sojan Jose
					Sojan Jose