escher 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d00625f53cdd3b7ad66a39b9cabcea43acb62c0e
4
- data.tar.gz: f7598ab91680f31be25a6e2e37f92f2cfc30a2eb
3
+ metadata.gz: bf5ca3954d669d4c1305dd98027a8b5d4fe37c49
4
+ data.tar.gz: 4a16a2338e1a81efade3a7bd9e01ac5bc888c453
5
5
  SHA512:
6
- metadata.gz: 7ee2cac687e5f94ed8caac6da7218c420f195416084a03ba8753c589df441cd7e24116e3ac089609f78314b3201c98b2ce0a57f397a33582caf2f43b8f1d8a63
7
- data.tar.gz: 0b506771ab44ad8bfc8f871cd61137a1b89e64028e492f27ca8d4275da80f35a5a2702c124dd88080ab131b7c2948199c6fdec9ac7b3d6825fefda7235efd108
6
+ metadata.gz: 7f121d4fc3afed7141855fc060e8a6f04af57f783d823b15a43f61bbad4dbcefc671514938b103d01e2fbbd605853aeb0cdb47a7d78762c2c86b5edf2820f133
7
+ data.tar.gz: 102ca5ed92167b8cfa9ddb9fca6d1cd54e5a6d32006a46e2965185cf575e91ff449012fa7e86be7578600687734adcfc9e6bc210d5ce81b25a409133d0b72c07
data/.travis.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
- - 2.1.2
4
+ - 2.1.2
5
+ - 2.2.1
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2014 Emarsys Technologies Kft.
3
+ Copyright (c) 2014-2015 Emarsys Technologies Kft.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -5,4 +5,4 @@ Escher helps you creating secure HTTP requests (for APIs) by signing HTTP(s) req
5
5
 
6
6
  The algorithm is based on [Amazon's _AWS Signature Version 4_](http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html), but we have generalized and extended it.
7
7
 
8
- More details will be available at our [documentation site](https://documentation.emarsys.com/).
8
+ More details will be available at our [documentation site](http://escherauth.io/).
data/escher.gemspec CHANGED
@@ -21,6 +21,8 @@ Gem::Specification.new do |spec|
21
21
  spec.required_ruby_version = '>= 1.9'
22
22
 
23
23
  spec.add_development_dependency "bundler", "~> 1.6"
24
+ spec.add_development_dependency "rails"
25
+
24
26
  spec.add_development_dependency "rake", "~> 10"
25
27
  spec.add_development_dependency "rspec", "~> 2"
26
28
 
data/lib/escher/auth.rb CHANGED
@@ -176,12 +176,12 @@ module Escher
176
176
  canonicalized_request = canonicalize(method, path, query_parts, body, headers, signed_headers.uniq)
177
177
  string_to_sign = get_string_to_sign(canonicalized_request)
178
178
 
179
- signing_key = Digest::HMAC.digest(short_date(@current_time), @algo_prefix + api_secret, @algo)
179
+ signing_key = OpenSSL::HMAC.digest(@algo, @algo_prefix + api_secret, short_date(@current_time))
180
180
  @credential_scope.split('/').each { |data|
181
- signing_key = Digest::HMAC.digest(data, signing_key, @algo)
181
+ signing_key = OpenSSL::HMAC.digest(@algo, signing_key, data)
182
182
  }
183
183
 
184
- Digest::HMAC.hexdigest(string_to_sign, signing_key, @algo)
184
+ OpenSSL::HMAC.hexdigest(@algo, signing_key, string_to_sign)
185
185
  end
186
186
 
187
187
 
@@ -236,9 +236,9 @@ module Escher
236
236
  def create_algo
237
237
  case @hash_algo
238
238
  when 'SHA256'
239
- @algo = Digest::SHA2.new(256)
239
+ @algo = OpenSSL::Digest::SHA256.new
240
240
  when 'SHA512'
241
- @algo = Digest::SHA2.new(512)
241
+ @algo = OpenSSL::Digest::SHA521.new
242
242
  else
243
243
  raise EscherError, 'Unidentified hash algorithm'
244
244
  end
@@ -0,0 +1,42 @@
1
+ module Escher
2
+ module Request
3
+ class ActionDispatchRequest < Base
4
+
5
+ def headers
6
+ request.env.
7
+ select { |header_name, _| header_name.start_with? "HTTP_" }.
8
+ map { |header_name, value| [header_name[5..-1].tr('_', '-'), value] }
9
+ end
10
+
11
+
12
+
13
+ def method
14
+ request.request_method
15
+ end
16
+
17
+
18
+
19
+ def body
20
+ request.body or ''
21
+ end
22
+
23
+
24
+
25
+ def path
26
+ request.env['REQUEST_PATH']
27
+ end
28
+
29
+
30
+
31
+ def query_values
32
+ Addressable::URI.new(:query => request.env['QUERY_STRING']).query_values(Array) or []
33
+ end
34
+
35
+
36
+
37
+ def set_header(header_name, value)
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -24,6 +24,39 @@ module Escher
24
24
  header[1]
25
25
  end
26
26
 
27
+
28
+
29
+ def method
30
+ raise("Implementation missing for #{__method__}")
31
+ end
32
+
33
+
34
+
35
+ def body
36
+ raise("Implementation missing for #{__method__}")
37
+ end
38
+
39
+
40
+
41
+ def headers
42
+ raise('Implementation missing, should return array of array with [key,value] pairs')
43
+ end
44
+
45
+
46
+
47
+ def path
48
+ raise("Implementation missing for #{__method__}")
49
+ end
50
+
51
+
52
+
53
+ def query_values
54
+ raise("Implementation missing for #{__method__}")
55
+ end
56
+
57
+
58
+
59
+
27
60
  end
28
61
  end
29
62
  end
@@ -1,8 +1,8 @@
1
- require_relative 'base'
2
-
3
- require_relative 'hash_request'
4
- require_relative 'legacy_request'
5
- require_relative 'rack_request'
1
+ require 'escher/request/base'
2
+ require 'escher/request/hash_request'
3
+ require 'escher/request/rack_request'
4
+ require 'escher/request/legacy_request'
5
+ require 'escher/request/action_dispatch_request'
6
6
 
7
7
  module Escher
8
8
  module Request
@@ -10,12 +10,19 @@ module Escher
10
10
 
11
11
  def self.from_request(request)
12
12
  case request
13
+
14
+ when defined?(ActionDispatch::Request) && ActionDispatch::Request
15
+ ActionDispatchRequest.new(request)
16
+
17
+ when defined?(Rack::Request) && Rack::Request
18
+ RackRequest.new(request)
19
+
13
20
  when Hash
14
- HashRequest.new request
15
- when lambda { |request| request.class.ancestors.map(&:to_s).include? "Rack::Request" }
16
- RackRequest.new request
21
+ HashRequest.new(request)
22
+
17
23
  else
18
- Escher::Request::LegacyRequest.new request
24
+ Escher::Request::LegacyRequest.new(request)
25
+
19
26
  end
20
27
  end
21
28
 
@@ -1,42 +1,62 @@
1
- module Escher
2
- module Request
3
- class RackRequest < Base
1
+ class Escher::Request::RackRequest < Escher::Request::Base
4
2
 
5
- def headers
6
- request.env.
7
- select { |header_name, _| header_name.start_with? "HTTP_" }.
8
- map { |header_name, value| [header_name[5..-1].tr('_', '-'), value] }
9
- end
3
+ def initialize(request_env)
4
+ super(request_env)
5
+ @rack_request = request_env
6
+ end
10
7
 
8
+ def env
9
+ @rack_request.env
10
+ end
11
11
 
12
+ def rack_request
13
+ @rack_request
14
+ end
12
15
 
13
- def method
14
- request.request_method
15
- end
16
+ def uri
17
+ @rack_request.env['REQUEST_URI']
18
+ end
16
19
 
20
+ def path
21
+ @rack_request.env['REQUEST_PATH']
22
+ end
17
23
 
24
+ def host
25
+ @rack_request.env['HTTP_HOST']
26
+ end
18
27
 
19
- def body
20
- request.body or ''
21
- end
28
+ def headers
29
+ @headers ||= @rack_request.env.select { |k, v| k =~ /^HTTP_/i }.map { |k, v| [k.sub(/^HTTP_/i, '').gsub('_', '-'), v] }
30
+ end
22
31
 
32
+ def method
33
+ @rack_request.request_method rescue @rack_request.env['REQUEST_METHOD']
34
+ end
23
35
 
36
+ def payload
37
+ @payload ||= fetch_payload
38
+ end
24
39
 
25
- def path
26
- request.env['REQUEST_PATH']
27
- end
40
+ alias body payload
28
41
 
42
+ def query_values
43
+ Addressable::URI.new(:query => request.env['QUERY_STRING']).query_values(Array) or []
44
+ end
29
45
 
46
+ def set_header(header_name, value)
47
+ end
30
48
 
31
- def query_values
32
- Addressable::URI.new(:query => request.env['QUERY_STRING']).query_values(Array) or []
33
- end
49
+ protected
34
50
 
51
+ def fetch_payload
52
+ rack_input = @rack_request.body
35
53
 
54
+ return rack_input.to_s if rack_input.nil? || rack_input.is_a?(String)
36
55
 
37
- def set_header(header_name, value)
38
- end
56
+ payload = rack_input.read
57
+ @rack_request.body.rewind
58
+ payload
39
59
 
40
- end
41
60
  end
42
- end
61
+
62
+ end
@@ -1,3 +1,3 @@
1
1
  module Escher
2
- VERSION = '0.3.2'
2
+ VERSION = '0.3.3'
3
3
  end
data/lib/escher.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'addressable/uri'
2
2
  require 'time'
3
- require 'digest'
3
+ require 'openssl'
4
4
 
5
5
  require 'escher/version'
6
6
  require 'escher/request/factory'
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+
3
+ require 'action_dispatch'
4
+
5
+ describe Escher::Request::ActionDispatchRequest do
6
+
7
+ let(:request_params) { {"PATH_INFO" => "/", } }
8
+ let(:request) { ActionDispatch::Request.new(request_params) }
9
+
10
+ subject { described_class.new request }
11
+
12
+ describe "#request" do
13
+ it "should return the underlying request object" do
14
+ expect(subject.request).to eq request
15
+ end
16
+ end
17
+
18
+
19
+ describe "#headers" do
20
+ it "should return only the HTTP request headers" do
21
+ request_params.merge! 'HTTP_HOST' => 'some host',
22
+ 'SOME_HEADER' => 'some header'
23
+
24
+ expect(subject.headers).to eq [['HOST', 'some host']]
25
+ end
26
+
27
+ it "should replace underscores with dashes in the header name" do
28
+ request_params.merge! 'HTTP_HOST_NAME' => 'some host'
29
+
30
+ expect(subject.headers).to eq [['HOST-NAME', 'some host']]
31
+ end
32
+ end
33
+
34
+
35
+ describe "#has_header?" do
36
+ it "should return true if request has specified header, false otherwise" do
37
+ request_params.merge! 'HTTP_HOST_NAME' => 'some host'
38
+
39
+ expect(subject.has_header? 'host-name').to be_truthy
40
+ expect(subject.has_header? 'no-such-header').to be_falsey
41
+ end
42
+ end
43
+
44
+
45
+ describe "#header" do
46
+ it "should return the value for the requested header" do
47
+ request_params.merge! 'HTTP_HOST' => 'some host'
48
+
49
+ expect(subject.header 'host').to eq 'some host'
50
+ end
51
+
52
+ it "should return nil if no such header exists" do
53
+ expect(subject.header 'host').to be_nil
54
+ end
55
+ end
56
+
57
+
58
+ describe "#method" do
59
+ it "should return the request method" do
60
+ request_params.merge! 'REQUEST_METHOD' => 'GET'
61
+
62
+ expect(subject.method).to eq 'GET'
63
+ end
64
+ end
65
+
66
+
67
+ describe "#body" do
68
+ it "should return the request body" do
69
+ request_params.merge! 'rack.input' => 'request body'
70
+
71
+ expect(subject.body).to eq 'request body'
72
+ end
73
+
74
+ it "should return empty string for no body" do
75
+ expect(subject.body).to eq ''
76
+ end
77
+ end
78
+
79
+
80
+ describe "#path" do
81
+ it "should return the request path" do
82
+ request_params.merge! 'REQUEST_PATH' => '/resources/id///'
83
+
84
+ expect(subject.path).to eq '/resources/id///'
85
+ end
86
+ end
87
+
88
+
89
+ describe "#query_values" do
90
+ it "should return the request query parameters as an array of key-value pairs" do
91
+ request_params.merge! 'QUERY_STRING' => 'search=query&param=value'
92
+
93
+ expect(subject.query_values).to eq [['search', 'query'], ['param', 'value']]
94
+ end
95
+
96
+ it "should return the query parameters regardless of fragments" do
97
+ request_params.merge! 'QUERY_STRING' => "@\#$%^&+=/,?><`\";:\\|][{}"
98
+
99
+ expect(subject.query_values).to eq [["@\#$%^"], ["+", "/,?><`\";:\\|][{}"]]
100
+ end
101
+
102
+ it "should return an empty array if the request has no query parameters" do
103
+ expect(subject.query_values).to eq []
104
+ end
105
+ end
106
+
107
+
108
+ describe "#set_header" do
109
+ it "should ignore calls" do
110
+ expect { subject.set_header 'test-header', 'test value' }.not_to raise_error
111
+ end
112
+ end
113
+
114
+ end
@@ -1,12 +1,20 @@
1
1
  require 'spec_helper'
2
+
3
+ require 'rack'
2
4
  require 'rack/request'
5
+ require 'action_dispatch'
3
6
 
4
7
  describe Escher::Request::Factory do
5
8
 
6
9
  describe ".from_request" do
7
- {{uri: "request uri"} => Escher::Request::HashRequest,
8
- Struct.new(:uri) => Escher::Request::LegacyRequest,
9
- Rack::Request.new({}) => Escher::Request::RackRequest}.each do |request, expected_class|
10
+ {
11
+
12
+ {uri: "request uri"} => Escher::Request::HashRequest,
13
+ Struct.new(:uri) => Escher::Request::LegacyRequest,
14
+ Rack::Request.new({}) => Escher::Request::RackRequest,
15
+ ActionDispatch::Request.new({}) => Escher::Request::ActionDispatchRequest
16
+
17
+ }.each do |request, expected_class|
10
18
 
11
19
  it "should return a #{expected_class.name} when the request to be wrapped is a #{request.class.name}" do
12
20
  expect(expected_class).to receive(:new).with(request).and_return "#{expected_class.name} wrapping request"
@@ -1,4 +1,6 @@
1
1
  require 'spec_helper'
2
+
3
+ require 'rack'
2
4
  require 'rack/request'
3
5
 
4
6
  describe Escher::Request::RackRequest do
data/spec/spec_helper.rb CHANGED
@@ -1 +1,3 @@
1
- require 'escher'
1
+ lib = File.expand_path('../../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'escher'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: escher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andras Barthazi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-10 00:00:00.000000000 Z
11
+ date: 2015-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -97,6 +111,7 @@ files:
97
111
  - escher.gemspec
98
112
  - lib/escher.rb
99
113
  - lib/escher/auth.rb
114
+ - lib/escher/request/action_dispatch_request.rb
100
115
  - lib/escher/request/base.rb
101
116
  - lib/escher/request/factory.rb
102
117
  - lib/escher/request/hash_request.rb
@@ -280,6 +295,7 @@ files:
280
295
  - spec/emarsys_testsuite/post-header-value-spaces.sreq
281
296
  - spec/emarsys_testsuite/post-header-value-spaces.sts
282
297
  - spec/escher/auth_spec.rb
298
+ - spec/escher/request/action_dispatch_request_spec.rb
283
299
  - spec/escher/request/factory_spec.rb
284
300
  - spec/escher/request/hash_request_spec.rb
285
301
  - spec/escher/request/rack_request_spec.rb
@@ -486,6 +502,7 @@ test_files:
486
502
  - spec/emarsys_testsuite/post-header-value-spaces.sreq
487
503
  - spec/emarsys_testsuite/post-header-value-spaces.sts
488
504
  - spec/escher/auth_spec.rb
505
+ - spec/escher/request/action_dispatch_request_spec.rb
489
506
  - spec/escher/request/factory_spec.rb
490
507
  - spec/escher/request/hash_request_spec.rb
491
508
  - spec/escher/request/rack_request_spec.rb