Skip to content

Commit

Permalink
Merge pull request maestrano#82 from x4d3/feature/intercom
Browse files Browse the repository at this point in the history
Add Intercom backend integration
  • Loading branch information
ouranos authored Sep 18, 2016
2 parents 41de14e + cf0b135 commit a4366b4
Show file tree
Hide file tree
Showing 12 changed files with 227 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ angular.module('mnoEnterprise.configuration', [])
.constant('PRICING_CONFIG', <%= Settings.pricing.to_json %>)
.constant('DOCK_CONFIG', <%= Settings.dock.to_json %>)
.constant('GOOGLE_TAG_CONTAINER_ID', <%= MnoEnterprise.google_tag_container.to_json %>)
.constant('INTERCOM_ID', <%= MnoEnterprise.intercom_id.to_json %>)
.constant('INTERCOM_ID', <%= MnoEnterprise.intercom_app_id.to_json %>)
.constant('APP_NAME', <%= MnoEnterprise.app_name.to_json %>)
28 changes: 28 additions & 0 deletions api/lib/mno_enterprise/audit_events_listener.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require 'httparty'

module MnoEnterprise
class AuditEventsListener
include HTTParty
base_uri "#{MnoEnterprise.mno_api_private_host || MnoEnterprise.mno_api_host}/api/mnoe/v1/audit_events"
read_timeout 0.1
basic_auth MnoEnterprise.tenant_id, MnoEnterprise.tenant_key

def info(key, current_user_id, description, metadata, object)
self.class.post('', body: {
data: {
key: key,
user_id: current_user_id,
description: description,
metadata: metadata,
subject_type: object.class.name,
subject_id: object.id
}})
rescue Net::ReadTimeout
# Meant to fail
end

end


end

Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ def create

app_instances = []
params[:apps].each do |product_name|
app_instances << @organization.app_instances.create(product: product_name)
app_instance = @organization.app_instances.create(product: product_name)
app_instances << app_instance
MnoEnterprise::EventLogger.info('app_add', current_user.id, "App added", app_instance.name, app_instance)
end

render json: app_instances.map(&:attributes).to_json, status: :created
Expand Down
21 changes: 6 additions & 15 deletions api/lib/mno_enterprise/event_logger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,14 @@

module MnoEnterprise
class EventLogger
include HTTParty
base_uri "#{MnoEnterprise.mno_api_private_host || MnoEnterprise.mno_api_host}/api/mnoe/v1/audit_events"
read_timeout 0.1
basic_auth MnoEnterprise.tenant_id, MnoEnterprise.tenant_key
@@listeners = [AuditEventsListener.new]
@@listeners << IntercomEventsListener.new if MnoEnterprise.intercom_enabled?

def self.info(key, current_user_id, description, metadata, object)
post('', body: {
data: {
key: key,
user_id: current_user_id,
description: description,
metadata: format_metadata(metadata, object),
subject_type: object.class.name,
subject_id: object.id
}})
rescue Net::ReadTimeout
# Meant to fail
formatted_metadata = format_metadata(metadata, object)
@@listeners.each do |listener|
listener.info(key, current_user_id, description, formatted_metadata, object)
end
end

def self.format_metadata(metadata, object)
Expand Down
84 changes: 84 additions & 0 deletions api/lib/mno_enterprise/intercom_events_listener.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
require 'intercom'

module MnoEnterprise

class IntercomEventsListener

attr_accessor :intercom

def initialize
self.intercom = ::Intercom::Client.new(app_id: MnoEnterprise.intercom_app_id, api_key: MnoEnterprise.intercom_api_key)
end

def info(key, current_user_id, description, metadata, object)
u = User.find(current_user_id)
begin
intercom.users.find(:user_id => current_user_id)
rescue Intercom::ResourceNotFound
self.update_intercom_user(u)
end
data = {created_at: Time.now.to_i, email: u.email}
case key
when 'user_update'
self.update_intercom_user(u)
return
when 'user_confirm'
data[:event_name] = 'finished-sign-up'
when 'dashboard_create'
data[:event_name] = 'added-dashboard'
when 'dashboard_delete'
data[:event_name] = 'removed-dashboard'
when 'widget_delete'
data[:event_name] = 'removed-widget'
when 'widget_create'
data[:event_name] = 'added-widget'
data[:metadata] = {widget: object.name}
when 'app_destroy'
data[:event_name] = 'deleted-app-' + object.app.nid
data[:metadata] = {type: 'single', app_list: object.app.nid}
when 'app_add'
data[:event_name] = 'added-app-' + object.app.nid
data[:metadata] = {type: 'single', app_list: object.app.nid}
else
data[:event_name] = key.tr!('_', '-')
end

self.intercom.events.create(data)

rescue Intercom::IntercomError => e
Rails.logger.debug '[INTERCOM] Could not call intercom: ' + e.message
end

def update_intercom_user(user)
data = {
user_id: user.id,
name: [user.name, user.surname].join(' '),
email: user.email,
created_at: user.created_at.to_i,
last_seen_ip: user.last_sign_in_ip,
custom_attributes: {}
}
data[:custom_attributes][:phone]= user.phone if user.phone

data[:companies] = user.organizations.map do |organization|
{
company_id: organization.id,
name: organization.name,
created_at: organization.created_at.to_i,
custom_attributes: {
industry: organization.industry,
size: organization.size,
credit_card_details: organization.credit_card?,
app_count: organization.app_instances.count,
app_list: organization.app_instances.map { |app| app.name }.to_sentence
}
}
end

intercom.users.create(data)
end

end

end

3 changes: 2 additions & 1 deletion api/mno-enterprise-api.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ Gem::Specification.new do |s|
s.add_runtime_dependency 'coffee-rails', '~> 4.1'
s.add_runtime_dependency 'health_check', '~> 1.5'
s.add_runtime_dependency 'httparty', '~> 0.13.7'

# Lock sprocket version
s.add_dependency 'sprockets-rails', '~> 2.3'

s.add_development_dependency 'intercom', '~> 3.5.4'
end
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require 'rails_helper'

module MnoEnterprise
RSpec.describe EventLogger do
RSpec.describe AuditEventsListener do

def info_data(user)
{
Expand All @@ -18,8 +18,8 @@ def info_data(user)

let(:user) { build(:user) }

describe "#info" do
subject { MnoEnterprise::EventLogger.info('user_update_password', user.id, "User password change", user.email, user) }
describe '#info' do
subject { MnoEnterprise::AuditEventsListener.new.info('user_update_password', user.id, 'User password change', user.email, user) }

it { expect(subject.code).to eq(200) }
it { expect(subject.request.options[:body]).to eq(info_data(user)) }
Expand Down
82 changes: 82 additions & 0 deletions api/spec/lib/mno_enterprise/intercom_events_listener_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
require 'rails_helper'

module MnoEnterprise
RSpec.describe IntercomEventsListener do
let(:app) { build(:app) }
let(:app_instance) { build(:app_instance, app: app, organization_id: organization.id) }
let(:user) { build(:user) }
let(:organization) { build(:organization) }
before do
api_stub_for(get: "/users/#{user.id}", response: from_api(user))
api_stub_for(get: "/users/#{user.id}/organizations", response: from_api([organization]))
api_stub_for(get: "/organizations/#{organization.id}/app_instances", response: from_api([app_instance]))
end


describe '#info' do
let(:events) { double('events') }
context 'when the user already exist in intercom' do
before do
users = double('users')

client = double('client', users: users, events: events)
expect(Intercom::Client).to receive(:new).with(app_id: MnoEnterprise.intercom_app_id, api_key: MnoEnterprise.intercom_api_key).and_return(client)

expect(users).to receive(:find)
end

subject { MnoEnterprise::IntercomEventsListener.new }

it 'add an event when an password is changed' do
expect(events).to receive(:create).with(hash_including(email: user.email, event_name: 'user-update-password'))
subject.info('user_update_password', user.id, 'User password change', user.email, user)
end

it 'add an event when an app is added' do
expect(events).to receive(:create).with(hash_including(email: user.email, event_name: 'added-app-' + app.nid, metadata: {type: 'single', app_list: app.nid}))
subject.info('app_add', user.id, 'App Added', user.email, app_instance)
end

end
context 'when the user does not exist in intercom' do
before do
users = double('users')

client = double('client', users: users, events: events)
expect(Intercom::Client).to receive(:new).with(app_id: MnoEnterprise.intercom_app_id, api_key: MnoEnterprise.intercom_api_key).and_return(client)

expect(users).to receive(:find).and_raise(Intercom::ResourceNotFound.new('not found'))
user_data = {
user_id: user.id,
name: [user.name, user.surname].join(' '),
email: user.email,
created_at: user.created_at.to_i,
last_seen_ip: user.last_sign_in_ip,
custom_attributes: {phone: user.phone},
companies:[
{
company_id: organization.id,
name: organization.name,
created_at: organization.created_at.to_i,
custom_attributes: {
industry: organization.industry,
size: organization.size,
credit_card_details: organization.credit_card?,
app_count: organization.app_instances.count,
app_list: organization.app_instances.map { |app| app.name }.to_sentence
}
}

]
}
expect(users).to receive(:create).with(user_data)
end
it 'add an event when an password is changed' do
expect(events).to receive(:create).with(hash_including(email: user.email, event_name: 'user-update-password'))
subject.info('user_update_password', user.id, 'User password change', user.email, user)
end
end

end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ SECRET_KEY_BASE: <%= SecureRandom.hex(64) %>
# Google Tag Manager
google_tag_container: GTM-TH3MLB

# Intercom(Uncomment and Add a valid intercom_id to enable)
# INTERCOM_ID: intercom_id
# Intercom - uncomment and add a valid intercom_id to enable
# INTERCOM_APP_ID: intercom_app_id
# INTERCOM_API_SECRET: intercom_api_secret
# INTERCOM_API_KEY: intercom_api_key
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@
#===============================================
# Google Tag Manager
config.google_tag_container = ENV['google_tag_container']
# intercom
config.intercom_id = ENV['INTERCOM_ID']

# Intercom
config.intercom_app_id = ENV['INTERCOM_APP_ID']
config.intercom_api_secret = ENV['INTERCOM_API_SECRET']
config.intercom_api_key = ENV['INTERCOM_API_KEY']

Expand Down
14 changes: 10 additions & 4 deletions core/lib/mno_enterprise/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@
require 'config'
require 'figaro'

require "mandrill_client"

require 'mandrill_client'
require 'accountingjs_serializer'

module MnoEnterprise
Expand Down Expand Up @@ -212,15 +211,20 @@ def self.mail_adapter=(adapter)
mattr_accessor :google_tag_container
@@google_tag_container = nil

mattr_accessor :intercom_id
@@intercom_id = nil
mattr_accessor :intercom_app_id
@@intercom_app_id = nil

mattr_accessor :intercom_api_secret
@@intercom_api_secret = nil

mattr_accessor :intercom_api_key
@@intercom_api_key = nil

# Define if Intercom is enabled. Only if the gem intercom is present
def self.intercom_enabled?
defined?(::Intercom) && intercom_app_id && intercom_api_key
end

#====================================
# Layout & Styling
#====================================
Expand Down Expand Up @@ -256,6 +260,8 @@ def self.style
@@style
end



# Default way to setup MnoEnterprise. Run rails generate mno-enterprise:install to create
# a fresh initializer with all configuration values.
def self.configure
Expand Down
3 changes: 3 additions & 0 deletions rails-template/templates/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ gem 'rails', '~> 4.2.6'
# Bundle edge Mnoe instead: gem 'mno-enterprise', github: 'maestrano/mno-enterprise'
gem 'mno-enterprise', '~> 3.0'

# Enable Intercom
# gem 'intercom', '~> 3.5.4'

# Use puma as the app server
gem 'puma'

Expand Down

0 comments on commit a4366b4

Please sign in to comment.