killbill-zendesk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +38 -0
- data/Gemfile +3 -0
- data/Jarfile +3 -0
- data/README.md +71 -0
- data/Rakefile +30 -0
- data/VERSION +1 -0
- data/config.ru +4 -0
- data/db/ddl.sql +10 -0
- data/db/schema.rb +13 -0
- data/killbill-zendesk.gemspec +41 -0
- data/killbill.properties +3 -0
- data/lib/zendesk/config/application.rb +36 -0
- data/lib/zendesk/user_updater.rb +115 -0
- data/lib/zendesk/user_updater_initializer.rb +44 -0
- data/lib/zendesk/zendesk_user.rb +6 -0
- data/lib/zendesk.rb +26 -0
- data/pom.xml +44 -0
- data/release.sh +28 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/zendesk/remote/integration_spec.rb +86 -0
- data/spec/zendesk/user_updater_spec.rb +34 -0
- metadata +219 -0
data/.gitignore
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
*.swp
|
4
|
+
.bundle
|
5
|
+
.config
|
6
|
+
coverage
|
7
|
+
InstalledFiles
|
8
|
+
lib/bundler/man
|
9
|
+
pkg
|
10
|
+
rdoc
|
11
|
+
spec/reports
|
12
|
+
test/tmp
|
13
|
+
test/version_tmp
|
14
|
+
tmp
|
15
|
+
|
16
|
+
# YARD artifacts
|
17
|
+
.yardoc
|
18
|
+
_yardoc
|
19
|
+
doc/
|
20
|
+
|
21
|
+
.jbundler
|
22
|
+
Jarfile.lock
|
23
|
+
Gemfile.lock
|
24
|
+
|
25
|
+
.DS_Store
|
26
|
+
|
27
|
+
# Build directory
|
28
|
+
killbill-zendesk/
|
29
|
+
|
30
|
+
# Config file
|
31
|
+
zendesk.yml
|
32
|
+
|
33
|
+
target
|
34
|
+
pom.xml.asc
|
35
|
+
|
36
|
+
.idea/
|
37
|
+
|
38
|
+
test.db
|
data/Gemfile
ADDED
data/Jarfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
killbill-zendesk-plugin
|
2
|
+
=======================
|
3
|
+
|
4
|
+
Plugin to mirror Kill Bill data into Zendesk.
|
5
|
+
|
6
|
+
User data mapping
|
7
|
+
-----------------
|
8
|
+
|
9
|
+
<table>
|
10
|
+
<tr>
|
11
|
+
<th>Zendesk attribute</th><th>Value</th>
|
12
|
+
</tr>
|
13
|
+
<tr>
|
14
|
+
<td>name</td><td><em>Kill Bill account name</em></td>
|
15
|
+
</tr>
|
16
|
+
<tr>
|
17
|
+
<td>external_id</td><td><em>Kill Bill account external key</em> if specified, <em>Kill Bill account id</em> otherwise</td>
|
18
|
+
</tr>
|
19
|
+
<tr>
|
20
|
+
<td>locale</td><td><em>Kill Bill account locale</em></td>
|
21
|
+
</tr>
|
22
|
+
<tr>
|
23
|
+
<td>time_zone</td><td><em>Kill Bill account timezone</em></td>
|
24
|
+
</tr>
|
25
|
+
<tr>
|
26
|
+
<td>email</td><td><em>Kill Bill account email</em></td>
|
27
|
+
</tr>
|
28
|
+
<tr>
|
29
|
+
<td>phone</td><td><em>Kill Bill account phone</em></td>
|
30
|
+
</tr>
|
31
|
+
<tr>
|
32
|
+
<td>details</td><td><em>Kill Bill account address1</em>, <em>Kill Bill account address2</em>, <em>Kill Bill account city</em>, <em>Kill Bill account state or province</em>, <em>Kill Bill account postal code</em>, <em>Kill Bill account country</em></td>
|
33
|
+
</tr>
|
34
|
+
</table>
|
35
|
+
|
36
|
+
|
37
|
+
Requirements
|
38
|
+
------------
|
39
|
+
|
40
|
+
The plugin needs a database to keep a local mapping between Kill Bill account ids and Zendesk user ids (this is to work around indexing delays in Zendesk). The latest version of the schema can be found here: https://raw.github.com/killbill/killbill-zendesk-plugin/master/db/ddl.sql.
|
41
|
+
|
42
|
+
|
43
|
+
Configuration
|
44
|
+
-------------
|
45
|
+
|
46
|
+
The plugin expects a `zendesk.yml` configuration file containing the following:
|
47
|
+
|
48
|
+
```
|
49
|
+
:zendesk:
|
50
|
+
:subdomain: 'mysubdomain'
|
51
|
+
:username: 'email@domain.com'
|
52
|
+
:password: 'password'
|
53
|
+
# Alternatively, to use Token Authentication or OAuth
|
54
|
+
#token: 'kX53RIXZKUFhZxSYhRxe7QGFocTkDmmERDxpcddF'
|
55
|
+
#access_token: 'kX53RIXZKUFhZxSYhRxe7QGFocTkDmmERDxpcddF'
|
56
|
+
# Optional
|
57
|
+
# :retry: true
|
58
|
+
|
59
|
+
:database:
|
60
|
+
:adapter: 'sqlite3'
|
61
|
+
:database: 'test.db'
|
62
|
+
# For MySQL
|
63
|
+
# :adapter: 'jdbc'
|
64
|
+
# :username: 'your-username'
|
65
|
+
# :password: 'your-password'
|
66
|
+
# :driver: 'com.mysql.jdbc.Driver'
|
67
|
+
# :url: 'jdbc:mysql://127.0.0.1:3306/your-database'
|
68
|
+
```
|
69
|
+
|
70
|
+
By default, the plugin will look at the plugin directory root (where `killbill.properties` is located) to find this file.
|
71
|
+
Alternatively, set the Kill Bill system property `-Dcom.ning.billing.osgi.bundles.jruby.conf.dir=/my/directory` to specify another location.
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
|
3
|
+
# Install tasks to build and release the plugin
|
4
|
+
require 'bundler/setup'
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
|
7
|
+
# Install test tasks
|
8
|
+
require 'rspec/core/rake_task'
|
9
|
+
namespace :test do
|
10
|
+
desc 'Run RSpec tests'
|
11
|
+
RSpec::Core::RakeTask.new do |task|
|
12
|
+
task.name = 'spec'
|
13
|
+
task.pattern = './spec/*/*_spec.rb'
|
14
|
+
end
|
15
|
+
|
16
|
+
namespace :remote do
|
17
|
+
desc 'Run RSpec remote tests'
|
18
|
+
RSpec::Core::RakeTask.new do |task|
|
19
|
+
task.name = 'spec'
|
20
|
+
task.pattern = './spec/*/remote/*_spec.rb'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Install tasks to package the plugin for Killbill
|
26
|
+
require 'killbill/rake_task'
|
27
|
+
Killbill::PluginHelper.install_tasks
|
28
|
+
|
29
|
+
# Run tests by default
|
30
|
+
task :default => 'test:spec'
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/config.ru
ADDED
data/db/ddl.sql
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
CREATE TABLE `zendesk_users` (
|
2
|
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
3
|
+
`kb_account_id` varchar(255) NOT NULL,
|
4
|
+
`zd_user_id` int(11) NOT NULL,
|
5
|
+
`created_at` datetime NOT NULL,
|
6
|
+
`updated_at` datetime NOT NULL,
|
7
|
+
PRIMARY KEY (`id`),
|
8
|
+
UNIQUE KEY `index_zendesk_users_on_kb_account_id` (`kb_account_id`),
|
9
|
+
UNIQUE KEY `index_zendesk_users_on_zd_user_id` (`zd_user_id`)
|
10
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
data/db/schema.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
ActiveRecord::Schema.define(:version => 20130606153635) do
|
4
|
+
create_table 'zendesk_users', :force => true do |t|
|
5
|
+
t.string 'kb_account_id', :null => false
|
6
|
+
t.integer 'zd_user_id', :null => false
|
7
|
+
t.datetime 'created_at', :null => false
|
8
|
+
t.datetime 'updated_at', :null => false
|
9
|
+
end
|
10
|
+
|
11
|
+
add_index(:zendesk_users, :kb_account_id, :unique => true)
|
12
|
+
add_index(:zendesk_users, :zd_user_id, :unique => true)
|
13
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
version = File.read(File.expand_path('../VERSION', __FILE__)).strip
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'killbill-zendesk'
|
5
|
+
s.version = version
|
6
|
+
s.summary = 'Plugin to mirror Kill Bill data into Zendesk'
|
7
|
+
s.description = 'Kill Bill notification plugin for Zendesk.'
|
8
|
+
|
9
|
+
s.required_ruby_version = '>= 1.9.3'
|
10
|
+
|
11
|
+
s.license = 'Apache License (2.0)'
|
12
|
+
|
13
|
+
s.author = 'Kill Bill core team'
|
14
|
+
s.email = 'killbilling-users@googlegroups.com'
|
15
|
+
s.homepage = 'http://kill-bill.org'
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.bindir = 'bin'
|
20
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
21
|
+
s.require_paths = ["lib"]
|
22
|
+
|
23
|
+
s.rdoc_options << '--exclude' << '.'
|
24
|
+
|
25
|
+
s.add_dependency 'killbill', '~> 1.0.19'
|
26
|
+
s.add_dependency 'sinatra', '~> 1.3.4'
|
27
|
+
s.add_dependency 'zendesk_api', '~> 0.3.10'
|
28
|
+
s.add_dependency 'activerecord', '~> 3.2.1'
|
29
|
+
if defined?(JRUBY_VERSION)
|
30
|
+
s.add_dependency 'activerecord-jdbcmysql-adapter', '~> 1.2.9'
|
31
|
+
end
|
32
|
+
|
33
|
+
s.add_development_dependency 'jbundler', '~> 0.4.1'
|
34
|
+
s.add_development_dependency 'rake', '>= 10.0.0'
|
35
|
+
s.add_development_dependency 'rspec', '~> 2.12.0'
|
36
|
+
if defined?(JRUBY_VERSION)
|
37
|
+
s.add_development_dependency 'activerecord-jdbcsqlite3-adapter', '~> 1.2.6'
|
38
|
+
else
|
39
|
+
s.add_development_dependency 'sqlite3', '~> 1.3.7'
|
40
|
+
end
|
41
|
+
end
|
data/killbill.properties
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
configure do
|
2
|
+
# Usage: rackup -Ilib -E test
|
3
|
+
if (development? or test?) and !Killbill::Zendesk::UserUpdaterInitializer.instance.initialized?
|
4
|
+
require 'logger'
|
5
|
+
Killbill::Zendesk::UserUpdaterInitializer.instance.initialize! File.expand_path(File.dirname(__FILE__) + '../../../../'),
|
6
|
+
nil,
|
7
|
+
Logger.new(STDOUT)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# curl -v -d'webrick=stupid' -XPUT http://127.0.0.1:9292/plugins/killbill-zendesk/users/6939c8c0-cf89-11e2-8b8b-0800200c9a66
|
12
|
+
put '/plugins/killbill-zendesk/users/:id' do
|
13
|
+
zendesk_user_url = Killbill::Zendesk::UserUpdaterInitializer.instance.updater.update(params[:id])
|
14
|
+
|
15
|
+
if zendesk_user_url
|
16
|
+
redirect zendesk_user_url
|
17
|
+
else
|
18
|
+
status 500, "Unable to update Zendesk user for id #{params[:id]}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# curl -v http://127.0.0.1:9292/plugins/killbill-zendesk/users/6939c8c0-cf89-11e2-8b8b-0800200c9a66
|
23
|
+
# Given a Kill Bill account id or Zendesk user id, retrieve the Kill Bill - Zendesk mapping
|
24
|
+
get '/plugins/killbill-zendesk/users/:id', :provides => 'json' do
|
25
|
+
if params[:id] =~ /[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}/
|
26
|
+
mapping = Killbill::Zendesk::ZendeskUser.find_by_kb_account_id(params[:id])
|
27
|
+
else
|
28
|
+
mapping = Killbill::Zendesk::ZendeskUser.find_by_zd_user_id(params[:id])
|
29
|
+
end
|
30
|
+
|
31
|
+
if mapping
|
32
|
+
mapping.to_json
|
33
|
+
else
|
34
|
+
status 404
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module Killbill::Zendesk
|
2
|
+
class UserUpdater
|
3
|
+
def initialize(client, kb_apis, logger)
|
4
|
+
@client = client
|
5
|
+
@kb_apis = kb_apis
|
6
|
+
@logger = logger
|
7
|
+
end
|
8
|
+
|
9
|
+
def update(lookup_key)
|
10
|
+
kb_account = lookup_kb_account(lookup_key)
|
11
|
+
|
12
|
+
user = find_by_kb_account(kb_account)
|
13
|
+
user = create_user(kb_account) if user.nil?
|
14
|
+
|
15
|
+
user.name = kb_account.name
|
16
|
+
user.external_id = kb_account.external_key || kb_account.id.to_s
|
17
|
+
user.locale = kb_account.locale
|
18
|
+
user.timezone = kb_account.time_zone
|
19
|
+
user.email = kb_account.email
|
20
|
+
user.phone = kb_account.phone
|
21
|
+
user.details = build_details_field(kb_account)
|
22
|
+
|
23
|
+
if user.save
|
24
|
+
@logger.info "Successfully updated #{user.name} in Zendesk: #{user.url}"
|
25
|
+
user.url
|
26
|
+
else
|
27
|
+
@logger.warn "Unable to update #{user.name} in Zendesk: #{user.url}"
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Find the Kill Bill account associated with that lookup_key (account id or external key)
|
33
|
+
def lookup_kb_account(lookup_key)
|
34
|
+
if lookup_key.is_a?(Killbill::Plugin::Model::UUID)
|
35
|
+
@kb_apis.get_account_by_id(lookup_key)
|
36
|
+
else
|
37
|
+
lookup_key_s = lookup_key.to_s
|
38
|
+
if lookup_key_s =~ /[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}/
|
39
|
+
lookup_kb_account(Killbill::Plugin::Model::UUID.new(lookup_key_s))
|
40
|
+
else
|
41
|
+
@kb_apis.get_account_by_key(lookup_key_s)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Build the Zendesk details field (address information)
|
47
|
+
def build_details_field(kb_account)
|
48
|
+
details = [kb_account.address1, kb_account.address2, kb_account.city, kb_account.state_or_province, kb_account.postal_code, kb_account.country]
|
49
|
+
(details.reject { |detail| detail.blank? }).join(', ')
|
50
|
+
end
|
51
|
+
|
52
|
+
# Create a user in Zendesk and save the id mapping locally
|
53
|
+
def create_user(kb_account)
|
54
|
+
# Create the user in Zendesk
|
55
|
+
user = @client.users.create(:name => kb_account.name)
|
56
|
+
|
57
|
+
# Save the mapping locally - this is required due to the indexing lag on the Zendesk side,
|
58
|
+
# see https://support.zendesk.com/entries/20239737:
|
59
|
+
# When you add new data to your Zendesk, it typically takes about 2 to 3 minutes before it's indexed and can be searched.
|
60
|
+
# This is unacceptable for us: if an account creation event is quickly followed by a account update event,
|
61
|
+
# we wouldn't be able to retrieve the user, potentially causing duplicates and/or triggering validation errors, e.g.
|
62
|
+
# Email 1370587241-test@tester.com is already being used by another user
|
63
|
+
ZendeskUser.create! :kb_account_id => kb_account.id.to_s, :zd_user_id => user.id
|
64
|
+
|
65
|
+
user
|
66
|
+
end
|
67
|
+
|
68
|
+
# Find the Zendesk user associated with that Kill Bill account
|
69
|
+
def find_by_kb_account(kb_account)
|
70
|
+
# Do we have already a mapping for that user?
|
71
|
+
zd_account = find_by_id(kb_account.id.to_s)
|
72
|
+
return zd_account if zd_account
|
73
|
+
|
74
|
+
# TODO In the search results below, should we worry about potential dups?
|
75
|
+
|
76
|
+
# First search by external_id, which is the safest method.
|
77
|
+
# The external_id is either the account external key...
|
78
|
+
zd_account = find_by_external_id(kb_account.external_key) if kb_account.external_key
|
79
|
+
return zd_account if zd_account
|
80
|
+
|
81
|
+
# ...or the Kill Bill account id
|
82
|
+
zd_account = find_by_external_id(kb_account.id.to_s)
|
83
|
+
return zd_account if zd_account
|
84
|
+
|
85
|
+
# At this point, we haven't matched this user yet. To reconcile it, use the email address which is guaranteed
|
86
|
+
# to exist on the Zendesk side
|
87
|
+
zd_account = find_by_email(kb_account.email) if kb_account.email
|
88
|
+
return zd_account if zd_account
|
89
|
+
|
90
|
+
# We couldn't find a match - the account will be created
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
|
94
|
+
def find_by_id(kb_account_id)
|
95
|
+
zd_user = ZendeskUser.find_by_kb_account_id(kb_account_id)
|
96
|
+
zd_user ? @client.users.find(:id => zd_user.zd_user_id) : nil
|
97
|
+
end
|
98
|
+
|
99
|
+
def find_by_external_id(external_id)
|
100
|
+
find_all_by_external_id(external_id).first
|
101
|
+
end
|
102
|
+
|
103
|
+
def find_all_by_external_id(external_id)
|
104
|
+
@client.search(:query => "type:user external_id:#{external_id}", :reload => true)
|
105
|
+
end
|
106
|
+
|
107
|
+
def find_by_email(email)
|
108
|
+
find_all_by_email(email).first
|
109
|
+
end
|
110
|
+
|
111
|
+
def find_all_by_email(email)
|
112
|
+
@client.search(:query => "type:user email:#{email}", :reload => true)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Killbill::Zendesk
|
2
|
+
class UserUpdaterInitializer
|
3
|
+
include Singleton
|
4
|
+
|
5
|
+
attr_reader :updater
|
6
|
+
|
7
|
+
def initialize!(conf_dir, kb_apis, logger)
|
8
|
+
# Parse the config file
|
9
|
+
begin
|
10
|
+
@config = YAML.load_file("#{conf_dir}/zendesk.yml")
|
11
|
+
rescue Errno::ENOENT
|
12
|
+
logger.warn "Unable to find the config file #{conf_dir}/zendesk.yml"
|
13
|
+
return
|
14
|
+
end
|
15
|
+
|
16
|
+
client = ZendeskAPI::Client.new do |config|
|
17
|
+
config.url = "https://#{@config[:zendesk][:subdomain]}.zendesk.com/api/v2"
|
18
|
+
|
19
|
+
config.username = @config[:zendesk][:username]
|
20
|
+
config.password = @config[:zendesk][:password]
|
21
|
+
config.token = @config[:zendesk][:token]
|
22
|
+
# Not yet available?
|
23
|
+
#config.access_token = @config[:zendesk][:access_token]
|
24
|
+
config.retry = true if @config[:zendesk][:retry]
|
25
|
+
|
26
|
+
config.logger = logger
|
27
|
+
end
|
28
|
+
|
29
|
+
if defined?(JRUBY_VERSION)
|
30
|
+
# See https://github.com/jruby/activerecord-jdbc-adapter/issues/302
|
31
|
+
require 'jdbc/mysql'
|
32
|
+
Jdbc::MySQL.load_driver(:require) if Jdbc::MySQL.respond_to?(:load_driver)
|
33
|
+
end
|
34
|
+
|
35
|
+
ActiveRecord::Base.establish_connection(@config[:database])
|
36
|
+
|
37
|
+
@updater = UserUpdater.new(client, kb_apis, logger)
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialized?
|
41
|
+
!@updater.nil?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/zendesk.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'sinatra'
|
3
|
+
|
4
|
+
require 'killbill'
|
5
|
+
require 'zendesk_api'
|
6
|
+
|
7
|
+
require 'zendesk/zendesk_user'
|
8
|
+
require 'zendesk/user_updater'
|
9
|
+
require 'zendesk/user_updater_initializer'
|
10
|
+
|
11
|
+
module Killbill::Zendesk
|
12
|
+
class ZendeskPlugin < Killbill::Plugin::Notification
|
13
|
+
|
14
|
+
# For testing
|
15
|
+
attr_reader :updater
|
16
|
+
|
17
|
+
def start_plugin
|
18
|
+
super
|
19
|
+
@updater = Killbill::Zendesk::UserUpdaterInitializer.instance.initialize!(@conf_dir, @kb_apis, @logger)
|
20
|
+
end
|
21
|
+
|
22
|
+
def on_event(event)
|
23
|
+
@updater.update(event.account_id) if [:ACCOUNT_CREATION, :ACCOUNT_CHANGE].include?(event.event_type.enum)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/pom.xml
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!--
|
3
|
+
~ Copyright 2010-2013 Ning, Inc.
|
4
|
+
~
|
5
|
+
~ Ning licenses this file to you under the Apache License, version 2.0
|
6
|
+
~ (the "License"); you may not use this file except in compliance with the
|
7
|
+
~ License. You may obtain a copy of the License at:
|
8
|
+
~
|
9
|
+
~ http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
~
|
11
|
+
~ Unless required by applicable law or agreed to in writing, software
|
12
|
+
~ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
13
|
+
~ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
14
|
+
~ License for the specific language governing permissions and limitations
|
15
|
+
~ under the License.
|
16
|
+
-->
|
17
|
+
|
18
|
+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
19
|
+
<parent>
|
20
|
+
<groupId>org.sonatype.oss</groupId>
|
21
|
+
<artifactId>oss-parent</artifactId>
|
22
|
+
<version>5</version>
|
23
|
+
</parent>
|
24
|
+
<modelVersion>4.0.0</modelVersion>
|
25
|
+
<groupId>com.ning.killbill.ruby</groupId>
|
26
|
+
<artifactId>zendesk-plugin</artifactId>
|
27
|
+
<packaging>pom</packaging>
|
28
|
+
<version>0.1.0</version>
|
29
|
+
<name>zendesk-plugin</name>
|
30
|
+
<url>http://github.com/killbill/killbill-zendesk-plugin</url>
|
31
|
+
<description>Plugin to mirror Kill Bill data into Zendesk</description>
|
32
|
+
<licenses>
|
33
|
+
<license>
|
34
|
+
<name>Apache License 2.0</name>
|
35
|
+
<url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
|
36
|
+
<distribution>repo</distribution>
|
37
|
+
</license>
|
38
|
+
</licenses>
|
39
|
+
<scm>
|
40
|
+
<connection>scm:git:git://github.com/killbill/killbill-zendesk-plugin.git</connection>
|
41
|
+
<url>https://github.com/killbill/killbill-zendesk-plugin/</url>
|
42
|
+
<developerConnection>scm:git:git@github.com:killbill/killbill-zendesk-plugin.git</developerConnection>
|
43
|
+
</scm>
|
44
|
+
</project>
|
data/release.sh
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
set -e
|
2
|
+
|
3
|
+
VERSION=`grep -E '<version>([0-9]+\.[0-9]+\.[0-9]+)</version>' pom.xml | sed 's/[\t \n]*<version>\(.*\)<\/version>[\t \n]*/\1/'`
|
4
|
+
if [ "$VERSION" != "$(cat $PWD/VERSION)" ]; then
|
5
|
+
echo "Unable to release: make sure the versions in pom.xml and VERSION match"
|
6
|
+
exit 1
|
7
|
+
fi
|
8
|
+
|
9
|
+
echo "Cleaning up"
|
10
|
+
rake killbill:clean ; rake build
|
11
|
+
|
12
|
+
echo "Pushing the gem to Rubygems"
|
13
|
+
rake release
|
14
|
+
|
15
|
+
echo "Building artifact"
|
16
|
+
rake killbill:package
|
17
|
+
|
18
|
+
ARTIFACT="$PWD/pkg/killbill-zendesk-$VERSION.tar.gz"
|
19
|
+
echo "Pushing $ARTIFACT to Maven Central"
|
20
|
+
mvn gpg:sign-and-deploy-file \
|
21
|
+
-DgroupId=com.ning.killbill.ruby \
|
22
|
+
-DartifactId=zendesk-plugin \
|
23
|
+
-Dversion=$VERSION \
|
24
|
+
-Dpackaging=tar.gz \
|
25
|
+
-DrepositoryId=ossrh-releases \
|
26
|
+
-Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ \
|
27
|
+
-Dfile=$ARTIFACT \
|
28
|
+
-DpomFile=pom.xml
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
require 'zendesk'
|
3
|
+
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
require 'rspec'
|
7
|
+
|
8
|
+
RSpec.configure do |config|
|
9
|
+
config.color_enabled = true
|
10
|
+
config.tty = true
|
11
|
+
config.formatter = 'documentation'
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'active_record'
|
15
|
+
ActiveRecord::Base.establish_connection(
|
16
|
+
:adapter => 'sqlite3',
|
17
|
+
:database => 'test.db'
|
18
|
+
)
|
19
|
+
# Create the schema
|
20
|
+
require File.expand_path(File.dirname(__FILE__) + '../../db/schema.rb')
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class KillbillApiWithFakeGetAccountById < Killbill::Plugin::KillbillApi
|
4
|
+
def initialize(*args)
|
5
|
+
super(*args)
|
6
|
+
@accounts = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_account(id, external_key, name, email)
|
10
|
+
@accounts[id.to_s] = Killbill::Plugin::Model::Account.new(id, nil, nil, nil, external_key, name, 1, email, 1, 'USD', nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, false, true)
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_account_by_id(id)
|
14
|
+
@accounts[id.to_s]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class MockEvent
|
19
|
+
attr_reader :event_type
|
20
|
+
attr_reader :account_id
|
21
|
+
|
22
|
+
def initialize(event_type, account_id)
|
23
|
+
@event_type = event_type
|
24
|
+
@account_id = account_id
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe Killbill::Zendesk::ZendeskPlugin do
|
29
|
+
before(:each) do
|
30
|
+
@plugin = Killbill::Zendesk::ZendeskPlugin.new
|
31
|
+
@plugin.conf_dir = File.expand_path(File.dirname(__FILE__) + '../../../../')
|
32
|
+
|
33
|
+
logger = Logger.new(STDOUT)
|
34
|
+
logger.level = Logger::DEBUG
|
35
|
+
@plugin.logger = logger
|
36
|
+
|
37
|
+
@plugin.kb_apis = KillbillApiWithFakeGetAccountById.new(nil)
|
38
|
+
|
39
|
+
@plugin.start_plugin
|
40
|
+
end
|
41
|
+
|
42
|
+
after(:each) do
|
43
|
+
@plugin.stop_plugin
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should be able to create and update a user' do
|
47
|
+
external_key, kb_account_id = create_kb_account
|
48
|
+
|
49
|
+
# Verify the initial state of our table
|
50
|
+
Killbill::Zendesk::ZendeskUser.count.should == 0
|
51
|
+
|
52
|
+
# Verify the account doesn't exist yet
|
53
|
+
@plugin.updater.find_by_external_id(external_key).should be_nil
|
54
|
+
|
55
|
+
# Send a creation event
|
56
|
+
@plugin.on_event MockEvent.new(Killbill::Plugin::Model::ExtBusEventType.new(:ACCOUNT_CREATION), kb_account_id)
|
57
|
+
|
58
|
+
# We should now verify the account exists, but we can't, due to indexing lag :/
|
59
|
+
#@plugin.updater.find_by_external_id(external_key).email.should == email
|
60
|
+
# Instead, we use our table
|
61
|
+
Killbill::Zendesk::ZendeskUser.count.should == 1
|
62
|
+
|
63
|
+
# Send an update event
|
64
|
+
@plugin.on_event MockEvent.new(Killbill::Plugin::Model::ExtBusEventType.new(:ACCOUNT_CHANGE), kb_account_id)
|
65
|
+
|
66
|
+
# Verify we didn't create dups
|
67
|
+
#@plugin.updater.find_all_by_external_id(external_key).count.should == 1
|
68
|
+
Killbill::Zendesk::ZendeskUser.count.should == 1
|
69
|
+
|
70
|
+
# Create a new user
|
71
|
+
external_key, kb_account_id = create_kb_account
|
72
|
+
@plugin.on_event MockEvent.new(Killbill::Plugin::Model::ExtBusEventType.new(:ACCOUNT_CREATION), kb_account_id)
|
73
|
+
|
74
|
+
Killbill::Zendesk::ZendeskUser.count.should == 2
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def create_kb_account
|
80
|
+
external_key = Time.now.to_i.to_s + '-test'
|
81
|
+
kb_account_id = Killbill::Plugin::Model::UUID.new(external_key)
|
82
|
+
email = external_key + '@tester.com'
|
83
|
+
@plugin.kb_apis.create_account(kb_account_id, external_key, 'Test tester', email)
|
84
|
+
return external_key, kb_account_id
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Killbill::Zendesk::UserUpdater do
|
4
|
+
it 'should build the details line' do
|
5
|
+
updater = Killbill::Zendesk::UserUpdater.new(nil, nil, nil)
|
6
|
+
|
7
|
+
account = build_account(nil, nil, nil, nil, nil, nil)
|
8
|
+
updater.build_details_field(account).should == ''
|
9
|
+
|
10
|
+
account = build_account('493 Slro road', nil, nil, nil, nil, nil)
|
11
|
+
updater.build_details_field(account).should == '493 Slro road'
|
12
|
+
|
13
|
+
account = build_account('493 Slro road', nil, 'Fola', nil, nil, nil)
|
14
|
+
updater.build_details_field(account).should == '493 Slro road, Fola'
|
15
|
+
|
16
|
+
account = build_account('493 Slro road', nil, 'Fola', 'FG', nil, nil)
|
17
|
+
updater.build_details_field(account).should == '493 Slro road, Fola, FG'
|
18
|
+
|
19
|
+
account = build_account('493 Slro road', nil, 'Fola', 'FG', 140, nil)
|
20
|
+
updater.build_details_field(account).should == '493 Slro road, Fola, FG, 140'
|
21
|
+
|
22
|
+
account = build_account('493 Slro road', 'apt 33', 'Fola', 'FG', 140, nil)
|
23
|
+
updater.build_details_field(account).should == '493 Slro road, apt 33, Fola, FG, 140'
|
24
|
+
|
25
|
+
account = build_account('493 Slro road', 'apt 33', 'Fola', 'FG', 140, 'Floq')
|
26
|
+
updater.build_details_field(account).should == '493 Slro road, apt 33, Fola, FG, 140, Floq'
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def build_account(address1, address2, city, state_or_province, postal_code, country)
|
32
|
+
Killbill::Plugin::Model::Account.new(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, address1, address2, nil, city, state_or_province, postal_code, country, nil, nil, nil)
|
33
|
+
end
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,219 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: killbill-zendesk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kill Bill core team
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-06-07 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: killbill
|
16
|
+
version_requirements: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 1.0.19
|
21
|
+
none: false
|
22
|
+
requirement: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.0.19
|
27
|
+
none: false
|
28
|
+
prerelease: false
|
29
|
+
type: :runtime
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: sinatra
|
32
|
+
version_requirements: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - "~>"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 1.3.4
|
37
|
+
none: false
|
38
|
+
requirement: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.3.4
|
43
|
+
none: false
|
44
|
+
prerelease: false
|
45
|
+
type: :runtime
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: zendesk_api
|
48
|
+
version_requirements: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - "~>"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 0.3.10
|
53
|
+
none: false
|
54
|
+
requirement: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - "~>"
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: 0.3.10
|
59
|
+
none: false
|
60
|
+
prerelease: false
|
61
|
+
type: :runtime
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: activerecord
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 3.2.1
|
69
|
+
none: false
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 3.2.1
|
75
|
+
none: false
|
76
|
+
prerelease: false
|
77
|
+
type: :runtime
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: activerecord-jdbcmysql-adapter
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - "~>"
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: 1.2.9
|
85
|
+
none: false
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 1.2.9
|
91
|
+
none: false
|
92
|
+
prerelease: false
|
93
|
+
type: :runtime
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: jbundler
|
96
|
+
version_requirements: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - "~>"
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: 0.4.1
|
101
|
+
none: false
|
102
|
+
requirement: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - "~>"
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: 0.4.1
|
107
|
+
none: false
|
108
|
+
prerelease: false
|
109
|
+
type: :development
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: rake
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 10.0.0
|
117
|
+
none: false
|
118
|
+
requirement: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 10.0.0
|
123
|
+
none: false
|
124
|
+
prerelease: false
|
125
|
+
type: :development
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: rspec
|
128
|
+
version_requirements: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - "~>"
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: 2.12.0
|
133
|
+
none: false
|
134
|
+
requirement: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 2.12.0
|
139
|
+
none: false
|
140
|
+
prerelease: false
|
141
|
+
type: :development
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: activerecord-jdbcsqlite3-adapter
|
144
|
+
version_requirements: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - "~>"
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: 1.2.6
|
149
|
+
none: false
|
150
|
+
requirement: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - "~>"
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: 1.2.6
|
155
|
+
none: false
|
156
|
+
prerelease: false
|
157
|
+
type: :development
|
158
|
+
description: Kill Bill notification plugin for Zendesk.
|
159
|
+
email: killbilling-users@googlegroups.com
|
160
|
+
executables: []
|
161
|
+
extensions: []
|
162
|
+
extra_rdoc_files: []
|
163
|
+
files:
|
164
|
+
- ".gitignore"
|
165
|
+
- Gemfile
|
166
|
+
- Jarfile
|
167
|
+
- README.md
|
168
|
+
- Rakefile
|
169
|
+
- VERSION
|
170
|
+
- config.ru
|
171
|
+
- db/ddl.sql
|
172
|
+
- db/schema.rb
|
173
|
+
- killbill-zendesk.gemspec
|
174
|
+
- killbill.properties
|
175
|
+
- lib/zendesk.rb
|
176
|
+
- lib/zendesk/config/application.rb
|
177
|
+
- lib/zendesk/user_updater.rb
|
178
|
+
- lib/zendesk/user_updater_initializer.rb
|
179
|
+
- lib/zendesk/zendesk_user.rb
|
180
|
+
- pom.xml
|
181
|
+
- release.sh
|
182
|
+
- spec/spec_helper.rb
|
183
|
+
- spec/zendesk/remote/integration_spec.rb
|
184
|
+
- spec/zendesk/user_updater_spec.rb
|
185
|
+
homepage: http://kill-bill.org
|
186
|
+
licenses:
|
187
|
+
- Apache License (2.0)
|
188
|
+
post_install_message:
|
189
|
+
rdoc_options:
|
190
|
+
- "--exclude"
|
191
|
+
- "."
|
192
|
+
require_paths:
|
193
|
+
- lib
|
194
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
195
|
+
requirements:
|
196
|
+
- - ">="
|
197
|
+
- !ruby/object:Gem::Version
|
198
|
+
version: 1.9.3
|
199
|
+
none: false
|
200
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
201
|
+
requirements:
|
202
|
+
- - ">="
|
203
|
+
- !ruby/object:Gem::Version
|
204
|
+
segments:
|
205
|
+
- 0
|
206
|
+
version: !binary |-
|
207
|
+
MA==
|
208
|
+
hash: 2
|
209
|
+
none: false
|
210
|
+
requirements: []
|
211
|
+
rubyforge_project:
|
212
|
+
rubygems_version: 1.8.24
|
213
|
+
signing_key:
|
214
|
+
specification_version: 3
|
215
|
+
summary: Plugin to mirror Kill Bill data into Zendesk
|
216
|
+
test_files:
|
217
|
+
- spec/spec_helper.rb
|
218
|
+
- spec/zendesk/remote/integration_spec.rb
|
219
|
+
- spec/zendesk/user_updater_spec.rb
|