lucid_shopify 0.5.3 → 0.7.0

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.
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