From 0c24df96a8444b7e85b0a8395deb9c34371767aa Mon Sep 17 00:00:00 2001 From: Muhsin Keloth Date: Wed, 22 Sep 2021 10:46:48 +0530 Subject: [PATCH] chore: Conversation custom attribute APIs (#3024) --- Gemfile | 6 +++- .../v1/accounts/conversations_controller.rb | 7 ++++ app/models/conversation.rb | 1 + .../custom_attributes.json.jbuilder | 1 + .../partials/_conversation.json.jbuilder | 1 + config/routes.rb | 1 + ..._add_custom_attributes_to_conversations.rb | 5 +++ db/schema.rb | 3 +- .../accounts/conversations_controller_spec.rb | 33 +++++++++++++++++++ 9 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 app/views/api/v1/accounts/conversations/custom_attributes.json.jbuilder create mode 100644 db/migrate/20210916060144_add_custom_attributes_to_conversations.rb diff --git a/Gemfile b/Gemfile index 1dddb482c..91a7f4888 100644 --- a/Gemfile +++ b/Gemfile @@ -56,7 +56,6 @@ gem 'activerecord-import' gem 'dotenv-rails' gem 'foreman' gem 'puma' -gem 'rack-timeout' gem 'webpacker', '~> 5.x' # metrics on heroku gem 'barnes' @@ -122,6 +121,11 @@ gem 'hairtrigger' gem 'procore-sift' +group :production, :staging do + # we dont want request timing out in development while using byebug + gem 'rack-timeout' +end + group :development do gem 'annotate' gem 'bullet' diff --git a/app/controllers/api/v1/accounts/conversations_controller.rb b/app/controllers/api/v1/accounts/conversations_controller.rb index d360723a6..59dc051a7 100644 --- a/app/controllers/api/v1/accounts/conversations_controller.rb +++ b/app/controllers/api/v1/accounts/conversations_controller.rb @@ -72,6 +72,11 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro @conversation.save! end + def custom_attributes + @conversation.custom_attributes = params.permit(custom_attributes: {})[:custom_attributes] + @conversation.save! + end + private def set_conversation_status @@ -112,6 +117,7 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro def conversation_params additional_attributes = params[:additional_attributes]&.permit! || {} + custom_attributes = params[:custom_attributes]&.permit! || {} status = params[:status].present? ? { status: params[:status] } : {} # TODO: temporary fallback for the old bot status in conversation, we will remove after couple of releases @@ -122,6 +128,7 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro contact_id: @contact_inbox.contact_id, contact_inbox_id: @contact_inbox.id, additional_attributes: additional_attributes, + custom_attributes: custom_attributes, snoozed_until: params[:snoozed_until] }.merge(status) end diff --git a/app/models/conversation.rb b/app/models/conversation.rb index f5d4f9680..71f6d0a36 100644 --- a/app/models/conversation.rb +++ b/app/models/conversation.rb @@ -6,6 +6,7 @@ # additional_attributes :jsonb # agent_last_seen_at :datetime # contact_last_seen_at :datetime +# custom_attributes :jsonb # identifier :string # last_activity_at :datetime not null # snoozed_until :datetime diff --git a/app/views/api/v1/accounts/conversations/custom_attributes.json.jbuilder b/app/views/api/v1/accounts/conversations/custom_attributes.json.jbuilder new file mode 100644 index 000000000..1ca512802 --- /dev/null +++ b/app/views/api/v1/accounts/conversations/custom_attributes.json.jbuilder @@ -0,0 +1 @@ +json.custom_attributes @conversation.custom_attributes diff --git a/app/views/api/v1/conversations/partials/_conversation.json.jbuilder b/app/views/api/v1/conversations/partials/_conversation.json.jbuilder index 12879b3d5..1e35e8217 100644 --- a/app/views/api/v1/conversations/partials/_conversation.json.jbuilder +++ b/app/views/api/v1/conversations/partials/_conversation.json.jbuilder @@ -33,5 +33,6 @@ json.contact_last_seen_at conversation.contact_last_seen_at.to_i json.agent_last_seen_at conversation.agent_last_seen_at.to_i json.unread_count conversation.unread_incoming_messages.count json.additional_attributes conversation.additional_attributes +json.custom_attributes conversation.custom_attributes json.account_id conversation.account_id json.labels conversation.label_list diff --git a/config/routes.rb b/config/routes.rb index d7b8cb276..a3239d962 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -72,6 +72,7 @@ Rails.application.routes.draw do post :toggle_status post :toggle_typing_status post :update_last_seen + post :custom_attributes end end diff --git a/db/migrate/20210916060144_add_custom_attributes_to_conversations.rb b/db/migrate/20210916060144_add_custom_attributes_to_conversations.rb new file mode 100644 index 000000000..ef5f8cac1 --- /dev/null +++ b/db/migrate/20210916060144_add_custom_attributes_to_conversations.rb @@ -0,0 +1,5 @@ +class AddCustomAttributesToConversations < ActiveRecord::Migration[6.1] + def change + add_column :conversations, :custom_attributes, :jsonb, default: {} + end +end diff --git a/db/schema.rb b/db/schema.rb index 88af58036..dcb1fe612 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_08_29_124254) do +ActiveRecord::Schema.define(version: 2021_09_16_060144) do # These are extensions that must be enabled in order to support this database enable_extension "pg_stat_statements" @@ -295,6 +295,7 @@ ActiveRecord::Schema.define(version: 2021_08_29_124254) do t.bigint "team_id" t.bigint "campaign_id" t.datetime "snoozed_until" + t.jsonb "custom_attributes", default: {} t.index ["account_id", "display_id"], name: "index_conversations_on_account_id_and_display_id", unique: true t.index ["account_id"], name: "index_conversations_on_account_id" t.index ["assignee_id", "account_id"], name: "index_conversations_on_assignee_id_and_account_id" diff --git a/spec/controllers/api/v1/accounts/conversations_controller_spec.rb b/spec/controllers/api/v1/accounts/conversations_controller_spec.rb index 7b66656c2..ec53ec853 100644 --- a/spec/controllers/api/v1/accounts/conversations_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/conversations_controller_spec.rb @@ -496,4 +496,37 @@ RSpec.describe 'Conversations API', type: :request do end end end + + describe 'POST /api/v1/accounts/{account.id}/conversations/:id/custom_attributes' do + let(:conversation) { create(:conversation, account: account) } + + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + post "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/custom_attributes" + + 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(:custom_attributes) { { user_id: 1001, created_date: '23/12/2012', subscription_id: 12 } } + let(:valid_params) { { custom_attributes: custom_attributes } } + + before do + create(:inbox_member, user: agent, inbox: conversation.inbox) + end + + it 'updates last seen' do + post "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/custom_attributes", + headers: agent.create_new_auth_token, + params: valid_params, + as: :json + + expect(response).to have_http_status(:success) + expect(conversation.reload.custom_attributes).not_to eq nil + expect(conversation.reload.custom_attributes.count).to eq 3 + end + end + end end