lucid_shopify 0.5.3 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -9
  3. data/lib/lucid_shopify/activate_charge.rb +9 -9
  4. data/lib/lucid_shopify/assert_callback.rb +61 -0
  5. data/lib/lucid_shopify/assert_webhook.rb +28 -0
  6. data/lib/lucid_shopify/charge.rb +33 -28
  7. data/lib/lucid_shopify/client.rb +12 -17
  8. data/lib/lucid_shopify/config.rb +45 -0
  9. data/lib/lucid_shopify/container.rb +23 -0
  10. data/lib/lucid_shopify/create_all_webhooks.rb +40 -0
  11. data/lib/lucid_shopify/create_charge.rb +9 -9
  12. data/lib/lucid_shopify/create_webhook.rb +24 -0
  13. data/lib/lucid_shopify/delegate_webhooks.rb +1 -1
  14. data/lib/lucid_shopify/delete_all_webhooks.rb +30 -0
  15. data/lib/lucid_shopify/delete_request.rb +3 -1
  16. data/lib/lucid_shopify/delete_webhook.rb +22 -0
  17. data/lib/lucid_shopify/error.rb +11 -0
  18. data/lib/lucid_shopify/fetch_access_token.rb +12 -14
  19. data/lib/lucid_shopify/get_request.rb +3 -1
  20. data/lib/lucid_shopify/post_request.rb +3 -1
  21. data/lib/lucid_shopify/put_request.rb +3 -1
  22. data/lib/lucid_shopify/request.rb +5 -5
  23. data/lib/lucid_shopify/request_credentials.rb +1 -1
  24. data/lib/lucid_shopify/response.rb +4 -21
  25. data/lib/lucid_shopify/send_request.rb +16 -23
  26. data/lib/lucid_shopify/send_throttled_request.rb +2 -2
  27. data/lib/lucid_shopify/version.rb +1 -1
  28. data/lib/lucid_shopify/webhook.rb +2 -1
  29. data/lib/lucid_shopify.rb +31 -23
  30. metadata +53 -7
  31. data/lib/lucid_shopify/credentials.rb +0 -42
  32. data/lib/lucid_shopify/result.rb +0 -33
  33. data/lib/lucid_shopify/verify_callback.rb +0 -70
  34. data/lib/lucid_shopify/verify_webhook.rb +0 -40
  35. data/lib/lucid_shopify/webhooks.rb +0 -82
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'lucid_shopify/request'
3
+ require 'lucid_shopify'
4
4
 
5
5
  module LucidShopify
6
6
  class PutRequest < Request
7
+ #
8
+ # @private
7
9
  #
8
10
  # @param credentials [RequestCredentials]
9
11
  # @param path [String] the endpoint relative to the base URL
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry-initializer'
3
+ require 'lucid_shopify'
4
4
 
5
5
  module LucidShopify
6
6
  #
@@ -29,10 +29,10 @@ module LucidShopify
29
29
  private def build_url
30
30
  admin_url = "https://#{credentials.myshopify_domain}/admin"
31
31
 
32
- path = path.sub(/^\//, '')
33
- path = path.sub(/\.json$/, '')
32
+ normalized_path = path.sub(/^\//, '')
33
+ normalized_path = path.sub(/\.json$/, '')
34
34
 
35
- admin_url + '/' + path + '.json'
35
+ admin_url + '/' + normalized_path + '.json'
36
36
  end
37
37
 
38
38
  #
@@ -43,7 +43,7 @@ module LucidShopify
43
43
 
44
44
  {}.tap do |headers|
45
45
  headers['Accept'] = 'application/json'
46
- headers['X-Shopify-Access-token'] = access_token if access_token
46
+ headers['X-Shopify-Access-Token'] = access_token if access_token
47
47
  end
48
48
  end
49
49
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry-initializer'
3
+ require 'lucid_shopify'
4
4
 
5
5
  module LucidShopify
6
6
  class RequestCredentials
@@ -1,14 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry-initializer'
4
3
  require 'json'
5
4
 
5
+ require 'lucid_shopify'
6
+
6
7
  module LucidShopify
7
8
  class Response
8
9
  #
9
10
  # @abstract
10
11
  #
11
- class Error < StandardError
12
+ class Error < Error
12
13
  extend Dry::Initializer
13
14
 
14
15
  # @return [Request]
@@ -62,29 +63,11 @@ module LucidShopify
62
63
  end
63
64
 
64
65
  #
65
- # @return [String]
66
- #
67
- # @see {#assert!}
68
- #
69
- def data!
70
- assert!.data
71
- end
72
-
73
- #
74
- # @return [Hash] the parsed response body
75
- #
76
- # @see {#assert!}
77
- #
78
- def data_hash!
79
- assert!.data_hash
80
- end
81
-
66
+ # @return [self]
82
67
  #
83
68
  # @raise [ClientError] for status 4xx
84
69
  # @raise [ServerError] for status 5xx
85
70
  #
86
- # @return [self]
87
- #
88
71
  def assert!
89
72
  case status_code
90
73
  when 400..499
@@ -1,13 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry-initializer'
4
3
  require 'http'
5
4
 
6
- require 'lucid_shopify/response'
5
+ require 'lucid_shopify'
7
6
 
8
7
  module LucidShopify
9
8
  class SendRequest
10
- class NetworkError < StandardError
9
+ class NetworkError < Error
11
10
  extend Dry::Initializer
12
11
 
13
12
  # @return [HTTP::Error]
@@ -24,23 +23,28 @@ module LucidShopify
24
23
  # @raise [Response::ClientError] for status 4xx
25
24
  # @raise [Response::ServerError] for status 5xx
26
25
  #
27
- def call(request, attempts = default_attempts)
28
- req = request
29
- res = send(req.http_method, req.url, req.options)
30
- res = Response.new(req, res.code, res.headers.to_h, res.to_s)
26
+ def call(request, attempts: default_attempts)
27
+ res = send(request)
28
+ res = Response.new(request, res.code, res.headers.to_h, res.to_s)
31
29
 
32
- res.data_hash!
33
- rescue *http_network_errors => e
30
+ res.assert!.data_hash
31
+ rescue HTTP::ConnectionError,
32
+ HTTP::ResponseError,
33
+ HTTP::TimeoutError => e
34
34
  raise NetworkError.new(e), e.message if attempts.zero?
35
35
 
36
- call(request, attempts - 1)
36
+ call(request, attempts: attempts - 1)
37
37
  end
38
38
 
39
+ #
40
+ # @param request [Request]
39
41
  #
40
42
  # @return [HTTP::Response]
41
43
  #
42
- private def send(http_method, url, options)
43
- HTTP.headers(request.headers).__send__(http_method, url, options)
44
+ private def send(request)
45
+ req = request
46
+
47
+ HTTP.headers(req.http_headers).__send__(req.http_method, req.url, req.options)
44
48
  end
45
49
 
46
50
  #
@@ -49,16 +53,5 @@ module LucidShopify
49
53
  private def default_attempts
50
54
  3
51
55
  end
52
-
53
- #
54
- # @return [Array<Class>]
55
- #
56
- private def http_network_errors
57
- [
58
- HTTP::ConnectionError,
59
- HTTP::ResponseError,
60
- HTTP::TimeoutError,
61
- ]
62
- end
63
56
  end
64
57
  end
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'lucid_shopify/send_request'
3
+ require 'lucid_shopify'
4
4
 
5
5
  module LucidShopify
6
6
  class SendThrottledRequest < SendRequest
7
7
  MINIMUM_INTERVAL = 500 # ms
8
8
 
9
9
  #
10
- # @see {SendRequest#call}
10
+ # @see SendRequest#call
11
11
  #
12
12
  private def call(*)
13
13
  interval
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LucidShopify
4
- VERSION = '0.5.3'
4
+ VERSION = '0.7.0'
5
5
  end
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry-initializer'
4
3
  require 'json'
5
4
 
5
+ require 'lucid_shopify'
6
+
6
7
  module LucidShopify
7
8
  class Webhook
8
9
  extend Dry::Initializer
data/lib/lucid_shopify.rb CHANGED
@@ -1,26 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Primarily for Bundler.
3
+ require 'dry/initializer'
4
4
 
5
- require 'lucid_shopify/activate_charge'
6
- require 'lucid_shopify/charge'
7
- require 'lucid_shopify/client'
8
- require 'lucid_shopify/create_charge'
9
- require 'lucid_shopify/credentials'
10
- require 'lucid_shopify/delegate_webhooks'
11
- require 'lucid_shopify/delete_request'
12
- require 'lucid_shopify/fetch_access_token'
13
- require 'lucid_shopify/get_request'
14
- require 'lucid_shopify/post_request'
15
- require 'lucid_shopify/put_request'
16
- require 'lucid_shopify/request_credentials'
17
- require 'lucid_shopify/request'
18
- require 'lucid_shopify/response'
19
- require 'lucid_shopify/result'
20
- require 'lucid_shopify/send_request'
21
- require 'lucid_shopify/send_throttled_request'
22
- require 'lucid_shopify/verify_callback'
23
- require 'lucid_shopify/verify_webhook'
24
- require 'lucid_shopify/version'
25
- require 'lucid_shopify/webhook'
26
- require 'lucid_shopify/webhooks'
5
+ module LucidShopify
6
+ autoload :ActivateCharge, 'lucid_shopify/activate_charge'
7
+ autoload :AssertCallback, 'lucid_shopify/assert_callback'
8
+ autoload :AssertWebhook, 'lucid_shopify/assert_webhook'
9
+ autoload :Charge, 'lucid_shopify/charge'
10
+ autoload :Client, 'lucid_shopify/client'
11
+ autoload :Config, 'lucid_shopify/config'
12
+ autoload :Container, 'lucid_shopify/container'
13
+ autoload :CreateAllWebhooks, 'lucid_shopify/create_all_webhooks'
14
+ autoload :CreateCharge, 'lucid_shopify/create_charge'
15
+ autoload :CreateWebhook, 'lucid_shopify/create_webhook'
16
+ autoload :DelegateWebhooks, 'lucid_shopify/delegate_webhooks'
17
+ autoload :DeleteAllWebhooks, 'lucid_shopify/delete_all_webhooks'
18
+ autoload :DeleteRequest, 'lucid_shopify/delete_request'
19
+ autoload :DeleteWebhook, 'lucid_shopify/delete_webhook'
20
+ autoload :Error, 'lucid_shopify/error'
21
+ autoload :FetchAccessToken, 'lucid_shopify/fetch_access_token'
22
+ autoload :GetRequest, 'lucid_shopify/get_request'
23
+ autoload :PostRequest, 'lucid_shopify/post_request'
24
+ autoload :PutRequest, 'lucid_shopify/put_request'
25
+ autoload :RequestCredentials, 'lucid_shopify/request_credentials'
26
+ autoload :Request, 'lucid_shopify/request'
27
+ autoload :Response, 'lucid_shopify/response'
28
+ autoload :Result, 'lucid_shopify/result'
29
+ autoload :SendRequest, 'lucid_shopify/send_request'
30
+ autoload :ThrottledRequest, 'lucid_shopify/send_throttled_request'
31
+ autoload :VERSION, 'lucid_shopify/version'
32
+ autoload :Webhook, 'lucid_shopify/webhook'
33
+ autoload :Webhooks, 'lucid_shopify/webhooks'
34
+ end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lucid_shopify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kelsey Judson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-02 00:00:00.000000000 Z
11
+ date: 2018-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dotenv
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.2'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '12.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '12.3'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: rspec
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +66,20 @@ dependencies:
38
66
  - - '='
39
67
  - !ruby/object:Gem::Version
40
68
  version: 0.52.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: dry-container
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.6'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.6'
41
83
  - !ruby/object:Gem::Dependency
42
84
  name: dry-initializer
43
85
  requirement: !ruby/object:Gem::Requirement
@@ -75,12 +117,20 @@ files:
75
117
  - README.md
76
118
  - lib/lucid_shopify.rb
77
119
  - lib/lucid_shopify/activate_charge.rb
120
+ - lib/lucid_shopify/assert_callback.rb
121
+ - lib/lucid_shopify/assert_webhook.rb
78
122
  - lib/lucid_shopify/charge.rb
79
123
  - lib/lucid_shopify/client.rb
124
+ - lib/lucid_shopify/config.rb
125
+ - lib/lucid_shopify/container.rb
126
+ - lib/lucid_shopify/create_all_webhooks.rb
80
127
  - lib/lucid_shopify/create_charge.rb
81
- - lib/lucid_shopify/credentials.rb
128
+ - lib/lucid_shopify/create_webhook.rb
82
129
  - lib/lucid_shopify/delegate_webhooks.rb
130
+ - lib/lucid_shopify/delete_all_webhooks.rb
83
131
  - lib/lucid_shopify/delete_request.rb
132
+ - lib/lucid_shopify/delete_webhook.rb
133
+ - lib/lucid_shopify/error.rb
84
134
  - lib/lucid_shopify/fetch_access_token.rb
85
135
  - lib/lucid_shopify/get_request.rb
86
136
  - lib/lucid_shopify/post_request.rb
@@ -88,14 +138,10 @@ files:
88
138
  - lib/lucid_shopify/request.rb
89
139
  - lib/lucid_shopify/request_credentials.rb
90
140
  - lib/lucid_shopify/response.rb
91
- - lib/lucid_shopify/result.rb
92
141
  - lib/lucid_shopify/send_request.rb
93
142
  - lib/lucid_shopify/send_throttled_request.rb
94
- - lib/lucid_shopify/verify_callback.rb
95
- - lib/lucid_shopify/verify_webhook.rb
96
143
  - lib/lucid_shopify/version.rb
97
144
  - lib/lucid_shopify/webhook.rb
98
- - lib/lucid_shopify/webhooks.rb
99
145
  homepage: https://github.com/lucidnz/gem-lucid_shopify
100
146
  licenses:
101
147
  - ISC
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dry-initializer'
4
-
5
- module LucidShopify
6
- MissingCredentialsError = Class.new(StandardError)
7
-
8
- class Credentials
9
- extend Dry::Initializer
10
-
11
- # @return [String]
12
- param :api_key
13
- # @return [String]
14
- param :shared_secret
15
- # @return [String]
16
- param :scope
17
- # @return [String]
18
- param :billing_callback_uri
19
- # @return [String]
20
- param :webhook_uri
21
- end
22
- end
23
-
24
- class << LucidShopify
25
- #
26
- # Assign default API credentials.
27
- #
28
- # @param credentials [LucidShopify::Credentials]
29
- #
30
- attr_writer :credentials
31
-
32
- #
33
- # @return [LucidShopify::Credentials]
34
- #
35
- # @raise [LucidShopify::MissingCredentialsError] if credentials are unset
36
- #
37
- def credentials
38
- raise MissingCredentialsError unless @credentials
39
-
40
- @credentials
41
- end
42
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module LucidShopify
4
- class Result
5
- #
6
- # @param value [Object]
7
- # @param error [Object]
8
- #
9
- def initialize(value, error = nil)
10
- @value = value
11
- @error = error
12
- end
13
-
14
- # @return [Object]
15
- attr_reader :value
16
- # @return [Object]
17
- attr_reader :error
18
-
19
- #
20
- # @return [Boolean]
21
- #
22
- def success?
23
- error.nil?
24
- end
25
-
26
- #
27
- # @return [Boolean]
28
- #
29
- def failure?
30
- !success?
31
- end
32
- end
33
- end
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'openssl'
4
-
5
- require 'lucid_shopify/credentials'
6
- require 'lucid_shopify/result'
7
-
8
- module LucidShopify
9
- class VerifyCallback
10
- #
11
- # @param credentials [LucidShopify::Credentials]
12
- #
13
- def initialize(credentials: LucidShopify.credentials)
14
- @credentials = credentials
15
- end
16
-
17
- # @return [LucidShopify::Credentials]
18
- attr_reader :credentials
19
-
20
- #
21
- # Verify that the callback request originated from Shopify.
22
- #
23
- # @param params_hash [Hash] the request params
24
- #
25
- # @return [Result]
26
- #
27
- def call(params_hash)
28
- digest = OpenSSL::Digest::SHA256.new
29
- digest = OpenSSL::HMAC.hexdigest(digest, credentials.shared_secret, encoded_params(params_hash))
30
- result = digest == params_hash[:hmac]
31
-
32
- Result.new(result, result ? nil : 'invalid request')
33
- end
34
-
35
- #
36
- # @param params_hash [Hash]
37
- #
38
- # @return [String]
39
- #
40
- private def encoded_params(params_hash)
41
- params_hash.reject do |k, _|
42
- k == :hmac
43
- end.map do |k, v|
44
- encode_key(k) + '=' + encode_value(v)
45
- end.join('&')
46
- end
47
-
48
- #
49
- # @param k [String, Symbol]
50
- #
51
- # @return [String]
52
- #
53
- private def encode_key(k)
54
- k.to_s.gsub(/./) do |chr|
55
- {'%' => '%25', '&' => '%26', '=' => '%3D'}[chr] || chr
56
- end
57
- end
58
-
59
- #
60
- # @param v [String]
61
- #
62
- # @return [String]
63
- #
64
- private def encode_value(v)
65
- v.gsub(/./) do |chr|
66
- {'%' => '%25', '&' => '%26'}[chr] || chr
67
- end
68
- end
69
- end
70
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'base64'
4
- require 'openssl'
5
-
6
- require 'lucid_shopify/credentials'
7
- require 'lucid_shopify/result'
8
-
9
- module LucidShopify
10
- class VerifyWebhook
11
- Error = Class.new(StandardError)
12
-
13
- #
14
- # @param credentials [LucidShopify::Credentials]
15
- #
16
- def initialize(credentials: LucidShopify.credentials)
17
- @credentials = credentials
18
- end
19
-
20
- # @return [LucidShopify::Credentials]
21
- attr_reader :credentials
22
-
23
- #
24
- # Verify that the webhook request originated from Shopify.
25
- #
26
- # @param data [String] the signed request data
27
- # @param hmac [String] the signature
28
- #
29
- # @return [Result]
30
- #
31
- def call(data, hmac)
32
- digest = OpenSSL::Digest::SHA256.new
33
- digest = OpenSSL::HMAC.digest(digest, credentials.shared_secret, data)
34
- digest = Base64.encode64(digest).strip
35
- result = digest == hmac
36
-
37
- Result.new(result, result ? nil : 'invalid request')
38
- end
39
- end
40
- end
@@ -1,82 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dry-initializer'
4
-
5
- require 'lucid_shopify/client'
6
- require 'lucid_shopify/credentials'
7
-
8
- module LucidShopify
9
- class Webhooks
10
- extend Dry::Initializer
11
-
12
- # @return [Client]
13
- option :client, default: proc { Client.new }
14
- # @return [Credentials]
15
- option :credentials, default: proc { LucidShopify.credentials }
16
-
17
- #
18
- # Delete any existing webhooks, then (re)create all webhooks for the shop.
19
- #
20
- # @param request_credentials [RequestCredentials]
21
- #
22
- def create_all(request_credentials)
23
- delete_all
24
-
25
- LucidShopify.webhooks.map do |webhook|
26
- Thread.new { create(request_credentials, webhook) }
27
- end.map(&:value)
28
- end
29
-
30
- #
31
- # Create a webhook.
32
- #
33
- # @param request_credentials [RequestCredentials]
34
- # @param webhook [Hash]
35
- #
36
- def create(request_credentials, webhook)
37
- data = {}
38
- data[:address] = credentials.webhook_uri
39
- data[:fields] = webhook[:fields] if webhook[:fields]
40
- data[:topic] = webhook[:topic]
41
-
42
- client.post_json(request_credentials, 'webhooks', webhook: data)
43
- end
44
-
45
- #
46
- # Delete any existing webhooks.
47
- #
48
- # @param request_credentials [RequestCredentials]
49
- #
50
- def delete_all(request_credentials)
51
- webhooks = client.get('webhooks')['webhooks']
52
-
53
- webhooks.map do |webhook|
54
- Thread.new { delete(request_credentials, webhook['id']) }
55
- end.map(&:value)
56
- end
57
-
58
- #
59
- # Delete a webhook.
60
- #
61
- # @param request_credentials [RequestCredentials]
62
- # @param id [Integer]
63
- #
64
- def delete(request_credentials, id)
65
- client.delete(request_credentials, "webhooks/#{id}")
66
- end
67
- end
68
- end
69
-
70
- class << LucidShopify
71
- #
72
- # Webhooks created for each shop.
73
- #
74
- # @return [Array<Hash>]
75
- #
76
- # @example
77
- # LucidShopify.webhooks << {topic: 'orders/create', fields: %w(id)}
78
- #
79
- def webhooks
80
- @webhooks ||= []
81
- end
82
- end