Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Squashed commit of the following:

commit 2d4df6a0cb83f1ddc0299b3a70b6aaba938786df
Author: Tiago Macedo <tftfmacedo@gmail.com>
Date:   Mon Mar 5 20:40:43 2012 +0100

    the oauth_authorize call now supports both redirect_url and app_key
    parameters

commit 8addeda525f01259b7db0800fcb39fc4d06a618d
Author: Tiago Macedo <tftfmacedo@gmail.com>
Date:   Mon Mar 5 20:39:55 2012 +0100

    bundler is now using only the gemspec, removing .rvmrc and adding some
    stuff to the git ignore

commit 7a48a73
Author: Jaime Iniesta <jaimeiniesta@gmail.com>
Date:   Sat Mar 3 09:26:50 2012 +0100

    Add oauth_authorize to README

commit deb2e7b
Author: Jaime Iniesta <jaimeiniesta@gmail.com>
Date:   Sat Mar 3 09:17:42 2012 +0100

    Revert "Add test for failing authorize due to missing app_key"

    This reverts commit 5edfcfd.

commit 5edfcfd
Author: Jaime Iniesta <jaimeiniesta@gmail.com>
Date:   Fri Mar 2 17:08:14 2012 +0100

    Add test for failing authorize due to missing app_key

commit d10ad8e
Author: Jaime Iniesta <jaimeiniesta@gmail.com>
Date:   Thu Mar 1 17:20:44 2012 +0100

    Update .travis.yml to test only 1.9.2 and 1.9.3

commit d8e5eaf
Author: Jaime Iniesta <jaimeiniesta@gmail.com>
Date:   Thu Mar 1 17:15:20 2012 +0100

    Add .travis.yml to specify ruby versions to try

commit 94fcfd0
Author: Jaime Iniesta <jaimeiniesta@gmail.com>
Date:   Thu Mar 1 17:12:42 2012 +0100

    Update VERSION to match gemspec

commit 0614097
Author: Jaime Iniesta <jaimeiniesta@gmail.com>
Date:   Thu Mar 1 17:07:46 2012 +0100

    Bring back authorize method, now we have authorize and oauth_authorize

commit da8c940
Author: Jaime Iniesta <jaimeiniesta@gmail.com>
Date:   Thu Mar 1 16:54:47 2012 +0100

    Update remote_test for oauth_authorize

commit 6cf1bf4
Author: Jaime Iniesta <jaimeiniesta@gmail.com>
Date:   Wed Feb 29 18:21:47 2012 +0100

    AuthorizeResponse can read redirect_url when using OAuth

commit 16e8e81
Author: Jaime Iniesta <jaimeiniesta@gmail.com>
Date:   Wed Feb 29 18:17:56 2012 +0100

    AuthorizeResponse can read app_key when using OAuth

commit 16886a5
Author: Jaime Iniesta <jaimeiniesta@gmail.com>
Date:   Wed Feb 29 18:06:26 2012 +0100

    Rename authorize method in Client as oauth_authorize

commit 5230a46
Author: Jaime Iniesta <jaimeiniesta@gmail.com>
Date:   Wed Feb 29 17:41:35 2012 +0100

    Update Gemfile

commit 2c1d942
Author: Jaime Iniesta <jaimeiniesta@gmail.com>
Date:   Wed Feb 29 17:41:08 2012 +0100

    Add .rvmrc to set desired ruby version for development

commit aa5b264
Author: Sebastian Arcila Valenzuela <sebastianarcila@gmail.com>
Date:   Wed Feb 8 11:27:03 2012 -0500

    add oauth setup

commit 92330f4
Author: Sebastian Arcila Valenzuela <sebastianarcila@gmail.com>
Date:   Fri Feb 3 11:01:31 2012 -0500

    use bundle setup to run tests

commit 697c0da
Author: Sebastian Arcila Valenzuela <sebastianarcila@gmail.com>
Date:   Fri Feb 3 10:09:07 2012 -0500

    add gemfile
  • Loading branch information...
commit 58418d9c8ffb545e5048d8fa15eaca49d73f4ac9 1 parent 9854621
@tmacedo tmacedo authored
View
2  .gitignore
@@ -1 +1,3 @@
pkg
+Gemfile.lock
+.*.swp
View
3  .travis.yml
@@ -0,0 +1,3 @@
+rvm:
+ - 1.9.2
+ - 1.9.3
View
6 3scale_client.gemspec
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
s.date = %q{2011-01-27}
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.
}
- s.email = %q{adam@3scale.net}
+ s.email = %q{adam@3scale.net tiago@3scale.net}
s.extra_rdoc_files = [
"README.rdoc"
]
@@ -51,5 +51,9 @@ Gem::Specification.new do |s|
else
s.add_dependency(%q<nokogiri>, [">= 0"])
end
+
+ s.add_development_dependency 'fakeweb'
+ s.add_development_dependency 'jeweler'
+ s.add_development_dependency 'mocha'
end
View
2  Gemfile
@@ -0,0 +1,2 @@
+source "http://rubygems.org"
+gemspec
View
33 Gemfile.lock
@@ -0,0 +1,33 @@
+PATH
+ remote: .
+ specs:
+ 3scale_client (2.2.7)
+ nokogiri
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ fakeweb (1.3.0)
+ git (1.2.5)
+ jeweler (1.8.3)
+ bundler (~> 1.0)
+ git (>= 1.2.5)
+ rake
+ rdoc
+ json (1.6.5)
+ metaclass (0.0.1)
+ mocha (0.10.5)
+ metaclass (~> 0.0.1)
+ nokogiri (1.5.0)
+ rake (0.9.2.2)
+ rdoc (3.12)
+ json (~> 1.4)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ 3scale_client!
+ fakeweb
+ jeweler
+ mocha
View
19 README.rdoc
@@ -6,7 +6,7 @@ This library is distributed as a gem:
gem install 3scale_client
-Or alternatively, download the source code from github:
+Or alternatively, download the source code from github:
http://github.com/3scale/3scale_ws_api_for_ruby
If you are using Bundler, please add this to your Gemfile:
@@ -74,12 +74,23 @@ down by the metrics and usage limit periods.
# If the limit is exceeded, this will be true, otherwise false:
usage_report.exceeded? # false
-If the authorization failed, the +error_code+ returns system error code and +error_message+
+If the authorization failed, the +error_code+ returns system error code and +error_message+
human readable error description:
-
+
response.error_code # "usage_limits_exceeded"
response.error_message # "Usage limits are exceeded"
+=== OAuth Authorize
+
+To authorize an application with OAuth, call the +oauth_authorize+ method passing it the application's id.
+
+ response = client.authorize(:app_id => "the app id")
+
+If the authorization is successful, the response will contain the +app_key+ and +redirect_url+ defined for this application:
+
+ response.app_key
+ response.redirect_url
+
=== Report
To report usage, use the +report+ method. You can report multiple transaction at the same time:
@@ -99,7 +110,7 @@ string has to be in a format parseable by the Time.parse method. For example:
"2010-04-28 12:38:33 +0200"
-If the timestamp is not in UTC, you have to specify a time offset. That's the "+0200"
+If the timestamp is not in UTC, you have to specify a time offset. That's the "+0200"
(two hours ahead of the Universal Coordinate Time) in the example abowe.
Then call the +success?+ method on the returned response object to see if the report was
View
5 Rakefile
@@ -1,8 +1,10 @@
# encoding: utf-8
+require "rubygems"
+require "bundler/setup"
require 'rake'
require 'rake/testtask'
-require 'rake/rdoctask'
+require 'rdoc/task'
desc 'Default: run unit tests.'
task :default => :test
@@ -11,7 +13,6 @@ desc 'Run unit tests.'
Rake::TestTask.new(:test) do |t|
t.pattern = 'test/**/*_test.rb'
t.verbose = true
- t.ruby_opts << '-rubygems'
end
desc 'Generate documentation.'
View
2  VERSION
@@ -1 +1 @@
-2.2.4
+2.2.7
View
4 lib/3scale/authorize_response.rb
@@ -8,6 +8,8 @@ def initialize
end
attr_accessor :plan
+ attr_accessor :app_key
+ attr_accessor :redirect_url
class UsageReport
attr_reader :metric
@@ -32,7 +34,7 @@ def period_end
def exceeded?
current_value > max_value
end
- end
+ end
attr_reader :usage_reports
View
69 lib/3scale/client.rb
@@ -8,7 +8,7 @@
module ThreeScale
Error = Class.new(RuntimeError)
-
+
class ServerError < Error
def initialize(response)
super('server error')
@@ -61,11 +61,11 @@ def initialize(options)
# app_id:: ID of the application to report the transaction for. This parameter is
# required.
# usage:: Hash of usage values. The keys are metric names and values are
- # correspoding numeric values. Example: {'hits' => 1, 'transfer' => 1024}.
+ # correspoding numeric values. Example: {'hits' => 1, 'transfer' => 1024}.
# This parameter is required.
# timestamp:: Timestamp of the transaction. This can be either a object of the
# ruby's Time class, or a string in the "YYYY-MM-DD HH:MM:SS" format
- # (if the time is in the UTC), or a string in
+ # (if the time is in the UTC), or a string in
# the "YYYY-MM-DD HH:MM:SS ZZZZZ" format, where the ZZZZZ is the time offset
# from the UTC. For example, "US Pacific Time" has offset -0800, "Tokyo"
# has offset +0900. This parameter is optional, and if not provided, equals
@@ -98,7 +98,7 @@ def report(*transactions)
uri = URI.parse("http://#{host}/transactions.xml")
http_response = Net::HTTP.post_form(uri, payload)
-
+
case http_response
when Net::HTTPSuccess
build_report_response
@@ -112,7 +112,7 @@ def report(*transactions)
# Authorize an application.
#
# == Parameters
- #
+ #
# Hash with options:
#
# app_id:: id of the application to authorize. This is required.
@@ -157,11 +157,61 @@ def authorize(options)
end
end
+ # Authorize an application with OAuth.
+ #
+ # == Parameters
+ #
+ # Hash with options:
+ #
+ # app_id:: id of the application to authorize. This is required.
+ #
+ # == Return
+ #
+ # A ThreeScale::AuthorizeResponse object. It's +success?+ method returns true if
+ # the authorization is successful, false otherwise. It contains additional information
+ # about the status of the usage. See the ThreeScale::AuthorizeResponse for more information.
+ #
+ # It also returns the app_key that corresponds to the given app_id
+ #
+ # In case of error, the +error_code+ returns code of the error and +error_message+
+ # human readable error description.
+ #
+ # In case of unexpected internal server error, this method raises a ThreeScale::ServerError
+ # exception.
+ #
+ # == Examples
+ #
+ # response = client.authorize(:app_id => '1234')
+ #
+ # if response.success?
+ # # All good. Proceed...
+ # end
+ #
+ def oauth_authorize(options)
+ path = "/transactions/oauth_authorize.xml" +
+ "?provider_key=#{CGI.escape(provider_key)}" +
+ "&app_id=#{CGI.escape(options[:app_id].to_s)}"
+ path += "&app_key=#{CGI.escape(options[:app_key])}" if options[:app_key]
+ path += "&redirect_url=#{CGI.escape(options[:redirect_url])}" if options[:redirect_url]
+
+ uri = URI.parse("http://#{host}#{path}")
+ http_response = Net::HTTP.get_response(uri)
+
+ case http_response
+ when Net::HTTPSuccess,Net::HTTPConflict
+ build_authorize_response(http_response.body)
+ when Net::HTTPClientError
+ build_error_response(http_response.body)
+ else
+ raise ServerError.new(http_response)
+ end
+ end
+
private
def encode_transactions(transactions)
result = {}
-
+
transactions.each_with_index do |transaction, index|
append_encoded_value(result, index, [:app_id], transaction[:app_id])
append_encoded_value(result, index, [:timestamp], transaction[:timestamp])
@@ -195,6 +245,11 @@ def build_authorize_response(body)
response.error!(doc.at_css('reason').content)
end
+ if doc.at_css('application')
+ response.app_key = doc.at_css('application key').content.to_s.strip
+ response.redirect_url = doc.at_css('application redirect_url').content.to_s.strip
+ end
+
response.plan = doc.at_css('plan').content.to_s.strip
doc.css('usage_reports usage_report').each do |node|
@@ -212,7 +267,7 @@ def build_authorize_response(body)
def build_error_response(body)
doc = Nokogiri::XML(body)
node = doc.at_css('error')
-
+
response = Response.new
response.error!(node.content.to_s.strip, node['code'].to_s.strip)
response
View
125 test/client_test.rb
@@ -29,7 +29,7 @@ def test_successful_authorize
body = '<status>
<authorized>true</authorized>
<plan>Ultimate</plan>
-
+
<usage_reports>
<usage_report metric="hits" period="day">
<period_start>2010-04-26 00:00:00 +0000</period_start>
@@ -54,7 +54,7 @@ def test_successful_authorize
assert response.success?
assert_equal 'Ultimate', response.plan
assert_equal 2, response.usage_reports.size
-
+
assert_equal :day, response.usage_reports[0].period
assert_equal Time.utc(2010, 4, 26), response.usage_reports[0].period_start
assert_equal Time.utc(2010, 4, 27), response.usage_reports[0].period_end
@@ -67,7 +67,7 @@ def test_successful_authorize
assert_equal 999872, response.usage_reports[1].current_value
assert_equal 150000, response.usage_reports[1].max_value
end
-
+
def test_successful_authorize_with_app_keys
body = '<status>
<authorized>true</authorized>
@@ -86,7 +86,7 @@ def test_authorize_with_exceeded_usage_limits
<reason>usage limits are exceeded</reason>
<plan>Ultimate</plan>
-
+
<usage_reports>
<usage_report metric="hits" period="day" exceeded="true">
<period_start>2010-04-26 00:00:00 +0000</period_start>
@@ -103,9 +103,9 @@ def test_authorize_with_exceeded_usage_limits
</usage_report>
</usage_reports>
</status>'
-
+
FakeWeb.register_uri(:get, "http://#{@host}/transactions/authorize.xml?provider_key=1234abcd&app_id=foo", :status => ['409'], :body => body)
-
+
response = @client.authorize(:app_id => 'foo')
assert !response.success?
@@ -115,7 +115,7 @@ def test_authorize_with_exceeded_usage_limits
def test_authorize_with_invalid_app_id
body = '<error code="application_not_found">application with id="foo" was not found</error>'
-
+
FakeWeb.register_uri(:get, "http://#{@host}/transactions/authorize.xml?provider_key=1234abcd&app_id=foo", :status => ['403', 'Forbidden'], :body => body)
response = @client.authorize(:app_id => 'foo')
@@ -124,7 +124,7 @@ def test_authorize_with_invalid_app_id
assert_equal 'application_not_found', response.error_code
assert_equal 'application with id="foo" was not found', response.error_message
end
-
+
def test_authorize_with_server_error
FakeWeb.register_uri(:get, "http://#{@host}/transactions/authorize.xml?provider_key=1234abcd&app_id=foo", :status => ['500', 'Internal Server Error'], :body => 'OMG! WTF!')
@@ -133,6 +133,111 @@ def test_authorize_with_server_error
end
end
+ def test_successful_oauth_authorize
+ body = '<status>
+ <authorized>true</authorized>
+ <application>
+ <id>94bd2de3</id>
+ <key>883bdb8dbc3b6b77dbcf26845560fdbb</key>
+ <redirect_url>http://localhost:8080/oauth/oauth_redirect</redirect_url>
+ </application>
+ <plan>Ultimate</plan>
+ <usage_reports>
+ <usage_report metric="hits" period="week">
+ <period_start>2012-01-30 00:00:00 +0000</period_start>
+ <period_end>2012-02-06 00:00:00 +0000</period_end>
+ <max_value>5000</max_value>
+ <current_value>1</current_value>
+ </usage_report>
+ <usage_report metric="update" period="minute">
+ <period_start>2012-02-03 00:00:00 +0000</period_start>
+ <period_end>2012-02-03 00:00:00 +0000</period_end>
+ <max_value>0</max_value>
+ <current_value>0</current_value>
+ </usage_report>
+ </usage_reports>
+ </status>'
+
+ FakeWeb.register_uri(:get, "http://#{@host}/transactions/oauth_authorize.xml?provider_key=1234abcd&app_id=foo&redirect_url=http%3A%2F%2Flocalhost%3A8080%2Foauth%2Foauth_redirect", :status => ['200', 'OK'], :body => body)
+
+ response = @client.oauth_authorize(:app_id => 'foo', :redirect_url => "http://localhost:8080/oauth/oauth_redirect")
+ assert response.success?
+
+ assert_equal '883bdb8dbc3b6b77dbcf26845560fdbb', response.app_key
+ assert_equal 'http://localhost:8080/oauth/oauth_redirect', response.redirect_url
+
+ assert_equal 'Ultimate', response.plan
+ assert_equal 2, response.usage_reports.size
+
+ assert_equal :week, response.usage_reports[0].period
+ assert_equal Time.utc(2012, 1, 30), response.usage_reports[0].period_start
+ assert_equal Time.utc(2012, 02, 06), response.usage_reports[0].period_end
+ assert_equal 1, response.usage_reports[0].current_value
+ assert_equal 5000, response.usage_reports[0].max_value
+
+ assert_equal :minute, response.usage_reports[1].period
+ assert_equal Time.utc(2012, 2, 03), response.usage_reports[1].period_start
+ assert_equal Time.utc(2012, 2, 03), response.usage_reports[1].period_end
+ assert_equal 0, response.usage_reports[1].current_value
+ assert_equal 0, response.usage_reports[1].max_value
+ end
+
+ def test_oauth_authorize_with_exceeded_usage_limits
+ body = '<status>
+ <authorized>false</authorized>
+ <reason>usage limits are exceeded</reason>
+ <application>
+ <id>94bd2de3</id>
+ <key>883bdb8dbc3b6b77dbcf26845560fdbb</key>
+ <redirect_url>http://localhost:8080/oauth/oauth_redirect</redirect_url>
+ </application>
+ <plan>Ultimate</plan>
+ <usage_reports>
+ <usage_report metric="hits" period="day" exceeded="true">
+ <period_start>2010-04-26 00:00:00 +0000</period_start>
+ <period_end>2010-04-27 00:00:00 +0000</period_end>
+ <current_value>50002</current_value>
+ <max_value>50000</max_value>
+ </usage_report>
+
+ <usage_report metric="hits" period="month">
+ <period_start>2010-04-01 00:00:00 +0000</period_start>
+ <period_end>2010-05-01 00:00:00 +0000</period_end>
+ <current_value>999872</current_value>
+ <max_value>150000</max_value>
+ </usage_report>
+ </usage_reports>
+ </status>'
+
+ FakeWeb.register_uri(:get, "http://#{@host}/transactions/oauth_authorize.xml?provider_key=1234abcd&app_id=foo", :status => ['409'], :body => body)
+
+ response = @client.oauth_authorize(:app_id => 'foo')
+
+ assert !response.success?
+ assert_equal 'usage limits are exceeded', response.error_message
+ assert response.usage_reports[0].exceeded?
+ end
+
+ def test_oauth_authorize_with_invalid_app_id
+ body = '<error code="application_not_found">application with id="foo" was not found</error>'
+
+ FakeWeb.register_uri(:get, "http://#{@host}/transactions/oauth_authorize.xml?provider_key=1234abcd&app_id=foo", :status => ['403', 'Forbidden'], :body => body)
+
+ response = @client.oauth_authorize(:app_id => 'foo')
+
+ assert !response.success?
+ assert_equal 'application_not_found', response.error_code
+ assert_equal 'application with id="foo" was not found', response.error_message
+ end
+
+ def test_authorize_with_server_error
+ FakeWeb.register_uri(:get, "http://#{@host}/transactions/oauth_authorize.xml?provider_key=1234abcd&app_id=foo", :status => ['500', 'Internal Server Error'], :body => 'OMG! WTF!')
+
+ assert_raise ThreeScale::ServerError do
+ @client.oauth_authorize(:app_id => 'foo')
+ end
+ end
+
def test_report_raises_an_exception_if_no_transactions_given
assert_raise ArgumentError do
@client.report
@@ -180,8 +285,8 @@ def test_failed_report
FakeWeb.register_uri(:post, "http://#{@host}/transactions.xml",
:status => ['403', 'Forbidden'],
:body => error_body)
-
- client = ThreeScale::Client.new(:provider_key => 'foo')
+
+ client = ThreeScale::Client.new(:provider_key => 'foo')
response = client.report({:app_id => 'abc', :usage => {'hits' => 1}})
assert !response.success?
View
19 test/remote_test.rb
@@ -1,7 +1,7 @@
require 'test/unit'
require '3scale/client'
-if ENV['TEST_3SCALE_PROVIDER_KEY'] &&
+if ENV['TEST_3SCALE_PROVIDER_KEY'] &&
ENV['TEST_3SCALE_APP_IDS'] &&
ENV['TEST_3SCALE_APP_KEYS']
class ThreeScale::RemoteTest < Test::Unit::TestCase
@@ -24,7 +24,7 @@ def setup
def test_successful_authorize
@app_keys.each do |app_key|
response = @client.authorize(:app_id => @app_ids[0], :app_key => app_key)
- assert response.success?, "Authorize should succeed for app_id=#{@app_ids[0]} and app_key=#{app_key}, but it didn't"
+ assert response.success?, "Authorize should succeed for app_id=#{@app_ids[0]} and app_key=#{app_key}, but it failed with: '#{response.error_message}'"
end
end
@@ -35,6 +35,21 @@ def test_failed_authorize
assert_equal 'application with id="invalid-id" was not found', response.error_message
end
+ def test_successful_oauth_authorize
+ @app_keys.each do |app_key|
+ response = @client.oauth_authorize(:app_id => @app_ids[0])
+ assert response.success?, "Authorize should succeed for app_id=#{@app_ids[0]} and app_key=#{app_key}, but it failed with: '#{response.error_message}'"
+ assert_equal app_key, response.app_key
+ end
+ end
+
+ def test_failed_oauth_authorize
+ response = @client.oauth_authorize(:app_id => 'invalid-id')
+ assert !response.success?
+ assert_equal 'application_not_found', response.error_code
+ assert_equal 'application with id="invalid-id" was not found', response.error_message
+ end
+
def test_successful_report
transactions = @app_ids.map do |app_id|
{:app_id => app_id, :usage => {'hits' => 1}}
Please sign in to comment.
Something went wrong with that request. Please try again.