bridge_api 0.1.54 → 0.1.63

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +7 -13
  3. data/README.md +17 -0
  4. data/bridge_api.gemspec +0 -1
  5. data/lib/bridge_api.rb +7 -5
  6. data/lib/bridge_api/api_array.rb +4 -2
  7. data/lib/bridge_api/client.rb +124 -56
  8. data/lib/bridge_api/client/account.rb +2 -1
  9. data/lib/bridge_api/client/affiliation.rb +13 -11
  10. data/lib/bridge_api/client/clone_object.rb +3 -3
  11. data/lib/bridge_api/client/course_template.rb +2 -0
  12. data/lib/bridge_api/client/custom_field.rb +2 -0
  13. data/lib/bridge_api/client/data_dump.rb +2 -0
  14. data/lib/bridge_api/client/enrollment.rb +2 -0
  15. data/lib/bridge_api/client/group.rb +2 -0
  16. data/lib/bridge_api/client/learner_item.rb +2 -0
  17. data/lib/bridge_api/client/live_course.rb +2 -0
  18. data/lib/bridge_api/client/live_course_enrollment.rb +2 -0
  19. data/lib/bridge_api/client/live_course_session.rb +3 -2
  20. data/lib/bridge_api/client/manager.rb +2 -0
  21. data/lib/bridge_api/client/program.rb +3 -1
  22. data/lib/bridge_api/client/program_enrollment.rb +6 -0
  23. data/lib/bridge_api/client/role.rb +2 -0
  24. data/lib/bridge_api/client/sub_account.rb +7 -1
  25. data/lib/bridge_api/client/user.rb +6 -5
  26. data/lib/bridge_api/version.rb +3 -1
  27. data/spec/bridge_api/client/account_spec.rb +6 -6
  28. data/spec/bridge_api/client/affiliations_spec.rb +3 -2
  29. data/spec/bridge_api/client/clone_object_spec.rb +8 -9
  30. data/spec/bridge_api/client/course_template_spec.rb +2 -0
  31. data/spec/bridge_api/client/custom_field_spec.rb +2 -0
  32. data/spec/bridge_api/client/data_dump_spec.rb +2 -0
  33. data/spec/bridge_api/client/enrollment_spec.rb +2 -0
  34. data/spec/bridge_api/client/group_spec.rb +2 -0
  35. data/spec/bridge_api/client/learner_items_spec.rb +2 -0
  36. data/spec/bridge_api/client/live_course_enrollments_spec.rb +2 -0
  37. data/spec/bridge_api/client/live_course_session_spec.rb +5 -3
  38. data/spec/bridge_api/client/live_course_spec.rb +2 -0
  39. data/spec/bridge_api/client/manager_spec.rb +2 -0
  40. data/spec/bridge_api/client/program_enrollment_spec.rb +7 -0
  41. data/spec/bridge_api/client/role_spec.rb +2 -0
  42. data/spec/bridge_api/client/sub_account_spec.rb +6 -4
  43. data/spec/bridge_api/client/user_spec.rb +2 -1
  44. data/spec/bridge_api/client_spec.rb +99 -5
  45. data/spec/support/fake_bridge.rb +8 -2
  46. data/spec/test_helper.rb +3 -1
  47. metadata +53 -68
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d39d608d1b30d380fb6fdb79ad8284d5c2e2e1fd132623b89717cf94a9f9071
4
- data.tar.gz: a8a72c682e3868563aa290f61b1dabb3295e34aff8ef6d9c61cff9f927a32bba
3
+ metadata.gz: f7d6ea6a260943cb99e83ffdd26cf7c0e68d0d383ca31e7cd96a16065261903a
4
+ data.tar.gz: a8e36b9a696de1d2245dcb8bea4844a21fac2b6da185032b07101d424e66143c
5
5
  SHA512:
6
- metadata.gz: 8b93008180e1bdb8af16f4fbc88f4fa642cbe20e655fcac04dc34ea0c5ba20b1f38ef3b5c32e098224f48da463a7e7288fc7726c57232fc6e5c666d741c505b4
7
- data.tar.gz: 10af8a2e42a4ca6db28abdeba4258bf6559a4b6f4ffc3907a0fe3d0f8820015a82b92a2001e08ae25cc3af2bd0653f4de58526f0301db6f0320db96d65a11d0a
6
+ metadata.gz: c9fb10e6dc27d66c2ba3273ebfd7b0770245590256d1782be1cf9398b3a61c4ef36e2af7677da48322cabc35d0ca932a2ab3828f650b523e0ba85f71e6b3db14
7
+ data.tar.gz: a828d6bef4d11150bd2b4968fdeb81908c06e44de3ab8fb044fff5bc09c61b586d15c466b12ca41496bb5e3d1d5990ab12464691d6b6876327b7094451fd58e8
@@ -1,17 +1,16 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bridge_api (0.1.48)
4
+ bridge_api (0.1.60)
5
5
  faraday (~> 0.9.0)
6
6
  faraday_middleware (>= 0.12.2)
7
7
  footrest (>= 0.5.1)
8
- logging (>= 2.2.2)
9
8
  paul_walker (>= 0.1.1)
10
9
 
11
10
  GEM
12
11
  remote: https://rubygems.org/
13
12
  specs:
14
- activesupport (5.2.2)
13
+ activesupport (5.2.3)
15
14
  concurrent-ruby (~> 1.0, >= 1.0.2)
16
15
  i18n (>= 0.7, < 2)
17
16
  minitest (~> 5.1)
@@ -20,29 +19,24 @@ GEM
20
19
  public_suffix (>= 2.0.2, < 4.0)
21
20
  byebug (8.2.5)
22
21
  coderay (1.1.2)
23
- concurrent-ruby (1.1.3)
22
+ concurrent-ruby (1.1.5)
24
23
  crack (0.4.3)
25
24
  safe_yaml (~> 1.0.0)
26
25
  diff-lcs (1.3)
27
26
  faraday (0.9.2)
28
27
  multipart-post (>= 1.2, < 3)
29
- faraday_middleware (0.12.2)
28
+ faraday_middleware (0.13.1)
30
29
  faraday (>= 0.7.4, < 1.0)
31
30
  footrest (0.5.3)
32
31
  activesupport (>= 3.0.0)
33
32
  faraday (>= 0.9.0, < 1)
34
33
  link_header (>= 0.0.7)
35
34
  hashdiff (0.3.7)
36
- i18n (1.1.1)
35
+ i18n (1.6.0)
37
36
  concurrent-ruby (~> 1.0)
38
37
  link_header (0.0.8)
39
- little-plugger (1.1.4)
40
- logging (2.2.2)
41
- little-plugger (~> 1.1)
42
- multi_json (~> 1.10)
43
38
  method_source (0.9.0)
44
39
  minitest (5.11.3)
45
- multi_json (1.13.1)
46
40
  multipart-post (2.0.0)
47
41
  paul_walker (0.1.1)
48
42
  redis (>= 4.0)
@@ -54,7 +48,7 @@ GEM
54
48
  rack-protection (1.5.5)
55
49
  rack
56
50
  rake (0.9.6)
57
- redis (4.0.3)
51
+ redis (4.1.0)
58
52
  rspec (2.99.0)
59
53
  rspec-core (~> 2.99.0)
60
54
  rspec-expectations (~> 2.99.0)
@@ -92,4 +86,4 @@ DEPENDENCIES
92
86
  webmock (~> 1.22.6)
93
87
 
94
88
  BUNDLED WITH
95
- 1.17.1
89
+ 1.17.2
data/README.md CHANGED
@@ -25,3 +25,20 @@ instantiating several instances of `client`, you can also supply your client
25
25
  initializer with `master_rate_limit: true`. This will use a redis
26
26
  keystore to track your rate limits across all instances of `client` and
27
27
  properly throttle your application as needed.
28
+
29
+ ## Token Pools
30
+
31
+ This supports token pooling to get around rate limiting issues in bridge (but should never be used without Core approval)
32
+ To use with Tokens:
33
+ ```
34
+ client = BridgeAPI::Client.new(tokens: ['token1', 'token2'], prefix: "https://yourdomain.bridgeapp.com")
35
+ ```
36
+ To use with API Keys:
37
+ ```
38
+ client = BridgeAPI::Client.new(api_keys: {'key1' => 'secret1', 'key2' => 'secret2'}, prefix: "https://yourdomain.bridgeapp.com")
39
+ ```
40
+
41
+ The logic will start with the first token provided, and check against the redis cache to see what its current limit
42
+ is. If its already under the limit threshold, it will rotate to the next in the pool, and perform the same check. It
43
+ will do this till it finds one that is not under the threshold, and use it. If none are found, it will sleep for the
44
+ configured time, and then try to make a call.
@@ -30,6 +30,5 @@ Gem::Specification.new do |gem|
30
30
  gem.add_dependency 'faraday', '~> 0.9.0'
31
31
  gem.add_dependency 'faraday_middleware', '>= 0.12.2'
32
32
  gem.add_dependency 'footrest', '>= 0.5.1'
33
- gem.add_dependency 'logging', '>= 2.2.2'
34
33
  gem.add_dependency 'paul_walker', '>= 0.1.1'
35
34
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bridge_api/version'
2
4
  require 'bridge_api/client'
3
5
 
4
6
  module BridgeAPI
5
7
  class << self
6
- require 'logging'
7
- attr_writer :enforce_rate_limits, :rate_limit_min, :rate_limits, :max_sleep_seconds, :min_sleep_seconds,
8
+ require 'logger'
9
+ attr_writer :enforce_rate_limits, :beginning_rate_limit, :rate_limits, :max_sleep_seconds, :min_sleep_seconds,
8
10
  :logger, :master_rate_limit, :master_mutex, :rate_limit_threshold
9
11
 
10
12
  def configure
@@ -15,8 +17,8 @@ module BridgeAPI
15
17
  @enforce_rate_limits ||= false
16
18
  end
17
19
 
18
- def rate_limit_min
19
- @rate_limit_min ||= 30
20
+ def beginning_rate_limit
21
+ @beginning_rate_limit ||= 30
20
22
  end
21
23
 
22
24
  def rate_limits
@@ -41,7 +43,7 @@ module BridgeAPI
41
43
 
42
44
  def logger
43
45
  return @logger if defined? @logger
44
- @logger = Logging.logger(STDOUT)
46
+ @logger = Logger.new(STDOUT)
45
47
  @logger.level = :debug
46
48
  @logger
47
49
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module BridgeAPI
3
4
  class ApiArray
@@ -18,7 +19,7 @@ module BridgeAPI
18
19
  @linked = {}
19
20
  @meta = {}
20
21
  @extra_meta_fields = []
21
- pattern = /.*(\/api\/.*)/
22
+ pattern = %r{.*(/api/.*)}
22
23
  path = response.env.url
23
24
  matches = pattern.match(path.to_s)
24
25
  mapping = nil
@@ -67,7 +68,6 @@ module BridgeAPI
67
68
  !@next_page.nil?
68
69
  end
69
70
 
70
-
71
71
  def next_page
72
72
  load_page(@next_page)
73
73
  end
@@ -119,8 +119,10 @@ module BridgeAPI
119
119
 
120
120
  def get_response_content(response)
121
121
  return [] unless response.body.is_a?(Hash)
122
+
122
123
  content = response.body.reject { |k, _v| @meta_fields.include?(k) || @extra_meta_fields.include?(k) }
123
124
  return content.values[0] unless content.empty?
125
+
124
126
  []
125
127
  end
126
128
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'footrest/client'
2
4
  require 'faraday'
3
5
  require 'footrest'
@@ -12,60 +14,126 @@ module BridgeAPI
12
14
  class Client < Footrest::Client
13
15
  require 'bridge_api/api_array'
14
16
 
15
- DATA_DUMP_DOWNLOAD_PATH = '/data_dumps/download'.freeze
16
- DATA_DUMP_PATH = '/data_dumps'.freeze
17
- COURSE_TEMPLATE_PATH = '/course_templates'.freeze
18
- ENROLLMENT_PATH = '/enrollments'.freeze
19
- LTI_TOOLS_PATH = '/lti_tools'.freeze
20
- PROGRAM_PATH = '/programs'.freeze
21
- PROGRAM_ENROLLMENT_PATH = '/learners'.freeze
22
- USER_PATH = '/users'.freeze
23
- GROUPS_PATH = '/groups'.freeze
24
- MANAGER_PATH = '/managers'.freeze
25
- ADMIN_PATH = '/admin'.freeze
26
- AUTHOR_PATH = '/author'.freeze
27
- LEARNER_PATH = '/learner'.freeze
28
- LEARNERS_PATH = '/learners'.freeze
29
- LEARNER_ITEMS_PATH = '/learner_items'.freeze
30
- CUSTOM_FIELD_PATH = '/custom_fields'.freeze
31
- SUB_ACCOUNT_PATH = '/sub_accounts'.freeze
32
- SUPPORT_PATH = '/support'.freeze
33
- ACCOUNT_PATH = '/accounts'.freeze
34
- CLONE_OBJECTS_PATH = '/clone_objects'.freeze
35
- API_VERSION = 1
36
- API_PATH = '/api'.freeze
37
- ROLE_PATH = '/roles'.freeze
38
- AFFILIATED_SUBACCOUNTS = '/affiliated_sub_accounts'.freeze
39
- BATCH_PATH = '/batch'.freeze
40
- LIVE_COURSES_PATH = '/live_courses'.freeze
41
- SESSIONS_PATH = '/sessions'.freeze
42
- PUBLISH_PATH = '/publish'.freeze
43
- WEB_CONFERENCE_PATH = '/web_conference'.freeze
44
- RESTORE_PATH = '/restore'.freeze
45
- DUE_DATE_PATH = '/due_date'.freeze
46
- RESET_PATH = '/reset'.freeze
47
- RESULT_MAPPING = {}
17
+ DATA_DUMP_DOWNLOAD_PATH = '/data_dumps/download'
18
+ DATA_DUMP_PATH = '/data_dumps'
19
+ COURSE_TEMPLATE_PATH = '/course_templates'
20
+ ENROLLMENT_PATH = '/enrollments'
21
+ LTI_TOOLS_PATH = '/lti_tools'
22
+ PROGRAM_PATH = '/programs'
23
+ PROGRAM_ENROLLMENT_PATH = '/learners'
24
+ USER_PATH = '/users'
25
+ GROUPS_PATH = '/groups'
26
+ MANAGER_PATH = '/managers'
27
+ ADMIN_PATH = '/admin'
28
+ AUTHOR_PATH = '/author'
29
+ LEARNER_PATH = '/learner'
30
+ LEARNERS_PATH = '/learners'
31
+ LEARNER_ITEMS_PATH = '/learner_items'
32
+ CUSTOM_FIELD_PATH = '/custom_fields'
33
+ SUB_ACCOUNT_PATH = '/sub_accounts'
34
+ SUPPORT_PATH = '/support'
35
+ ACCOUNT_PATH = '/accounts'
36
+ CLONE_OBJECTS_PATH = '/clone_objects'
37
+ API_VERSION = 1
38
+ API_PATH = '/api'
39
+ ROLE_PATH = '/roles'
40
+ AFFILIATED_SUBACCOUNTS = '/affiliated_sub_accounts'
41
+ BATCH_PATH = '/batch'
42
+ LIVE_COURSES_PATH = '/live_courses'
43
+ SESSIONS_PATH = '/sessions'
44
+ PUBLISH_PATH = '/publish'
45
+ WEB_CONFERENCE_PATH = '/web_conference'
46
+ RESTORE_PATH = '/restore'
47
+ DUE_DATE_PATH = '/due_date'
48
+ RESET_PATH = '/reset'
49
+ RESULT_MAPPING = {}
48
50
 
49
51
  Dir[File.dirname(__FILE__) + '/client/*.rb'].each do |file|
50
52
  require file
51
53
  include const_get(File.basename(file).gsub('.rb', '').split('_').map(&:capitalize).join('').to_s)
52
54
  end
53
55
 
56
+ def initialize(options = {}, &block)
57
+ if BridgeAPI.enforce_rate_limits && has_token_pool?(options)
58
+ options = initialize_from_token_pool(options)
59
+ end
60
+ super
61
+ end
62
+
54
63
  # Override Footrest request for ApiArray support
55
64
  def request(method, &block)
56
- enforce_rate_limits
65
+ if has_token_pool?(config)
66
+ (config[:api_tokens] || config[:api_keys].keys).size.times do
67
+ break unless rate_limit_reached?
68
+
69
+ rotate_token!
70
+ end
71
+ end
72
+ enforce_rate_limits if rate_limit_reached?
57
73
  response = connection.send(method, &block)
58
74
  apply_rate_limits(response)
59
75
  ApiArray.process_response(response, self, RESULT_MAPPING)
60
76
  end
61
77
 
78
+ def has_token_pool?(config)
79
+ config[:api_keys].is_a?(Hash) && config[:api_keys].keys.count >= 1 ||
80
+ config[:api_tokens].is_a?(Array) && config[:api_tokens].count >= 1
81
+ end
82
+
83
+ # Since a pool is passed in, initialize first token with the first token passed in
84
+ def initialize_from_token_pool(config)
85
+ if config[:api_keys].is_a?(Hash)
86
+ creds = config[:api_keys].first
87
+ config[:api_key] ||= creds[0]
88
+ config[:api_secret] ||= creds[1]
89
+ elsif config[:api_tokens].is_a?(Array)
90
+ config[:token] ||= config[:api_tokens].first
91
+ end
92
+ config
93
+ end
94
+
95
+ # rotates to the next token in the pool (by order in which they were provided)
96
+ def rotate_token!
97
+ BridgeAPI.master_mutex.synchronize do
98
+ old_api_key = config[:api_key]
99
+ if config[:api_keys].is_a?(Hash)
100
+ keys = config[:api_keys].keys
101
+ return if keys.count <= 1
102
+
103
+ key = get_next_key(keys, config[:api_key])
104
+ config[:api_key] = key
105
+ config[:api_secret] = config[:api_keys][key]
106
+ elsif config[:api_tokens].is_a?(Array)
107
+ keys = config[:api_tokens]
108
+ return if keys.count <= 1
109
+
110
+ token = get_next_key(keys, config[:token])
111
+ config[:token] = token
112
+ end
113
+ BridgeAPI.logger.debug('rotating API Keys')
114
+ set_connection(config)
115
+ end
116
+ end
117
+
118
+ def get_next_key(keys, current_key)
119
+ i = keys.index(current_key) || -1
120
+ i = (i + 2) > keys.count ? 0 : (i + 1)
121
+ keys[i]
122
+ end
123
+
124
+ def rate_limit_reached?
125
+ return false unless BridgeAPI.enforce_rate_limits && limit_remaining.present?
126
+
127
+ limit_remaining < BridgeAPI.rate_limit_threshold
128
+ end
129
+
62
130
  def enforce_rate_limits
63
- return unless BridgeAPI.enforce_rate_limits && limit_remaining.present?
64
- return unless limit_remaining < BridgeAPI.rate_limit_threshold
65
- tts = ((BridgeAPI.rate_limit_min - limit_remaining) / 5).ceil
66
- tts = BridgeAPI.min_sleep_seconds if tts < BridgeAPI.min_sleep_seconds
67
- tts = BridgeAPI.max_sleep_seconds if tts > BridgeAPI.max_sleep_seconds
68
- message = "Bridge API rate limit minimum #{BridgeAPI.rate_limit_min} reached for key: '#{config[:api_key]}'. "\
131
+ return unless rate_limit_reached?
132
+
133
+ tts = ((BridgeAPI.beginning_rate_limit - limit_remaining) / 5).ceil
134
+ tts = BridgeAPI.min_sleep_seconds if tts < BridgeAPI.min_sleep_seconds
135
+ tts = BridgeAPI.max_sleep_seconds if tts > BridgeAPI.max_sleep_seconds
136
+ message = "Bridge API rate limit minimum #{BridgeAPI.rate_limit_threshold} reached for key: '#{config[:api_key]}'. "\
69
137
  "Sleeping for #{tts} second(s) to catch up ~zzZZ~. "\
70
138
  "Limit Remaining: #{limit_remaining}"
71
139
  BridgeAPI.logger.debug(message)
@@ -79,6 +147,7 @@ module BridgeAPI
79
147
  def apply_rate_limits(response)
80
148
  limit = response.headers['x-rate-limit-remaining']
81
149
  return if limit.nil?
150
+
82
151
  BridgeAPI.logger.debug("BRIDGE RATE LIMIT REMAINING: #{limit}")
83
152
  self.limit_remaining = limit.to_i
84
153
  end
@@ -88,8 +157,8 @@ module BridgeAPI
88
157
  BridgeAPI.master_mutex.synchronize do
89
158
  limit = PaulWalker::RateLimit.get(config[:api_key], config[:api_key])
90
159
  if limit.nil?
91
- PaulWalker::RateLimit.add(config[:api_key], config[:api_key], 0, BridgeAPI::rate_limit_min)
92
- limit = {current: 0}.with_indifferent_access
160
+ PaulWalker::RateLimit.add(config[:api_key], config[:api_key], 0, BridgeAPI.beginning_rate_limit)
161
+ limit = { current: 0 }.with_indifferent_access
93
162
  end
94
163
  limit['current']
95
164
  end
@@ -101,7 +170,7 @@ module BridgeAPI
101
170
  def limit_remaining=(value)
102
171
  if using_master_rate_limit?
103
172
  BridgeAPI.master_mutex.synchronize do
104
- PaulWalker::RateLimit.add(config[:api_key], config[:api_key], value, BridgeAPI::rate_limit_min)
173
+ PaulWalker::RateLimit.add(config[:api_key], config[:api_key], value, BridgeAPI.beginning_rate_limit)
105
174
  end
106
175
  else
107
176
  BridgeAPI.rate_limits[config[:api_key]] = value
@@ -110,26 +179,25 @@ module BridgeAPI
110
179
 
111
180
  def set_connection(config)
112
181
  config[:logger] = config[:logging] if config[:logging]
113
- @connection = Faraday.new(url: config[:prefix]) do |faraday|
114
- faraday.request :multipart
115
- faraday.request :url_encoded
182
+ @connection = Faraday.new(url: config[:prefix]) do |faraday|
183
+ faraday.request :multipart
184
+ faraday.request :url_encoded
116
185
  if config[:logger] == true
117
186
  faraday.response :logger
118
187
  elsif config[:logger]
119
188
  faraday.use Faraday::Response::Logger, config[:logger]
120
189
  end
121
- faraday.use Footrest::FollowRedirects, limit: 5 unless config[:follow_redirects] == false
122
- faraday.adapter Faraday.default_adapter
123
- faraday.use Footrest::ParseJson, content_type: /\bjson$/
124
- faraday.use Footrest::RaiseFootrestErrors
125
- faraday.use Footrest::Pagination
126
- faraday.headers[:accept] = 'application/json'
127
- faraday.headers[:authorization] = "Bearer #{config[:token]}" if config[:token]
128
- faraday.headers[:user_agent] = 'Footrest'
190
+ faraday.use Footrest::FollowRedirects, limit: 5 unless config[:follow_redirects] == false
191
+ faraday.adapter Faraday.default_adapter
192
+ faraday.use Footrest::ParseJson, content_type: /\bjson$/
193
+ faraday.use Footrest::RaiseFootrestErrors
194
+ faraday.use Footrest::Pagination
195
+ faraday.headers[:accept] = 'application/json'
196
+ faraday.headers[:user_agent] = 'Footrest'
129
197
  if config[:api_key] && config[:api_secret]
130
- faraday.headers[:authorization] = 'Basic ' + Base64.strict_encode64("#{config[:api_key]}:#{config[:api_secret]}")
198
+ faraday.headers[:authorization] = 'Basic ' + Base64.strict_encode64("#{config[:api_key]}:#{config[:api_secret]}")
131
199
  elsif config[:token]
132
- faraday.headers[:authorization] = "Bearer #{config[:token]}"
200
+ faraday.headers[:authorization] = "Bearer #{config[:token]}"
133
201
  else
134
202
  raise 'No api authorization provided'
135
203
  end
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module BridgeAPI
2
4
  class Client
3
5
  module Account
4
-
5
6
  def create_account(params = {})
6
7
  post("#{API_PATH}#{ADMIN_PATH}/sub_accounts", params)
7
8
  end
@@ -1,17 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module BridgeAPI
2
- class Client
3
- module Affiliation
4
- def list_affiliations(params = {})
5
- get("#{API_PATH}#{AUTHOR_PATH}#{AFFILIATED_SUBACCOUNTS}", params)
6
- end
4
+ class Client
5
+ module Affiliation
6
+ def list_affiliations(params = {})
7
+ get("#{API_PATH}#{AUTHOR_PATH}#{AFFILIATED_SUBACCOUNTS}", params)
8
+ end
7
9
 
8
- def revoke_affiliations_batch(params = {})
9
- put("#{API_PATH}#{AUTHOR_PATH}#{AFFILIATED_SUBACCOUNTS}/revoke_batch", params)
10
- end
10
+ def revoke_affiliations_batch(params = {})
11
+ put("#{API_PATH}#{AUTHOR_PATH}#{AFFILIATED_SUBACCOUNTS}/revoke_batch", params)
12
+ end
11
13
 
12
- def share_affiliations_batch(params = {})
13
- put("#{API_PATH}#{AUTHOR_PATH}#{AFFILIATED_SUBACCOUNTS}/share_batch", params)
14
- end
14
+ def share_affiliations_batch(params = {})
15
+ put("#{API_PATH}#{AUTHOR_PATH}#{AFFILIATED_SUBACCOUNTS}/share_batch", params)
15
16
  end
16
17
  end
17
18
  end
19
+ end