chore: Expose widget config via an API (#2645)

Expose widget config via an API so that the UI could be detached from the rails Application.
This commit is contained in:
Sojan Jose
2021-07-21 01:26:32 +05:30
committed by GitHub
parent caf8669db5
commit a0886d37bc
8 changed files with 142 additions and 12 deletions

View File

@@ -94,6 +94,10 @@ class Api::V1::Widget::BaseController < ApplicationController
{ timestamp: permitted_params[:message][:timestamp] }
end
def permitted_params
params.permit(:website_token)
end
def message_params
{
account_id: conversation.account_id,

View File

@@ -4,10 +4,4 @@ class Api::V1::Widget::CampaignsController < Api::V1::Widget::BaseController
def index
@campaigns = @web_widget.inbox.campaigns.where(enabled: true)
end
private
def permitted_params
params.permit(:website_token)
end
end

View File

@@ -0,0 +1,41 @@
class Api::V1::Widget::ConfigsController < Api::V1::Widget::BaseController
before_action :set_global_config
def create
build_contact
set_token
end
private
def set_global_config
@global_config = GlobalConfig.get('LOGO_THUMBNAIL', 'BRAND_NAME', 'WIDGET_BRAND_URL')
end
def set_contact
@contact_inbox = @web_widget.inbox.contact_inboxes.find_by(
source_id: auth_token_params[:source_id]
)
@contact = @contact_inbox&.contact
end
def build_contact
return if @contact.present?
@contact_inbox = @web_widget.create_contact_inbox(additional_attributes)
@contact = @contact_inbox.contact
end
def set_token
payload = { source_id: @contact_inbox.source_id, inbox_id: @web_widget.inbox.id }
@token = ::Widget::TokenService.new(payload: payload).generate_token
end
def additional_attributes
if @web_widget.inbox.account.feature_enabled?('ip_lookup')
{ created_at_ip: request.remote_ip }
else
{}
end
end
end

View File

@@ -4,10 +4,4 @@ class Api::V1::Widget::InboxMembersController < Api::V1::Widget::BaseController
def index
@inbox_members = @web_widget.inbox.inbox_members.includes(:user)
end
private
def permitted_params
params.permit(:website_token)
end
end

View File

@@ -1,3 +1,4 @@
# TODO : Delete this and associated spec once 'api/widget/config' end point is merged
class WidgetsController < ActionController::Base
before_action :set_global_config
before_action :set_web_widget

View File

@@ -0,0 +1,28 @@
json.chatwoot_website_channel do
json.avatar_url @web_widget.inbox.avatar_url
json.has_a_connected_agent_bot @web_widget.inbox.agent_bot&.name
json.locale @web_widget.account.locale
json.website_name @web_widget.inbox.name
json.website_token @web_widget.website_token
json.welcome_tagline @web_widget.welcome_tagline
json.welcome_title @web_widget.welcome_title
json.widget_color @web_widget.widget_color
json.enabled_features @web_widget.selected_feature_flags
json.enabled_languages available_locales_with_name
json.reply_time @web_widget.reply_time
json.pre_chat_form_enabled @web_widget.pre_chat_form_enabled
json.pre_chat_form_options @web_widget.pre_chat_form_options
json.working_hours_enabled @web_widget.inbox.working_hours_enabled
json.csat_survey_enabled @web_widget.inbox.csat_survey_enabled
json.working_hours @web_widget.inbox.working_hours
json.out_of_office_message @web_widget.inbox.out_of_office_message
json.utc_off_set ActiveSupport::TimeZone[@web_widget.inbox.timezone].formatted_offset
end
json.chatwoot_widget_defaults do
json.use_inbox_avatar_for_bot ActiveModel::Type::Boolean.new.cast(ENV.fetch('USE_INBOX_AVATAR_FOR_BOT', false))
end
json.contact do
json.pubsub_token @contact.pubsub_token
end
json.auth_token @token
json.global_config @global_config

View File

@@ -152,6 +152,7 @@ Rails.application.routes.draw do
resource :notification_subscriptions, only: [:create]
namespace :widget do
resource :config, only: [:create]
resources :campaigns, only: [:index]
resources :events, only: [:create]
resources :messages, only: [:index, :create, :update]

View File

@@ -0,0 +1,67 @@
require 'rails_helper'
RSpec.describe '/api/v1/widget/config', type: :request do
let(:account) { create(:account) }
let(:web_widget) { create(:channel_widget, account: account) }
let!(:contact) { create(:contact, account: account) }
let(:contact_inbox) { create(:contact_inbox, contact: contact, inbox: web_widget.inbox) }
let(:payload) { { source_id: contact_inbox.source_id, inbox_id: web_widget.inbox.id } }
let(:token) { ::Widget::TokenService.new(payload: payload).generate_token }
describe 'POST /api/v1/widget/config' do
let(:params) { { website_token: web_widget.website_token } }
let(:response_keys) { %w[chatwoot_website_channel chatwoot_widget_defaults contact auth_token global_config] }
context 'with invalid website token' do
it 'returns not found' do
post '/api/v1/widget/config', params: { website_token: '' }
expect(response).to have_http_status(:not_found)
end
end
context 'with correct website token and missing X-Auth-Token' do
it 'returns widget config along with a new contact' do
expect do
post '/api/v1/widget/config',
params: params,
as: :json
end.to change(Contact, :count).by(1)
expect(response).to have_http_status(:success)
response_data = JSON.parse(response.body)
expect(response_data.keys).to include(*response_keys)
end
end
context 'with correct website token and valid X-Auth-Token' do
it 'returns widget config along with the same contact' do
expect do
post '/api/v1/widget/config',
params: params,
headers: { 'X-Auth-Token' => token },
as: :json
end.to change(Contact, :count).by(0)
expect(response).to have_http_status(:success)
response_data = JSON.parse(response.body)
expect(response_data.keys).to include(*response_keys)
expect(response_data['contact']['pubsub_token']).to eq(contact.pubsub_token)
end
end
context 'with correct website token and invalid X-Auth-Token' do
it 'returns widget config and new contact with error message' do
expect do
post '/api/v1/widget/config',
params: params,
headers: { 'X-Auth-Token' => 'invalid token' },
as: :json
end.to change(Contact, :count).by(1)
expect(response).to have_http_status(:success)
response_data = JSON.parse(response.body)
expect(response_data.keys).to include(*response_keys)
end
end
end
end