api_signature 0.1.0 → 0.1.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e907dd2adc3e3558f0f5fc7a00131ccac6d71aac
4
- data.tar.gz: 7db50a3800bc9c2e77eea7d7a543a1054d40073c
3
+ metadata.gz: 6b3f7f58448cc08c412e475bd5967b8af6cfb972
4
+ data.tar.gz: 13783e19a83c42cdbc744036a44065f6deb7a56c
5
5
  SHA512:
6
- metadata.gz: 527fd053ef63b32c5ce09cfa0e020c7dbc9a125e52b8332703e4bc2b20380e44557e6e51f30fbc64565238236daef9db38716f738c49c23fb2e05bcadece8fb1
7
- data.tar.gz: fb6449eb2de6530c14175f8faa775ba0a62466ac8581714255b9f62134d007525a3cc9f3aef62ad2d65402aea39f9f569e13dc748c7c4277fc4a2872e455356b
6
+ metadata.gz: 73189d7c54d5bef421df7d7f195bc8e2c708e2b5d67e85ee4151e35a02f34165db50420c836e0ee7ab2199f5e2adc5223146ba1560e6767867c1b1b7b1534e07
7
+ data.tar.gz: 1f61c800c0be84c0874807188774118ba332b57a92dca59b5116244131a9ebdd15cb505fbda2363da87c9662a00019db676f36f68bb21d2874f6a5b2db3e7875
data/README.md CHANGED
@@ -114,6 +114,67 @@ ApiSignature.setup do |config|
114
114
  end
115
115
  ```
116
116
 
117
+ ## Testing
118
+
119
+ In your `rails_helper.rb`:
120
+
121
+ ```ruby
122
+ require 'api_signature/spec_support/helper'
123
+
124
+ RSpec.configure do |config|
125
+ config.include ApiSignature::SpecSupport::Helper, type: :controller
126
+ end
127
+ ```
128
+
129
+ This will enable the following methods in controller tests:
130
+
131
+ * get_with_signature(client, action_name, params = {})
132
+ * post_with_signature(client, action_name, params = {})
133
+ * put_with_signature(client, action_name, params = {})
134
+ * patch_with_signature(client, action_name, params = {})
135
+ * delete_with_signature(client, action_name, params = {})
136
+
137
+ `client` object should respond to `#api_key` and `#api_secret`
138
+
139
+ Example usage:
140
+
141
+ ```ruby
142
+ RSpec.describe Api::V1::OrdersController do
143
+ let(:client) { FactoryBot.create(:client) }
144
+ # or any object, that responds to #api_key and #api_secret
145
+ # let(:client) { OpenStruct.new(api_key: 'some_key', api_secret: 'some_api_secret') }
146
+
147
+ it 'should filter orders by state' do
148
+ get_with_signature client, :index, state: :paid
149
+
150
+ expect(last_response.status).to eq 200
151
+ expect(last_response.body).to have_node(:orders)
152
+ expect(last_response.body).to have_node(:state).with('paid')
153
+ end
154
+
155
+ let(:order_attributes) { FactoryBot.attributes_for(:order) }
156
+
157
+ it 'should create new order' do
158
+ post_with_signature client, :create, order: order_attributes
159
+ end
160
+ end
161
+ ```
162
+
163
+ For nested resources path can be specified explicitly using `path` parameter:
164
+
165
+ ```ruby
166
+ # path: /api/v1/orders/:order_id/comments
167
+
168
+ RSpec.describe Api::V1::CommentsController do
169
+ let(:client) { OpenStruct.new(api_key: 'some_key', api_secret: 'some_api_secret') }
170
+ let(:order) { FactoryBot.create(:order) }
171
+
172
+ it 'should update comment for order' do
173
+ put_with_signature client, :update, path: { order_id: order.id }, comment: { content: 'Some value' }
174
+ end
175
+ end
176
+ ```
177
+
117
178
  ## Development
118
179
 
119
180
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -28,5 +28,5 @@ Gem::Specification.new do |spec|
28
28
  spec.add_development_dependency 'rspec', '~> 3.0'
29
29
 
30
30
  spec.add_dependency 'activesupport', '>= 4.0'
31
- spec.add_dependency 'rack', '~> 2.0', '>= 2.0.5'
31
+ spec.add_dependency 'rack', '>= 2.0'
32
32
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ApiSignature
4
+ module SpecSupport
5
+ class HeadersBuilder
6
+ attr_reader :access_key, :secret, :http_method, :path
7
+
8
+ def initialize(access_key, secret, http_method, path)
9
+ @access_key = access_key
10
+ @secret = secret
11
+ @http_method = http_method
12
+ @path = path
13
+ end
14
+
15
+ def headers
16
+ {
17
+ 'HTTP_X_ACCESS_KEY' => access_key,
18
+ 'HTTP_X_TIMESTAMP' => options[:timestamp],
19
+ 'HTTP_X_SIGNATURE' => generator.generate_signature(secret)
20
+ }
21
+ end
22
+
23
+ private
24
+
25
+ def generator
26
+ @generator ||= ::ApiSignature::Generator.new(options)
27
+ end
28
+
29
+ def options
30
+ @options ||= {
31
+ request_method: http_method.to_s.upcase,
32
+ path: path,
33
+ access_key: access_key,
34
+ timestamp: Time.zone.now.to_i
35
+ }
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'api_signature/spec_support/path_builder'
4
+ require 'api_signature/spec_support/headers_builder'
5
+
6
+ module ApiSignature
7
+ module SpecSupport
8
+ module Helper
9
+ include Rack::Test::Methods
10
+
11
+ def app
12
+ Rails.app_class
13
+ end
14
+
15
+ def get_with_signature(client, *args)
16
+ with_signature(:get, client.api_key, client.api_secret, *args)
17
+ end
18
+
19
+ def post_with_signature(client, *args)
20
+ with_signature(:post, client.api_key, client.api_secret, *args)
21
+ end
22
+
23
+ def put_with_signature(client, *args)
24
+ with_signature(:put, client.api_key, client.api_secret, *args)
25
+ end
26
+
27
+ alias patch_with_signature put_with_signature
28
+
29
+ def delete_with_signature(client, *args)
30
+ with_signature(:delete, client.api_key, client.api_secret, *args)
31
+ end
32
+
33
+ private
34
+
35
+ def with_signature(http_method, api_key, secret, action_name, params = {})
36
+ path = PathBuilder.new(controller, action_name, params).path
37
+ headers = HeadersBuilder.new(api_key, secret, http_method, path).headers
38
+
39
+ send(http_method, path, params, headers)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ApiSignature
4
+ module SpecSupport
5
+ class PathBuilder
6
+ attr_reader :controller, :action_name, :params
7
+
8
+ PRIMARY_KEYS = [:id, :token].freeze
9
+
10
+ def initialize(controller, action_name, params = {})
11
+ @controller = controller
12
+ @action_name = action_name
13
+ @params = params
14
+ end
15
+
16
+ def path
17
+ if params[:path].present?
18
+ hash = params.delete(:path)
19
+ url_options.merge!(hash)
20
+ params.merge!(hash)
21
+ end
22
+
23
+ controller.url_for(url_options)
24
+ end
25
+
26
+ private
27
+
28
+ def url_options
29
+ @url_options ||= {
30
+ action: action_name,
31
+ controller: controller.controller_path,
32
+ only_path: true
33
+ }.merge(key_options || {})
34
+ end
35
+
36
+ def key_options
37
+ key = (params.keys.map(&:to_sym) & PRIMARY_KEYS).first
38
+ { key => params[key] } if params[key].present?
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ApiSignature
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.1'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api_signature
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igor Galeta
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2018-06-22 00:00:00.000000000 Z
12
+ date: 2018-06-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -105,22 +105,16 @@ dependencies:
105
105
  name: rack
106
106
  requirement: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '2.0'
111
108
  - - ">="
112
109
  - !ruby/object:Gem::Version
113
- version: 2.0.5
110
+ version: '2.0'
114
111
  type: :runtime
115
112
  prerelease: false
116
113
  version_requirements: !ruby/object:Gem::Requirement
117
114
  requirements:
118
- - - "~>"
119
- - !ruby/object:Gem::Version
120
- version: '2.0'
121
115
  - - ">="
122
116
  - !ruby/object:Gem::Version
123
- version: 2.0.5
117
+ version: '2.0'
124
118
  description:
125
119
  email:
126
120
  - igor.malinovskiy@netfix.xyz
@@ -144,6 +138,9 @@ files:
144
138
  - lib/api_signature/builder.rb
145
139
  - lib/api_signature/generator.rb
146
140
  - lib/api_signature/request.rb
141
+ - lib/api_signature/spec_support/headers_builder.rb
142
+ - lib/api_signature/spec_support/helper.rb
143
+ - lib/api_signature/spec_support/path_builder.rb
147
144
  - lib/api_signature/validator.rb
148
145
  - lib/api_signature/version.rb
149
146
  homepage: https://github.com/psyipm/api_signature
@@ -166,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
163
  version: '0'
167
164
  requirements: []
168
165
  rubyforge_project:
169
- rubygems_version: 2.5.2
166
+ rubygems_version: 2.6.14.1
170
167
  signing_key:
171
168
  specification_version: 4
172
169
  summary: Sign API requests with HMAC signature