pusher 0.4.3 → 0.5.0
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.
- data/README.md +1 -1
 - data/Rakefile +1 -0
 - data/VERSION +1 -1
 - data/lib/pusher.rb +2 -2
 - data/lib/pusher/channel.rb +23 -43
 - data/lib/pusher/request.rb +38 -0
 - data/pusher.gemspec +7 -6
 - data/spec/pusher_spec.rb +21 -1
 - metadata +21 -11
 - data/lib/pusher/authentication.rb +0 -142
 - data/spec/authentication_spec.rb +0 -176
 
    
        data/README.md
    CHANGED
    
    | 
         @@ -30,7 +30,7 @@ Asynchronous triggering 
     | 
|
| 
       30 
30 
     | 
    
         | 
| 
       31 
31 
     | 
    
         
             
            To avoid blocking in a typical web application, if you are running inside eventmachine (for example if you use the thin server), you may wish to use the `trigger_async` method which uses the em-http-request gem to make api requests to pusher. It returns a deferrable which you can optionally bind to with success and failure callbacks. This is not a gem dependency, so you will need to install it manually.
         
     | 
| 
       32 
32 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
                d = Pusher['a_channel']. 
     | 
| 
      
 33 
     | 
    
         
            +
                d = Pusher['a_channel'].trigger_async('an_event', {:some => 'data'}, socket_id)
         
     | 
| 
       34 
34 
     | 
    
         
             
                d.callback {
         
     | 
| 
       35 
35 
     | 
    
         
             
                  # Do something on success
         
     | 
| 
       36 
36 
     | 
    
         
             
                }
         
     | 
    
        data/Rakefile
    CHANGED
    
    | 
         @@ -14,6 +14,7 @@ begin 
     | 
|
| 
       14 
14 
     | 
    
         
             
                gem.add_dependency "json"
         
     | 
| 
       15 
15 
     | 
    
         
             
                gem.add_dependency "crack"
         
     | 
| 
       16 
16 
     | 
    
         
             
                gem.add_dependency "ruby-hmac"
         
     | 
| 
      
 17 
     | 
    
         
            +
                gem.add_dependency 'signature'
         
     | 
| 
       17 
18 
     | 
    
         
             
                gem.add_development_dependency "rspec", ">= 1.2.9"
         
     | 
| 
       18 
19 
     | 
    
         
             
                gem.add_development_dependency "webmock"
         
     | 
| 
       19 
20 
     | 
    
         
             
                # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
         
     | 
    
        data/VERSION
    CHANGED
    
    | 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            0. 
     | 
| 
      
 1 
     | 
    
         
            +
            0.5.0
         
     | 
    
        data/lib/pusher.rb
    CHANGED
    
    | 
         @@ -18,7 +18,7 @@ module Pusher 
     | 
|
| 
       18 
18 
     | 
    
         
             
                end
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
                def authentication_token
         
     | 
| 
       21 
     | 
    
         
            -
                   
     | 
| 
      
 21 
     | 
    
         
            +
                  Signature::Token.new(@key, @secret)
         
     | 
| 
       22 
22 
     | 
    
         
             
                end
         
     | 
| 
       23 
23 
     | 
    
         
             
              end
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
         @@ -36,4 +36,4 @@ module Pusher 
     | 
|
| 
       36 
36 
     | 
    
         
             
            end
         
     | 
| 
       37 
37 
     | 
    
         | 
| 
       38 
38 
     | 
    
         
             
            require 'pusher/channel'
         
     | 
| 
       39 
     | 
    
         
            -
            require 'pusher/ 
     | 
| 
      
 39 
     | 
    
         
            +
            require 'pusher/request'
         
     | 
    
        data/lib/pusher/channel.rb
    CHANGED
    
    | 
         @@ -1,12 +1,17 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'crack/core_extensions' # Used for Hash#to_params
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'signature'
         
     | 
| 
       2 
3 
     | 
    
         
             
            require 'digest/md5'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'hmac-sha2'
         
     | 
| 
       3 
5 
     | 
    
         | 
| 
       4 
6 
     | 
    
         
             
            require 'json'
         
     | 
| 
       5 
7 
     | 
    
         
             
            require 'uri'
         
     | 
| 
       6 
8 
     | 
    
         | 
| 
       7 
9 
     | 
    
         
             
            module Pusher
         
     | 
| 
       8 
10 
     | 
    
         
             
              class Channel
         
     | 
| 
      
 11 
     | 
    
         
            +
                attr_reader :name
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
       9 
13 
     | 
    
         
             
                def initialize(app_id, name)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @name = name
         
     | 
| 
       10 
15 
     | 
    
         
             
                  @uri = URI::HTTP.build({
         
     | 
| 
       11 
16 
     | 
    
         
             
                    :host => Pusher.host,
         
     | 
| 
       12 
17 
     | 
    
         
             
                    :port => Pusher.port,
         
     | 
| 
         @@ -21,13 +26,13 @@ module Pusher 
     | 
|
| 
       21 
26 
     | 
    
         
             
                  require 'em-http' unless defined?(EventMachine::HttpRequest)
         
     | 
| 
       22 
27 
     | 
    
         | 
| 
       23 
28 
     | 
    
         
             
                  @http_async ||= EventMachine::HttpRequest.new(@uri)
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
                   
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  request = Pusher::Request.new(@uri, event_name, data, socket_id)
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
       27 
32 
     | 
    
         
             
                  deferrable = EM::DefaultDeferrable.new
         
     | 
| 
       28 
33 
     | 
    
         | 
| 
       29 
34 
     | 
    
         
             
                  http = @http_async.post({
         
     | 
| 
       30 
     | 
    
         
            -
                    :query => query, :timeout => 2, :body => body
         
     | 
| 
      
 35 
     | 
    
         
            +
                    :query => request.query, :timeout => 2, :body => request.body
         
     | 
| 
       31 
36 
     | 
    
         
             
                  })
         
     | 
| 
       32 
37 
     | 
    
         
             
                  http.callback {
         
     | 
| 
       33 
38 
     | 
    
         
             
                    begin
         
     | 
| 
         @@ -49,12 +54,11 @@ module Pusher 
     | 
|
| 
       49 
54 
     | 
    
         
             
                  require 'net/http' unless defined?(Net::HTTP)
         
     | 
| 
       50 
55 
     | 
    
         | 
| 
       51 
56 
     | 
    
         
             
                  @http_sync ||= Net::HTTP.new(@uri.host, @uri.port)
         
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
                   
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
                  response = @http_sync.post("#{@uri.path}?#{query.to_params}", 
     | 
| 
       56 
     | 
    
         
            -
                    'Content-Type'=> 'application/json'
         
     | 
| 
       57 
     | 
    
         
            -
                  })
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  request = Pusher::Request.new(@uri, event_name, data, socket_id)
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                  response = @http_sync.post("#{@uri.path}?#{request.query.to_params}",
         
     | 
| 
      
 61 
     | 
    
         
            +
                    request.body, { 'Content-Type'=> 'application/json' })
         
     | 
| 
       58 
62 
     | 
    
         | 
| 
       59 
63 
     | 
    
         
             
                  handle_response(response.code.to_i, response.body.chomp)
         
     | 
| 
       60 
64 
     | 
    
         
             
                end
         
     | 
| 
         @@ -65,12 +69,15 @@ module Pusher 
     | 
|
| 
       65 
69 
     | 
    
         
             
                  handle_error e
         
     | 
| 
       66 
70 
     | 
    
         
             
                end
         
     | 
| 
       67 
71 
     | 
    
         | 
| 
       68 
     | 
    
         
            -
                def  
     | 
| 
       69 
     | 
    
         
            -
                  if  
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
     | 
    
         
            -
                   
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
                   
     | 
| 
      
 72 
     | 
    
         
            +
                def socket_auth(socket_id)
         
     | 
| 
      
 73 
     | 
    
         
            +
                  raise "Invalid socket_id" if socket_id.nil? || socket_id.empty?
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                  string_to_sign = "#{socket_id}:#{name}"
         
     | 
| 
      
 76 
     | 
    
         
            +
                  Pusher.logger.debug "Signing #{string_to_sign}"
         
     | 
| 
      
 77 
     | 
    
         
            +
                  token = Pusher.authentication_token
         
     | 
| 
      
 78 
     | 
    
         
            +
                  signature = HMAC::SHA256.hexdigest(token.secret, string_to_sign)
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                  return "#{token.key}:#{signature}"
         
     | 
| 
       74 
81 
     | 
    
         
             
                end
         
     | 
| 
       75 
82 
     | 
    
         | 
| 
       76 
83 
     | 
    
         
             
                private
         
     | 
| 
         @@ -79,34 +86,7 @@ module Pusher 
     | 
|
| 
       79 
86 
     | 
    
         
             
                  Pusher.logger.error("#{e.message} (#{e.class})")
         
     | 
| 
       80 
87 
     | 
    
         
             
                  Pusher.logger.debug(e.backtrace.join("\n"))
         
     | 
| 
       81 
88 
     | 
    
         
             
                end
         
     | 
| 
       82 
     | 
    
         
            -
                
         
     | 
| 
       83 
     | 
    
         
            -
                def construct_request(event_name, data, socket_id)
         
     | 
| 
       84 
     | 
    
         
            -
                  params = {
         
     | 
| 
       85 
     | 
    
         
            -
                    :name => event_name,
         
     | 
| 
       86 
     | 
    
         
            -
                  }
         
     | 
| 
       87 
     | 
    
         
            -
                  params[:socket_id] = socket_id if socket_id
         
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
                  body = case data
         
     | 
| 
       90 
     | 
    
         
            -
                  when String
         
     | 
| 
       91 
     | 
    
         
            -
                    data
         
     | 
| 
       92 
     | 
    
         
            -
                  else
         
     | 
| 
       93 
     | 
    
         
            -
                    begin
         
     | 
| 
       94 
     | 
    
         
            -
                      self.class.turn_into_json(data)
         
     | 
| 
       95 
     | 
    
         
            -
                    rescue => e
         
     | 
| 
       96 
     | 
    
         
            -
                      Pusher.logger.error("Could not convert #{data.inspect} into JSON")
         
     | 
| 
       97 
     | 
    
         
            -
                      raise e
         
     | 
| 
       98 
     | 
    
         
            -
                    end
         
     | 
| 
       99 
     | 
    
         
            -
                  end
         
     | 
| 
       100 
     | 
    
         
            -
                  params[:body_md5] = Digest::MD5.hexdigest(body)
         
     | 
| 
       101 
89 
     | 
    
         | 
| 
       102 
     | 
    
         
            -
                  request = Authentication::Request.new('POST', @uri.path, params)
         
     | 
| 
       103 
     | 
    
         
            -
                  auth_hash = request.sign(Pusher.authentication_token)
         
     | 
| 
       104 
     | 
    
         
            -
             
     | 
| 
       105 
     | 
    
         
            -
                  query_params = params.merge(auth_hash)
         
     | 
| 
       106 
     | 
    
         
            -
                  
         
     | 
| 
       107 
     | 
    
         
            -
                  return query_params, body
         
     | 
| 
       108 
     | 
    
         
            -
                end
         
     | 
| 
       109 
     | 
    
         
            -
                
         
     | 
| 
       110 
90 
     | 
    
         
             
                def handle_response(status_code, body)
         
     | 
| 
       111 
91 
     | 
    
         
             
                  case status_code
         
     | 
| 
       112 
92 
     | 
    
         
             
                  when 202
         
     | 
| 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Pusher
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Request
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_reader :body, :query
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(resource, event_name, data, socket_id, token = nil)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  params = {
         
     | 
| 
      
 7 
     | 
    
         
            +
                    :name => event_name,
         
     | 
| 
      
 8 
     | 
    
         
            +
                  }
         
     | 
| 
      
 9 
     | 
    
         
            +
                  params[:socket_id] = socket_id if socket_id
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  @body = case data
         
     | 
| 
      
 12 
     | 
    
         
            +
                  when String
         
     | 
| 
      
 13 
     | 
    
         
            +
                    data
         
     | 
| 
      
 14 
     | 
    
         
            +
                  else
         
     | 
| 
      
 15 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 16 
     | 
    
         
            +
                      self.class.turn_into_json(data)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    rescue => e
         
     | 
| 
      
 18 
     | 
    
         
            +
                      Pusher.logger.error("Could not convert #{data.inspect} into JSON")
         
     | 
| 
      
 19 
     | 
    
         
            +
                      raise e
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                  params[:body_md5] = Digest::MD5.hexdigest(body)
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  request = Signature::Request.new('POST', resource.path, params)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  auth_hash = request.sign(token || Pusher.authentication_token)
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  @query = params.merge(auth_hash)
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def self.turn_into_json(data)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  if Object.const_defined?('ActiveSupport')
         
     | 
| 
      
 32 
     | 
    
         
            +
                    data.to_json
         
     | 
| 
      
 33 
     | 
    
         
            +
                  else
         
     | 
| 
      
 34 
     | 
    
         
            +
                    JSON.generate(data)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
    
        data/pusher.gemspec
    CHANGED
    
    | 
         @@ -5,11 +5,11 @@ 
     | 
|
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            Gem::Specification.new do |s|
         
     | 
| 
       7 
7 
     | 
    
         
             
              s.name = %q{pusher}
         
     | 
| 
       8 
     | 
    
         
            -
              s.version = "0. 
     | 
| 
      
 8 
     | 
    
         
            +
              s.version = "0.5.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-05- 
     | 
| 
      
 12 
     | 
    
         
            +
              s.date = %q{2010-05-14}
         
     | 
| 
       13 
13 
     | 
    
         
             
              s.description = %q{Wrapper for pusherapp.com REST api}
         
     | 
| 
       14 
14 
     | 
    
         
             
              s.email = %q{support@pusherapp.com}
         
     | 
| 
       15 
15 
     | 
    
         
             
              s.extra_rdoc_files = [
         
     | 
| 
         @@ -24,10 +24,9 @@ Gem::Specification.new do |s| 
     | 
|
| 
       24 
24 
     | 
    
         
             
                 "Rakefile",
         
     | 
| 
       25 
25 
     | 
    
         
             
                 "VERSION",
         
     | 
| 
       26 
26 
     | 
    
         
             
                 "lib/pusher.rb",
         
     | 
| 
       27 
     | 
    
         
            -
                 "lib/pusher/authentication.rb",
         
     | 
| 
       28 
27 
     | 
    
         
             
                 "lib/pusher/channel.rb",
         
     | 
| 
      
 28 
     | 
    
         
            +
                 "lib/pusher/request.rb",
         
     | 
| 
       29 
29 
     | 
    
         
             
                 "pusher.gemspec",
         
     | 
| 
       30 
     | 
    
         
            -
                 "spec/authentication_spec.rb",
         
     | 
| 
       31 
30 
     | 
    
         
             
                 "spec/pusher_spec.rb",
         
     | 
| 
       32 
31 
     | 
    
         
             
                 "spec/spec.opts",
         
     | 
| 
       33 
32 
     | 
    
         
             
                 "spec/spec_helper.rb"
         
     | 
| 
         @@ -38,8 +37,7 @@ Gem::Specification.new do |s| 
     | 
|
| 
       38 
37 
     | 
    
         
             
              s.rubygems_version = %q{1.3.6}
         
     | 
| 
       39 
38 
     | 
    
         
             
              s.summary = %q{Pusher App client}
         
     | 
| 
       40 
39 
     | 
    
         
             
              s.test_files = [
         
     | 
| 
       41 
     | 
    
         
            -
                "spec/ 
     | 
| 
       42 
     | 
    
         
            -
                 "spec/pusher_spec.rb",
         
     | 
| 
      
 40 
     | 
    
         
            +
                "spec/pusher_spec.rb",
         
     | 
| 
       43 
41 
     | 
    
         
             
                 "spec/spec_helper.rb"
         
     | 
| 
       44 
42 
     | 
    
         
             
              ]
         
     | 
| 
       45 
43 
     | 
    
         | 
| 
         @@ -51,12 +49,14 @@ Gem::Specification.new do |s| 
     | 
|
| 
       51 
49 
     | 
    
         
             
                  s.add_runtime_dependency(%q<json>, [">= 0"])
         
     | 
| 
       52 
50 
     | 
    
         
             
                  s.add_runtime_dependency(%q<crack>, [">= 0"])
         
     | 
| 
       53 
51 
     | 
    
         
             
                  s.add_runtime_dependency(%q<ruby-hmac>, [">= 0"])
         
     | 
| 
      
 52 
     | 
    
         
            +
                  s.add_runtime_dependency(%q<signature>, [">= 0"])
         
     | 
| 
       54 
53 
     | 
    
         
             
                  s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
         
     | 
| 
       55 
54 
     | 
    
         
             
                  s.add_development_dependency(%q<webmock>, [">= 0"])
         
     | 
| 
       56 
55 
     | 
    
         
             
                else
         
     | 
| 
       57 
56 
     | 
    
         
             
                  s.add_dependency(%q<json>, [">= 0"])
         
     | 
| 
       58 
57 
     | 
    
         
             
                  s.add_dependency(%q<crack>, [">= 0"])
         
     | 
| 
       59 
58 
     | 
    
         
             
                  s.add_dependency(%q<ruby-hmac>, [">= 0"])
         
     | 
| 
      
 59 
     | 
    
         
            +
                  s.add_dependency(%q<signature>, [">= 0"])
         
     | 
| 
       60 
60 
     | 
    
         
             
                  s.add_dependency(%q<rspec>, [">= 1.2.9"])
         
     | 
| 
       61 
61 
     | 
    
         
             
                  s.add_dependency(%q<webmock>, [">= 0"])
         
     | 
| 
       62 
62 
     | 
    
         
             
                end
         
     | 
| 
         @@ -64,6 +64,7 @@ Gem::Specification.new do |s| 
     | 
|
| 
       64 
64 
     | 
    
         
             
                s.add_dependency(%q<json>, [">= 0"])
         
     | 
| 
       65 
65 
     | 
    
         
             
                s.add_dependency(%q<crack>, [">= 0"])
         
     | 
| 
       66 
66 
     | 
    
         
             
                s.add_dependency(%q<ruby-hmac>, [">= 0"])
         
     | 
| 
      
 67 
     | 
    
         
            +
                s.add_dependency(%q<signature>, [">= 0"])
         
     | 
| 
       67 
68 
     | 
    
         
             
                s.add_dependency(%q<rspec>, [">= 1.2.9"])
         
     | 
| 
       68 
69 
     | 
    
         
             
                s.add_dependency(%q<webmock>, [">= 0"])
         
     | 
| 
       69 
70 
     | 
    
         
             
              end
         
     | 
    
        data/spec/pusher_spec.rb
    CHANGED
    
    | 
         @@ -169,7 +169,7 @@ describe Pusher do 
     | 
|
| 
       169 
169 
     | 
    
         
             
                  end
         
     | 
| 
       170 
170 
     | 
    
         
             
                end
         
     | 
| 
       171 
171 
     | 
    
         | 
| 
       172 
     | 
    
         
            -
                describe " 
     | 
| 
      
 172 
     | 
    
         
            +
                describe "Channel#trigger_async" do
         
     | 
| 
       173 
173 
     | 
    
         
             
                  #in order to match URLs when testing http requests
         
     | 
| 
       174 
174 
     | 
    
         
             
                  #override the method that converts query hash to string
         
     | 
| 
       175 
175 
     | 
    
         
             
                  #to include a sort so URL is consistent
         
     | 
| 
         @@ -261,5 +261,25 @@ describe Pusher do 
     | 
|
| 
       261 
261 
     | 
    
         
             
                    }
         
     | 
| 
       262 
262 
     | 
    
         
             
                  end
         
     | 
| 
       263 
263 
     | 
    
         
             
                end
         
     | 
| 
      
 264 
     | 
    
         
            +
             
     | 
| 
      
 265 
     | 
    
         
            +
                describe "Channel#socket_auth" do
         
     | 
| 
      
 266 
     | 
    
         
            +
                  before :each do
         
     | 
| 
      
 267 
     | 
    
         
            +
                    @channel = Pusher['test_channel']
         
     | 
| 
      
 268 
     | 
    
         
            +
                  end
         
     | 
| 
      
 269 
     | 
    
         
            +
             
     | 
| 
      
 270 
     | 
    
         
            +
                  it "should return an authentication string given a socket id" do
         
     | 
| 
      
 271 
     | 
    
         
            +
                    auth = @channel.socket_auth('socketid')
         
     | 
| 
      
 272 
     | 
    
         
            +
             
     | 
| 
      
 273 
     | 
    
         
            +
                    auth.should == '12345678900000001:827076f551e22451357939e4c7bb1200de29f921d5bf80b40d71668f9cd61c40'
         
     | 
| 
      
 274 
     | 
    
         
            +
                  end
         
     | 
| 
      
 275 
     | 
    
         
            +
             
     | 
| 
      
 276 
     | 
    
         
            +
                  it "should raise error if authentication is invalid" do
         
     | 
| 
      
 277 
     | 
    
         
            +
                    [nil, ''].each do |invalid|
         
     | 
| 
      
 278 
     | 
    
         
            +
                      lambda {
         
     | 
| 
      
 279 
     | 
    
         
            +
                        @channel.socket_auth(invalid)
         
     | 
| 
      
 280 
     | 
    
         
            +
                      }.should raise_error
         
     | 
| 
      
 281 
     | 
    
         
            +
                    end
         
     | 
| 
      
 282 
     | 
    
         
            +
                  end
         
     | 
| 
      
 283 
     | 
    
         
            +
                end
         
     | 
| 
       264 
284 
     | 
    
         
             
              end
         
     | 
| 
       265 
285 
     | 
    
         
             
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version 
     | 
|
| 
       4 
4 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       5 
5 
     | 
    
         
             
              segments: 
         
     | 
| 
       6 
6 
     | 
    
         
             
              - 0
         
     | 
| 
       7 
     | 
    
         
            -
              -  
     | 
| 
       8 
     | 
    
         
            -
              -  
     | 
| 
       9 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 7 
     | 
    
         
            +
              - 5
         
     | 
| 
      
 8 
     | 
    
         
            +
              - 0
         
     | 
| 
      
 9 
     | 
    
         
            +
              version: 0.5.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-05- 
     | 
| 
      
 17 
     | 
    
         
            +
            date: 2010-05-14 00:00:00 +01:00
         
     | 
| 
       18 
18 
     | 
    
         
             
            default_executable: 
         
     | 
| 
       19 
19 
     | 
    
         
             
            dependencies: 
         
     | 
| 
       20 
20 
     | 
    
         
             
            - !ruby/object:Gem::Dependency 
         
     | 
| 
         @@ -54,9 +54,21 @@ dependencies: 
     | 
|
| 
       54 
54 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       55 
55 
     | 
    
         
             
              version_requirements: *id003
         
     | 
| 
       56 
56 
     | 
    
         
             
            - !ruby/object:Gem::Dependency 
         
     | 
| 
       57 
     | 
    
         
            -
              name:  
     | 
| 
      
 57 
     | 
    
         
            +
              name: signature
         
     | 
| 
       58 
58 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       59 
59 
     | 
    
         
             
              requirement: &id004 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 60 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 61 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 62 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 63 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 64 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 65 
     | 
    
         
            +
                    version: "0"
         
     | 
| 
      
 66 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 67 
     | 
    
         
            +
              version_requirements: *id004
         
     | 
| 
      
 68 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 69 
     | 
    
         
            +
              name: rspec
         
     | 
| 
      
 70 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 71 
     | 
    
         
            +
              requirement: &id005 !ruby/object:Gem::Requirement 
         
     | 
| 
       60 
72 
     | 
    
         
             
                requirements: 
         
     | 
| 
       61 
73 
     | 
    
         
             
                - - ">="
         
     | 
| 
       62 
74 
     | 
    
         
             
                  - !ruby/object:Gem::Version 
         
     | 
| 
         @@ -66,11 +78,11 @@ dependencies: 
     | 
|
| 
       66 
78 
     | 
    
         
             
                    - 9
         
     | 
| 
       67 
79 
     | 
    
         
             
                    version: 1.2.9
         
     | 
| 
       68 
80 
     | 
    
         
             
              type: :development
         
     | 
| 
       69 
     | 
    
         
            -
              version_requirements: * 
     | 
| 
      
 81 
     | 
    
         
            +
              version_requirements: *id005
         
     | 
| 
       70 
82 
     | 
    
         
             
            - !ruby/object:Gem::Dependency 
         
     | 
| 
       71 
83 
     | 
    
         
             
              name: webmock
         
     | 
| 
       72 
84 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       73 
     | 
    
         
            -
              requirement: & 
     | 
| 
      
 85 
     | 
    
         
            +
              requirement: &id006 !ruby/object:Gem::Requirement 
         
     | 
| 
       74 
86 
     | 
    
         
             
                requirements: 
         
     | 
| 
       75 
87 
     | 
    
         
             
                - - ">="
         
     | 
| 
       76 
88 
     | 
    
         
             
                  - !ruby/object:Gem::Version 
         
     | 
| 
         @@ -78,7 +90,7 @@ dependencies: 
     | 
|
| 
       78 
90 
     | 
    
         
             
                    - 0
         
     | 
| 
       79 
91 
     | 
    
         
             
                    version: "0"
         
     | 
| 
       80 
92 
     | 
    
         
             
              type: :development
         
     | 
| 
       81 
     | 
    
         
            -
              version_requirements: * 
     | 
| 
      
 93 
     | 
    
         
            +
              version_requirements: *id006
         
     | 
| 
       82 
94 
     | 
    
         
             
            description: Wrapper for pusherapp.com REST api
         
     | 
| 
       83 
95 
     | 
    
         
             
            email: support@pusherapp.com
         
     | 
| 
       84 
96 
     | 
    
         
             
            executables: []
         
     | 
| 
         @@ -96,10 +108,9 @@ files: 
     | 
|
| 
       96 
108 
     | 
    
         
             
            - Rakefile
         
     | 
| 
       97 
109 
     | 
    
         
             
            - VERSION
         
     | 
| 
       98 
110 
     | 
    
         
             
            - lib/pusher.rb
         
     | 
| 
       99 
     | 
    
         
            -
            - lib/pusher/authentication.rb
         
     | 
| 
       100 
111 
     | 
    
         
             
            - lib/pusher/channel.rb
         
     | 
| 
      
 112 
     | 
    
         
            +
            - lib/pusher/request.rb
         
     | 
| 
       101 
113 
     | 
    
         
             
            - pusher.gemspec
         
     | 
| 
       102 
     | 
    
         
            -
            - spec/authentication_spec.rb
         
     | 
| 
       103 
114 
     | 
    
         
             
            - spec/pusher_spec.rb
         
     | 
| 
       104 
115 
     | 
    
         
             
            - spec/spec.opts
         
     | 
| 
       105 
116 
     | 
    
         
             
            - spec/spec_helper.rb
         
     | 
| 
         @@ -134,6 +145,5 @@ signing_key: 
     | 
|
| 
       134 
145 
     | 
    
         
             
            specification_version: 3
         
     | 
| 
       135 
146 
     | 
    
         
             
            summary: Pusher App client
         
     | 
| 
       136 
147 
     | 
    
         
             
            test_files: 
         
     | 
| 
       137 
     | 
    
         
            -
            - spec/authentication_spec.rb
         
     | 
| 
       138 
148 
     | 
    
         
             
            - spec/pusher_spec.rb
         
     | 
| 
       139 
149 
     | 
    
         
             
            - spec/spec_helper.rb
         
     | 
| 
         @@ -1,142 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require 'hmac-sha2'
         
     | 
| 
       2 
     | 
    
         
            -
            require 'base64'
         
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
            module Authentication
         
     | 
| 
       5 
     | 
    
         
            -
              class AuthenticationError < RuntimeError; end
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
              class Token
         
     | 
| 
       8 
     | 
    
         
            -
                attr_reader :key, :secret
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
                def initialize(key, secret)
         
     | 
| 
       11 
     | 
    
         
            -
                  @key, @secret = key, secret
         
     | 
| 
       12 
     | 
    
         
            -
                end
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
                def sign(request)
         
     | 
| 
       15 
     | 
    
         
            -
                  request.sign(self)
         
     | 
| 
       16 
     | 
    
         
            -
                end
         
     | 
| 
       17 
     | 
    
         
            -
              end
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
              class Request
         
     | 
| 
       20 
     | 
    
         
            -
                attr_accessor :path, :query_hash
         
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
                # http://www.w3.org/TR/NOTE-datetime
         
     | 
| 
       23 
     | 
    
         
            -
                ISO8601 = "%Y-%m-%dT%H:%M:%SZ"
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
                def initialize(method, path, query)
         
     | 
| 
       26 
     | 
    
         
            -
                  raise ArgumentError, "Expected string" unless path.kind_of?(String)
         
     | 
| 
       27 
     | 
    
         
            -
                  raise ArgumentError, "Expected hash" unless query.kind_of?(Hash)
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
                  query_hash = {}
         
     | 
| 
       30 
     | 
    
         
            -
                  auth_hash = {}
         
     | 
| 
       31 
     | 
    
         
            -
                  query.each do |key, v|
         
     | 
| 
       32 
     | 
    
         
            -
                    k = key.to_s.downcase
         
     | 
| 
       33 
     | 
    
         
            -
                    k[0..4] == 'auth_' ? auth_hash[k] = v : query_hash[k] = v
         
     | 
| 
       34 
     | 
    
         
            -
                  end
         
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
                  @method = method.upcase
         
     | 
| 
       37 
     | 
    
         
            -
                  @path, @query_hash, @auth_hash = path, query_hash, auth_hash
         
     | 
| 
       38 
     | 
    
         
            -
                end
         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
                def sign(token)
         
     | 
| 
       41 
     | 
    
         
            -
                  @auth_hash = {
         
     | 
| 
       42 
     | 
    
         
            -
                    :auth_version => "1.0",
         
     | 
| 
       43 
     | 
    
         
            -
                    :auth_key => token.key,
         
     | 
| 
       44 
     | 
    
         
            -
                    :auth_timestamp => Time.now.to_i
         
     | 
| 
       45 
     | 
    
         
            -
                  }
         
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
                  @auth_hash[:auth_signature] = signature(token)
         
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
                  return @auth_hash
         
     | 
| 
       50 
     | 
    
         
            -
                end
         
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
                # Authenticates the request with a token
         
     | 
| 
       53 
     | 
    
         
            -
                #
         
     | 
| 
       54 
     | 
    
         
            -
                # Timestamp check: Unless timestamp_grace is set to nil (which will skip
         
     | 
| 
       55 
     | 
    
         
            -
                # the timestamp check), an exception will be raised if timestamp is not
         
     | 
| 
       56 
     | 
    
         
            -
                # supplied or if the timestamp provided is not within timestamp_grace of
         
     | 
| 
       57 
     | 
    
         
            -
                # the real time (defaults to 10 minutes)
         
     | 
| 
       58 
     | 
    
         
            -
                #
         
     | 
| 
       59 
     | 
    
         
            -
                # Signature check: Raises an exception if the signature does not match the
         
     | 
| 
       60 
     | 
    
         
            -
                # computed value
         
     | 
| 
       61 
     | 
    
         
            -
                #
         
     | 
| 
       62 
     | 
    
         
            -
                def authenticate_by_token!(token, timestamp_grace = 600)
         
     | 
| 
       63 
     | 
    
         
            -
                  validate_version!
         
     | 
| 
       64 
     | 
    
         
            -
                  validate_timestamp!(timestamp_grace)
         
     | 
| 
       65 
     | 
    
         
            -
                  validate_signature!(token)
         
     | 
| 
       66 
     | 
    
         
            -
                  true
         
     | 
| 
       67 
     | 
    
         
            -
                end
         
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
                def authenticate_by_token(token, timestamp_grace = 600)
         
     | 
| 
       70 
     | 
    
         
            -
                  authenticate_by_token!(token, timestamp_grace)
         
     | 
| 
       71 
     | 
    
         
            -
                rescue AuthenticationError
         
     | 
| 
       72 
     | 
    
         
            -
                  false
         
     | 
| 
       73 
     | 
    
         
            -
                end
         
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
       75 
     | 
    
         
            -
                def authenticate(timestamp_grace = 600, &block)
         
     | 
| 
       76 
     | 
    
         
            -
                  key = @auth_hash['auth_key']
         
     | 
| 
       77 
     | 
    
         
            -
                  raise AuthenticationError, "Authentication key required" unless key
         
     | 
| 
       78 
     | 
    
         
            -
                  token = yield key
         
     | 
| 
       79 
     | 
    
         
            -
                  unless token && token.secret
         
     | 
| 
       80 
     | 
    
         
            -
                    raise AuthenticationError, "Invalid authentication key"
         
     | 
| 
       81 
     | 
    
         
            -
                  end
         
     | 
| 
       82 
     | 
    
         
            -
                  authenticate_by_token!(token, timestamp_grace)
         
     | 
| 
       83 
     | 
    
         
            -
                  return token
         
     | 
| 
       84 
     | 
    
         
            -
                end
         
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
                def auth_hash
         
     | 
| 
       87 
     | 
    
         
            -
                  raise "Request not signed" unless @auth_hash && @auth_hash[:auth_signature]
         
     | 
| 
       88 
     | 
    
         
            -
                  @auth_hash
         
     | 
| 
       89 
     | 
    
         
            -
                end
         
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
                private
         
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
                  def signature(token)
         
     | 
| 
       94 
     | 
    
         
            -
                    HMAC::SHA256.hexdigest(token.secret, string_to_sign)
         
     | 
| 
       95 
     | 
    
         
            -
                  end
         
     | 
| 
       96 
     | 
    
         
            -
             
     | 
| 
       97 
     | 
    
         
            -
                  def string_to_sign
         
     | 
| 
       98 
     | 
    
         
            -
                    [@method, @path, parameter_string].join("\n")
         
     | 
| 
       99 
     | 
    
         
            -
                  end
         
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
     | 
    
         
            -
                  def parameter_string
         
     | 
| 
       102 
     | 
    
         
            -
                    param_hash = @query_hash.merge(@auth_hash || {})
         
     | 
| 
       103 
     | 
    
         
            -
             
     | 
| 
       104 
     | 
    
         
            -
                    # Convert keys to lowercase strings
         
     | 
| 
       105 
     | 
    
         
            -
                    hash = {}; param_hash.each { |k,v| hash[k.to_s.downcase] = v }
         
     | 
| 
       106 
     | 
    
         
            -
             
     | 
| 
       107 
     | 
    
         
            -
                    # Exclude signature from signature generation!
         
     | 
| 
       108 
     | 
    
         
            -
                    hash.delete("auth_signature")
         
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
       110 
     | 
    
         
            -
                    hash.keys.sort.map { |k| "#{k}=#{hash[k]}" }.join("&")
         
     | 
| 
       111 
     | 
    
         
            -
                  end
         
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
                  def validate_version!
         
     | 
| 
       114 
     | 
    
         
            -
                    version = @auth_hash["auth_version"]
         
     | 
| 
       115 
     | 
    
         
            -
                    raise AuthenticationError, "Version required" unless version
         
     | 
| 
       116 
     | 
    
         
            -
                    raise AuthenticationError, "Version not supported" unless version == '1.0'
         
     | 
| 
       117 
     | 
    
         
            -
                  end
         
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
                  def validate_timestamp!(grace)
         
     | 
| 
       120 
     | 
    
         
            -
                    return true if grace.nil?
         
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
       122 
     | 
    
         
            -
                    timestamp = @auth_hash["auth_timestamp"]
         
     | 
| 
       123 
     | 
    
         
            -
                    error = (timestamp.to_i - Time.now.to_i).abs
         
     | 
| 
       124 
     | 
    
         
            -
                    raise AuthenticationError, "Timestamp required" unless timestamp
         
     | 
| 
       125 
     | 
    
         
            -
                    if error >= grace
         
     | 
| 
       126 
     | 
    
         
            -
                      raise AuthenticationError, "Timestamp expired: Given timestamp "\
         
     | 
| 
       127 
     | 
    
         
            -
                        "(#{Time.at(timestamp.to_i).utc.strftime(ISO8601)}) "\
         
     | 
| 
       128 
     | 
    
         
            -
                        "not within #{grace}s of server time "\
         
     | 
| 
       129 
     | 
    
         
            -
                        "(#{Time.now.utc.strftime(ISO8601)})"
         
     | 
| 
       130 
     | 
    
         
            -
                    end
         
     | 
| 
       131 
     | 
    
         
            -
                    return true
         
     | 
| 
       132 
     | 
    
         
            -
                  end
         
     | 
| 
       133 
     | 
    
         
            -
             
     | 
| 
       134 
     | 
    
         
            -
                  def validate_signature!(token)
         
     | 
| 
       135 
     | 
    
         
            -
                    unless @auth_hash["auth_signature"] == signature(token)
         
     | 
| 
       136 
     | 
    
         
            -
                      raise AuthenticationError, "Invalid signature: you should have "\
         
     | 
| 
       137 
     | 
    
         
            -
                        "sent HmacSHA256Hex(#{string_to_sign.inspect}, your_secret_key)"
         
     | 
| 
       138 
     | 
    
         
            -
                    end
         
     | 
| 
       139 
     | 
    
         
            -
                    return true
         
     | 
| 
       140 
     | 
    
         
            -
                  end
         
     | 
| 
       141 
     | 
    
         
            -
              end
         
     | 
| 
       142 
     | 
    
         
            -
            end
         
     | 
    
        data/spec/authentication_spec.rb
    DELETED
    
    | 
         @@ -1,176 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require File.expand_path('../spec_helper', __FILE__)
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            describe Authentication do
         
     | 
| 
       4 
     | 
    
         
            -
              before :each do
         
     | 
| 
       5 
     | 
    
         
            -
                Time.stub!(:now).and_return(Time.at(1234))
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
                @token = Authentication::Token.new('key', 'secret')
         
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
                @request = Authentication::Request.new('POST', '/some/path', {
         
     | 
| 
       10 
     | 
    
         
            -
                  "query" => "params",
         
     | 
| 
       11 
     | 
    
         
            -
                  "go" => "here"
         
     | 
| 
       12 
     | 
    
         
            -
                })
         
     | 
| 
       13 
     | 
    
         
            -
                @signature = @request.sign(@token)[:auth_signature]
         
     | 
| 
       14 
     | 
    
         
            -
              end
         
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
              it "should generate base64 encoded signature from correct key" do
         
     | 
| 
       17 
     | 
    
         
            -
                @request.send(:string_to_sign).should == "POST\n/some/path\nauth_key=key&auth_timestamp=1234&auth_version=1.0&go=here&query=params"
         
     | 
| 
       18 
     | 
    
         
            -
                @signature.should == '3b237953a5ba6619875cbb2a2d43e8da9ef5824e8a2c689f6284ac85bc1ea0db'
         
     | 
| 
       19 
     | 
    
         
            -
              end
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
              it "should make auth_hash available after request is signed" do
         
     | 
| 
       22 
     | 
    
         
            -
                request = Authentication::Request.new('POST', '/some/path', {
         
     | 
| 
       23 
     | 
    
         
            -
                  "query" => "params"
         
     | 
| 
       24 
     | 
    
         
            -
                })
         
     | 
| 
       25 
     | 
    
         
            -
                lambda {
         
     | 
| 
       26 
     | 
    
         
            -
                  request.auth_hash
         
     | 
| 
       27 
     | 
    
         
            -
                }.should raise_error('Request not signed')
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
                request.sign(@token)
         
     | 
| 
       30 
     | 
    
         
            -
                request.auth_hash.should == {
         
     | 
| 
       31 
     | 
    
         
            -
                  :auth_signature => "da078fcedd72941b6c873caa40d0d6b2000ebfc700cee802b128dd20f72e74e9",
         
     | 
| 
       32 
     | 
    
         
            -
                  :auth_version => "1.0",
         
     | 
| 
       33 
     | 
    
         
            -
                  :auth_key => "key",
         
     | 
| 
       34 
     | 
    
         
            -
                  :auth_timestamp => 1234
         
     | 
| 
       35 
     | 
    
         
            -
                }
         
     | 
| 
       36 
     | 
    
         
            -
              end
         
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
              it "should cope with symbol keys" do
         
     | 
| 
       39 
     | 
    
         
            -
                @request.query_hash = {
         
     | 
| 
       40 
     | 
    
         
            -
                  :query => "params",
         
     | 
| 
       41 
     | 
    
         
            -
                  :go => "here"
         
     | 
| 
       42 
     | 
    
         
            -
                }
         
     | 
| 
       43 
     | 
    
         
            -
                @request.sign(@token)[:auth_signature].should == @signature
         
     | 
| 
       44 
     | 
    
         
            -
              end
         
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
              it "should cope with upcase keys (keys are lowercased before signing)" do
         
     | 
| 
       47 
     | 
    
         
            -
                @request.query_hash = {
         
     | 
| 
       48 
     | 
    
         
            -
                  "Query" => "params",
         
     | 
| 
       49 
     | 
    
         
            -
                  "GO" => "here"
         
     | 
| 
       50 
     | 
    
         
            -
                }
         
     | 
| 
       51 
     | 
    
         
            -
                @request.sign(@token)[:auth_signature].should == @signature
         
     | 
| 
       52 
     | 
    
         
            -
              end
         
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
              it "should use the path to generate signature" do
         
     | 
| 
       55 
     | 
    
         
            -
                @request.path = '/some/other/path'
         
     | 
| 
       56 
     | 
    
         
            -
                @request.sign(@token)[:auth_signature].should_not == @signature
         
     | 
| 
       57 
     | 
    
         
            -
              end
         
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
              it "should use the query string keys to generate signature" do
         
     | 
| 
       60 
     | 
    
         
            -
                @request.query_hash = {
         
     | 
| 
       61 
     | 
    
         
            -
                  "other" => "query"
         
     | 
| 
       62 
     | 
    
         
            -
                }
         
     | 
| 
       63 
     | 
    
         
            -
                @request.sign(@token)[:auth_signature].should_not == @signature
         
     | 
| 
       64 
     | 
    
         
            -
              end
         
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
              it "should use the query string values to generate signature" do
         
     | 
| 
       67 
     | 
    
         
            -
                @request.query_hash = {
         
     | 
| 
       68 
     | 
    
         
            -
                  "key" => "notfoo",
         
     | 
| 
       69 
     | 
    
         
            -
                  "other" => 'bar'
         
     | 
| 
       70 
     | 
    
         
            -
                }
         
     | 
| 
       71 
     | 
    
         
            -
                @request.sign(@token)[:signature].should_not == @signature
         
     | 
| 
       72 
     | 
    
         
            -
              end
         
     | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
       74 
     | 
    
         
            -
              describe "verification" do
         
     | 
| 
       75 
     | 
    
         
            -
                before :each do
         
     | 
| 
       76 
     | 
    
         
            -
                  Time.stub!(:now).and_return(Time.at(1234))
         
     | 
| 
       77 
     | 
    
         
            -
                  @request.sign(@token)
         
     | 
| 
       78 
     | 
    
         
            -
                  @params = @request.query_hash.merge(@request.auth_hash)
         
     | 
| 
       79 
     | 
    
         
            -
                end
         
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
                it "should verify requests" do
         
     | 
| 
       82 
     | 
    
         
            -
                  request = Authentication::Request.new('POST', '/some/path', @params)
         
     | 
| 
       83 
     | 
    
         
            -
                  request.authenticate_by_token(@token).should == true
         
     | 
| 
       84 
     | 
    
         
            -
                end
         
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
                it "should raise error if signature is not correct" do
         
     | 
| 
       87 
     | 
    
         
            -
                  @params[:auth_signature] =  'asdf'
         
     | 
| 
       88 
     | 
    
         
            -
                  request = Authentication::Request.new('POST', '/some/path', @params)
         
     | 
| 
       89 
     | 
    
         
            -
                  lambda {
         
     | 
| 
       90 
     | 
    
         
            -
                    request.authenticate_by_token!(@token)
         
     | 
| 
       91 
     | 
    
         
            -
                  }.should raise_error('Invalid signature: you should have sent HmacSHA256Hex("POST\n/some/path\nauth_key=key&auth_timestamp=1234&auth_version=1.0&go=here&query=params", your_secret_key)')
         
     | 
| 
       92 
     | 
    
         
            -
                end
         
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
       94 
     | 
    
         
            -
                it "should raise error if timestamp not available" do
         
     | 
| 
       95 
     | 
    
         
            -
                  @params.delete(:auth_timestamp)
         
     | 
| 
       96 
     | 
    
         
            -
                  request = Authentication::Request.new('POST', '/some/path', @params)
         
     | 
| 
       97 
     | 
    
         
            -
                  lambda {
         
     | 
| 
       98 
     | 
    
         
            -
                    request.authenticate_by_token!(@token)
         
     | 
| 
       99 
     | 
    
         
            -
                  }.should raise_error('Timestamp required')
         
     | 
| 
       100 
     | 
    
         
            -
                end
         
     | 
| 
       101 
     | 
    
         
            -
             
     | 
| 
       102 
     | 
    
         
            -
                it "should raise error if timestamp has expired (default of 600s)" do
         
     | 
| 
       103 
     | 
    
         
            -
                  request = Authentication::Request.new('POST', '/some/path', @params)
         
     | 
| 
       104 
     | 
    
         
            -
                  Time.stub!(:now).and_return(Time.at(1234 + 599))
         
     | 
| 
       105 
     | 
    
         
            -
                  request.authenticate_by_token!(@token).should == true
         
     | 
| 
       106 
     | 
    
         
            -
                  Time.stub!(:now).and_return(Time.at(1234 - 599))
         
     | 
| 
       107 
     | 
    
         
            -
                  request.authenticate_by_token!(@token).should == true
         
     | 
| 
       108 
     | 
    
         
            -
                  Time.stub!(:now).and_return(Time.at(1234 + 600))
         
     | 
| 
       109 
     | 
    
         
            -
                  lambda {
         
     | 
| 
       110 
     | 
    
         
            -
                    request.authenticate_by_token!(@token)
         
     | 
| 
       111 
     | 
    
         
            -
                  }.should raise_error("Timestamp expired: Given timestamp (1970-01-01T00:20:34Z) not within 600s of server time (1970-01-01T00:30:34Z)")
         
     | 
| 
       112 
     | 
    
         
            -
                  Time.stub!(:now).and_return(Time.at(1234 - 600))
         
     | 
| 
       113 
     | 
    
         
            -
                  lambda {
         
     | 
| 
       114 
     | 
    
         
            -
                    request.authenticate_by_token!(@token)
         
     | 
| 
       115 
     | 
    
         
            -
                  }.should raise_error("Timestamp expired: Given timestamp (1970-01-01T00:20:34Z) not within 600s of server time (1970-01-01T00:10:34Z)")
         
     | 
| 
       116 
     | 
    
         
            -
                end
         
     | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
                it "should be possible to customize the timeout grace period" do
         
     | 
| 
       119 
     | 
    
         
            -
                  grace = 10
         
     | 
| 
       120 
     | 
    
         
            -
                  request = Authentication::Request.new('POST', '/some/path', @params)
         
     | 
| 
       121 
     | 
    
         
            -
                  Time.stub!(:now).and_return(Time.at(1234 + grace - 1))
         
     | 
| 
       122 
     | 
    
         
            -
                  request.authenticate_by_token!(@token, grace).should == true
         
     | 
| 
       123 
     | 
    
         
            -
                  Time.stub!(:now).and_return(Time.at(1234 + grace))
         
     | 
| 
       124 
     | 
    
         
            -
                  lambda {
         
     | 
| 
       125 
     | 
    
         
            -
                    request.authenticate_by_token!(@token, grace)
         
     | 
| 
       126 
     | 
    
         
            -
                  }.should raise_error("Timestamp expired: Given timestamp (1970-01-01T00:20:34Z) not within 10s of server time (1970-01-01T00:20:44Z)")
         
     | 
| 
       127 
     | 
    
         
            -
                end
         
     | 
| 
       128 
     | 
    
         
            -
             
     | 
| 
       129 
     | 
    
         
            -
                it "should be possible to skip timestamp check by passing nil" do
         
     | 
| 
       130 
     | 
    
         
            -
                  request = Authentication::Request.new('POST', '/some/path', @params)
         
     | 
| 
       131 
     | 
    
         
            -
                  Time.stub!(:now).and_return(Time.at(1234 + 1000))
         
     | 
| 
       132 
     | 
    
         
            -
                  request.authenticate_by_token!(@token, nil).should == true
         
     | 
| 
       133 
     | 
    
         
            -
                end
         
     | 
| 
       134 
     | 
    
         
            -
                
         
     | 
| 
       135 
     | 
    
         
            -
                it "should check that auth_version is supplied" do
         
     | 
| 
       136 
     | 
    
         
            -
                  @params.delete(:auth_version)
         
     | 
| 
       137 
     | 
    
         
            -
                  request = Authentication::Request.new('POST', '/some/path', @params)
         
     | 
| 
       138 
     | 
    
         
            -
                  lambda {
         
     | 
| 
       139 
     | 
    
         
            -
                    request.authenticate_by_token!(@token)
         
     | 
| 
       140 
     | 
    
         
            -
                  }.should raise_error('Version required')
         
     | 
| 
       141 
     | 
    
         
            -
                end
         
     | 
| 
       142 
     | 
    
         
            -
             
     | 
| 
       143 
     | 
    
         
            -
                it "should check that auth_version equals 1.0" do
         
     | 
| 
       144 
     | 
    
         
            -
                  @params[:auth_version] = '1.1'
         
     | 
| 
       145 
     | 
    
         
            -
                  request = Authentication::Request.new('POST', '/some/path', @params)
         
     | 
| 
       146 
     | 
    
         
            -
                  lambda {
         
     | 
| 
       147 
     | 
    
         
            -
                    request.authenticate_by_token!(@token)
         
     | 
| 
       148 
     | 
    
         
            -
                  }.should raise_error('Version not supported')
         
     | 
| 
       149 
     | 
    
         
            -
                end
         
     | 
| 
       150 
     | 
    
         
            -
             
     | 
| 
       151 
     | 
    
         
            -
                describe "when used with optional block" do
         
     | 
| 
       152 
     | 
    
         
            -
                  it "should optionally take a block which yields the signature" do
         
     | 
| 
       153 
     | 
    
         
            -
                    request = Authentication::Request.new('POST', '/some/path', @params)
         
     | 
| 
       154 
     | 
    
         
            -
                    request.authenticate do |key|
         
     | 
| 
       155 
     | 
    
         
            -
                      key.should == @token.key
         
     | 
| 
       156 
     | 
    
         
            -
                      @token
         
     | 
| 
       157 
     | 
    
         
            -
                    end.should == @token
         
     | 
| 
       158 
     | 
    
         
            -
                  end
         
     | 
| 
       159 
     | 
    
         
            -
             
     | 
| 
       160 
     | 
    
         
            -
                  it "should raise error if no auth_key supplied to request" do
         
     | 
| 
       161 
     | 
    
         
            -
                    @params.delete(:auth_key)
         
     | 
| 
       162 
     | 
    
         
            -
                    request = Authentication::Request.new('POST', '/some/path', @params)
         
     | 
| 
       163 
     | 
    
         
            -
                    lambda {
         
     | 
| 
       164 
     | 
    
         
            -
                      request.authenticate { |key| nil }
         
     | 
| 
       165 
     | 
    
         
            -
                    }.should raise_error('Authentication key required')
         
     | 
| 
       166 
     | 
    
         
            -
                  end
         
     | 
| 
       167 
     | 
    
         
            -
             
     | 
| 
       168 
     | 
    
         
            -
                  it "should raise error if block returns nil (i.e. key doesn't exist)" do
         
     | 
| 
       169 
     | 
    
         
            -
                    request = Authentication::Request.new('POST', '/some/path', @params)
         
     | 
| 
       170 
     | 
    
         
            -
                    lambda {
         
     | 
| 
       171 
     | 
    
         
            -
                      request.authenticate { |key| nil }
         
     | 
| 
       172 
     | 
    
         
            -
                    }.should raise_error('Invalid authentication key')
         
     | 
| 
       173 
     | 
    
         
            -
                  end
         
     | 
| 
       174 
     | 
    
         
            -
                end
         
     | 
| 
       175 
     | 
    
         
            -
              end
         
     | 
| 
       176 
     | 
    
         
            -
            end
         
     |