api_signature 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +61 -0
- data/api_signature.gemspec +1 -1
- data/lib/api_signature/spec_support/headers_builder.rb +39 -0
- data/lib/api_signature/spec_support/helper.rb +43 -0
- data/lib/api_signature/spec_support/path_builder.rb +42 -0
- data/lib/api_signature/version.rb +1 -1
- metadata +8 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6b3f7f58448cc08c412e475bd5967b8af6cfb972
|
4
|
+
data.tar.gz: 13783e19a83c42cdbc744036a44065f6deb7a56c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
data/api_signature.gemspec
CHANGED
@@ -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
|
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.
|
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-
|
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
|
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
|
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.
|
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
|