diff --git a/app/controllers/api/v1/accounts/agent_bots_controller.rb b/app/controllers/api/v1/accounts/agent_bots_controller.rb new file mode 100644 index 000000000..7348ef255 --- /dev/null +++ b/app/controllers/api/v1/accounts/agent_bots_controller.rb @@ -0,0 +1,35 @@ +class Api::V1::Accounts::AgentBotsController < Api::V1::Accounts::BaseController + before_action :current_account + before_action :check_authorization + before_action :agent_bot, except: [:index, :create] + + def index + @agent_bots = AgentBot.where(account_id: [nil, Current.account.id]) + end + + def show; end + + def create + @agent_bot = Current.account.agent_bots.create!(permitted_params) + end + + def update + @agent_bot.update!(permitted_params) + end + + def destroy + @agent_bot.destroy + head :ok + end + + private + + def agent_bot + @agent_bot = AgentBot.where(account_id: [nil, Current.account.id]).find(params[:id]) if params[:action] == 'show' + @agent_bot ||= Current.account.agent_bots.find(params[:id]) + end + + def permitted_params + params.permit(:name, :description, :outgoing_url) + end +end diff --git a/app/controllers/api/v1/accounts/inboxes_controller.rb b/app/controllers/api/v1/accounts/inboxes_controller.rb index 014e213d4..8a5f5b9b9 100644 --- a/app/controllers/api/v1/accounts/inboxes_controller.rb +++ b/app/controllers/api/v1/accounts/inboxes_controller.rb @@ -38,6 +38,10 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController update_channel_feature_flags end + def agent_bot + @agent_bot = @inbox.agent_bot + end + def set_agent_bot if @agent_bot agent_bot_inbox = @inbox.agent_bot_inbox || AgentBotInbox.new(inbox: @inbox) diff --git a/app/controllers/api/v1/agent_bots_controller.rb b/app/controllers/api/v1/agent_bots_controller.rb deleted file mode 100644 index a82f71bb9..000000000 --- a/app/controllers/api/v1/agent_bots_controller.rb +++ /dev/null @@ -1,7 +0,0 @@ -class Api::V1::AgentBotsController < Api::BaseController - skip_before_action :authenticate_user! - - def index - render json: AgentBot.all - end -end diff --git a/app/controllers/platform/api/v1/agent_bots_controller.rb b/app/controllers/platform/api/v1/agent_bots_controller.rb new file mode 100644 index 000000000..0c79e118d --- /dev/null +++ b/app/controllers/platform/api/v1/agent_bots_controller.rb @@ -0,0 +1,35 @@ +class Platform::Api::V1::AgentBotsController < PlatformController + before_action :set_resource, except: [:index, :create] + before_action :validate_platform_app_permissible, except: [:index, :create] + + def index + @resources = @platform_app.platform_app_permissibles.where(permissible_type: 'AgentBot').all + end + + def create + @resource = AgentBot.new(agent_bot_params) + @resource.save! + @platform_app.platform_app_permissibles.find_or_create_by(permissible: @resource) + end + + def show; end + + def update + @resource.update!(agent_bot_params) + end + + def destroy + @resource.destroy! + head :ok + end + + private + + def set_resource + @resource = AgentBot.find(params[:id]) + end + + def agent_bot_params + params.permit(:name, :description, :account_id, :outgoing_url) + end +end diff --git a/app/dashboards/agent_bot_dashboard.rb b/app/dashboards/agent_bot_dashboard.rb index ca6ca7ad1..87605135d 100644 --- a/app/dashboards/agent_bot_dashboard.rb +++ b/app/dashboards/agent_bot_dashboard.rb @@ -15,8 +15,7 @@ class AgentBotDashboard < Administrate::BaseDashboard description: Field::String, outgoing_url: Field::String, created_at: Field::DateTime, - updated_at: Field::DateTime, - hide_input_for_bot_conversations: Field::Boolean + updated_at: Field::DateTime }.freeze # COLLECTION_ATTRIBUTES @@ -39,7 +38,6 @@ class AgentBotDashboard < Administrate::BaseDashboard name description outgoing_url - hide_input_for_bot_conversations ].freeze # FORM_ATTRIBUTES @@ -49,7 +47,6 @@ class AgentBotDashboard < Administrate::BaseDashboard name description outgoing_url - hide_input_for_bot_conversations ].freeze # COLLECTION_FILTERS diff --git a/app/javascript/widget/mixins/configMixin.js b/app/javascript/widget/mixins/configMixin.js index df26add3b..c70d9ca57 100644 --- a/app/javascript/widget/mixins/configMixin.js +++ b/app/javascript/widget/mixins/configMixin.js @@ -1,8 +1,5 @@ export default { computed: { - hideInputForBotConversations() { - return window.chatwootWebChannel.hideInputForBotConversations; - }, useInboxAvatarForBot() { return window.chatwootWidgetDefaults.useInboxAvatarForBot; }, diff --git a/app/javascript/widget/mixins/specs/configMixin.spec.js b/app/javascript/widget/mixins/specs/configMixin.spec.js index 014a7930a..663cf695d 100644 --- a/app/javascript/widget/mixins/specs/configMixin.spec.js +++ b/app/javascript/widget/mixins/specs/configMixin.spec.js @@ -3,7 +3,6 @@ import configMixin from '../configMixin'; import Vue from 'vue'; global.chatwootWebChannel = { - hideInputForBotConversations: true, avatarUrl: 'https://test.url', hasAConnectedAgentBot: 'AgentBot', enabledFeatures: ['emoji_picker', 'attachments'], @@ -25,12 +24,10 @@ describe('configMixin', () => { const wrapper = createWrapper(vm); expect(wrapper.vm.hasEmojiPickerEnabled).toBe(true); expect(wrapper.vm.hasAttachmentsEnabled).toBe(true); - expect(wrapper.vm.hideInputForBotConversations).toBe(true); expect(wrapper.vm.hasAConnectedAgentBot).toBe(true); expect(wrapper.vm.useInboxAvatarForBot).toBe(true); expect(wrapper.vm.inboxAvatarUrl).toBe('https://test.url'); expect(wrapper.vm.channelConfig).toEqual({ - hideInputForBotConversations: true, avatarUrl: 'https://test.url', hasAConnectedAgentBot: 'AgentBot', enabledFeatures: ['emoji_picker', 'attachments'], diff --git a/app/javascript/widget/views/Home.vue b/app/javascript/widget/views/Home.vue index 3d77f33b5..a86c29a28 100755 --- a/app/javascript/widget/views/Home.vue +++ b/app/javascript/widget/views/Home.vue @@ -62,10 +62,7 @@ leave-class="opacity-100 transform translate-y-0" leave-to-class="opacity-0 transform " > -
+
accounts.id) # class AgentBot < ApplicationRecord @@ -18,6 +26,7 @@ class AgentBot < ApplicationRecord has_many :agent_bot_inboxes, dependent: :destroy has_many :inboxes, through: :agent_bot_inboxes has_many :messages, as: :sender, dependent: :restrict_with_exception + belongs_to :account, dependent: :destroy, optional: true def available_name name diff --git a/app/policies/agent_bot_policy.rb b/app/policies/agent_bot_policy.rb new file mode 100644 index 000000000..4d5e363ea --- /dev/null +++ b/app/policies/agent_bot_policy.rb @@ -0,0 +1,21 @@ +class AgentBotPolicy < ApplicationPolicy + def index? + @account_user.administrator? || @account_user.agent? + end + + def update? + @account_user.administrator? + end + + def show? + @account_user.administrator? || @account_user.agent? + end + + def create? + @account_user.administrator? + end + + def destroy? + @account_user.administrator? + end +end diff --git a/app/policies/inbox_policy.rb b/app/policies/inbox_policy.rb index 927ff9435..0bfe6fe40 100644 --- a/app/policies/inbox_policy.rb +++ b/app/policies/inbox_policy.rb @@ -27,6 +27,10 @@ class InboxPolicy < ApplicationPolicy true end + def agent_bot? + true + end + def campaigns? @account_user.administrator? end diff --git a/app/views/api/v1/accounts/agent_bots/create.json.jbuilder b/app/views/api/v1/accounts/agent_bots/create.json.jbuilder new file mode 100644 index 000000000..453ef5cb4 --- /dev/null +++ b/app/views/api/v1/accounts/agent_bots/create.json.jbuilder @@ -0,0 +1 @@ +json.partial! 'api/v1/models/agent_bot.json.jbuilder', resource: @agent_bot diff --git a/app/views/api/v1/accounts/agent_bots/index.json.jbuilder b/app/views/api/v1/accounts/agent_bots/index.json.jbuilder new file mode 100644 index 000000000..d65188ff2 --- /dev/null +++ b/app/views/api/v1/accounts/agent_bots/index.json.jbuilder @@ -0,0 +1,3 @@ +json.array! @agent_bots do |agent_bot| + json.partial! 'api/v1/models/agent_bot.json.jbuilder', resource: agent_bot +end diff --git a/app/views/api/v1/accounts/agent_bots/show.json.jbuilder b/app/views/api/v1/accounts/agent_bots/show.json.jbuilder new file mode 100644 index 000000000..453ef5cb4 --- /dev/null +++ b/app/views/api/v1/accounts/agent_bots/show.json.jbuilder @@ -0,0 +1 @@ +json.partial! 'api/v1/models/agent_bot.json.jbuilder', resource: @agent_bot diff --git a/app/views/api/v1/accounts/agent_bots/update.json.jbuilder b/app/views/api/v1/accounts/agent_bots/update.json.jbuilder new file mode 100644 index 000000000..453ef5cb4 --- /dev/null +++ b/app/views/api/v1/accounts/agent_bots/update.json.jbuilder @@ -0,0 +1 @@ +json.partial! 'api/v1/models/agent_bot.json.jbuilder', resource: @agent_bot diff --git a/app/views/api/v1/accounts/inboxes/agent_bot.json.jbuilder b/app/views/api/v1/accounts/inboxes/agent_bot.json.jbuilder new file mode 100644 index 000000000..73b364f04 --- /dev/null +++ b/app/views/api/v1/accounts/inboxes/agent_bot.json.jbuilder @@ -0,0 +1,3 @@ +json.agent_bot do + json.partial! 'api/v1/models/agent_bot.json.jbuilder', resource: @agent_bot if @agent_bot.present? +end diff --git a/app/views/api/v1/models/_agent_bot.json.jbuilder b/app/views/api/v1/models/_agent_bot.json.jbuilder new file mode 100644 index 000000000..1aa152186 --- /dev/null +++ b/app/views/api/v1/models/_agent_bot.json.jbuilder @@ -0,0 +1,5 @@ +json.id resource.id +json.name resource.name +json.description resource.description +json.outgoing_url resource.name +json.account_id resource.account_id diff --git a/app/views/platform/api/v1/agent_bots/create.json.jbuilder b/app/views/platform/api/v1/agent_bots/create.json.jbuilder new file mode 100644 index 000000000..32123ab29 --- /dev/null +++ b/app/views/platform/api/v1/agent_bots/create.json.jbuilder @@ -0,0 +1 @@ +json.partial! 'platform/api/v1/models/agent_bot.json.jbuilder', resource: @resource diff --git a/app/views/platform/api/v1/agent_bots/index.json.jbuilder b/app/views/platform/api/v1/agent_bots/index.json.jbuilder new file mode 100644 index 000000000..9dd6dcce6 --- /dev/null +++ b/app/views/platform/api/v1/agent_bots/index.json.jbuilder @@ -0,0 +1,3 @@ +json.array! @resources do |resource| + json.partial! 'platform/api/v1/models/agent_bot.json.jbuilder', resource: resource.permissible +end diff --git a/app/views/platform/api/v1/agent_bots/show.json.jbuilder b/app/views/platform/api/v1/agent_bots/show.json.jbuilder new file mode 100644 index 000000000..32123ab29 --- /dev/null +++ b/app/views/platform/api/v1/agent_bots/show.json.jbuilder @@ -0,0 +1 @@ +json.partial! 'platform/api/v1/models/agent_bot.json.jbuilder', resource: @resource diff --git a/app/views/platform/api/v1/agent_bots/update.json.jbuilder b/app/views/platform/api/v1/agent_bots/update.json.jbuilder new file mode 100644 index 000000000..32123ab29 --- /dev/null +++ b/app/views/platform/api/v1/agent_bots/update.json.jbuilder @@ -0,0 +1 @@ +json.partial! 'platform/api/v1/models/agent_bot.json.jbuilder', resource: @resource diff --git a/app/views/platform/api/v1/models/_agent_bot.json.jbuilder b/app/views/platform/api/v1/models/_agent_bot.json.jbuilder new file mode 100644 index 000000000..1aa152186 --- /dev/null +++ b/app/views/platform/api/v1/models/_agent_bot.json.jbuilder @@ -0,0 +1,5 @@ +json.id resource.id +json.name resource.name +json.description resource.description +json.outgoing_url resource.name +json.account_id resource.account_id diff --git a/app/views/widgets/show.html.erb b/app/views/widgets/show.html.erb index 85297111a..c63dd08eb 100644 --- a/app/views/widgets/show.html.erb +++ b/app/views/widgets/show.html.erb @@ -8,9 +8,6 @@ window.chatwootWebChannel = { avatarUrl: '<%= @web_widget.inbox.avatar_url %>', hasAConnectedAgentBot: '<%= @web_widget.inbox.agent_bot&.name %>', - <% if @web_widget.inbox.agent_bot %> - hideInputForBotConversations: <%= @web_widget.inbox.agent_bot.hide_input_for_bot_conversations %>, - <% end %> locale: '<%= @web_widget.account.locale %>', websiteName: '<%= @web_widget.inbox.name %>', websiteToken: '<%= @web_widget.website_token %>', diff --git a/config/routes.rb b/config/routes.rb index bbfe3599b..499588e42 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -38,6 +38,8 @@ Rails.application.routes.draw do end resources :agents, except: [:show, :edit, :new] + resources :agent_bots, only: [:index, :create, :show, :update, :destroy] + resources :callbacks, only: [] do collection do post :register_facebook_page @@ -97,6 +99,7 @@ Rails.application.routes.draw do resources :inboxes, only: [:index, :create, :update, :destroy] do get :assignable_agents, on: :member get :campaigns, on: :member + get :agent_bot, on: :member post :set_agent_bot, on: :member end resources :inbox_members, only: [:create, :show], param: :inbox_id @@ -151,8 +154,6 @@ Rails.application.routes.draw do resource :profile, only: [:show, :update] resource :notification_subscriptions, only: [:create] - resources :agent_bots, only: [:index] - namespace :widget do resources :campaigns, only: [:index] resources :events, only: [:create] @@ -194,6 +195,7 @@ Rails.application.routes.draw do get :login end end + resources :agent_bots, only: [:index, :create, :show, :update, :destroy] resources :accounts, only: [:create, :show, :update, :destroy] do resources :account_users, only: [:index, :create] do collection do diff --git a/db/migrate/20210520200729_add_account_id_to_agent_bots.rb b/db/migrate/20210520200729_add_account_id_to_agent_bots.rb new file mode 100644 index 000000000..cd4a26073 --- /dev/null +++ b/db/migrate/20210520200729_add_account_id_to_agent_bots.rb @@ -0,0 +1,6 @@ +class AddAccountIdToAgentBots < ActiveRecord::Migration[6.0] + def change + remove_column :agent_bots, :hide_input_for_bot_conversations, :boolean + add_reference :agent_bots, :account, foreign_key: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 60f080d5c..5a1fd235b 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_05_13_083044) do +ActiveRecord::Schema.define(version: 2021_05_20_200729) do # These are extensions that must be enabled in order to support this database enable_extension "pg_stat_statements" @@ -97,7 +97,8 @@ ActiveRecord::Schema.define(version: 2021_05_13_083044) do t.string "outgoing_url" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false - t.boolean "hide_input_for_bot_conversations", default: false + t.bigint "account_id" + t.index ["account_id"], name: "index_agent_bots_on_account_id" end create_table "attachments", id: :serial, force: :cascade do |t| @@ -611,6 +612,7 @@ ActiveRecord::Schema.define(version: 2021_05_13_083044) do add_foreign_key "account_users", "accounts" add_foreign_key "account_users", "users" add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" + add_foreign_key "agent_bots", "accounts" add_foreign_key "campaigns", "accounts" add_foreign_key "campaigns", "inboxes" add_foreign_key "contact_inboxes", "contacts" diff --git a/spec/controllers/api/v1/accounts/agent_bots_controller_spec.rb b/spec/controllers/api/v1/accounts/agent_bots_controller_spec.rb new file mode 100644 index 000000000..60442e6d6 --- /dev/null +++ b/spec/controllers/api/v1/accounts/agent_bots_controller_spec.rb @@ -0,0 +1,180 @@ +require 'rails_helper' + +RSpec.describe 'Agent Bot API', type: :request do + let!(:account) { create(:account) } + let!(:agent_bot) { create(:agent_bot, account: account) } + let(:admin) { create(:user, account: account, role: :administrator) } + let(:agent) { create(:user, account: account, role: :agent) } + + describe 'GET /api/v1/accounts/{account.id}/agent_bots' do + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + get "/api/v1/accounts/#{account.id}/agent_bots" + + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + it 'returns all the agent_bots in account along with global agent bots' do + global_bot = create(:agent_bot) + get "/api/v1/accounts/#{account.id}/agent_bots", + headers: agent.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + expect(response.body).to include(agent_bot.name) + expect(response.body).to include(global_bot.name) + end + end + end + + describe 'GET /api/v1/accounts/{account.id}/agent_bots/:id' do + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + get "/api/v1/accounts/#{account.id}/agent_bots/#{agent_bot.id}" + + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + it 'shows the agent bot' do + get "/api/v1/accounts/#{account.id}/agent_bots/#{agent_bot.id}", + headers: agent.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + expect(response.body).to include(agent_bot.name) + end + + it 'will show a global agent bot' do + global_bot = create(:agent_bot) + get "/api/v1/accounts/#{account.id}/agent_bots/#{global_bot.id}", + headers: agent.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + expect(response.body).to include(global_bot.name) + end + end + end + + describe 'POST /api/v1/accounts/{account.id}/agent_bots' do + let(:valid_params) { { name: 'test' } } + + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + expect { post "/api/v1/accounts/#{account.id}/agent_bots", params: valid_params }.to change(Label, :count).by(0) + + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + it 'creates the agent bot when administrator' do + expect do + post "/api/v1/accounts/#{account.id}/agent_bots", headers: admin.create_new_auth_token, + params: valid_params + end.to change(AgentBot, :count).by(1) + + expect(response).to have_http_status(:success) + end + + it 'would not create the agent bot when agent' do + expect do + post "/api/v1/accounts/#{account.id}/agent_bots", headers: agent.create_new_auth_token, + params: valid_params + end.to change(AgentBot, :count).by(0) + + expect(response).to have_http_status(:unauthorized) + end + end + end + + describe 'PATCH /api/v1/accounts/{account.id}/agent_bots/:id' do + let(:valid_params) { { name: 'test_updated' } } + + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + patch "/api/v1/accounts/#{account.id}/agent_bots/#{agent_bot.id}", + params: valid_params + + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + it 'updates the agent bot' do + patch "/api/v1/accounts/#{account.id}/agent_bots/#{agent_bot.id}", + headers: admin.create_new_auth_token, + params: valid_params, + as: :json + + expect(response).to have_http_status(:success) + expect(agent_bot.reload.name).to eq('test_updated') + end + + it 'would not update the agent bot when agent' do + patch "/api/v1/accounts/#{account.id}/agent_bots/#{agent_bot.id}", + headers: agent.create_new_auth_token, + params: valid_params, + as: :json + + expect(response).to have_http_status(:unauthorized) + expect(agent_bot.reload.name).not_to eq('test_updated') + end + + it 'would not update a global agent bot' do + global_bot = create(:agent_bot) + patch "/api/v1/accounts/#{account.id}/agent_bots/#{global_bot.id}", + headers: admin.create_new_auth_token, + params: valid_params, + as: :json + + expect(response).to have_http_status(:not_found) + expect(agent_bot.reload.name).not_to eq('test_updated') + end + end + end + + describe 'DELETE /api/v1/accounts/{account.id}/agent_bots/:id' do + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + delete "/api/v1/accounts/#{account.id}/agent_bots/#{agent_bot.id}" + + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + it 'deletes an agent bot when administrator' do + delete "/api/v1/accounts/#{account.id}/agent_bots/#{agent_bot.id}", + headers: admin.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + expect(account.agent_bots.size).to eq(0) + end + + it 'would not delete the agent bot when agent' do + delete "/api/v1/accounts/#{account.id}/agent_bots/#{agent_bot.id}", + headers: agent.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:unauthorized) + expect(account.agent_bots.size).not_to eq(0) + end + + it 'would not delete a global agent bot' do + global_bot = create(:agent_bot) + delete "/api/v1/accounts/#{account.id}/agent_bots/#{global_bot.id}", + headers: admin.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:not_found) + expect(account.agent_bots.size).not_to eq(0) + end + end + end +end diff --git a/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb b/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb index 5efa8049c..a4143df25 100644 --- a/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb @@ -2,6 +2,8 @@ require 'rails_helper' RSpec.describe 'Inboxes API', type: :request do let(:account) { create(:account) } + let(:agent) { create(:user, account: account, role: :agent) } + let(:admin) { create(:user, account: account, role: :administrator) } describe 'GET /api/v1/accounts/{account.id}/inboxes' do context 'when it is an unauthenticated user' do @@ -15,11 +17,11 @@ RSpec.describe 'Inboxes API', type: :request do context 'when it is an authenticated user' do let(:agent) { create(:user, account: account, role: :agent) } let(:admin) { create(:user, account: account, role: :administrator) } + let(:inbox) { create(:inbox, account: account) } before do create(:inbox, account: account) - second_inbox = create(:inbox, account: account) - create(:inbox_member, user: agent, inbox: second_inbox) + create(:inbox_member, user: agent, inbox: inbox) end it 'returns all inboxes of current_account as administrator' do @@ -54,9 +56,6 @@ RSpec.describe 'Inboxes API', type: :request do end context 'when it is an authenticated user' do - let(:agent) { create(:user, account: account, role: :agent) } - let(:admin) { create(:user, account: account, role: :administrator) } - before do create(:inbox_member, user: agent, inbox: inbox) end @@ -92,7 +91,9 @@ RSpec.describe 'Inboxes API', type: :request do let!(:campaign) { create(:campaign, account: account, inbox: inbox) } it 'returns unauthorized for agents' do - get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/campaigns" + get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/campaigns", + headers: agent.create_new_auth_token, + as: :json expect(response).to have_http_status(:unauthorized) end @@ -263,6 +264,42 @@ RSpec.describe 'Inboxes API', type: :request do end end + describe 'GET /api/v1/accounts/{account.id}/inboxes/{inbox.id}/agent_bot' do + let(:inbox) { create(:inbox, account: account) } + + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/agent_bot" + + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + it 'returns empty when no agent bot is present' do + get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/agent_bot", + headers: agent.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + inbox_data = JSON.parse(response.body, symbolize_names: true) + expect(inbox_data[:agent_bot].blank?).to eq(true) + end + + it 'returns the agent bot attached to the inbox' do + agent_bot = create(:agent_bot) + create(:agent_bot_inbox, agent_bot: agent_bot, inbox: inbox) + get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/agent_bot", + headers: agent.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + inbox_data = JSON.parse(response.body, symbolize_names: true) + expect(inbox_data[:agent_bot][:name]).to eq agent_bot.name + end + end + end + describe 'POST /api/v1/accounts/{account.id}/inboxes/:id/set_agent_bot' do let(:inbox) { create(:inbox, account: account) } let(:agent_bot) { create(:agent_bot) } diff --git a/spec/controllers/api/v1/agent_bots_controller_spec.rb b/spec/controllers/api/v1/agent_bots_controller_spec.rb deleted file mode 100644 index 258fad5c3..000000000 --- a/spec/controllers/api/v1/agent_bots_controller_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -require 'rails_helper' - -RSpec.describe 'Profile API', type: :request do - let!(:agent_bot1) { create(:agent_bot) } - let!(:agent_bot2) { create(:agent_bot) } - - describe 'GET /api/v1/agent_bots' do - it 'returns all the agent bots in the system' do - get '/api/v1/agent_bots', - as: :json - - expect(response).to have_http_status(:success) - expect(response.body).to include(agent_bot1.name) - expect(response.body).to include(agent_bot2.name) - end - end -end diff --git a/spec/controllers/platform/api/v1/agent_bots_controller_spec.rb b/spec/controllers/platform/api/v1/agent_bots_controller_spec.rb new file mode 100644 index 000000000..d56e1dfb9 --- /dev/null +++ b/spec/controllers/platform/api/v1/agent_bots_controller_spec.rb @@ -0,0 +1,172 @@ +require 'rails_helper' + +RSpec.describe 'Platform Agent Bot API', type: :request do + let!(:agent_bot) { create(:agent_bot) } + + describe 'GET /platform/api/v1/agent_bots' do + context 'when it is an unauthenticated platform app' do + it 'returns unauthorized' do + get '/platform/api/v1/agent_bots' + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an invalid platform app token' do + it 'returns unauthorized' do + get '/platform/api/v1/agent_bots', headers: { api_access_token: 'invalid' }, as: :json + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated platform app' do + let(:platform_app) { create(:platform_app) } + + it 'returns unauthorized when its not a permissible object' do + get '/platform/api/v1/agent_bots', headers: { api_access_token: platform_app.access_token.token }, as: :json + expect(response).to have_http_status(:success) + data = JSON.parse(response.body) + expect(data.length).to eq(0) + end + + it 'shows a agent_bot when its permissible object' do + create(:platform_app_permissible, platform_app: platform_app, permissible: agent_bot) + + get '/platform/api/v1/agent_bots', + headers: { api_access_token: platform_app.access_token.token }, as: :json + + expect(response).to have_http_status(:success) + data = JSON.parse(response.body) + expect(data.length).to eq(1) + end + end + end + + describe 'GET /platform/api/v1/agent_bots/{agent_bot_id}' do + context 'when it is an unauthenticated platform app' do + it 'returns unauthorized' do + get "/platform/api/v1/agent_bots/#{agent_bot.id}" + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an invalid platform app token' do + it 'returns unauthorized' do + get "/platform/api/v1/agent_bots/#{agent_bot.id}", headers: { api_access_token: 'invalid' }, as: :json + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated platform app' do + let(:platform_app) { create(:platform_app) } + + it 'returns unauthorized when its not a permissible object' do + get "/platform/api/v1/agent_bots/#{agent_bot.id}", headers: { api_access_token: platform_app.access_token.token }, as: :json + expect(response).to have_http_status(:unauthorized) + end + + it 'shows a agent_bot when its permissible object' do + create(:platform_app_permissible, platform_app: platform_app, permissible: agent_bot) + + get "/platform/api/v1/agent_bots/#{agent_bot.id}", + headers: { api_access_token: platform_app.access_token.token }, as: :json + + expect(response).to have_http_status(:success) + data = JSON.parse(response.body) + expect(data['name']).to eq(agent_bot.name) + end + end + end + + describe 'POST /platform/api/v1/agent_bots/' do + context 'when it is an unauthenticated platform app' do + it 'returns unauthorized' do + post '/platform/api/v1/agent_bots' + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an invalid platform app token' do + it 'returns unauthorized' do + post '/platform/api/v1/agent_bots/', headers: { api_access_token: 'invalid' }, as: :json + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated platform app' do + let(:platform_app) { create(:platform_app) } + + it 'creates a new agent bot' do + post '/platform/api/v1/agent_bots/', params: { name: 'test' }, + headers: { api_access_token: platform_app.access_token.token }, as: :json + + expect(response).to have_http_status(:success) + data = JSON.parse(response.body) + expect(data['name']).to eq('test') + expect(platform_app.platform_app_permissibles.first.permissible_id).to eq data['id'] + end + end + end + + describe 'PATCH /platform/api/v1/agent_bots/{agent_bot_id}' do + context 'when it is an unauthenticated platform app' do + it 'returns unauthorized' do + patch "/platform/api/v1/agent_bots/#{agent_bot.id}" + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an invalid platform app token' do + it 'returns unauthorized' do + patch "/platform/api/v1/agent_bots/#{agent_bot.id}", headers: { api_access_token: 'invalid' }, as: :json + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated platform app' do + let(:platform_app) { create(:platform_app) } + + it 'returns unauthorized when its not a permissible object' do + patch "/platform/api/v1/agent_bots/#{agent_bot.id}", params: { name: 'test' }, + headers: { api_access_token: platform_app.access_token.token }, as: :json + expect(response).to have_http_status(:unauthorized) + end + + it 'updates the agent_bot' do + create(:platform_app_permissible, platform_app: platform_app, permissible: agent_bot) + patch "/platform/api/v1/agent_bots/#{agent_bot.id}", params: { name: 'test123' }, + headers: { api_access_token: platform_app.access_token.token }, as: :json + + expect(response).to have_http_status(:success) + data = JSON.parse(response.body) + expect(data['name']).to eq('test123') + end + end + end + + describe 'DELETE /platform/api/v1/agent_bots/{agent_bot_id}' do + context 'when it is an unauthenticated platform app' do + it 'returns unauthorized' do + delete "/platform/api/v1/agent_bots/#{agent_bot.id}", headers: { api_access_token: 'invalid' }, as: :json + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated platform app' do + let(:platform_app) { create(:platform_app) } + + it 'returns unauthorized when its not a permissible object' do + delete "/platform/api/v1/agent_bots/#{agent_bot.id}", headers: { api_access_token: 'invalid' }, as: :json + expect(response).to have_http_status(:unauthorized) + end + + it 'returns deletes the account user' do + create(:platform_app_permissible, platform_app: platform_app, permissible: agent_bot) + + delete "/platform/api/v1/agent_bots/#{agent_bot.id}", headers: { api_access_token: platform_app.access_token.token }, as: :json + + expect(response).to have_http_status(:success) + expect(AgentBot.count).to eq 0 + end + end + end +end