whiplash-app 0.9.5 → 0.10.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e0e2ae334bdd40de1ae96543cd86eb7506e3de9a7d65d04b003fa67d2eb83da1
4
- data.tar.gz: a2ae0fe3f75c4ed25e7703c85f71495609f10434c9bf3d687483d1ad440a5513
3
+ metadata.gz: c1bf73813a5c4e7bdc0417901e1734afb3dade5b3fbd9e1dc3c8b31b0b0bdcc3
4
+ data.tar.gz: 7ec1abc0b3adaf3f68d1f43f2c19f42bf700277b0c368e383c42cddedc80e1a1
5
5
  SHA512:
6
- metadata.gz: 1fd9e63cc8d1359a38adc462eb4818928d4ea84bc1e57db46e1fa9725ef547c59172763727f8fc7957c8de22d0a3720a437040789966116ce5a1c0a833ad210f
7
- data.tar.gz: 0f35b12647a50d4a4c8fbb1a0f24fb6d40946c19dbbeb4d0238eb19d5c075fd3958e2cea68a72072d8db5770c83d18a5c1bc831a3bee2497e9cc7a4bfde52913
6
+ metadata.gz: f7b75b10c21856dd22bf2c1d2652ac875f5283d483f56d5123f9b86f93d71bfe76081b3a96cfb4bd5108fddad6f35ce89585128295fafc671ed62913060790c5
7
+ data.tar.gz: 7950a5979e5e3fbee7f91785507a22dbc5d506c83bcea2acb10ac22708abe13ba55b2fee353c298187df66457fb020bcab812896b81529006f61f8fda24e720a
data/README.md CHANGED
@@ -59,18 +59,26 @@ As long as all of your apps are on the same subdomain, they will share auth cook
59
59
 
60
60
  ```json
61
61
  {
62
- "oauth_token": XXXXXXX,
63
- "user": {"id":151,"email":"mark@getwhiplash.com","role":"admin","locale":"en","first_name":"Mark","last_name":"Dickson","partner_id":null,"warehouse_id": 1,"customer_ids":[1, 2, 3]}
62
+ "oauth_token": "XXXXXXX",
63
+ "user": {"id":151,"email":"mark@getwhiplash.com","role":"admin","locale":"en","first_name":"Mark","last_name":"Dickson","partner_id":null, "customer_ids":[1, 2, 3]},
64
+ "customer": {"id": 123, "name": "BooYaa"},
65
+ "warehouse": {"id": 1, "name": "Ann Arbor"}
64
66
  }
65
67
  ```
66
68
 
67
69
  You get a variety of helper methods for free:
68
70
 
69
71
  `init_whiplash_api` - This instantiates `@whiplash_api` which can be used to make requests, out of the box
70
- `current_user` - This is a **hash** with the above fields; you typically shouldn't need much more user info than this
72
+ `current_user` - This is a **hash** with the above fields; you typically shouldn't need much more user info than this'
73
+ `current_customer` - This is a **hash** with the above fields; you typically shouldn't need much more user info than this
74
+ `current_warehouse` - This is a **hash** with the above fields; you typically shouldn't need much more user info than this
71
75
  `require_user` - Typically you'd use this in a `before_action`. You almost always want this in `ApplicationController`.
72
76
  `set_locale!` - Sets the locale based on the value in the user hash
73
- `set_current_user_cookie!` - Updates the current user cookie with fresh data from the api. You typically won't need this, unless your app updates fields like `warehouse_id` or `locale`.
77
+ `set_current_user_cookie!` - Updates the current user cookie with fresh data from the api. You typically won't need this, unless your app updates fields like `locale`.
78
+ `set_current_customer_cookie!` - Updates the current customer cookie with fresh data from the api; typically used after you've changed customer
79
+ `set_current_warehouse_cookie!` - Updates the current customer cookie with fresh data from the api; typically used after you've changed warehouse
80
+ `unset_current_customer_cookie!` - Deletes the current customer cookie, with appropriate domain settings
81
+ `unset_current_warehouse_cookie!` - Deletes the current warehouse cookie, with appropriate domain settings
74
82
  `core_url` - Shorthand for `ENV['WHIPLASH_API_URL']`
75
83
  `core_url_for` - Link back to Core like `core_url_for('login')`
76
84
 
@@ -9,7 +9,8 @@ module Whiplash
9
9
  def require_canonical_host!
10
10
  canonical_host = ENV.fetch('CANONICAL_HOST', false).in?([true, 'true', 1, '1'])
11
11
  return unless canonical_host
12
- application_host = URI.parse(Rails.configuration.app_url).host
12
+ return unless Rails.configuration.respond_to?(:application_url)
13
+ application_host = URI.parse(Rails.configuration.application_url).host
13
14
  return if application_host == request.host
14
15
  return unless request.method_symbol == :get # can't redirect PUT, POST, DELETE
15
16
 
@@ -17,7 +18,7 @@ module Whiplash
17
18
  end
18
19
 
19
20
  def redirect_to_canonical_host(query_params, status=301)
20
- redirect_to "#{Rails.configuration.app_url}#{request.path}#{'?' if query_params.to_query.present?}#{query_params.to_query}", status: status
21
+ redirect_to "#{Rails.configuration.application_url}#{request.path}#{'?' if query_params.to_query.present?}#{query_params.to_query}", status: status
21
22
  end
22
23
 
23
24
  end
@@ -8,21 +8,78 @@ module Whiplash
8
8
  helper_method :cookie_domain,
9
9
  :core_url,
10
10
  :core_url_for,
11
- :current_user
11
+ :current_customer,
12
+ :current_user,
13
+ :current_warehouse
12
14
  end
13
15
 
14
16
  private
15
17
 
18
+ def application_domain
19
+ return nil if Rails.configuration.application_url.blank?
20
+ host = URI.parse(Rails.configuration.application_url).host
21
+ '.' + host
22
+ end
23
+
24
+ def clear_application_cookies!
25
+ return if application_domain.blank?
26
+ cookie_keys_we_care_about.each { |k| cookies.delete(k, domain: application_domain) }
27
+ end
28
+
29
+ def clear_domain_cookies!
30
+ cookie_keys_we_care_about.each { |k| cookies.delete(k, domain: cookie_domain) }
31
+ end
32
+
16
33
  def cookie_domain
17
- '.' + URI.parse(core_url).host
34
+ host = URI.parse(core_url).host
35
+ host.gsub!('www.', '')
36
+ '.' + host
37
+ end
38
+
39
+ def cookie_keys_we_care_about
40
+ %i(
41
+ _session
42
+ customer
43
+ customer_id
44
+ oauth_token
45
+ partner_id
46
+ user
47
+ user_id
48
+ warehouse
49
+ warehouse_id
50
+ )
18
51
  end
19
52
 
20
53
  def core_url
21
- ENV['WHIPLASH_API_URL']
54
+ ENV['WHIPLASH_CORE_URL'] || ENV['WHIPLASH_API_URL']
22
55
  end
23
56
 
24
- def core_url_for(path)
25
- [core_url, path].join('/')
57
+ def core_url_for(path, query_params = {})
58
+ out = [core_url, path].join('/')
59
+ out = [out, query_params.to_query].join('?') if query_params.present?
60
+ return out
61
+ end
62
+
63
+ def current_customer
64
+ return if cookies[:customer].blank?
65
+ begin
66
+ customer_hash = JSON.parse(cookies[:customer])
67
+ @current_customer ||= customer_hash
68
+ rescue StandardError => e
69
+ Rails.logger.warn "Customer could not be initialized: #{e.message}"
70
+ nil
71
+ end
72
+ end
73
+
74
+ def current_customer_full
75
+ return if cookies[:customer].blank?
76
+ begin
77
+ customer_hash = JSON.parse(cookies[:customer])
78
+ @current_customer ||= @whiplash_api.get!("customers/#{customer_hash['id']}").body
79
+ rescue StandardError => e
80
+ Rails.logger.warn "Customer could not be initialized: #{e.message}"
81
+ nil
82
+ end
26
83
  end
27
84
 
28
85
  def current_user
@@ -35,12 +92,37 @@ module Whiplash
35
92
  end
36
93
  end
37
94
 
95
+ def current_warehouse
96
+ return if cookies[:warehouse].blank?
97
+ begin
98
+ warehouse_hash = JSON.parse(cookies[:warehouse])
99
+ @current_warehouse ||= warehouse_hash
100
+ rescue StandardError => e
101
+ Rails.logger.warn "Warehouse could not be initialized: #{e.message}"
102
+ @current_warehouse = nil
103
+ end
104
+ end
105
+
106
+ def current_warehouse_full
107
+ return if cookies[:warehouse].blank?
108
+ begin
109
+ warehouse_hash = JSON.parse(cookies[:warehouse])
110
+ @whiplash_api.get!("warehouses/#{warehouse_hash['id']}").body
111
+ rescue StandardError => e
112
+ Rails.logger.warn "Warehouse could not be initialized: #{e.message}"
113
+ nil
114
+ end
115
+ end
116
+
38
117
  def http_scheme
39
118
  URI(core_url).scheme
40
119
  end
41
120
 
42
121
  def init_whiplash_api(options = {})
43
- return redirect_to core_url_for('login') if cookies[:oauth_token].blank?
122
+ if cookies[:oauth_token].blank?
123
+ clear_application_cookies!
124
+ return redirect_to core_url_for('login', redirect_url: request.original_url)
125
+ end
44
126
  token = {access_token: cookies[:oauth_token]}
45
127
  begin
46
128
  @whiplash_api = Whiplash::App.new(token, options)
@@ -51,7 +133,9 @@ module Whiplash
51
133
  end
52
134
 
53
135
  def require_user
54
- redirect_to core_url_for('login') if current_user.blank?
136
+ return if current_user.present?
137
+ clear_application_cookies!
138
+ redirect_to core_url_for('login', redirect_url: request.original_url)
55
139
  end
56
140
 
57
141
  def set_locale!
@@ -59,10 +143,25 @@ module Whiplash
59
143
  I18n.locale = current_user.try('locale') || I18n.default_locale
60
144
  end
61
145
 
146
+ def set_current_customer_cookie!(customer_id, expires_at = nil)
147
+ customer = @whiplash_api.get!("customers/#{customer_id}").body
148
+ user = @whiplash_api.get!("me").body
149
+ fields_we_care_about = %w(id name)
150
+ customer_hash = customer.slice(*fields_we_care_about)
151
+ expires_at ||= user['current_sign_in_expires_at']
152
+
153
+ shared_values = {
154
+ expires: DateTime.parse(expires_at),
155
+ secure: http_scheme == 'https',
156
+ samesite: :strict,
157
+ domain: cookie_domain
158
+ }
159
+ cookies[:customer] = shared_values.merge(value: customer_hash.to_json)
160
+ end
62
161
 
63
162
  def set_current_user_cookie!(expires_at = nil)
64
163
  user = @whiplash_api.get!("me").body
65
- fields_we_care_about = %w(id email role locale first_name last_name partner_id warehouse_id customer_ids)
164
+ fields_we_care_about = %w(id email role locale first_name last_name partner_id customer_ids)
66
165
  user_hash = user.slice(*fields_we_care_about)
67
166
  expires_at ||= user['current_sign_in_expires_at']
68
167
 
@@ -75,6 +174,30 @@ module Whiplash
75
174
  cookies[:user] = shared_values.merge(value: user_hash.to_json)
76
175
  end
77
176
 
177
+ def set_current_warehouse_cookie!(warehouse_id, expires_at = nil)
178
+ warehouse = @whiplash_api.get!("warehouses/#{warehouse_id}").body
179
+ user = @whiplash_api.get!("me").body
180
+ fields_we_care_about = %w(id name slug)
181
+ warehouse_hash = warehouse.slice(*fields_we_care_about)
182
+ expires_at ||= user['current_sign_in_expires_at']
183
+
184
+ shared_values = {
185
+ expires: DateTime.parse(expires_at),
186
+ secure: http_scheme == 'https',
187
+ samesite: :strict,
188
+ domain: cookie_domain
189
+ }
190
+ cookies[:warehouse] = shared_values.merge(value: warehouse_hash.to_json)
191
+ end
192
+
193
+ def unset_current_customer_cookie!
194
+ cookies.delete(:customer, domain: cookie_domain)
195
+ end
196
+
197
+ def unset_current_warehouse_cookie!
198
+ cookies.delete(:warehouse, domain: cookie_domain)
199
+ end
200
+
78
201
  end
79
202
  end
80
203
  end
@@ -20,7 +20,7 @@ module Whiplash
20
20
  end
21
21
 
22
22
  initializer "whiplash_app.action_controller" do
23
- ActiveSupport.on_load(:action_controller) do
23
+ ActiveSupport.on_load(:action_controller_base) do
24
24
  include Whiplash::App::CanonicalHost
25
25
  include Whiplash::App::ControllerHelpers
26
26
  end
@@ -1,5 +1,5 @@
1
1
  module Whiplash
2
2
  class App
3
- VERSION = "0.9.5"
3
+ VERSION = "0.10.0"
4
4
  end
5
5
  end
data/lib/whiplash/app.rb CHANGED
@@ -6,6 +6,7 @@ require "whiplash/app/version"
6
6
  require "errors/whiplash_api_error"
7
7
  require "oauth2"
8
8
  require "faraday"
9
+ require 'faraday/net_http_persistent'
9
10
 
10
11
  # Rails app stuff
11
12
  if defined?(Rails::Railtie)
@@ -40,9 +41,21 @@ module Whiplash
40
41
 
41
42
  def connection
42
43
  Faraday.new [self.class.api_url, versioned_api_url].join("/") do |conn|
44
+ # Authentication
43
45
  conn.request :authorization, 'Bearer', token.token
44
46
  conn.request :json
45
47
  conn.response :json, :content_type => /\bjson$/
48
+ conn.options.timeout = 30 # Total request timeout
49
+ conn.options.open_timeout = 5 # Connection establishment timeout
50
+
51
+ # Use persistent HTTP connections (requires net-http-persistent gem)
52
+ begin
53
+ conn.adapter :net_http_persistent
54
+ rescue LoadError
55
+ # Fallback to default adapter if net-http-persistent isn't available
56
+ Rails.logger.warn "[WhiplashApp] net-http-persistent gem not found, using default adapter" if defined?(Rails)
57
+ conn.adapter Faraday.default_adapter
58
+ end
46
59
  end
47
60
  end
48
61
 
@@ -112,4 +125,4 @@ module Net
112
125
 
113
126
  end
114
127
  end
115
- end
128
+ end
data/whiplash-app.gemspec CHANGED
@@ -20,9 +20,10 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_dependency "oauth2", "~> 2.0.4"
22
22
  spec.add_dependency "faraday", "~> 2.7"
23
+ spec.add_dependency 'faraday-net_http_persistent'
23
24
 
24
25
  spec.add_development_dependency "bundler", ">= 2.2"
25
26
  spec.add_development_dependency "rake", ">= 12.3.3"
26
27
  spec.add_development_dependency "rspec", "~> 3.0"
27
- spec.add_development_dependency "pry" , '~> 0.12.2'
28
+ spec.add_development_dependency "pry", "~> 0.14"
28
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: whiplash-app
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.5
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Don Sullivan, Mark Dickson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-01-10 00:00:00.000000000 Z
11
+ date: 2025-05-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oauth2
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: faraday-net_http_persistent
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +100,14 @@ dependencies:
86
100
  requirements:
87
101
  - - "~>"
88
102
  - !ruby/object:Gem::Version
89
- version: 0.12.2
103
+ version: '0.14'
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
108
  - - "~>"
95
109
  - !ruby/object:Gem::Version
96
- version: 0.12.2
110
+ version: '0.14'
97
111
  description: this gem provides connectivity to the Whiplash API for authentication
98
112
  and REST requests.
99
113
  email:
@@ -141,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
155
  - !ruby/object:Gem::Version
142
156
  version: '0'
143
157
  requirements: []
144
- rubygems_version: 3.4.10
158
+ rubygems_version: 3.1.6
145
159
  signing_key:
146
160
  specification_version: 4
147
161
  summary: this gem provides connectivity to the Whiplash API for authentication and