panda 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -26,6 +26,7 @@ require 'spec/rake/spectask'
26
26
  Spec::Rake::SpecTask.new(:spec) do |spec|
27
27
  spec.libs << 'lib' << 'spec'
28
28
  spec.spec_files = FileList['spec/**/*_spec.rb']
29
+ spec.ruby_opts = ['-rrubygems']
29
30
  end
30
31
 
31
32
  Spec::Rake::SpecTask.new(:rcov) do |spec|
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
@@ -7,7 +7,7 @@ require 'base64'
7
7
 
8
8
  class Panda
9
9
  class ApiAuthentication
10
- def self.authenticate(verb, request_uri, host, secret_key, params_given={})
10
+ def self.generate_signature(verb, request_uri, host, secret_key, params_given={})
11
11
  # Ensure all param keys are strings
12
12
  params = {}; params_given.each {|k,v| params[k.to_s] = v }
13
13
 
@@ -21,46 +21,26 @@ class Panda
21
21
  hmac = HMAC::SHA256.new( secret_key )
22
22
  hmac.update( string_to_sign )
23
23
  # chomp is important! the base64 encoded version will have a newline at the end
24
- signature = Base64.encode64(hmac.digest).chomp
25
-
26
- return signature
27
- end
28
-
29
- # Insist on specific method of URL encoding, RFC3986.
30
- def self.url_encode(string)
31
- # It's kinda like CGI.escape, except CGI.escape is encoding a tilde when
32
- # it ought not to be, so we turn it back. Also space NEEDS to be %20 not +.
33
- return CGI.escape(string).gsub("%7E", "~").gsub("+", "%20")
24
+ Base64.encode64(hmac.digest).chomp
34
25
  end
35
26
 
36
27
  # param keys should be strings, not symbols please. return a string joined
37
28
  # by & in canonical order.
38
29
  def self.canonical_querystring(params)
39
30
  # I hope this built-in sort sorts by byte order, that's what's required.
40
- values = params.keys.sort.collect {|key| [url_encode(key), url_encode(params[key])].join("=") }
41
-
42
- return values.join("&")
43
- end
44
-
45
- def self.add_params_to_request_uri(request_uri, params)
46
- request_uri + '?' + hash_to_query(params)
47
- end
48
- # Insist on specific method of URL encoding, RFC3986.
49
- def self.url_encode(string)
50
- string = string.to_s
51
- # It's kinda like CGI.escape, except CGI.escape is encoding a tilde when
52
- # it ought not to be, so we turn it back. Also space NEEDS to be %20 not +.
53
- return CGI.escape(string).gsub("%7E", "~").gsub("+", "%20")
31
+ params.keys.sort.collect {|key| [url_encode(key), url_encode(params[key])].join("=") }.join("&")
54
32
  end
55
33
 
56
34
  # Turns a hash into a query string, returns the query string.
57
35
  # url-encodes everything to Amazon's specifications.
58
36
  def self.hash_to_query(hash)
59
- hash.collect do |key, value|
60
-
61
- url_encode(key) + "=" + url_encode(value)
37
+ hash.collect{|key, value| url_encode(key) + "=" + url_encode(value) }.join("&")
38
+ end
62
39
 
63
- end.join("&")
40
+ # It's kinda like CGI.escape, except CGI.escape is encoding a tilde when
41
+ # it ought not to be, so we turn it back. Also space NEEDS to be %20 not +.
42
+ def self.url_encode(string)
43
+ CGI.escape(string.to_s).gsub("%7E", "~").gsub("+", "%20")
64
44
  end
65
45
  end
66
46
  end
@@ -10,30 +10,26 @@ class Panda
10
10
  @secret_key = params["secret_key"] || params[:secret_key]
11
11
  @api_host = params["api_host"] || params[:api_host]
12
12
  @api_port = params["api_port"] || params[:api_port]
13
-
14
13
  @prefix = params["prefix_url"] || "v#{@api_version}"
15
-
16
14
  @connection = RestClient::Resource.new(api_url)
17
15
  end
18
16
 
19
17
  def get(request_uri, params={})
20
- append_authentication_params!("GET", request_uri, params)
21
- @connection[ApiAuthentication.add_params_to_request_uri(request_uri, params)].get
18
+ query = signed_query("GET", request_uri, params)
19
+ @connection[request_uri + '?' + query].get
22
20
  end
23
21
 
24
22
  def post(request_uri, params)
25
- append_authentication_params!("POST", request_uri, params)
26
- @connection[request_uri].post(params)
23
+ @connection[request_uri].post(signed_params("POST", request_uri, params))
27
24
  end
28
25
 
29
26
  def put(request_uri, params)
30
- append_authentication_params!("PUT", request_uri, params)
31
- @connection[request_uri].put(params)
27
+ @connection[request_uri].put(signed_params("PUT", request_uri, params))
32
28
  end
33
29
 
34
30
  def delete(request_uri, params={})
35
- append_authentication_params!("DELETE", request_uri, params)
36
- @connection[ApiAuthentication.add_params_to_request_uri(request_uri, params)].delete
31
+ query = signed_query("DELETE", request_uri, params)
32
+ @connection[request_uri + '?' + query].delete
37
33
  end
38
34
 
39
35
  def authentication_params(verb, request_uri, params)
@@ -45,13 +41,20 @@ class Panda
45
41
  return auth_params
46
42
  end
47
43
 
48
- def api_url
49
- "http://#{@api_host}:#{@api_port}/#{@prefix}"
44
+ def signed_query(*args)
45
+ ApiAuthentication.hash_to_query(signed_params(*args))
46
+ end
47
+
48
+ def signed_params(verb, request_uri, params = {}, timestamp_str = nil)
49
+ auth_params = params
50
+ auth_params['cloud_id'] = @cloud_id
51
+ auth_params['access_key'] = @access_key
52
+ auth_params['timestamp'] = timestamp_str || Time.now.iso8601(6)
53
+ auth_params['signature'] = ApiAuthentication.generate_signature(verb, request_uri, @api_host, @secret_key, params.merge(auth_params))
54
+ auth_params
50
55
  end
51
- private
52
56
 
53
- def append_authentication_params!(verb, request_uri, params)
54
- auth_params = authentication_params(verb, request_uri, params)
55
- params.merge!(auth_params)
57
+ def api_url
58
+ "http://#{@api_host}:#{@api_port}/#{@prefix}"
56
59
  end
57
60
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{panda}
8
- s.version = "0.3.0"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["New Bamboo"]
12
- s.date = %q{2010-02-22}
12
+ s.date = %q{2010-02-23}
13
13
  s.description = %q{Panda Client}
14
14
  s.email = %q{info@pandastream.com}
15
15
  s.extra_rdoc_files = [
@@ -4,7 +4,6 @@ describe Panda do
4
4
  before(:each) do
5
5
  FakeWeb.allow_net_connect = false
6
6
  @panda = Panda.new({"access_key" => "my_access_key", "secret_key" => "my_secret_key", "api_host" => "myapihost", "api_port" => 85, "cloud_id" => 'my_cloud_id' })
7
- # Panda.connect!({"access_key" => "my_access_key", "secret_key" => "my_secret_key", "api_host" => "myapihost", "api_port" => 85, "cloud_id" => 'my_cloud_id' })
8
7
  Time.stub!(:now).and_return(mock("time", :iso8601 => "2009-11-04T17:54:11+00:00"))
9
8
  end
10
9
 
@@ -20,5 +19,28 @@ describe Panda do
20
19
  FakeWeb.should have_requested(:delete, "http://myapihost:85/v2/videos/1?timestamp=2009-11-04T17%3A54%3A11%2B00%3A00&signature=t0IYclDXgjZFRYaMf0Gbg%2B5vOqp7q8QQRN8tlQ3bk8Q%3D&access_key=my_access_key&cloud_id=my_cloud_id")
21
20
  end
22
21
 
22
+ it "should create a signed version of the parameters" do
23
+ signed_params = @panda.signed_params('POST',
24
+ '/videos.json',
25
+ {"param1" => 'one', "param2" => 'two'}
26
+ )
27
+ signed_params.should == {
28
+ 'access_key' => "my_access_key",
29
+ 'timestamp' => "2009-11-04T17:54:11+00:00",
30
+ 'cloud_id' => 'my_cloud_id',
31
+ 'signature' => 'w66goW6Ve5CT9Ibbx3ryvq4XM8OfIfSZe5oapgZBaUs=',
32
+ 'param1' => 'one',
33
+ 'param2' => 'two'
34
+ }
35
+ end
36
+
37
+ it "should create a signed version of the parameters without additional arguments" do
38
+ @panda.signed_params('POST', '/videos.json').should == {
39
+ 'access_key' => "my_access_key",
40
+ 'timestamp' => "2009-11-04T17:54:11+00:00",
41
+ 'cloud_id' => 'my_cloud_id',
42
+ 'signature' => 'TI2n/dsSllxFhxcEShRGKWtDSqxu+kuJUPs335NavMo='
43
+ }
44
+ end
23
45
 
24
46
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 3
7
+ - 4
8
8
  - 0
9
- version: 0.3.0
9
+ version: 0.4.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - New Bamboo
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-02-22 00:00:00 +00:00
17
+ date: 2010-02-23 00:00:00 +00:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency