3scale_client 2.0.1 → 2.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{3scale_client}
8
- s.version = "2.0.1"
8
+ s.version = "2.2.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Adam Cig\303\241nek"]
12
- s.date = %q{2010-04-28}
11
+ s.authors = ["Adam Cigánek"]
12
+ s.date = %q{2010-09-15}
13
13
  s.description = %q{This gem allows to easily connect an application that provides a Web Service with the 3scale API Management System to authorize it's users and report the usage.
14
14
  }
15
15
  s.email = %q{adam@3scale.net}
@@ -23,9 +23,9 @@ Gem::Specification.new do |s|
23
23
  "README.rdoc",
24
24
  "Rakefile",
25
25
  "VERSION",
26
- "lib/three_scale/authorize_response.rb",
27
- "lib/three_scale/client.rb",
28
- "lib/three_scale/response.rb",
26
+ "lib/3scale/authorize_response.rb",
27
+ "lib/3scale/client.rb",
28
+ "lib/3scale/response.rb",
29
29
  "test/client_test.rb",
30
30
  "test/remote_test.rb"
31
31
  ]
data/README.rdoc CHANGED
@@ -1,15 +1,10 @@
1
1
  = Client for 3scale web service management system API
2
2
 
3
- This library provides client for the 3scale web service management API.
4
-
3
+ Please note: This version of the library targets the new API, which is currently in beta phase. Please contact 3scale support as support@3scale.net before you use it. You can also use older version (2.0.1) targeting the old API: http://github.com/3scale/3scale_ws_api_for_ruby/tree/v2.0.1.
4
+
5
5
  == Installation
6
6
 
7
- This library is distributed as a gem. First, add gemcutter to your gem source list,
8
- unless it's already there:
9
-
10
- gem source --add http://gemcutter.org
11
-
12
- Then install the gem:
7
+ This library is distributed as a gem:
13
8
 
14
9
  gem install 3scale_client
15
10
 
@@ -32,10 +27,10 @@ Because the object is stateless, you can create just one and store it globally.
32
27
 
33
28
  === Authorize
34
29
 
35
- To authorize a particular user, call the +authorize+ method passing it the user key
36
- identifiing the user:
30
+ To authorize an application, call the +authorize+ method passing it the application's id and
31
+ optionally a key:
37
32
 
38
- response = client.authorize(:user_key => "the user key")
33
+ response = client.authorize(:app_id => "the app id", :app_id => "the app key")
39
34
 
40
35
  Then call the +success?+ method on the returned object to see if the authorization was
41
36
  successful.
@@ -43,57 +38,55 @@ successful.
43
38
  if response.success?
44
39
  # All fine, proceeed.
45
40
  else
46
- # Something's wrong with this user.
41
+ # Something's wrong with this application.
47
42
  end
48
43
 
49
- If the authorization succeeded, the response object contains additional information about
50
- the status of the user:
44
+ If both provider key and app id are valid, the response object contains additional
45
+ information about the status of the application:
51
46
 
52
- # Returns the name of the plan the user is signed up to.
47
+ # Returns the name of the plan the application is signed up to.
53
48
  response.plan
54
49
 
55
- If the plan has defined usage limits, the response contains details about how close the user
56
- is to meet these limits:
50
+ If the plan has defined usage limits, the response contains details about the usage broken
51
+ down by the metrics and usage limit periods.
57
52
 
58
- # The usages array contains one element per each usage limit defined on the plan.
59
- usage = response.usages[0]
53
+ # The usage_reports array contains one element per each usage limit defined on the plan.
54
+ usage_report = response.usage_reports[0]
60
55
 
61
56
  # The metric
62
- usage.metric # "hits"
57
+ usage_report.metric # "hits"
63
58
 
64
59
  # The period the limit applies to
65
- usage.period # :day
66
- usage.period_start # "Wed Apr 28 00:00:00 +0200 2010"
67
- usage.period_end # "Wed Apr 28 23:59:59 +0200 2010"
60
+ usage_report.period # :day
61
+ usage_report.period_start # "Wed Apr 28 00:00:00 +0200 2010"
62
+ usage_report.period_end # "Wed Apr 28 23:59:59 +0200 2010"
68
63
 
69
- # The current value the user already consumed in the period
70
- usage.current_value # 8032
64
+ # The current value the application already consumed in the period
65
+ usage_report.current_value # 8032
71
66
 
72
67
  # The maximal value allowed by the limit in the period
73
- usage.max_value # 10000
74
-
75
- If the authorization failed, the +errors+ method contains one or more errors with more
76
- detailed information:
77
-
78
- error = response.errors[0]
68
+ usage_report.max_value # 10000
79
69
 
80
- # Error code
81
- error.code # "user.exceeded_limits"
70
+ # If the limit is exceeded, this will be true, otherwise false:
71
+ usage_report.exceeded? # false
82
72
 
83
- # Human readable error message
84
- error.message # "Usage limits are exceeded"
73
+ If the authorization failed, the +error_code+ returns system error code and +error_message+
74
+ human readable error description:
75
+
76
+ response.error_code # "usage_limits_exceeded"
77
+ response.error_message # "Usage limits are exceeded"
85
78
 
86
79
  === Report
87
80
 
88
81
  To report usage, use the +report+ method. You can report multiple transaction at the same time:
89
82
 
90
- response = client.report({:user_key => "first user's key", :usage => {'hits' => 1}},
91
- {:user_key => "second user's key", :usage => {'hits' => 1}})
83
+ response = client.report({:app_id => "first app id", :usage => {'hits' => 1}},
84
+ {:app_id => "second app id", :usage => {'hits' => 1}})
92
85
 
93
- The :user_key and :usage parameters are required. Additionaly, you can specify a timestamp
86
+ The :app_id and :usage parameters are required. Additionaly, you can specify a timestamp
94
87
  of transaction:
95
88
 
96
- response = client.report({:user_key => "user's key", :usage => {'hits' => 1},
89
+ response = client.report({:app_id => "app id", :usage => {'hits' => 1},
97
90
  :timestamp => Time.local(2010, 4, 28, 12, 36)})
98
91
 
99
92
  The timestamp can be either a Time object (from ruby's standard library) or something that
@@ -111,19 +104,14 @@ successful.
111
104
  if response.success?
112
105
  # All OK.
113
106
  else
114
- # There were some errors
107
+ # There was an error.
115
108
  end
116
109
 
117
- If the report was successful, you are done. Otherwise, the +errors+ method will return array
118
- of errors with more detailed information. Each of these errors has the +index+ attribute that
119
- returns numeric index of the transaction this error corresponds to. For example, if you report
120
- three transactions, first two are ok and the last one has invalid user key, there will be
121
- an error in the +errors+ array with the +index+ equal to 2 (the indices start at 0):
110
+ In case of error, the +error_code+ returns system error code and +error_message+
111
+ human readable error description:
122
112
 
123
- error = response.errors[0]
124
- error.index # 2
125
- error.code # "user.invalid_key"
126
- error.message # "User key is invalid"
113
+ response.error_code # "provider_key_invalid"
114
+ response.error_message # "provider key \"foo\" is invalid"
127
115
 
128
116
  == Legal
129
117
 
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'rake'
2
4
  require 'rake/testtask'
3
5
  require 'rake/rdoctask'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.1
1
+ 2.2.4
@@ -2,14 +2,14 @@ require 'time'
2
2
 
3
3
  module ThreeScale
4
4
  class AuthorizeResponse < Response
5
- def initialize(options = {})
6
- super({:success => true}.merge(options))
7
- @usages = options[:usages] || []
5
+ def initialize
6
+ super
7
+ @usage_reports = []
8
8
  end
9
9
 
10
10
  attr_accessor :plan
11
11
 
12
- class Usage
12
+ class UsageReport
13
13
  attr_reader :metric
14
14
  attr_reader :period
15
15
  attr_reader :current_value
@@ -28,12 +28,16 @@ module ThreeScale
28
28
  def period_end
29
29
  @parsed_period_end ||= @period_end && Time.parse(@period_end)
30
30
  end
31
+
32
+ def exceeded?
33
+ current_value > max_value
34
+ end
31
35
  end
32
36
 
33
- attr_reader :usages
37
+ attr_reader :usage_reports
34
38
 
35
- def add_usage(options)
36
- @usages << Usage.new(options)
39
+ def add_usage_report(options)
40
+ @usage_reports << UsageReport.new(options)
37
41
  end
38
42
  end
39
43
  end
@@ -3,8 +3,8 @@ require 'uri'
3
3
  require 'net/http'
4
4
  require 'nokogiri'
5
5
 
6
- require 'three_scale/response'
7
- require 'three_scale/authorize_response'
6
+ require '3scale/response'
7
+ require '3scale/authorize_response'
8
8
 
9
9
  module ThreeScale
10
10
  Error = Class.new(RuntimeError)
@@ -24,10 +24,10 @@ module ThreeScale
24
24
  #
25
25
  # client = ThreeScale::Client.new(:provider_key => "your provider key")
26
26
  #
27
- # response = client.authorize(:user_key => "yout user's key")
27
+ # response = client.authorize(:app_id => "an app id", :app_key => "a secret key")
28
28
  #
29
29
  # if response.success?
30
- # response = client.report(:user_key => "your user's key", :usage => {"hits" => 1})
30
+ # response = client.report(:app_id => "some app id", :usage => {"hits" => 1})
31
31
  #
32
32
  # if response.success?
33
33
  # # all fine.
@@ -37,7 +37,7 @@ module ThreeScale
37
37
  # end
38
38
  #
39
39
  class Client
40
- DEFAULT_HOST = 'server.3scale.net'
40
+ DEFAULT_HOST = 'su1.3scale.net'
41
41
 
42
42
  def initialize(options)
43
43
  if options[:provider_key].nil? || options[:provider_key] =~ /^\s*$/
@@ -58,7 +58,7 @@ module ThreeScale
58
58
  # The parameters the transactions to report. Each transaction is a hash with
59
59
  # these elements:
60
60
  #
61
- # user_key:: API key of the user to report the transaction for. This parameter is
61
+ # app_id:: ID of the application to report the transaction for. This parameter is
62
62
  # required.
63
63
  # usage:: Hash of usage values. The keys are metric names and values are
64
64
  # correspoding numeric values. Example: {'hits' => 1, 'transfer' => 1024}.
@@ -81,12 +81,12 @@ module ThreeScale
81
81
  #
82
82
  # == Examples
83
83
  #
84
- # # Report two transactions of two users.
85
- # client.report({:user_key => 'foo', :usage => {'hits' => 1}},
86
- # {:user_key => 'bar', :usage => {'hits' => 1}})
84
+ # # Report two transactions of two applications.
85
+ # client.report({:app_id => 'foo', :usage => {'hits' => 1}},
86
+ # {:app_id => 'bar', :usage => {'hits' => 1}})
87
87
  #
88
88
  # # Report one transaction with timestamp.
89
- # client.report({:user_key => 'foo',
89
+ # client.report({:app_id => 'foo',
90
90
  # :timestamp => Time.local(2010, 4, 27, 15, 14),
91
91
  # :usage => {'hits' => 1})
92
92
  #
@@ -97,34 +97,42 @@ module ThreeScale
97
97
  payload['provider_key'] = CGI.escape(provider_key)
98
98
 
99
99
  uri = URI.parse("http://#{host}/transactions.xml")
100
-
101
- process_response(Net::HTTP.post_form(uri, payload)) do |http_response|
102
- Response.new(:success => true)
100
+ http_response = Net::HTTP.post_form(uri, payload)
101
+
102
+ case http_response
103
+ when Net::HTTPSuccess
104
+ build_report_response
105
+ when Net::HTTPClientError
106
+ build_error_response(http_response.body)
107
+ else
108
+ raise ServerError.new(http_response)
103
109
  end
104
110
  end
105
111
 
106
- # Authorize a user.
112
+ # Authorize an application.
107
113
  #
108
114
  # == Parameters
109
115
  #
110
116
  # Hash with options:
111
117
  #
112
- # user_key:: API key of the user to authorize. This is required.
118
+ # app_id:: id of the application to authorize. This is required.
119
+ # app_key:: secret key assigned to the application. Required only if application has
120
+ # a key defined.
113
121
  #
114
122
  # == Return
115
123
  #
116
124
  # An ThreeScale::AuthorizeResponse object. It's +success?+ method returns true if
117
- # the authorization is successful. In that case, it contains additional information
118
- # about the status of the use. See the ThreeScale::AuthorizeResponse for more information.
119
- # In case of error, the +success?+ method returns false and the +errors+ contains list
120
- # of errors with more details.
125
+ # the authorization is successful, false otherwise. It contains additional information
126
+ # about the status of the usage. See the ThreeScale::AuthorizeResponse for more information.
127
+ # In case of error, the +error_code+ returns code of the error and +error_message+
128
+ # human readable error description.
121
129
  #
122
130
  # In case of unexpected internal server error, this method raises a ThreeScale::ServerError
123
131
  # exception.
124
132
  #
125
133
  # == Examples
126
134
  #
127
- # response = client.authorize(:user_key => 'foo')
135
+ # response = client.authorize(:app_id => '1234')
128
136
  #
129
137
  # if response.success?
130
138
  # # All good. Proceed...
@@ -133,21 +141,15 @@ module ThreeScale
133
141
  def authorize(options)
134
142
  path = "/transactions/authorize.xml" +
135
143
  "?provider_key=#{CGI.escape(provider_key)}" +
136
- "&user_key=#{CGI.escape(options[:user_key].to_s)}"
144
+ "&app_id=#{CGI.escape(options[:app_id].to_s)}"
145
+ path += "&app_key=#{CGI.escape(options[:app_key])}" if options[:app_key]
137
146
 
138
147
  uri = URI.parse("http://#{host}#{path}")
148
+ http_response = Net::HTTP.get_response(uri)
139
149
 
140
- process_response(Net::HTTP.get_response(uri)) do |http_response|
141
- build_authorize_response(http_response.body)
142
- end
143
- end
144
-
145
- private
146
-
147
- def process_response(http_response)
148
150
  case http_response
149
151
  when Net::HTTPSuccess
150
- yield(http_response)
152
+ build_authorize_response(http_response.body)
151
153
  when Net::HTTPClientError
152
154
  build_error_response(http_response.body)
153
155
  else
@@ -155,11 +157,13 @@ module ThreeScale
155
157
  end
156
158
  end
157
159
 
160
+ private
161
+
158
162
  def encode_transactions(transactions)
159
163
  result = {}
160
164
 
161
165
  transactions.each_with_index do |transaction, index|
162
- append_encoded_value(result, index, [:user_key], transaction[:user_key])
166
+ append_encoded_value(result, index, [:app_id], transaction[:app_id])
163
167
  append_encoded_value(result, index, [:timestamp], transaction[:timestamp])
164
168
  append_encoded_value(result, index, [:client_ip], transaction[:client_ip])
165
169
 
@@ -175,38 +179,42 @@ module ThreeScale
175
179
  result["transactions[#{index}][#{names.join('][')}]"] = CGI.escape(value.to_s) if value
176
180
  end
177
181
 
182
+ def build_report_response
183
+ response = Response.new
184
+ response.success!
185
+ response
186
+ end
187
+
178
188
  def build_authorize_response(body)
179
189
  response = AuthorizeResponse.new
180
190
  doc = Nokogiri::XML(body)
181
191
 
192
+ if doc.at_css('authorized').content == 'true'
193
+ response.success!
194
+ else
195
+ response.error!(doc.at_css('reason').content)
196
+ end
197
+
182
198
  response.plan = doc.at_css('plan').content.to_s.strip
183
199
 
184
- doc.css('usage').each do |node|
185
- response.add_usage(:metric => node['metric'].to_s.strip,
186
- :period => node['period'].to_s.strip.to_sym,
187
- :period_start => node.at('period_start').content,
188
- :period_end => node.at('period_end').content,
189
- :current_value => node.at('current_value').content.to_i,
190
- :max_value => node.at('max_value').content.to_i)
200
+ doc.css('usage_reports usage_report').each do |node|
201
+ response.add_usage_report(:metric => node['metric'].to_s.strip,
202
+ :period => node['period'].to_s.strip.to_sym,
203
+ :period_start => node.at('period_start').content,
204
+ :period_end => node.at('period_end').content,
205
+ :current_value => node.at('current_value').content.to_i,
206
+ :max_value => node.at('max_value').content.to_i)
191
207
  end
192
208
 
193
209
  response
194
210
  end
195
211
 
196
212
  def build_error_response(body)
197
- response = Response.new(:success => false)
198
213
  doc = Nokogiri::XML(body)
199
-
200
- doc.css('error').each do |node|
201
- response.add_error(node['index'].to_i,
202
-
203
- # Backwards compatibility: error code is sometimes in
204
- # the "id" attribute.
205
- node['code'] || node['id'],
206
-
207
- node.content.to_s.strip)
208
- end
209
-
214
+ node = doc.at_css('error')
215
+
216
+ response = Response.new
217
+ response.error!(node.content.to_s.strip, node['code'].to_s.strip)
210
218
  response
211
219
  end
212
220
  end
@@ -0,0 +1,24 @@
1
+ module ThreeScale
2
+ class Response
3
+ def success!
4
+ @error_code = nil
5
+ @error_message = nil
6
+ end
7
+
8
+ def error!(message, code = nil)
9
+ @error_code = code
10
+ @error_message = message
11
+ end
12
+
13
+ def success?
14
+ @error_code.nil? && @error_message.nil?
15
+ end
16
+
17
+ # System error code.
18
+ attr_reader :error_code
19
+
20
+ # Human readable error message.
21
+ attr_reader :error_message
22
+ end
23
+ end
24
+
data/test/client_test.rb CHANGED
@@ -2,7 +2,7 @@ require 'test/unit'
2
2
  require 'fakeweb'
3
3
  require 'mocha'
4
4
 
5
- require 'three_scale/client'
5
+ require '3scale/client'
6
6
 
7
7
  class ThreeScale::ClientTest < Test::Unit::TestCase
8
8
  def setup
@@ -10,6 +10,7 @@ class ThreeScale::ClientTest < Test::Unit::TestCase
10
10
  FakeWeb.allow_net_connect = false
11
11
 
12
12
  @client = ThreeScale::Client.new(:provider_key => '1234abcd')
13
+ @host = ThreeScale::Client::DEFAULT_HOST
13
14
  end
14
15
 
15
16
  def test_raises_exception_if_provider_key_is_missing
@@ -21,69 +22,114 @@ class ThreeScale::ClientTest < Test::Unit::TestCase
21
22
  def test_default_host
22
23
  client = ThreeScale::Client.new(:provider_key => '1234abcd')
23
24
 
24
- assert_equal 'server.3scale.net', client.host
25
+ assert_equal 'su1.3scale.net', client.host
25
26
  end
26
27
 
27
28
  def test_successful_authorize
28
29
  body = '<status>
30
+ <authorized>true</authorized>
29
31
  <plan>Ultimate</plan>
30
-
31
- <usage metric="hits" period="day">
32
- <period_start>2010-04-26 00:00:00</period_start>
33
- <period_end>2010-04-26 23:59:59</period_end>
34
- <current_value>10023</current_value>
35
- <max_value>50000</max_value>
36
- </usage>
37
-
38
- <usage metric="hits" period="month">
39
- <period_start>2010-04-01 00:00:00</period_start>
40
- <period_end>2010-04-30 23:59:59</period_end>
41
- <current_value>999872</current_value>
42
- <max_value>150000</max_value>
43
- </usage>
32
+
33
+ <usage_reports>
34
+ <usage_report metric="hits" period="day">
35
+ <period_start>2010-04-26 00:00:00 +0000</period_start>
36
+ <period_end>2010-04-27 00:00:00 +0000</period_end>
37
+ <current_value>10023</current_value>
38
+ <max_value>50000</max_value>
39
+ </usage_report>
40
+
41
+ <usage_report metric="hits" period="month">
42
+ <period_start>2010-04-01 00:00:00 +0000</period_start>
43
+ <period_end>2010-05-01 00:00:00 +0000</period_end>
44
+ <current_value>999872</current_value>
45
+ <max_value>150000</max_value>
46
+ </usage_report>
47
+ </usage_reports>
44
48
  </status>'
45
49
 
46
- FakeWeb.register_uri(:get, 'http://server.3scale.net/transactions/authorize.xml?provider_key=1234abcd&user_key=foo', :status => ['200', 'OK'], :body => body)
50
+ FakeWeb.register_uri(:get, "http://#{@host}/transactions/authorize.xml?provider_key=1234abcd&app_id=foo", :status => ['200', 'OK'], :body => body)
47
51
 
48
- response = @client.authorize(:user_key => 'foo')
52
+ response = @client.authorize(:app_id => 'foo')
49
53
 
50
54
  assert response.success?
51
55
  assert_equal 'Ultimate', response.plan
52
- assert_equal 2, response.usages.size
56
+ assert_equal 2, response.usage_reports.size
53
57
 
54
- assert_equal :day, response.usages[0].period
55
- assert_equal Time.local(2010, 4, 26), response.usages[0].period_start
56
- assert_equal Time.local(2010, 4, 26, 23, 59, 59), response.usages[0].period_end
57
- assert_equal 10023, response.usages[0].current_value
58
- assert_equal 50000, response.usages[0].max_value
59
-
60
- assert_equal :month, response.usages[1].period
61
- assert_equal Time.local(2010, 4, 1), response.usages[1].period_start
62
- assert_equal Time.local(2010, 4, 30, 23, 59, 59), response.usages[1].period_end
63
- assert_equal 999872, response.usages[1].current_value
64
- assert_equal 150000, response.usages[1].max_value
58
+ assert_equal :day, response.usage_reports[0].period
59
+ assert_equal Time.utc(2010, 4, 26), response.usage_reports[0].period_start
60
+ assert_equal Time.utc(2010, 4, 27), response.usage_reports[0].period_end
61
+ assert_equal 10023, response.usage_reports[0].current_value
62
+ assert_equal 50000, response.usage_reports[0].max_value
63
+
64
+ assert_equal :month, response.usage_reports[1].period
65
+ assert_equal Time.utc(2010, 4, 1), response.usage_reports[1].period_start
66
+ assert_equal Time.utc(2010, 5, 1), response.usage_reports[1].period_end
67
+ assert_equal 999872, response.usage_reports[1].current_value
68
+ assert_equal 150000, response.usage_reports[1].max_value
65
69
  end
70
+
71
+ def test_successful_authorize_with_app_keys
72
+ body = '<status>
73
+ <authorized>true</authorized>
74
+ <plan>Ultimate</plan>
75
+ </status>'
76
+
77
+ FakeWeb.register_uri(:get, "http://#{@host}/transactions/authorize.xml?provider_key=1234abcd&app_id=foo&app_key=toosecret", :status => ['200', 'OK'], :body => body)
66
78
 
67
- def test_failed_authorize
68
- error_body = '<error code="user.exceeded_limits">
69
- usage limits are exceeded
70
- </error>'
79
+ response = @client.authorize(:app_id => 'foo', :app_key => 'toosecret')
80
+ assert response.success?
81
+ end
82
+
83
+ def test_authorize_with_exceeded_usage_limits
84
+ body = '<status>
85
+ <authorized>false</authorized>
86
+ <reason>usage limits are exceeded</reason>
87
+
88
+ <plan>Ultimate</plan>
89
+
90
+ <usage_reports>
91
+ <usage_report metric="hits" period="day" exceeded="true">
92
+ <period_start>2010-04-26 00:00:00 +0000</period_start>
93
+ <period_end>2010-04-27 00:00:00 +0000</period_end>
94
+ <current_value>50002</current_value>
95
+ <max_value>50000</max_value>
96
+ </usage_report>
97
+
98
+ <usage_report metric="hits" period="month">
99
+ <period_start>2010-04-01 00:00:00 +0000</period_start>
100
+ <period_end>2010-05-01 00:00:00 +0000</period_end>
101
+ <current_value>999872</current_value>
102
+ <max_value>150000</max_value>
103
+ </usage_report>
104
+ </usage_reports>
105
+ </status>'
106
+
107
+ FakeWeb.register_uri(:get, "http://#{@host}/transactions/authorize.xml?provider_key=1234abcd&app_id=foo", :status => ['200', 'OK'], :body => body)
71
108
 
72
- FakeWeb.register_uri(:get, 'http://server.3scale.net/transactions/authorize.xml?provider_key=1234abcd&user_key=foo', :status => ['403', 'Forbidden'], :body => error_body)
109
+ response = @client.authorize(:app_id => 'foo')
110
+
111
+ assert !response.success?
112
+ assert_equal 'usage limits are exceeded', response.error_message
113
+ assert response.usage_reports[0].exceeded?
114
+ end
115
+
116
+ def test_authorize_with_invalid_app_id
117
+ body = '<error code="application_not_found">application with id="foo" was not found</error>'
73
118
 
74
- response = @client.authorize(:user_key => 'foo')
119
+ FakeWeb.register_uri(:get, "http://#{@host}/transactions/authorize.xml?provider_key=1234abcd&app_id=foo", :status => ['403', 'Forbidden'], :body => body)
120
+
121
+ response = @client.authorize(:app_id => 'foo')
75
122
 
76
123
  assert !response.success?
77
- assert_equal 1, response.errors.size
78
- assert_equal 'user.exceeded_limits', response.errors[0].code
79
- assert_equal 'usage limits are exceeded', response.errors[0].message
124
+ assert_equal 'application_not_found', response.error_code
125
+ assert_equal 'application with id="foo" was not found', response.error_message
80
126
  end
81
127
 
82
128
  def test_authorize_with_server_error
83
- FakeWeb.register_uri(:get, 'http://server.3scale.net/transactions/authorize.xml?provider_key=1234abcd&user_key=foo', :status => ['500', 'Internal Server Error'], :body => 'OMG! WTF!')
129
+ FakeWeb.register_uri(:get, "http://#{@host}/transactions/authorize.xml?provider_key=1234abcd&app_id=foo", :status => ['500', 'Internal Server Error'], :body => 'OMG! WTF!')
84
130
 
85
131
  assert_raise ThreeScale::ServerError do
86
- @client.authorize(:user_key => 'foo')
132
+ @client.authorize(:app_id => 'foo')
87
133
  end
88
134
  end
89
135
 
@@ -94,10 +140,10 @@ class ThreeScale::ClientTest < Test::Unit::TestCase
94
140
  end
95
141
 
96
142
  def test_successful_report
97
- FakeWeb.register_uri(:post, 'http://server.3scale.net/transactions.xml',
143
+ FakeWeb.register_uri(:post, "http://#{@host}/transactions.xml",
98
144
  :status => ['200', 'OK'])
99
145
 
100
- response = @client.report({:user_key => 'foo',
146
+ response = @client.report({:app_id => 'foo',
101
147
  :timestamp => Time.local(2010, 4, 27, 15, 00),
102
148
  :usage => {'hits' => 1}})
103
149
 
@@ -111,59 +157,45 @@ class ThreeScale::ClientTest < Test::Unit::TestCase
111
157
  Net::HTTP.expects(:post_form).
112
158
  with(anything,
113
159
  'provider_key' => '1234abcd',
114
- 'transactions[0][user_key]' => 'foo',
160
+ 'transactions[0][app_id]' => 'foo',
115
161
  'transactions[0][usage][hits]' => '1',
116
162
  'transactions[0][timestamp]' => CGI.escape('2010-04-27 15:42:17 0200'),
117
- 'transactions[1][user_key]' => 'bar',
163
+ 'transactions[1][app_id]' => 'bar',
118
164
  'transactions[1][usage][hits]' => '1',
119
165
  'transactions[1][timestamp]' => CGI.escape('2010-04-27 15:55:12 0200')).
120
166
  returns(http_response)
121
167
 
122
- @client.report({:user_key => 'foo',
168
+ @client.report({:app_id => 'foo',
123
169
  :usage => {'hits' => 1},
124
170
  :timestamp => '2010-04-27 15:42:17 0200'},
125
171
 
126
- {:user_key => 'bar',
172
+ {:app_id => 'bar',
127
173
  :usage => {'hits' => 1},
128
174
  :timestamp => '2010-04-27 15:55:12 0200'})
129
175
  end
130
176
 
131
177
  def test_failed_report
132
- error_body = '<errors>
133
- <error code="user.invalid_key" index="0">
134
- user key is invalid
135
- </error>
136
- <error code="provider.invalid_metric" index="1">
137
- metric does not exist
138
- </error>
139
- </errors>'
140
-
141
- FakeWeb.register_uri(:post, 'http://server.3scale.net/transactions.xml',
178
+ error_body = '<error code="provider_key_invalid">provider key "foo" is invalid</error>'
179
+
180
+ FakeWeb.register_uri(:post, "http://#{@host}/transactions.xml",
142
181
  :status => ['403', 'Forbidden'],
143
182
  :body => error_body)
144
183
 
145
- response = @client.report({:user_key => 'bogus', :usage => {'hits' => 1}},
146
- {:user_key => 'bar', :usage => {'monkeys' => 1000000000}})
184
+ client = ThreeScale::Client.new(:provider_key => 'foo')
185
+ response = client.report({:app_id => 'abc', :usage => {'hits' => 1}})
147
186
 
148
187
  assert !response.success?
149
- assert_equal 2, response.errors.size
150
-
151
- assert_equal 0, response.errors[0].index
152
- assert_equal 'user.invalid_key', response.errors[0].code
153
- assert_equal 'user key is invalid', response.errors[0].message
154
-
155
- assert_equal 1, response.errors[1].index
156
- assert_equal 'provider.invalid_metric', response.errors[1].code
157
- assert_equal 'metric does not exist', response.errors[1].message
188
+ assert_equal 'provider_key_invalid', response.error_code
189
+ assert_equal 'provider key "foo" is invalid', response.error_message
158
190
  end
159
191
 
160
192
  def test_report_with_server_error
161
- FakeWeb.register_uri(:post, 'http://server.3scale.net/transactions.xml',
193
+ FakeWeb.register_uri(:post, "http://#{@host}/transactions.xml",
162
194
  :status => ['500', 'Internal Server Error'],
163
195
  :body => 'OMG! WTF!')
164
196
 
165
197
  assert_raise ThreeScale::ServerError do
166
- @client.report({:user_key => 'foo', :usage => {'hits' => 1}})
198
+ @client.report({:app_id => 'foo', :usage => {'hits' => 1}})
167
199
  end
168
200
  end
169
201
  end
data/test/remote_test.rb CHANGED
@@ -1,11 +1,17 @@
1
1
  require 'test/unit'
2
- require 'three_scale/client'
2
+ require '3scale/client'
3
3
 
4
- if ENV['TEST_3SCALE_PROVIDER_KEY'] && ENV['TEST_3SCALE_USER_KEYS']
4
+ if ENV['TEST_3SCALE_PROVIDER_KEY'] &&
5
+ ENV['TEST_3SCALE_APP_IDS'] &&
6
+ ENV['TEST_3SCALE_APP_KEYS']
5
7
  class ThreeScale::RemoteTest < Test::Unit::TestCase
6
8
  def setup
7
9
  @provider_key = ENV['TEST_3SCALE_PROVIDER_KEY']
8
- @user_keys = ENV['TEST_3SCALE_USER_KEYS'].split(',').map { |key| key.strip }
10
+
11
+ stripper = lambda { |string| string.strip }
12
+
13
+ @app_ids = ENV['TEST_3SCALE_APP_IDS'].split(',').map(&stripper)
14
+ @app_keys = ENV['TEST_3SCALE_APP_KEYS'].split(',').map(&stripper)
9
15
 
10
16
  @client = ThreeScale::Client.new(:provider_key => @provider_key)
11
17
 
@@ -16,26 +22,44 @@ if ENV['TEST_3SCALE_PROVIDER_KEY'] && ENV['TEST_3SCALE_USER_KEYS']
16
22
  end
17
23
 
18
24
  def test_successful_authorize
19
- response = @client.authorize(:user_key => @user_keys[0])
20
- assert response.success?
25
+ @app_keys.each do |app_key|
26
+ response = @client.authorize(:app_id => @app_ids[0], :app_key => app_key)
27
+ assert response.success?, "Authorize should succeed for app_id=#{@app_ids[0]} and app_key=#{app_key}, but it didn't"
28
+ end
21
29
  end
22
30
 
23
31
  def test_failed_authorize
24
- response = @client.authorize(:user_key => 'invalid-user-key')
32
+ response = @client.authorize(:app_id => 'invalid-id')
25
33
  assert !response.success?
26
- assert_equal 'user.invalid_key', response.errors[0].code
34
+ assert_equal 'application_not_found', response.error_code
35
+ assert_equal 'application with id="invalid-id" was not found', response.error_message
27
36
  end
28
37
 
29
38
  def test_successful_report
30
- transactions = @user_keys.map do |user_key|
31
- {:user_key => user_key, :usage => {'hits' => 1}}
39
+ transactions = @app_ids.map do |app_id|
40
+ {:app_id => app_id, :usage => {'hits' => 1}}
32
41
  end
33
42
 
34
43
  response = @client.report(*transactions)
35
44
  assert response.success?
36
45
  end
46
+
47
+ def test_failed_report
48
+ transactions = @app_ids.map do |app_id|
49
+ {:app_id => app_id, :usage => {'hits' => 1}}
50
+ end
51
+
52
+ client = ThreeScale::Client.new(:provider_key => 'invalid-key')
53
+ response = client.report(*transactions)
54
+ assert !response.success?
55
+ assert_equal 'provider_key_invalid', response.error_code
56
+ assert_equal 'provider key "invalid-key" is invalid', response.error_message
57
+ end
37
58
  end
38
59
 
39
60
  else
40
- puts "You need to set enviroment variables TEST_3SCALE_PROVIDER_KEY and TEST_3SCALE_USER_KEYS to run this remote test."
61
+ puts "This test executes real requests against 3scale backend server. It needs to know provider key, application ids and application keys to use in the requests. You have to set these environment variables:"
62
+ puts " * TEST_3SCALE_PROVIDER_KEY - a provider key."
63
+ puts " * TEST_3SCALE_APP_IDS - list of application ids, separated by commas."
64
+ puts " * TEST_3SCALE_APP_KEYS - list of application keys corresponding to the FIRST id in the TEST_3SCALE_APP_IDS list. Also separated by commas."
41
65
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 2
7
- - 0
8
- - 1
9
- version: 2.0.1
7
+ - 2
8
+ - 4
9
+ version: 2.2.4
10
10
  platform: ruby
11
11
  authors:
12
12
  - "Adam Cig\xC3\xA1nek"
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-28 00:00:00 +02:00
17
+ date: 2010-09-15 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -46,9 +46,9 @@ files:
46
46
  - README.rdoc
47
47
  - Rakefile
48
48
  - VERSION
49
- - lib/three_scale/authorize_response.rb
50
- - lib/three_scale/client.rb
51
- - lib/three_scale/response.rb
49
+ - lib/3scale/authorize_response.rb
50
+ - lib/3scale/client.rb
51
+ - lib/3scale/response.rb
52
52
  - test/client_test.rb
53
53
  - test/remote_test.rb
54
54
  has_rdoc: true
@@ -1,21 +0,0 @@
1
- module ThreeScale
2
- class Response
3
- def initialize(options)
4
- @success = options[:success]
5
- @errors = options[:errors] || []
6
- end
7
-
8
- def success?
9
- @success
10
- end
11
-
12
- Error = Struct.new(:index, :code, :message)
13
-
14
- attr_reader :errors
15
-
16
- def add_error(*args)
17
- @errors << Error.new(*args)
18
- end
19
- end
20
- end
21
-