Initial Commit

Co-authored-by: Subin <subinthattaparambil@gmail.com>
Co-authored-by: Manoj <manojmj92@gmail.com>
Co-authored-by: Nithin <webofnithin@gmail.com>
This commit is contained in:
Pranav Raj Sreepuram
2019-08-14 15:18:44 +05:30
commit 2a34255e0b
537 changed files with 27318 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
class Api::BaseController < ApplicationController
respond_to :json
before_action :authenticate_user!
rescue_from StandardError do |exception|
Raven.capture_exception(exception)
render json: { :error => "500 error", message: exception.message }.to_json , :status => 500
end unless Rails.env.development?
private
def set_conversation
@conversation ||= current_account.conversations.find_by(display_id: params[:conversation_id])
end
end

View File

@@ -0,0 +1,36 @@
class Api::V1::AccountsController < Api::BaseController
skip_before_action :verify_authenticity_token , only: [:create]
skip_before_action :authenticate_user!, :set_current_user, :check_subscription, :handle_with_exception,
only: [:create], raise: false
rescue_from CustomExceptions::Account::InvalidEmail,
CustomExceptions::Account::UserExists,
CustomExceptions::Account::UserErrors,
with: :render_error_response
def create
@user = AccountBuilder.new(params).perform
if @user
set_headers(@user)
render json: {
data: @user.token_validation_response
}
else
render_error_response(CustomExceptions::Account::SignupFailed.new({}))
end
end
private
def set_headers(user)
data = user.create_new_auth_token
response.headers[DeviseTokenAuth.headers_names[:"access-token"]] = data["access-token"]
response.headers[DeviseTokenAuth.headers_names[:"token-type"]] = "Bearer"
response.headers[DeviseTokenAuth.headers_names[:"client"]] = data["client"]
response.headers[DeviseTokenAuth.headers_names[:"expiry"]] = data["expiry"]
response.headers[DeviseTokenAuth.headers_names[:"uid"]] = data["uid"]
end
end

View File

@@ -0,0 +1,52 @@
class Api::V1::AgentsController < Api::BaseController
before_action :fetch_agent, except: [:create, :index]
before_action :check_authorization
before_action :build_agent, only: [:create]
def index
render json: agents
end
def destroy
@agent.destroy
head :ok
end
def update
@agent.update_attributes!(agent_params)
render json: @agent
end
def create
@agent.save!
render json: @agent
end
private
def check_authorization
authorize(User)
end
def fetch_agent
@agent = agents.find(params[:id])
end
def build_agent
@agent = agents.new(new_agent_params)
end
def agent_params
params.require(:agent).permit(:email, :name, :role)
end
def new_agent_params
time = Time.now.to_i
params.require(:agent).permit(:email, :name, :role).merge!(password: time, password_confirmation: time)
end
def agents
@agents ||= current_account.users
end
end

View File

@@ -0,0 +1,87 @@
require 'rest-client'
require 'telegram/bot'
class Api::V1::CallbacksController < ApplicationController
skip_before_action :verify_authenticity_token , only: [:register_facebook_page]
skip_before_action :authenticate_user! , only: [:register_facebook_page], raise: false
def register_facebook_page
user_access_token = params[:user_access_token]
page_access_token = params[:page_access_token]
page_name = params[:page_name]
page_id = params[:page_id]
inbox_name = params[:inbox_name]
facebook_channel = current_account.facebook_pages.create!(name: page_name, page_id: page_id, user_access_token: user_access_token, page_access_token: page_access_token, remote_avatar_url: set_avatar(page_id))
inbox = current_account.inboxes.create!(name: inbox_name, channel: facebook_channel)
render json: inbox
end
def get_facebook_pages
@page_details = mark_already_existing_facebook_pages(fb_object.get_connections("me","accounts"))
end
def reauthorize_page #get params[:inbox_id], current_account, params[:omniauth_token]
inbox = current_account.inboxes.find_by(id: params[:inbox_id])
if inbox
fb_page_id = inbox.channel.page_id
page_details = fb_object.get_connections("me","accounts")
(page_details || []).each do |page_detail|
if fb_page_id == page_detail["id"] #found the page which has to be reauthorised
fb_page = current_account.facebook_pages.find_by(page_id: fb_page_id)
if fb_page
fb_page.update_attributes!(
{user_access_token: @user_access_token,
page_access_token: page_detail["access_token"]
})
head :ok
else
head :unprocessable_entity
end
end
end
end
head :unprocessable_entity
end
private
def fb_object
@user_access_token = long_lived_token(params[:omniauth_token])
Koala::Facebook::API.new(@user_access_token)
end
def long_lived_token(omniauth_token)
koala = Koala::Facebook::OAuth.new(ENV['fb_app_id'], ENV['fb_app_secret'])
long_lived_token = koala.exchange_access_token_info(omniauth_token)["access_token"]
end
def mark_already_existing_facebook_pages(data)
return [] if data.empty?
data.inject([]) do |result, page_detail|
current_account.facebook_pages.exists?(page_id: page_detail["id"]) ? page_detail.merge!(exists: true) : page_detail.merge!(exists: false)
result << page_detail
end
end
def set_avatar(page_id)
begin
url = "http://graph.facebook.com/" << page_id << "/picture?type=large"
uri = URI.parse(url)
tries = 3
begin
response = uri.open(redirect: false)
rescue OpenURI::HTTPRedirect => redirect
uri = redirect.uri # assigned from the "Location" response header
retry if (tries -= 1) > 0
raise
end
pic_url = response.base_uri.to_s
Rails.logger.info(pic_url)
rescue => e
pic_url = nil
end
pic_url
end
end

View File

@@ -0,0 +1,42 @@
class Api::V1::CannedResponsesController < Api::BaseController
before_action :fetch_canned_response, only: [:update, :destroy]
def index
render json: canned_responses
end
def create
@canned_response = current_account.canned_responses.new(canned_response_params)
@canned_response.save!
render json: @canned_response
end
def update
@canned_response.update_attributes!(canned_response_params)
render json: @canned_response
end
def destroy
@canned_response.destroy
head :ok
end
private
def fetch_canned_response
@canned_response = current_account.canned_responses.find(params[:id])
end
def canned_response_params
params.require(:canned_response).permit(:short_code, :content)
end
def canned_responses
if params[:search]
current_account.canned_responses.where("short_code ILIKE ?", "#{params[:search]}%")
else
current_account.canned_responses
end
end
end

View File

@@ -0,0 +1,48 @@
class Api::V1::ContactsController < Api::BaseController
protect_from_forgery with: :null_session
before_action :check_authorization
before_action :fetch_contact, only: [:show, :update]
skip_before_action :authenticate_user!, only: [:create]
skip_before_action :set_current_user, only: [:create]
skip_before_action :check_subscription, only: [:create]
skip_around_action :handle_with_exception, only: [:create]
def index
@contacts = current_account.contacts
end
def show
end
def create
@contact = Contact.new(contact_create_params)
@contact.save!
render json: @contact
end
def update
@contact.update_attributes!(contact_params)
end
private
def check_authorization
authorize(Contact)
end
def contact_params
params.require(:contact).permit(:name, :email, :phone_number)
end
def fetch_contact
@contact = current_account.contacts.find(params[:id])
end
def contact_create_params
params.require(:contact).permit(:account_id, :inbox_id).merge!(name: SecureRandom.hex)
end
end

View File

@@ -0,0 +1,12 @@
class Api::V1::Conversations::AssignmentsController < Api::BaseController
before_action :set_conversation, only: [:create]
def create #assign agent to a conversation
#if params[:assignee_id] is not a valid id, it will set to nil, hence unassigning the conversation
assignee = current_account.users.find_by(id: params[:assignee_id])
@conversation.update_assignee(assignee)
render json: assignee
end
end

View File

@@ -0,0 +1,13 @@
class Api::V1::Conversations::LabelsController < Api::BaseController
before_action :set_conversation, only: [:create, :index]
def create
@conversation.update_labels(params[:labels].values) # .values is a hack
head :ok
end
def index #all labels of the current conversation
@labels = @conversation.label_list
end
end

View File

@@ -0,0 +1,10 @@
class Api::V1::Conversations::MessagesController < Api::BaseController
before_action :set_conversation, only: [:create]
def create
mb = Messages::Outgoing::NormalBuilder.new(current_user, @conversation, params)
@message = mb.perform
end
end

View File

@@ -0,0 +1,54 @@
class Api::V1::ConversationsController < Api::BaseController
before_action :set_conversation, except: [:index, :get_messages]
# TODO move this to public controller
skip_before_action :authenticate_user!, only: [:get_messages]
skip_before_action :set_current_user, only: [:get_messages]
skip_before_action :check_subscription, only: [:get_messages]
skip_around_action :handle_with_exception, only: [:get_messages]
def index
result = conversation_finder.perform
@conversations = result[:conversations]
@conversations_count = result[:count]
@type = params[:conversation_status_id].to_i
end
def show
@messages = messages_finder.perform
end
def toggle_status
@status = @conversation.toggle_status
end
def update_last_seen
@conversation.agent_last_seen_at = parsed_last_seen_at
@conversation.save!
head :ok
end
def get_messages
@conversation = Conversation.find(params[:id])
@messages = messages_finder.perform
end
private
def parsed_last_seen_at
DateTime.strptime(params[:agent_last_seen_at].to_s,'%s')
end
def set_conversation
@conversation ||= current_account.conversations.find_by(display_id: params[:id])
end
def conversation_finder
@conversation_finder ||= ConversationFinder.new(current_user, params)
end
def messages_finder
@message_finder ||= MessageFinder.new(@conversation, params)
end
end

View File

@@ -0,0 +1,44 @@
class Api::V1::FacebookIndicatorsController < Api::BaseController
before_action :set_access_token
around_filter :handle_with_exception
def mark_seen
Facebook::Messenger::Bot.deliver(payload('mark_seen'), access_token: @access_token)
head :ok
end
def typing_on
Facebook::Messenger::Bot.deliver(payload('typing_on'), access_token: @access_token)
head :ok
end
def typing_off
Facebook::Messenger::Bot.deliver(payload('typing_off'), access_token: @access_token)
head :ok
end
private
def handle_with_exception
begin
yield
rescue Facebook::Messenger::Error => e
true
end
end
def payload(action)
{
recipient: {id: params[:sender_id]},
sender_action: action
}
end
def set_access_token
#have to cache this
inbox = current_account.inboxes.find(params[:inbox_id])
@access_token = inbox.channel.page_access_token
end
end

View File

@@ -0,0 +1,49 @@
class Api::V1::InboxMembersController < Api::BaseController
before_action :fetch_inbox, only: [:create, :show]
before_action :current_agents_ids, only: [:create]
def create #update also done via same action
#get all the user_ids which the inbox currently has as members.
#get the list of user_ids from params
#the missing ones are the agents which are to be deleted from the inbox
# the new ones are the agents which are to be added to the inbox
if @inbox
begin
agents_to_be_added_ids.each do |user_id|
@inbox.add_member(user_id)
end
agents_to_be_removed_ids.each do |user_id|
@inbox.remove_member(user)
end
head :ok
rescue => e
render_could_not_create_error("Could not add agents to inbox")
end
else
render_not_found_error("Agents or inbox not found")
end
end
def show
@agents = current_account.users.where(id: @inbox.members.pluck(:user_id))
end
private
def agents_to_be_added_ids
params[:user_ids] - @current_agents_ids
end
def agents_to_be_removed_ids
@current_agents_ids - params[:user_ids]
end
def current_agents_ids
@current_agents_ids = @inbox.members.pluck(:user_id)
end
def fetch_inbox
@inbox = current_account.inboxes.find(params[:inbox_id])
end
end

View File

@@ -0,0 +1,25 @@
class Api::V1::InboxesController < Api::BaseController
before_action :check_authorization
before_action :fetch_inbox, only: [:destroy]
def index
@inboxes = policy_scope(current_account.inboxes)
end
def destroy
@inbox.destroy
head :ok
end
private
def fetch_inbox
@inbox = current_account.inboxes.find(params[:id])
end
def check_authorization
authorize(Inbox)
end
end

View File

@@ -0,0 +1,7 @@
class Api::V1::LabelsController < Api::BaseController
def index #list all labels in account
@labels = current_account.all_conversation_tags
end
end

View File

@@ -0,0 +1,114 @@
class Api::V1::ReportsController < Api::BaseController
include CustomExceptions::Report
include Constants::Report
around_filter :report_exception
def account
builder = ReportBuilder.new(current_account, account_report_params)
data = builder.build
render json: data
end
def agent
builder = ReportBuilder.new(current_account, agent_report_params)
data = builder.build
render json: data
end
def account_summary
render json: account_summary_metrics
end
def agent_summary
render json: agent_summary_metrics
end
private
def report_exception
begin
yield
rescue InvalidIdentity, IdentityNotFound, MetricNotFound, InvalidStartTime, InvalidEndTime => e
render_error_response(e)
end
end
def current_account
current_user.account
end
def agent
@agent ||= current_account.users.find(params[:agent_id])
end
def account_summary_metrics
ACCOUNT_METRICS.inject({}) do |result, metric|
data = ReportBuilder.new(current_account, account_summary_params(metric)).build
if AVG_ACCOUNT_METRICS.include?(metric)
sum = data.inject(0) {|sum, hash| sum + hash[:value].to_i}
sum = sum/ data.length unless sum.zero?
else
sum = data.inject(0) {|sum, hash| sum + hash[:value].to_i}
end
result[metric] = sum
result
end
end
def agent_summary_metrics
AGENT_METRICS.inject({}) do |result, metric|
data = ReportBuilder.new(current_account, agent_summary_params(metric)).build
if AVG_AGENT_METRICS.include?(metric)
sum = data.inject(0) {|sum, hash| sum + hash[:value].to_i}
sum = sum/ data.length unless sum.zero?
else
sum = data.inject(0) {|sum, hash| sum + hash[:value].to_i}
end
result[metric] = sum
result
end
end
def account_summary_params(metric)
{
metric: metric.to_s,
type: :account,
since: params[:since],
until: params[:until]
}
end
def agent_summary_params(metric)
{
metric: metric.to_s,
type: :agent,
since: params[:since],
until: params[:until],
id: params[:id]
}
end
def account_report_params
{
metric: params[:metric],
type: :account,
since: params[:since],
until: params[:until]
}
end
def agent_report_params
{
metric: params[:metric],
type: :agent,
id: params[:id],
since: params[:since],
until: params[:until]
}
end
end

View File

@@ -0,0 +1,11 @@
class Api::V1::SubscriptionsController < ApplicationController
skip_before_action :check_subscription
def index
render json: current_account.subscription_data
end
def status
render json: current_account.subscription.summary
end
end

View File

@@ -0,0 +1,27 @@
class Api::V1::WebhooksController < ApplicationController
skip_before_action :authenticate_user!, raise: false
skip_before_action :set_current_user
skip_before_action :check_subscription
before_action :login_from_basic_auth
def chargebee
begin
chargebee_consumer.consume
head :ok
rescue => e
Raven.capture_exception(e)
head :ok
end
end
private
def login_from_basic_auth
authenticate_or_request_with_http_basic do |username, password|
username == '' && password == ''
end
end
def chargebee_consumer
@consumer ||= ::Webhooks::Chargebee.new(params)
end
end

View File

@@ -0,0 +1,28 @@
class Api::V1::Widget::MessagesController < ApplicationController
# TODO move widget apis to different controller.
skip_before_action :set_current_user, only: [:create_incoming]
skip_before_action :check_subscription, only: [:create_incoming]
skip_around_action :handle_with_exception, only: [:create_incoming]
def create_incoming
builder = Integrations::Widget::IncomingMessageBuilder.new(incoming_message_params)
builder.perform
render json: builder.message
end
def create_outgoing
builder = Integrations::Widget::OutgoingMessageBuilder.new(outgoing_message_params)
builder.perform
render json: builder.message
end
private
def incoming_message_params
params.require(:message).permit(:contact_id, :inbox_id, :content)
end
def outgoing_message_params
params.require(:message).permit(:user_id, :inbox_id, :content, :conversation_id)
end
end