zuora_connect-D 1.6.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +38 -0
- data/app/assets/javascripts/zuora_connect/api/v1/app_instance.js +2 -0
- data/app/assets/javascripts/zuora_connect/application.js +13 -0
- data/app/assets/stylesheets/zuora_connect/api/v1/app_instance.css +4 -0
- data/app/assets/stylesheets/zuora_connect/application.css +15 -0
- data/app/controllers/zuora_connect/admin/tenant_controller.rb +11 -0
- data/app/controllers/zuora_connect/api/v1/app_instance_controller.rb +37 -0
- data/app/controllers/zuora_connect/application_controller.rb +8 -0
- data/app/controllers/zuora_connect/static_controller.rb +26 -0
- data/app/helpers/zuora_connect/api/v1/app_instance_helper.rb +4 -0
- data/app/helpers/zuora_connect/application_helper.rb +5 -0
- data/app/models/zuora_connect/app_instance.rb +5 -0
- data/app/models/zuora_connect/app_instance_base.rb +755 -0
- data/app/models/zuora_connect/login.rb +37 -0
- data/app/views/layouts/zuora_connect/application.html.erb +14 -0
- data/app/views/sql/refresh_aggregate_table.txt +84 -0
- data/app/views/zuora_connect/static/invalid_app_instance_error.html.erb +65 -0
- data/app/views/zuora_connect/static/session_error.html.erb +63 -0
- data/config/initializers/apartment.rb +95 -0
- data/config/initializers/object_method_hooks.rb +27 -0
- data/config/initializers/redis.rb +10 -0
- data/config/initializers/resque.rb +5 -0
- data/config/initializers/to_bool.rb +24 -0
- data/config/routes.rb +12 -0
- data/db/migrate/20100718151733_create_connect_app_instances.rb +9 -0
- data/db/migrate/20101024162319_add_tokens_to_app_instance.rb +6 -0
- data/db/migrate/20101024220705_add_token_to_app_instance.rb +5 -0
- data/db/migrate/20110131211919_add_sessions_table.rb +13 -0
- data/db/migrate/20110411200303_add_expiration_to_app_instance.rb +5 -0
- data/db/migrate/20110413191512_add_new_api_token.rb +5 -0
- data/db/migrate/20110503003602_add_catalog_data_to_app_instance.rb +6 -0
- data/db/migrate/20110503003603_add_catalog_mappings_to_app_instance.rb +5 -0
- data/db/migrate/20110503003604_catalog_default.rb +5 -0
- data/db/migrate/20180301052853_add_catalog_attempted_at.rb +5 -0
- data/lib/resque/additions.rb +53 -0
- data/lib/resque/dynamic_queues.rb +142 -0
- data/lib/resque/self_lookup.rb +19 -0
- data/lib/tasks/zuora_connect_tasks.rake +24 -0
- data/lib/zuora_connect.rb +38 -0
- data/lib/zuora_connect/configuration.rb +40 -0
- data/lib/zuora_connect/controllers/helpers.rb +165 -0
- data/lib/zuora_connect/engine.rb +30 -0
- data/lib/zuora_connect/exceptions.rb +67 -0
- data/lib/zuora_connect/railtie.rb +35 -0
- data/lib/zuora_connect/version.rb +3 -0
- data/lib/zuora_connect/views/helpers.rb +9 -0
- data/test/controllers/zuora_connect/api/v1/app_instance_controller_test.rb +13 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +26 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +41 -0
- data/test/dummy/config/environments/production.rb +79 -0
- data/test/dummy/config/environments/test.rb +42 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +2 -0
- data/test/dummy/log/test.log +0 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/fixtures/zuora_connect/app_instances.yml +11 -0
- data/test/integration/navigation_test.rb +8 -0
- data/test/lib/generators/zuora_connect/datatable_generator_test.rb +16 -0
- data/test/models/zuora_connect/app_instance_test.rb +9 -0
- data/test/test_helper.rb +21 -0
- data/test/zuora_connect_test.rb +7 -0
- metadata +408 -0
@@ -0,0 +1,6 @@
|
|
1
|
+
class AddTokensToAppInstance < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
add_column :zuora_connect_app_instances, :access_token, :string unless column_exists? :zuora_connect_app_instances, :access_token
|
4
|
+
add_column :zuora_connect_app_instances, :refresh_token, :string unless column_exists? :zuora_connect_app_instances, :refresh_token
|
5
|
+
end
|
6
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class AddSessionsTable < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
if !ActiveRecord::Base.connection.table_exists?('sessions')
|
4
|
+
create_table :sessions do |t|
|
5
|
+
t.string :session_id, :null => false
|
6
|
+
t.text :data
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
add_index :sessions, :session_id, :unique => true
|
10
|
+
add_index :sessions, :updated_at
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
class AddCatalogDataToAppInstance < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
add_column :zuora_connect_app_instances, :catalog_updated_at, :datetime unless column_exists? :zuora_connect_app_instances, :catalog_updated_at
|
4
|
+
add_column :zuora_connect_app_instances, :catalog, :jsonb, default: {} unless column_exists? :zuora_connect_app_instances, :catalog
|
5
|
+
end
|
6
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Resque
|
2
|
+
module Additions
|
3
|
+
def dequeue_from(queue, klass, *args)
|
4
|
+
####### ------ Resque Job --------
|
5
|
+
# Perform before_dequeue hooks. Don't perform dequeue if any hook returns false
|
6
|
+
before_hooks = Plugin.before_dequeue_hooks(klass).collect do |hook|
|
7
|
+
klass.send(hook, *args)
|
8
|
+
end
|
9
|
+
return if before_hooks.any? { |result| result == false }
|
10
|
+
|
11
|
+
destroyed = Job.destroy(queue, klass, *args)
|
12
|
+
|
13
|
+
Plugin.after_dequeue_hooks(klass).each do |hook|
|
14
|
+
klass.send(hook, *args)
|
15
|
+
end
|
16
|
+
|
17
|
+
destroyed
|
18
|
+
end
|
19
|
+
|
20
|
+
####### ------ Resque Delayed Job --------
|
21
|
+
# Returns delayed jobs schedule timestamp for +klass+, +args+.
|
22
|
+
def scheduled_at_with_queue(queue, klass, *args)
|
23
|
+
search = encode(job_to_hash_with_queue(queue,klass, args))
|
24
|
+
redis.smembers("timestamps:#{search}").map do |key|
|
25
|
+
key.tr('delayed:', '').to_i
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Given an encoded item, remove it from the delayed_queue
|
30
|
+
def remove_delayed_with_queue(queue, klass, *args)
|
31
|
+
search = encode(job_to_hash_with_queue(queue,klass, args))
|
32
|
+
remove_delayed_job(search)
|
33
|
+
end
|
34
|
+
|
35
|
+
#Given a timestamp and job (klass + args) it removes all instances and
|
36
|
+
# returns the count of jobs removed.
|
37
|
+
#
|
38
|
+
# O(N) where N is the number of jobs scheduled to fire at the given
|
39
|
+
# timestamp
|
40
|
+
def remove_delayed_job_with_queue_from_timestamp(timestamp, queue, klass, *args)
|
41
|
+
return 0 if Resque.inline?
|
42
|
+
|
43
|
+
key = "delayed:#{timestamp.to_i}"
|
44
|
+
encoded_job = encode(job_to_hash_with_queue(queue, klass, args))
|
45
|
+
|
46
|
+
redis.srem("timestamps:#{encoded_job}", key)
|
47
|
+
count = redis.lrem(key, 0, encoded_job)
|
48
|
+
clean_up_timestamp(key, timestamp)
|
49
|
+
|
50
|
+
count
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module Resque
|
2
|
+
module DynamicQueues
|
3
|
+
def filter_busy_queues qs
|
4
|
+
busy_queues = Resque::Worker.working.map { |worker| worker.job["queue"] }.compact
|
5
|
+
Array(qs.dup).compact - busy_queues
|
6
|
+
end
|
7
|
+
|
8
|
+
def rotated_queues
|
9
|
+
@n ||= 0
|
10
|
+
@n += 1
|
11
|
+
rot_queues = queues # since we rely on the resque-dynamic-queues plugin, this is all the queues, expanded out
|
12
|
+
if rot_queues.size > 0
|
13
|
+
@n = @n % rot_queues.size
|
14
|
+
rot_queues.rotate(@n)
|
15
|
+
else
|
16
|
+
rot_queues
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def queue_depth queuename
|
21
|
+
busy_queues = Resque::Worker.working.map { |worker| worker.job["queue"] }.compact
|
22
|
+
# find the queuename, count it.
|
23
|
+
busy_queues.select {|q| q == queuename }.size
|
24
|
+
end
|
25
|
+
|
26
|
+
DEFAULT_QUEUE_DEPTH = 0
|
27
|
+
def should_work_on_queue? queuename
|
28
|
+
return true if @queues.include? '*' # workers with QUEUES=* are special and are not subject to queue depth setting
|
29
|
+
max = DEFAULT_QUEUE_DEPTH
|
30
|
+
unless ENV["RESQUE_QUEUE_DEPTH"].nil? || ENV["RESQUE_QUEUE_DEPTH"] == ""
|
31
|
+
max = ENV["RESQUE_QUEUE_DEPTH"].to_i
|
32
|
+
end
|
33
|
+
return true if max == 0 # 0 means no limiting
|
34
|
+
cur_depth = queue_depth(queuename)
|
35
|
+
log! "queue #{queuename} depth = #{cur_depth} max = #{max}"
|
36
|
+
return true if cur_depth < max
|
37
|
+
false
|
38
|
+
end
|
39
|
+
|
40
|
+
def reserve_with_round_robin
|
41
|
+
grouped_queues = queues.sort.group_by{|u| /(\d{1,20})_.*/.match(u) ? /(\d{1,20})_.*/.match(u).captures.first : nil}
|
42
|
+
|
43
|
+
#Instance queue grouping
|
44
|
+
if !grouped_queues.keys.include?(nil) && grouped_queues.keys.size > 0
|
45
|
+
@n ||= 0
|
46
|
+
@n += 1
|
47
|
+
@n = @n % grouped_queues.keys.size
|
48
|
+
|
49
|
+
grouped_queues.keys.rotate(@n).each do |key|
|
50
|
+
grouped_queues[key].each do |queue|
|
51
|
+
log! "Checking #{queue}"
|
52
|
+
if should_work_on_queue?(queue) && @job_in_progress = Resque::Job.reserve(queue)
|
53
|
+
log! "Found job on #{queue}"
|
54
|
+
return @job_in_progress
|
55
|
+
end
|
56
|
+
end
|
57
|
+
@n += 1 # Start the next search at the queue after the one from which we pick a job.
|
58
|
+
end
|
59
|
+
nil
|
60
|
+
else
|
61
|
+
return reserve_without_round_robin
|
62
|
+
end
|
63
|
+
|
64
|
+
rescue Exception => e
|
65
|
+
log "Error reserving job: #{e.inspect}"
|
66
|
+
log e.backtrace.join("\n")
|
67
|
+
raise e
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns a list of queues to use when searching for a job.
|
71
|
+
#
|
72
|
+
# A splat ("*") means you want every queue (in alpha order) - this
|
73
|
+
# can be useful for dynamically adding new queues.
|
74
|
+
#
|
75
|
+
# The splat can also be used as a wildcard within a queue name,
|
76
|
+
# e.g. "*high*", and negation can be indicated with a prefix of "!"
|
77
|
+
#
|
78
|
+
# An @key can be used to dynamically look up the queue list for key from redis.
|
79
|
+
# If no key is supplied, it defaults to the worker's hostname, and wildcards
|
80
|
+
# and negations can be used inside this dynamic queue list. Set the queue
|
81
|
+
# list for a key with Resque.set_dynamic_queue(key, ["q1", "q2"]
|
82
|
+
#
|
83
|
+
def queues_with_dynamic
|
84
|
+
queue_names = @queues.dup
|
85
|
+
|
86
|
+
return queues_without_dynamic if queue_names.grep(/(^!)|(^@)|(\*)/).size == 0
|
87
|
+
|
88
|
+
real_queues = Resque.queues
|
89
|
+
matched_queues = []
|
90
|
+
|
91
|
+
#Remove Queues under Api Limits
|
92
|
+
api_limit_instances = Redis.current.keys('APILimits:*').map {|key| key.split('APILimits:').last.to_i}
|
93
|
+
real_queues = real_queues.select {|key| key if !api_limit_instances.include?((key.match(/^(\d*)_.*/) || [])[1].to_i)} ## 2
|
94
|
+
|
95
|
+
#Queue Pausing
|
96
|
+
paused_instances = Redis.current.keys('resque:PauseQueue:*').map {|key| key.split('resque:PauseQueue:').last.to_i}
|
97
|
+
real_queues = real_queues.select {|key| key if !paused_instances.include?((key.match(/^(\d*)_.*/) || [])[1].to_i)}
|
98
|
+
|
99
|
+
while q = queue_names.shift
|
100
|
+
q = q.to_s
|
101
|
+
|
102
|
+
if q =~ /^(!)?@(.*)/
|
103
|
+
key = $2.strip
|
104
|
+
key = hostname if key.size == 0
|
105
|
+
|
106
|
+
add_queues = Resque.get_dynamic_queue(key)
|
107
|
+
add_queues.map! { |q| q.gsub!(/^!/, '') || q.gsub!(/^/, '!') } if $1
|
108
|
+
|
109
|
+
queue_names.concat(add_queues)
|
110
|
+
next
|
111
|
+
end
|
112
|
+
|
113
|
+
if q =~ /^!/
|
114
|
+
negated = true
|
115
|
+
q = q[1..-1]
|
116
|
+
end
|
117
|
+
|
118
|
+
patstr = q.gsub(/\*/, '.*')
|
119
|
+
pattern = /^#{patstr}$/
|
120
|
+
if negated
|
121
|
+
matched_queues -= matched_queues.grep(pattern)
|
122
|
+
else
|
123
|
+
matches = real_queues.grep(/^#{pattern}$/)
|
124
|
+
matches = [q] if matches.size == 0 && q == patstr
|
125
|
+
matched_queues.concat(matches.sort)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
return matched_queues.uniq
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
def self.included(receiver)
|
134
|
+
receiver.class_eval do
|
135
|
+
alias queues_without_dynamic queues
|
136
|
+
alias queues queues_with_dynamic
|
137
|
+
alias reserve_without_round_robin reserve
|
138
|
+
alias reserve reserve_with_round_robin
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Resque
|
2
|
+
module SelfLookup
|
3
|
+
def payload_class_enhanced
|
4
|
+
@payload_class ||= constantize(@payload['class'])
|
5
|
+
@payload_class.instance_eval { class << self; self end }.send(:attr_accessor, :worker)
|
6
|
+
@payload_class.instance_eval { class << self; self end }.send(:attr_accessor, :job)
|
7
|
+
@payload_class.worker = self.worker
|
8
|
+
@payload_class.job = self
|
9
|
+
return @payload_class
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.included(receiver)
|
13
|
+
receiver.class_eval do
|
14
|
+
alias payload_class_old payload_class
|
15
|
+
alias payload_class payload_class_enhanced
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# desc "Explaining what the task does"
|
2
|
+
# task :connect do
|
3
|
+
# # Task goes here
|
4
|
+
# end
|
5
|
+
|
6
|
+
namespace :db do
|
7
|
+
desc 'Also create shared_extensions Schema'
|
8
|
+
task :extensions => :environment do
|
9
|
+
# Create Schema
|
10
|
+
ActiveRecord::Base.connection.execute 'CREATE SCHEMA IF NOT EXISTS shared_extensions;'
|
11
|
+
# Enable Hstore
|
12
|
+
ActiveRecord::Base.connection.execute 'CREATE EXTENSION IF NOT EXISTS HSTORE SCHEMA shared_extensions;'
|
13
|
+
# Enable UUID-OSSP
|
14
|
+
ActiveRecord::Base.connection.execute 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp" SCHEMA shared_extensions;'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Rake::Task["db:create"].enhance do
|
19
|
+
Rake::Task["db:extensions"].invoke
|
20
|
+
end
|
21
|
+
|
22
|
+
Rake::Task["db:test:purge"].enhance do
|
23
|
+
Rake::Task["db:extensions"].invoke
|
24
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'zuora_connect/configuration'
|
2
|
+
require "zuora_connect/engine"
|
3
|
+
require 'zuora_connect/exceptions'
|
4
|
+
require 'zuora_connect/controllers/helpers'
|
5
|
+
require 'zuora_connect/views/helpers'
|
6
|
+
require 'zuora_connect/railtie'
|
7
|
+
require 'resque/additions'
|
8
|
+
require 'resque/dynamic_queues'
|
9
|
+
require 'resque/self_lookup'
|
10
|
+
|
11
|
+
module ZuoraConnect
|
12
|
+
class << self
|
13
|
+
attr_accessor :configuration
|
14
|
+
end
|
15
|
+
module Controllers
|
16
|
+
autoload :Helpers, 'zuora_connect/controllers/helpers'
|
17
|
+
end
|
18
|
+
|
19
|
+
module Views
|
20
|
+
ActionView::Base.send(:include, Helpers)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.configuration
|
24
|
+
@configuration ||= Configuration.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.reset
|
28
|
+
@configuration = Configuration.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.configure
|
32
|
+
yield(configuration)
|
33
|
+
::Apartment.excluded_models << "Delayed::Job" if configuration.delayed_job
|
34
|
+
::Apartment.excluded_models.concat(configuration.additional_apartment_models) if configuration.additional_apartment_models.class == Array
|
35
|
+
|
36
|
+
return configuration
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ZuoraConnect
|
2
|
+
class Configuration
|
3
|
+
attr_accessor :oauth_client_id, :oauth_client_secret, :oauth_client_redirect_uri,:use_s3, :default_locale,:dev_mode_appinstance ,:dev_mode_admin, :dev_mode_user, :dev_mode_pass, :default_time_zone,:delayed_job,:url, :private_key, :dev_mode_logins,:dev_mode_mode, :dev_mode_options, :mode, :timeout,:dev_mode_secret_access_key,:dev_mode_access_key_id,:aws_region, :s3_bucket_name, :s3_folder_name, :additional_apartment_models
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@default_locale = :en
|
7
|
+
@default_time_zone = Time.zone
|
8
|
+
@url = "https://connect.zuora.com"
|
9
|
+
@mode = "Production"
|
10
|
+
@delayed_job = false
|
11
|
+
@use_s3 = false
|
12
|
+
@private_key = ENV["CONNECT_KEY"]
|
13
|
+
@additional_apartment_models = []
|
14
|
+
|
15
|
+
# OAuth Settings
|
16
|
+
@oauth_client_id = ""
|
17
|
+
@oauth_client_secret = ""
|
18
|
+
@oauth_client_redirect_uri = "https://connect.zuora.com/"
|
19
|
+
|
20
|
+
# DEV MODE OPTIONS
|
21
|
+
@dev_mode_logins = { "target_login" => {"tenant_type" => "Zuora", "username" => "user", "password" => "pass", "url" => "url"} }
|
22
|
+
@dev_mode_options = {"name" => {"config_name" => "name", "datatype" => "type", "value" => "value"}}
|
23
|
+
@dev_mode_mode = "Universal"
|
24
|
+
@dev_mode_appinstance = "1"
|
25
|
+
@dev_mode_user = "test"
|
26
|
+
@dev_mode_pass = "test"
|
27
|
+
@dev_mode_admin = false
|
28
|
+
@dev_mode_secret_access_key = nil
|
29
|
+
@dev_mode_access_key_id = nil
|
30
|
+
@aws_region = "us-west-2"
|
31
|
+
@s3_bucket_name = "rbm-apps"
|
32
|
+
@s3_folder_name = Rails.application.class.parent_name
|
33
|
+
end
|
34
|
+
|
35
|
+
def private_key
|
36
|
+
raise "Private Key Not Set" if @private_key.blank?
|
37
|
+
@private_key.include?("BEGIN") ? @private_key : Base64.urlsafe_decode64(@private_key)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'apartment/migrator'
|
2
|
+
module ZuoraConnect
|
3
|
+
module Controllers
|
4
|
+
module Helpers
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def authenticate_app_api_request
|
8
|
+
#Skip session for api requests
|
9
|
+
Thread.current[:appinstance] = nil
|
10
|
+
request.session_options[:skip] = true
|
11
|
+
start_time = Time.now
|
12
|
+
if request.headers["API-Token"].present?
|
13
|
+
@appinstance = ZuoraConnect::AppInstance.where(:api_token => request.headers["API-Token"]).first
|
14
|
+
Rails.logger.debug("[#{@appinstance.id}] API REQUEST - API token") if @appinstance.present?
|
15
|
+
check_instance
|
16
|
+
else
|
17
|
+
authenticate_or_request_with_http_basic do |username, password|
|
18
|
+
@appinstance = ZuoraConnect::AppInstance.where(:token => password).first
|
19
|
+
@appinstance ||= ZuoraConnect::AppInstance.where(:api_token => password).first
|
20
|
+
Rails.logger.debug("[#{@appinstance.id}] API REQUEST - Basic Auth") if @appinstance.present?
|
21
|
+
check_instance
|
22
|
+
end
|
23
|
+
end
|
24
|
+
Rails.logger.info("[#{@appinstance.blank? ? "N/A" : @appinstance.id}] Authenticate App API Request Completed In - #{(Time.now - start_time).round(2)}s")
|
25
|
+
end
|
26
|
+
|
27
|
+
def authenticate_connect_app_request
|
28
|
+
Thread.current[:appinstance] = nil
|
29
|
+
start_time = Time.now
|
30
|
+
if ZuoraConnect.configuration.mode == "Production"
|
31
|
+
if request["data"]
|
32
|
+
setup_instance_via_data
|
33
|
+
else
|
34
|
+
setup_instance_via_session
|
35
|
+
end
|
36
|
+
else
|
37
|
+
setup_instance_via_dev_mode
|
38
|
+
end
|
39
|
+
#Call .data_lookup with the current session to retrieve session. In some cases session may be stored/cache in redis
|
40
|
+
#so data lookup provides a model method that can be overriden per app.
|
41
|
+
if params[:controller] != 'zuora_connect/api/v1/app_instance' && params[:action] != 'drop'
|
42
|
+
if @appinstance.new_session_for_ui_requests(:params => params)
|
43
|
+
@appinstance.new_session(:session => @appinstance.data_lookup(:session => session))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
PaperTrail.whodunnit = session["#{@appinstance.id}::user::email"] if defined?(PaperTrail) && session["#{@appinstance.id}::user::email"].present?
|
47
|
+
begin
|
48
|
+
I18n.locale = session["#{@appinstance.id}::user::locale"] ? session["#{@appinstance.id}::user::locale"] : @appinstance.locale
|
49
|
+
rescue I18n::InvalidLocale => ex
|
50
|
+
Rails.logger.error("Invalid Locale: #{ex.message}")
|
51
|
+
end
|
52
|
+
Time.zone = session["#{@appinstance.id}::user::timezone"] ? session["#{@appinstance.id}::user::timezone"] : @appinstance.timezone
|
53
|
+
Rails.logger.info("[#{@appinstance.blank? ? "N/A" : @appinstance.id}] Authenticate App Request Completed In - #{(Time.now - start_time).round(2)}s")
|
54
|
+
end
|
55
|
+
|
56
|
+
def persist_connect_app_session
|
57
|
+
if @appinstance.present?
|
58
|
+
if defined?(Redis.current)
|
59
|
+
@appinstance.cache_app_instance
|
60
|
+
else
|
61
|
+
session.merge!(@appinstance.save_data)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def check_connect_admin!
|
67
|
+
raise ZuoraConnect::Exceptions::AccessDenied.new("User is not an authorized admin for this application") if !session["#{@appinstance.id}::admin"]
|
68
|
+
end
|
69
|
+
|
70
|
+
def check_connect_admin
|
71
|
+
return session["#{@appinstance.id}::admin"]
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
def setup_instance_via_data
|
76
|
+
session.clear
|
77
|
+
values = JSON.parse(ZuoraConnect::AppInstance.decrypt_response(Base64.urlsafe_decode64(request["data"])))
|
78
|
+
Rails.logger.debug("Data: #{values.to_json}")
|
79
|
+
if values["param_data"]
|
80
|
+
values["param_data"].each do |k ,v|
|
81
|
+
params[k] = v
|
82
|
+
end
|
83
|
+
end
|
84
|
+
session["#{values["appInstance"]}::destroy"] = values["destroy"]
|
85
|
+
session["appInstance"] = values["appInstance"]
|
86
|
+
if values["current_user"]
|
87
|
+
session["#{values["appInstance"]}::admin"] = values["current_user"]["admin"] ? values["current_user"]["admin"] : false
|
88
|
+
session["#{values["appInstance"]}::user::timezone"] = values["current_user"]["timezone"]
|
89
|
+
session["#{values["appInstance"]}::user::locale"] = values["current_user"]["locale"]
|
90
|
+
session["#{values["appInstance"]}::user::email"] = values["current_user"]["email"]
|
91
|
+
end
|
92
|
+
|
93
|
+
Rails.logger.debug("App Params: #{values.to_json}}") if Rails.env != "production"
|
94
|
+
|
95
|
+
@appinstance = ZuoraConnect::AppInstance.where(:id => values["appInstance"].to_i).first
|
96
|
+
if @appinstance.blank?
|
97
|
+
Apartment::Tenant.switch!("public")
|
98
|
+
begin
|
99
|
+
Apartment::Tenant.create(values["appInstance"].to_s)
|
100
|
+
rescue Apartment::TenantExists => ex
|
101
|
+
Rails.logger.debug("Tenant Already Exists")
|
102
|
+
end
|
103
|
+
@appinstance = ZuoraConnect::AppInstance.new(:api_token => values[:api_token],:id => values["appInstance"].to_i, :access_token => values["access_token"].blank? ? values["user"] : values["access_token"], :token => values["refresh_token"] , :refresh_token => values["refresh_token"].blank? ? values["key"] : values["refresh_token"], :oauth_expires_at => values["expires"])
|
104
|
+
@appinstance.save(:validate => false)
|
105
|
+
else
|
106
|
+
@appinstance.access_token = values["access_token"] if !values["access_token"].blank? && @appinstance.access_token != values["access_token"]
|
107
|
+
@appinstance.refresh_token = values["refresh_token"] if !values["refresh_token"].blank? && @appinstance.refresh_token != values["refresh_token"]
|
108
|
+
@appinstance.oauth_expires_at = values["expires"] if !values["expires"].blank?
|
109
|
+
@appinstance.api_token = values["api_token"] if !values["api_token"].blank? && @appinstance.api_token != values["api_token"]
|
110
|
+
if @appinstance.access_token_changed? && @appinstance.refresh_token_changed?
|
111
|
+
@appinstance.save(:validate => false)
|
112
|
+
else
|
113
|
+
raise ZuoraConnect::Exceptions::AccessDenied.new("Authorization mistmatch. Possible tampering")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def setup_instance_via_session
|
119
|
+
if session["appInstance"].present?
|
120
|
+
@appinstance = ZuoraConnect::AppInstance.where(:id => session["appInstance"]).first
|
121
|
+
else
|
122
|
+
raise ZuoraConnect::Exceptions::SessionInvalid.new("Session Blank -- Relaunch Application")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def setup_instance_via_dev_mode
|
127
|
+
session["appInstance"] = ZuoraConnect.configuration.dev_mode_appinstance
|
128
|
+
user = ZuoraConnect.configuration.dev_mode_user
|
129
|
+
key = ZuoraConnect.configuration.dev_mode_pass
|
130
|
+
values = {:user => user , :key => key, :appinstance => session["appInstance"]}
|
131
|
+
@appinstance = ZuoraConnect::AppInstance.where(:id => values[:appinstance].to_i).first
|
132
|
+
if @appinstance.blank?
|
133
|
+
Apartment::Tenant.switch!("public")
|
134
|
+
begin
|
135
|
+
Apartment::Tenant.create(values[:appinstance].to_s)
|
136
|
+
rescue Apartment::TenantExists => ex
|
137
|
+
Apartment::Tenant.drop(values[:appinstance].to_s)
|
138
|
+
retry
|
139
|
+
end
|
140
|
+
|
141
|
+
@appinstance = ZuoraConnect::AppInstance.new(:id => values[:appinstance].to_i, :access_token => values[:user], :refresh_token => values[:key], :token => "#{values[:key]}#{values[:key]}", :api_token => "#{values[:key]}#{values[:key]}")
|
142
|
+
@appinstance.save(:validate => false)
|
143
|
+
end
|
144
|
+
if @appinstance.access_token.blank? || @appinstance.refresh_token.blank? || @appinstance.token.blank? || @appinstance.api_token.blank?
|
145
|
+
@appinstance.update_attributes!(:access_token => values["user"], :refresh_token => values["key"], :token => "#{values[:key]}#{values[:key]}", :api_token => "#{values[:key]}#{values[:key]}")
|
146
|
+
end
|
147
|
+
session["#{@appinstance.id}::admin"] = ZuoraConnect.configuration.dev_mode_admin
|
148
|
+
end
|
149
|
+
|
150
|
+
#API ONLY
|
151
|
+
def check_instance
|
152
|
+
if @appinstance.present?
|
153
|
+
if @appinstance.new_session_for_api_requests(:params => params)
|
154
|
+
@appinstance.new_session(:session => @appinstance.data_lookup(:session => session))
|
155
|
+
end
|
156
|
+
Thread.current[:appinstance] = @appinstance
|
157
|
+
PaperTrail.whodunnit = "API User" if defined?(PaperTrail)
|
158
|
+
return true
|
159
|
+
else
|
160
|
+
render text: "Access Denied", status: :unauthorized
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|