easy_meli 0.3.0 → 0.6.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 +4 -4
- data/.github/workflows/ci.yml +32 -0
- data/CHANGELOG.md +12 -0
- data/README.md +10 -14
- data/lib/easy_meli.rb +19 -0
- data/lib/easy_meli/api_client.rb +26 -12
- data/lib/easy_meli/authorization_client.rb +25 -5
- data/lib/easy_meli/constants.rb +8 -0
- data/lib/easy_meli/errors.rb +59 -3
- data/lib/easy_meli/version.rb +1 -1
- metadata +10 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c8dc1140d9368b076baf0a49a9742aea8de95565a90512152c9c58ec2b98723
|
4
|
+
data.tar.gz: 543cbed2c4789b0259b62f11d332a02c3b5b281feb2c5b60c5f87fd8640c0754
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c2a7ecfa32beed3a9329b01312b1cfd4ed70fceb26469dc90e8d0d2c3b42186a9c1ec06f115f1dc5fa15236aa48d99b7e074a089fad7f710bddaf2bcb324680a
|
7
|
+
data.tar.gz: dfc01a8544c0f2d23711888fdfa3fb6a6f6f68196782d41cb501c1f50d53900882fb5c1b8d7a9f88e610eb1fafc8112447943ff87b8793af7fccd29e800a6d17
|
@@ -0,0 +1,32 @@
|
|
1
|
+
name: CI
|
2
|
+
on:
|
3
|
+
pull_request:
|
4
|
+
branches: [ master ]
|
5
|
+
push:
|
6
|
+
branches: [ master ]
|
7
|
+
jobs:
|
8
|
+
test:
|
9
|
+
runs-on: ubuntu-latest
|
10
|
+
strategy:
|
11
|
+
matrix:
|
12
|
+
ruby_version: [ '2.6' ]
|
13
|
+
steps:
|
14
|
+
- name: Checkout
|
15
|
+
uses: actions/checkout@v2
|
16
|
+
- name: Setup ruby ${{ matrix.ruby_version }}
|
17
|
+
uses: actions/setup-ruby@v1
|
18
|
+
with:
|
19
|
+
ruby-version: ${{ matrix.ruby_version }}
|
20
|
+
- name: Setup cache key and directory for gems cache
|
21
|
+
uses: actions/cache@v1
|
22
|
+
with:
|
23
|
+
path: vendor/bundle
|
24
|
+
key: ${{ runner.os }}-gem-use-ruby-${{ matrix.ruby_version }}-${{ hashFiles('**/Gemfile.lock') }}
|
25
|
+
- name: Bundle install
|
26
|
+
run: |
|
27
|
+
gem install bundler:1.17.0
|
28
|
+
bundle config path vendor/bundle
|
29
|
+
bundle install --jobs 4 --retry 3
|
30
|
+
- name: Run tests
|
31
|
+
run: |
|
32
|
+
bundle exec rake test
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## V 0.6.1
|
4
|
+
- Fix a bug in the error raising in the authorization client introduced in V 0.6.0
|
5
|
+
|
6
|
+
## V 0.6.0
|
7
|
+
- Classify an `invalid_token` response as an `InvalidTokenError`.
|
8
|
+
- `Malformed access_token` error changed from `AuthenticationError` to `InvalidTokenError`.
|
9
|
+
|
10
|
+
## V 0.5.0
|
11
|
+
- `self.api_client` Prevent access_token override when initialize together with a refresh_token.
|
12
|
+
- Raises a EasyMeli::TooManyRequestsError if a 429 response status is returned.
|
data/README.md
CHANGED
@@ -32,26 +32,26 @@ end
|
|
32
32
|
To get the authorization url that the end-user uses to give your app authorization to access MercadoLibre on your part call the `authorization_url` with the desired country and the url to redirect to in order to complete the authorization.
|
33
33
|
|
34
34
|
```ruby
|
35
|
-
EasyMeli
|
35
|
+
EasyMeli.authorization_url('MX', 'your_redirect_url')
|
36
36
|
```
|
37
37
|
|
38
38
|
Once MercadoLibre calls your redirect url you can get a refresh token by calling
|
39
39
|
|
40
40
|
```ruby
|
41
|
-
response = EasyMeli
|
41
|
+
response = EasyMeli.create_token('the_code_in_the_redirect', 'the_same_redirect_url_as_above')
|
42
42
|
```
|
43
43
|
This will return a response object with a json body that you can easily access via `response.to_h`.
|
44
44
|
|
45
|
-
If you want to refresh the token call
|
45
|
+
If you want to refresh the token call
|
46
46
|
|
47
47
|
```ruby
|
48
|
-
|
48
|
+
access_token = EasyMeli.access_token('a_refresh_token')
|
49
49
|
```
|
50
50
|
|
51
51
|
Once you can have an access token you can create a client and call the supported http verb methods.
|
52
52
|
|
53
53
|
```ruby
|
54
|
-
client = EasyMeli
|
54
|
+
client = EasyMeli.api_client(access_token: access_token)
|
55
55
|
|
56
56
|
client.get(path, query: { a: 1 })
|
57
57
|
client.post(path, query: { a: 1 }, body: { b: 1 })
|
@@ -59,25 +59,21 @@ client.put(path, query: { a: 1 }, body: { b: 1 })
|
|
59
59
|
client.delete(path, query: { a: 1 })
|
60
60
|
```
|
61
61
|
|
62
|
-
You can also pass a logger
|
62
|
+
You can also pass a logger to any methods that make remote calls. The logger class must implement a `log` method which will be called with the [HTTParty response](https://www.rubydoc.info/github/jnunemaker/httparty/HTTParty/Response) for every remote request sent.
|
63
63
|
|
64
64
|
```ruby
|
65
|
-
EasyMeli
|
66
|
-
EasyMeli
|
65
|
+
EasyMeli.create_token('the_code_in_the_redirect', 'the_same_redirect_url_as_above', logger: my_logger)
|
66
|
+
EasyMeli.api_client(refresh_token: refresh_token, logger: my_logger)
|
67
67
|
```
|
68
68
|
|
69
|
-
###
|
69
|
+
### Example of how to retrieve a user profile
|
70
70
|
```ruby
|
71
71
|
EasyMeli.configure do |config|
|
72
72
|
config.application_id = "your_app_id"
|
73
73
|
config.secret_key = "your_secret_key"
|
74
74
|
end
|
75
75
|
|
76
|
-
|
77
|
-
token = authorization_client.refresh_token(previously_stored_refresh_token).to_h['access_token']
|
78
|
-
|
79
|
-
api_client = EasyMeli::ApiClient.new(token)
|
80
|
-
|
76
|
+
api_client = EasyMeli.api_client(refresh_token: refresh_token)
|
81
77
|
response = api_client.get('/users/me')
|
82
78
|
|
83
79
|
```
|
data/lib/easy_meli.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
require 'httparty'
|
2
2
|
|
3
3
|
require 'easy_meli/version'
|
4
|
+
require 'easy_meli/constants'
|
4
5
|
require 'easy_meli/errors'
|
5
6
|
require 'easy_meli/configuration'
|
6
7
|
require 'easy_meli/authorization_client'
|
7
8
|
require 'easy_meli/api_client'
|
8
9
|
|
9
10
|
module EasyMeli
|
11
|
+
|
10
12
|
def self.configuration
|
11
13
|
@configuration ||= Configuration.new
|
12
14
|
end
|
@@ -14,4 +16,21 @@ module EasyMeli
|
|
14
16
|
def self.configure
|
15
17
|
yield(configuration)
|
16
18
|
end
|
19
|
+
|
20
|
+
def self.authorization_url(country_code, redirect_uri)
|
21
|
+
EasyMeli::AuthorizationClient.authorization_url(country_code, redirect_uri)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.create_token(code, redirect_uri, logger: nil)
|
25
|
+
EasyMeli::AuthorizationClient.create_token(code, redirect_uri, logger: logger)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.access_token(refresh_token, logger: nil)
|
29
|
+
EasyMeli::AuthorizationClient.access_token(refresh_token, logger: logger)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.api_client(access_token: nil, refresh_token: nil, logger: nil)
|
33
|
+
access_token ||= self.access_token(refresh_token, logger: logger) if refresh_token
|
34
|
+
EasyMeli::ApiClient.new(access_token, logger: logger)
|
35
|
+
end
|
17
36
|
end
|
data/lib/easy_meli/api_client.rb
CHANGED
@@ -5,18 +5,24 @@ class EasyMeli::ApiClient
|
|
5
5
|
|
6
6
|
API_ROOT_URL = 'https://api.mercadolibre.com'
|
7
7
|
|
8
|
-
|
9
|
-
'invalid_grant' =>
|
10
|
-
'forbidden' =>
|
11
|
-
'
|
8
|
+
ERROR_LIST = {
|
9
|
+
'invalid_grant' => EasyMeli::InvalidGrantError,
|
10
|
+
'forbidden' => EasyMeli::ForbiddenError,
|
11
|
+
'invalid_token' => EasyMeli::InvalidTokenError,
|
12
|
+
'Malformed access_token' => EasyMeli::MalformedTokenError
|
12
13
|
}
|
13
14
|
|
14
|
-
|
15
|
+
STATUS_ERRORS = {
|
16
|
+
429 => EasyMeli::TooManyRequestsError
|
17
|
+
}
|
18
|
+
|
19
|
+
base_uri API_ROOT_URL
|
20
|
+
headers EasyMeli::DEFAULT_HEADERS
|
15
21
|
format :json
|
16
22
|
|
17
23
|
attr_reader :logger, :access_token
|
18
24
|
|
19
|
-
def initialize(access_token, logger: nil)
|
25
|
+
def initialize(access_token = nil, logger: nil)
|
20
26
|
@logger = logger
|
21
27
|
@access_token = access_token
|
22
28
|
end
|
@@ -41,20 +47,23 @@ class EasyMeli::ApiClient
|
|
41
47
|
|
42
48
|
def send_request(verb, path = '', params = {})
|
43
49
|
query = params[:query] || params['query'] || {}
|
44
|
-
query[:access_token] = access_token
|
50
|
+
query[:access_token] = access_token if access_token
|
51
|
+
|
45
52
|
self.class.send(verb, path, params.merge(query)).tap do |response|
|
46
53
|
logger&.log response
|
47
54
|
check_authentication(response)
|
55
|
+
check_status(response)
|
48
56
|
end
|
49
57
|
end
|
50
58
|
|
51
59
|
def check_authentication(response)
|
52
|
-
response_message = error_message_from_body(response.to_h)
|
60
|
+
response_message = error_message_from_body(response.to_h) if response.parsed_response.is_a? Hash
|
53
61
|
return if response_message.to_s.empty?
|
54
|
-
|
55
|
-
|
62
|
+
|
63
|
+
ERROR_LIST.keys.each do |key|
|
56
64
|
if response_message.include?(key)
|
57
|
-
|
65
|
+
exception = ERROR_LIST[key]
|
66
|
+
raise exception.new(response)
|
58
67
|
end
|
59
68
|
end
|
60
69
|
end
|
@@ -63,4 +72,9 @@ class EasyMeli::ApiClient
|
|
63
72
|
return if body.nil?
|
64
73
|
body['error'].to_s.empty? ? body['message'] : body['error']
|
65
74
|
end
|
66
|
-
|
75
|
+
|
76
|
+
def check_status(response)
|
77
|
+
status_error = STATUS_ERRORS[response.code]
|
78
|
+
raise status_error.new(response) if status_error
|
79
|
+
end
|
80
|
+
end
|
@@ -20,7 +20,9 @@ class EasyMeli::AuthorizationClient
|
|
20
20
|
PT: 'https://auth.mercadolibre.com.pt',
|
21
21
|
DO: 'https://auth.mercadolibre.com.do'
|
22
22
|
}
|
23
|
+
ACCESS_TOKEN_KEY = 'access_token'
|
23
24
|
|
25
|
+
headers EasyMeli::DEFAULT_HEADERS
|
24
26
|
format :json
|
25
27
|
|
26
28
|
attr_reader :logger
|
@@ -33,12 +35,30 @@ class EasyMeli::AuthorizationClient
|
|
33
35
|
params = {
|
34
36
|
client_id: EasyMeli.configuration.application_id,
|
35
37
|
response_type: 'code',
|
36
|
-
redirect_uri: redirect_uri
|
38
|
+
redirect_uri: redirect_uri
|
37
39
|
}
|
38
40
|
HTTParty::Request.new(:get, country_auth_url(country_code), query: params).uri.to_s
|
39
41
|
end
|
40
42
|
|
41
|
-
def create_token(code, redirect_uri)
|
43
|
+
def self.create_token(code, redirect_uri, logger: nil)
|
44
|
+
response = self.new(logger: logger).create_token_with_response(code, redirect_uri)
|
45
|
+
if response.success?
|
46
|
+
response.to_h
|
47
|
+
else
|
48
|
+
raise EasyMeli::CreateTokenError.new(response)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.access_token(refresh_token, logger: nil)
|
53
|
+
response = self.new(logger: logger).access_token_with_response(refresh_token)
|
54
|
+
if response.success?
|
55
|
+
response.to_h[EasyMeli::AuthorizationClient::ACCESS_TOKEN_KEY]
|
56
|
+
else
|
57
|
+
raise EasyMeli::InvalidTokenError.new(response)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def create_token_with_response(code, redirect_uri)
|
42
62
|
query_params = merge_auth_params(
|
43
63
|
grant_type: 'authorization_code',
|
44
64
|
code: code,
|
@@ -47,7 +67,7 @@ class EasyMeli::AuthorizationClient
|
|
47
67
|
post_auth(query_params)
|
48
68
|
end
|
49
69
|
|
50
|
-
def
|
70
|
+
def access_token_with_response(refresh_token)
|
51
71
|
query_params = merge_auth_params(
|
52
72
|
grant_type: 'refresh_token',
|
53
73
|
refresh_token: refresh_token
|
@@ -64,7 +84,7 @@ class EasyMeli::AuthorizationClient
|
|
64
84
|
end
|
65
85
|
|
66
86
|
def self.country_auth_url(country_code)
|
67
|
-
url = BASE_AUTH_URLS[country_code.to_s.upcase.to_sym] ||
|
87
|
+
url = BASE_AUTH_URLS[country_code.to_s.upcase.to_sym] ||
|
68
88
|
(raise ArgumentError.new('%s is an invalid country code' % country_code))
|
69
89
|
[url, AUTH_PATH].join
|
70
90
|
end
|
@@ -75,4 +95,4 @@ class EasyMeli::AuthorizationClient
|
|
75
95
|
client_secret: EasyMeli.configuration.secret_key
|
76
96
|
)
|
77
97
|
end
|
78
|
-
end
|
98
|
+
end
|
data/lib/easy_meli/errors.rb
CHANGED
@@ -2,11 +2,67 @@ module EasyMeli
|
|
2
2
|
class Error < StandardError
|
3
3
|
attr_reader :response
|
4
4
|
|
5
|
-
def initialize(
|
5
|
+
def initialize(response)
|
6
6
|
@response = response
|
7
|
-
super(
|
7
|
+
super(local_message)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def local_message
|
13
|
+
raise NotImplementedError
|
8
14
|
end
|
9
15
|
end
|
10
16
|
|
11
17
|
class AuthenticationError < Error; end
|
12
|
-
|
18
|
+
|
19
|
+
class CreateTokenError < AuthenticationError
|
20
|
+
private
|
21
|
+
|
22
|
+
def local_message
|
23
|
+
'Error Creating Token'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class InvalidGrantError < AuthenticationError
|
28
|
+
private
|
29
|
+
|
30
|
+
def local_message
|
31
|
+
'Invalid Grant'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class ForbiddenError < AuthenticationError
|
36
|
+
private
|
37
|
+
|
38
|
+
def local_message
|
39
|
+
'Forbidden'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class AccessTokenError < Error; end
|
44
|
+
|
45
|
+
class InvalidTokenError < AccessTokenError
|
46
|
+
private
|
47
|
+
|
48
|
+
def local_message
|
49
|
+
'Invalid Token'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class MalformedTokenError < AccessTokenError
|
54
|
+
private
|
55
|
+
|
56
|
+
def local_message
|
57
|
+
'Malformed access token'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class TooManyRequestsError < Error
|
62
|
+
private
|
63
|
+
|
64
|
+
def local_message
|
65
|
+
'Too many requests'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/easy_meli/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: easy_meli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Northam
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -108,14 +108,16 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
-
description:
|
111
|
+
description:
|
112
112
|
email:
|
113
113
|
- eric@northam.us
|
114
114
|
executables: []
|
115
115
|
extensions: []
|
116
116
|
extra_rdoc_files: []
|
117
117
|
files:
|
118
|
+
- ".github/workflows/ci.yml"
|
118
119
|
- ".gitignore"
|
120
|
+
- CHANGELOG.md
|
119
121
|
- Gemfile
|
120
122
|
- LICENSE.txt
|
121
123
|
- README.md
|
@@ -127,6 +129,7 @@ files:
|
|
127
129
|
- lib/easy_meli/api_client.rb
|
128
130
|
- lib/easy_meli/authorization_client.rb
|
129
131
|
- lib/easy_meli/configuration.rb
|
132
|
+
- lib/easy_meli/constants.rb
|
130
133
|
- lib/easy_meli/errors.rb
|
131
134
|
- lib/easy_meli/version.rb
|
132
135
|
homepage: https://github.com/easybroker/easy_meli
|
@@ -134,7 +137,7 @@ licenses:
|
|
134
137
|
- MIT
|
135
138
|
metadata:
|
136
139
|
homepage_uri: https://github.com/easybroker/easy_meli
|
137
|
-
post_install_message:
|
140
|
+
post_install_message:
|
138
141
|
rdoc_options: []
|
139
142
|
require_paths:
|
140
143
|
- lib
|
@@ -149,8 +152,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
149
152
|
- !ruby/object:Gem::Version
|
150
153
|
version: '0'
|
151
154
|
requirements: []
|
152
|
-
rubygems_version: 3.
|
153
|
-
signing_key:
|
155
|
+
rubygems_version: 3.1.4
|
156
|
+
signing_key:
|
154
157
|
specification_version: 4
|
155
158
|
summary: A simple gem to work with MercadoLibre's API
|
156
159
|
test_files: []
|