chore: General fixes and clean up (#1169)

This commit is contained in:
Sojan Jose 2020-08-25 23:04:02 +05:30 committed by GitHub
parent 124e43b477
commit 2193de9853
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 111 additions and 121 deletions

View file

@ -50,6 +50,8 @@ class Messages::Facebook::MessageBuilder
def attach_file(attachment, file_url)
file_resource = LocalResource.new(file_url)
attachment.file.attach(io: file_resource.file, filename: file_resource.tmp_filename, content_type: file_resource.encoding)
rescue Errno::ETIMEDOUT, Errno::ECONNREFUSED => e
Rails.logger.info "invalid url #{file_url} : #{e.message}"
end
def conversation

View file

@ -81,6 +81,8 @@ class Api::V1::Accounts::CallbacksController < Api::V1::Accounts::BaseController
avatar_resource = LocalResource.new(uri)
facebook_inbox.avatar.attach(io: avatar_resource.file, filename: avatar_resource.tmp_filename, content_type: avatar_resource.encoding)
rescue Errno::ETIMEDOUT, Errno::ECONNREFUSED => e
Rails.logger.info "invalid url #{file_url} : #{e.message}"
end
def get_avatar_url(page_id)

View file

@ -1,5 +1,6 @@
class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseController
include Events::Types
before_action :conversation, except: [:index]
before_action :contact_inbox, only: [:create]

View file

@ -9,7 +9,11 @@ class AsyncDispatcher < BaseDispatcher
end
def listeners
listeners = [EventListener.instance, WebhookListener.instance, HookListener.instance]
listeners = [
EventListener.instance,
WebhookListener.instance,
InstallationWebhookListener.instance, HookListener.instance
]
listeners
end
end

View file

@ -4,5 +4,7 @@ class ContactAvatarJob < ApplicationJob
def perform(contact, avatar_url)
avatar_resource = LocalResource.new(avatar_url)
contact.avatar.attach(io: avatar_resource.file, filename: avatar_resource.tmp_filename, content_type: avatar_resource.encoding)
rescue Errno::ETIMEDOUT, Errno::ECONNREFUSED => e
Rails.logger.info "invalid url #{file_url} : #{e.message}"
end
end

View file

@ -0,0 +1,19 @@
class InstallationWebhookListener < BaseListener
def account_created(event)
payload = event.data[:account].webhook_data.merge(event: __method__.to_s)
deliver_webhook_payloads(payload)
end
def account_destroyed(event)
payload = event.data[:account].webhook_data.merge(event: __method__.to_s)
deliver_webhook_payloads(payload)
end
private
def deliver_webhook_payloads(payload)
# Deliver the installation event
webhook_url = InstallationConfig.find_by(name: 'INSTALLATION_EVENTS_WEBHOOK_URL')&.value
WebhookJob.perform_later(webhook_url, payload) if webhook_url
end
end

View file

@ -16,8 +16,6 @@
class Account < ApplicationRecord
# used for single column multi flags
include FlagShihTzu
include Events::Types
include Reportable
include Featurable
@ -54,7 +52,7 @@ class Account < ApplicationRecord
enum locale: LANGUAGES_CONFIG.map { |key, val| [val[:iso_639_1_code], key] }.to_h
after_create :notify_creation
after_create_commit :notify_creation
after_destroy :notify_deletion
def agents

View file

@ -24,8 +24,6 @@
#
class AccountUser < ApplicationRecord
include Events::Types
belongs_to :account
belongs_to :user
belongs_to :inviter, class_name: 'User', optional: true
@ -33,7 +31,7 @@ class AccountUser < ApplicationRecord
enum role: { agent: 0, administrator: 1 }
accepts_nested_attributes_for :account
after_create :notify_creation, :create_notification_setting
after_create_commit :notify_creation, :create_notification_setting
after_destroy :notify_deletion, :destroy_notification_setting
validates :user_id, uniqueness: { scope: :account_id }

View file

@ -1,7 +1,11 @@
class ApplicationRecord < ActiveRecord::Base
include Events::Types
self.abstract_class = true
# the models that exposed in email templates through liquid
DROPPABLES = %w[Account Channel Conversation Inbox User].freeze
# ModelDrop class should exist in app/drops
def to_drop
return unless DROPPABLES.include?(self.class.name)

View file

@ -26,7 +26,6 @@ class Contact < ApplicationRecord
include Pubsubable
include Avatarable
include AvailabilityStatusable
include Events::Types
validates :account_id, presence: true
validates :email, allow_blank: true, uniqueness: { scope: [:account_id], case_sensitive: false }

View file

@ -31,8 +31,6 @@
#
class Conversation < ApplicationRecord
include Events::Types
validates :account_id, presence: true
validates :inbox_id, presence: true

View file

@ -28,8 +28,6 @@
#
class Message < ApplicationRecord
include Events::Types
NUMBER_OF_PERMITTED_ATTACHMENTS = 15
validates :account_id, presence: true
@ -105,6 +103,7 @@ class Message < ApplicationRecord
created_at: created_at,
message_type: message_type,
content_type: content_type,
private: private,
content_attributes: content_attributes,
source_id: source_id,
sender: sender.try(:webhook_data),

View file

@ -1,97 +0,0 @@
class Plan
attr_accessor :key, :attributes
def initialize(key, attributes = {})
@key = key.to_sym
@attributes = attributes
end
def name
attributes[:name]
end
def id
attributes[:id]
end
def price
attributes[:price]
end
def active
attributes[:active]
end
def version
attributes[:version]
end
class << self
def config
Hashie::Mash.new(PLAN_CONFIG)
end
def default_trial_period
(config['trial_period'] || 14).days
end
def default_pricing_version
config['default_pricing_version']
end
def default_plans
load_active_plans + load_inactive_plans
end
def all_plans
default_plans
end
def active_plans
all_plans.select(&:active)
end
def paid_plan
active_plans.first
end
def inactive_plans
all_plans.reject(&:active)
end
def trial_plan
all_plans.detect { |plan| plan.key == :trial }
end
def plans_of_version(version)
all_plans.select { |plan| plan.version == version }
end
def find_by_key(key)
key = key.to_sym
all_plans.detect { |plan| plan.key == key }.dup
end
# #helpers
def load_active_plans
result = []
Plan.config.active.each_pair do |version, plans|
plans.each_pair do |key, attributes|
result << Plan.new(key, attributes.merge(active: true, version: version))
end
end
result
end
def load_inactive_plans
result = []
Plan.config.inactive.each_pair do |version, plans|
plans.each_pair do |key, attributes|
result << Plan.new(key, attributes.merge(active: false, version: version))
end
end
result
end
end
end

View file

@ -41,7 +41,6 @@ class User < ApplicationRecord
include Avatarable
# Include default devise modules.
include DeviseTokenAuth::Concerns::User
include Events::Types
include Pubsubable
include Rails.application.routes.url_helpers
include Reportable
@ -78,7 +77,7 @@ class User < ApplicationRecord
before_validation :set_password_and_uid, on: :create
after_create :create_access_token
after_create_commit :create_access_token
after_save :update_presence_in_redis, if: :saved_change_to_availability?
scope :order_by_full_name, -> { order('lower(name) ASC') }

View file

@ -107,5 +107,7 @@ class Twilio::IncomingMessageService
)
@message.save!
rescue Errno::ETIMEDOUT, Errno::ECONNREFUSED => e
Rails.logger.info "invalid url #{file_url} : #{e.message}"
end
end

View file

@ -22,3 +22,5 @@
value: false
- name: BRAND_NAME
value: 'Chatwoot'
- name: 'INSTALLATION_EVENTS_WEBHOOK_URL'
value:

View file

@ -1,10 +1,12 @@
# frozen_string_literal: true
module Events::Types
### Installation Events ###
# account events
ACCOUNT_CREATED = 'account.created'
ACCOUNT_DESTROYED = 'account.destroyed'
#### Account Events ###
# channel events
WEBWIDGET_TRIGGERED = 'webwidget.triggered'
@ -28,10 +30,7 @@ module Events::Types
CONTACT_CREATED = 'contact.created'
CONTACT_UPDATED = 'contact.updated'
# subscription events
# agent events
AGENT_ADDED = 'agent.added'
AGENT_REMOVED = 'agent.removed'
SUBSCRIPTION_CREATED = 'subscription.created'
SUBSCRIPTION_REACTIVATED = 'subscription.reactivated'
SUBSCRIPTION_DEACTIVATED = 'subscription.deactivated'
end

View file

@ -1,6 +1,8 @@
class Webhooks::Trigger
def self.execute(url, payload)
RestClient.post(url, payload.to_json, { content_type: :json, accept: :json })
rescue RestClient::NotFound => e
Rails.logger.info "invalid url #{url} : #{e.message}"
rescue StandardError => e
Raven.capture_exception(e)
end

View file

@ -0,0 +1,6 @@
FactoryBot.define do
factory :installation_config do
name { 'xyc' }
value { 1.5 }
end
end

View file

@ -0,0 +1,44 @@
require 'rails_helper'
describe InstallationWebhookListener do
let(:listener) { described_class.instance }
let!(:account) { create(:account) }
let!(:event) { Events::Base.new(event_name, Time.zone.now, account: account) }
describe '#account_created' do
let(:event_name) { :'account.created' }
context 'when installation config is not configured' do
it 'does not trigger webhook' do
expect(WebhookJob).to receive(:perform_later).exactly(0).times
listener.account_created(event)
end
end
context 'when installation config is configured' do
it 'triggers webhook' do
create(:installation_config, name: 'INSTALLATION_EVENTS_WEBHOOK_URL', value: 'https://test.com')
expect(WebhookJob).to receive(:perform_later).with('https://test.com', account.webhook_data.merge(event: 'account_created')).once
listener.account_created(event)
end
end
end
describe '#account_destroyed' do
let(:event_name) { :'account.destroyed' }
context 'when installation config is not configured' do
it 'does not trigger webhook' do
expect(WebhookJob).to receive(:perform_later).exactly(0).times
listener.account_destroyed(event)
end
end
context 'when installation config is configured' do
it 'triggers webhook' do
create(:installation_config, name: 'INSTALLATION_EVENTS_WEBHOOK_URL', value: 'https://test.com')
expect(WebhookJob).to receive(:perform_later).with('https://test.com', account.webhook_data.merge(event: 'account_destroyed')).once
listener.account_destroyed(event)
end
end
end
end

View file

@ -17,7 +17,7 @@ describe WebhookListener do
context 'when webhook is not configured' do
it 'does not trigger webhook' do
expect(RestClient).to receive(:post).exactly(0).times
expect(WebhookJob).to receive(:perform_later).exactly(0).times
listener.message_created(event)
end
end

View file

@ -12,7 +12,10 @@ properties:
description: Flag to identify if it is a private note
content_type:
type: string
enum: ['input_select', 'form', 'cards']
enum: ['input_email', 'cards', 'input_select', 'form' , 'article']
example: 'cards'
description: 'if you want to create custom message types'
content_attributes:
type: object
description: options/form object
description: attributes based on your content type

View file

@ -1641,14 +1641,18 @@
"content_type": {
"type": "string",
"enum": [
"input_email",
"cards",
"input_select",
"form",
"cards"
]
"article"
],
"example": "cards",
"description": "if you want to create custom message types"
},
"content_attributes": {
"type": "object",
"description": "options/form object"
"description": "attributes based on your content type"
}
}
}