duodealer_app 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/app/controllers/duodealer_app/callback_controller.rb +10 -10
  4. data/app/controllers/duodealer_app/sessions_controller.rb +23 -23
  5. data/app/controllers/duodealer_app/webhooks_controller.rb +1 -1
  6. data/lib/duodealer_app/controller_concerns/login_protection.rb +29 -29
  7. data/lib/duodealer_app/controller_concerns/webhook_verification.rb +2 -2
  8. data/lib/duodealer_app/jobs/scripttags_manager_job.rb +3 -3
  9. data/lib/duodealer_app/jobs/webhooks_manager_job.rb +2 -2
  10. data/lib/duodealer_app/version.rb +1 -1
  11. data/lib/generators/duodealer_app/install/templates/duodealer_provider.rb +0 -2
  12. data/lib/generators/duodealer_app/rotate_duodealer_token_job/templates/rotate_duodealer_token_job.rb +7 -7
  13. metadata +2 -18
  14. data/app/controllers/concerns/duodealer_app/authenticated.rb-e +0 -15
  15. data/app/controllers/duodealer_app/authenticated_controller.rb-e +0 -9
  16. data/app/controllers/duodealer_app/callback_controller.rb-e +0 -104
  17. data/app/controllers/duodealer_app/extension_verification_controller.rb-e +0 -19
  18. data/app/controllers/duodealer_app/sessions_controller.rb-e +0 -159
  19. data/app/controllers/duodealer_app/webhooks_controller.rb-e +0 -37
  20. data/app/views/duodealer_app/partials/_button_styles.html.erb-e +0 -104
  21. data/app/views/duodealer_app/partials/_card_styles.html.erb-e +0 -33
  22. data/app/views/duodealer_app/partials/_empty_state_styles.html.erb-e +0 -129
  23. data/app/views/duodealer_app/partials/_layout_styles.html.erb-e +0 -167
  24. data/app/views/duodealer_app/partials/_typography_styles.html.erb-e +0 -35
  25. data/app/views/duodealer_app/sessions/enable_cookies.html.erb-e +0 -75
  26. data/app/views/duodealer_app/sessions/new.html.erb-e +0 -123
  27. data/app/views/duodealer_app/sessions/request_storage_access.html.erb-e +0 -68
  28. data/app/views/duodealer_app/sessions/top_level_interaction.html.erb-e +0 -64
  29. data/app/views/duodealer_app/shared/redirect.html.erb-e +0 -23
@@ -3,16 +3,16 @@
3
3
  module Duodealer
4
4
  class RotateDuodealerTokenJob < ActiveJob::Base
5
5
  def perform(params)
6
- @shop = Shop.find_by(duodealer_domain: params[:shop_domain])
7
- return unless @shop
6
+ @account = Account.find_by(duodealer_domain: params[:account_domain])
7
+ return unless @account
8
8
 
9
9
  config = DuodealerApp.configuration
10
- uri = URI("https://#{@shop.duodealer_domain}/admin/oauth/access_token")
10
+ uri = URI("https://#{@account.duodealer_domain}/admin/oauth/access_token")
11
11
  post_data = {
12
12
  client_id: config.api_key,
13
13
  client_secret: config.secret,
14
14
  refresh_token: params[:refresh_token],
15
- access_token: @shop.duodealer_token,
15
+ access_token: @account.duodealer_token,
16
16
  }
17
17
 
18
18
  @response = Net::HTTP.post_form(uri, post_data)
@@ -21,7 +21,7 @@ module Duodealer
21
21
  access_token = JSON.parse(@response.body)['access_token']
22
22
  return log_error(no_access_token_error_message) unless access_token
23
23
 
24
- @shop.update(duodealer_token: access_token)
24
+ @account.update(duodealer_token: access_token)
25
25
  end
26
26
 
27
27
  private
@@ -31,11 +31,11 @@ module Duodealer
31
31
  end
32
32
 
33
33
  def no_access_token_error_message
34
- "RotateDuodealerTokenJob response returned no access token for shop: #{@shop.duodealer_domain}"
34
+ "RotateDuodealerTokenJob response returned no access token for account: #{@account.duodealer_domain}"
35
35
  end
36
36
 
37
37
  def response_exception_error_message
38
- "RotateDuodealerTokenJob failed for shop: #{@shop.duodealer_domain}." \
38
+ "RotateDuodealerTokenJob failed for account: #{@account.duodealer_domain}." \
39
39
  "Response returned status: #{@response.code}. Error message: #{@response.message}. "
40
40
  end
41
41
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: duodealer_app
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Raio
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-22 00:00:00.000000000 Z
11
+ date: 2020-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: browser_sniffer
@@ -234,37 +234,21 @@ files:
234
234
  - app/assets/javascripts/duodealer_app/top_level.js
235
235
  - app/assets/javascripts/duodealer_app/top_level_interaction.js
236
236
  - app/controllers/concerns/duodealer_app/authenticated.rb
237
- - app/controllers/concerns/duodealer_app/authenticated.rb-e
238
237
  - app/controllers/duodealer_app/authenticated_controller.rb
239
- - app/controllers/duodealer_app/authenticated_controller.rb-e
240
238
  - app/controllers/duodealer_app/callback_controller.rb
241
- - app/controllers/duodealer_app/callback_controller.rb-e
242
239
  - app/controllers/duodealer_app/extension_verification_controller.rb
243
- - app/controllers/duodealer_app/extension_verification_controller.rb-e
244
240
  - app/controllers/duodealer_app/sessions_controller.rb
245
- - app/controllers/duodealer_app/sessions_controller.rb-e
246
241
  - app/controllers/duodealer_app/webhooks_controller.rb
247
- - app/controllers/duodealer_app/webhooks_controller.rb-e
248
242
  - app/views/duodealer_app/partials/_button_styles.html.erb
249
- - app/views/duodealer_app/partials/_button_styles.html.erb-e
250
243
  - app/views/duodealer_app/partials/_card_styles.html.erb
251
- - app/views/duodealer_app/partials/_card_styles.html.erb-e
252
244
  - app/views/duodealer_app/partials/_empty_state_styles.html.erb
253
- - app/views/duodealer_app/partials/_empty_state_styles.html.erb-e
254
245
  - app/views/duodealer_app/partials/_layout_styles.html.erb
255
- - app/views/duodealer_app/partials/_layout_styles.html.erb-e
256
246
  - app/views/duodealer_app/partials/_typography_styles.html.erb
257
- - app/views/duodealer_app/partials/_typography_styles.html.erb-e
258
247
  - app/views/duodealer_app/sessions/enable_cookies.html.erb
259
- - app/views/duodealer_app/sessions/enable_cookies.html.erb-e
260
248
  - app/views/duodealer_app/sessions/new.html.erb
261
- - app/views/duodealer_app/sessions/new.html.erb-e
262
249
  - app/views/duodealer_app/sessions/request_storage_access.html.erb
263
- - app/views/duodealer_app/sessions/request_storage_access.html.erb-e
264
250
  - app/views/duodealer_app/sessions/top_level_interaction.html.erb
265
- - app/views/duodealer_app/sessions/top_level_interaction.html.erb-e
266
251
  - app/views/duodealer_app/shared/redirect.html.erb
267
- - app/views/duodealer_app/shared/redirect.html.erb-e
268
252
  - config/locales/cs.yml
269
253
  - config/locales/da.yml
270
254
  - config/locales/de.yml
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DuodealerApp
4
- module Authenticated
5
- extend ActiveSupport::Concern
6
-
7
- included do
8
- include DuodealerApp::Localization
9
- include DuodealerApp::LoginProtection
10
- include DuodealerApp::EmbeddedApp
11
- before_action :login_again_if_different_user_or_shop
12
- around_action :duodealer_session
13
- end
14
- end
15
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DuodealerApp
4
- class AuthenticatedController < ApplicationController
5
- include DuodealerApp::Authenticated
6
-
7
- protect_from_forgery with: :exception
8
- end
9
- end
@@ -1,104 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DuodealerApp
4
- # Performs login after OAuth completes
5
- class CallbackController < ApplicationController
6
- include DuodealerApp::LoginProtection
7
-
8
- def callback
9
- if auth_hash
10
- login_shop
11
- install_webhooks
12
- install_scripttags
13
- perform_after_authenticate_job
14
-
15
- redirect_to return_address
16
- else
17
- flash[:error] = I18n.t("could_not_log_in")
18
- redirect_to(login_url_with_optional_shop)
19
- end
20
- end
21
-
22
- private
23
- def login_shop
24
- reset_session_options
25
- set_duodealer_session
26
- end
27
-
28
- def auth_hash
29
- request.env["omniauth.auth"]
30
- end
31
-
32
- def shop_name
33
- auth_hash.uid
34
- end
35
-
36
- def associated_user
37
- return if auth_hash["extra"].blank?
38
-
39
- auth_hash["extra"]["associated_user"]
40
- end
41
-
42
- def token
43
- auth_hash["credentials"]["token"]
44
- end
45
-
46
- def reset_session_options
47
- request.session_options[:renew] = true
48
- session.delete(:_csrf_token)
49
- end
50
-
51
- def set_duodealer_session
52
- session_store = DuodealerAPI::Session.new(
53
- domain: shop_name,
54
- token: token,
55
- api_version: DuodealerApp.configuration.api_version
56
- )
57
- session[:duodealer] = DuodealerApp::SessionRepository.store(session_store, user: associated_user)
58
- session[:duodealer_domain] = shop_name
59
- session[:duodealer_user] = associated_user
60
-
61
- if DuodealerApp.configuration.per_user_tokens?
62
- # Adds the user_session to the session to determine if the logged in user has changed
63
- user_session = auth_hash&.extra&.session
64
- raise IndexError, "Missing user session signature" if user_session.nil?
65
- session[:user_session] = user_session
66
- end
67
- end
68
-
69
- def install_webhooks
70
- return unless DuodealerApp.configuration.has_webhooks?
71
-
72
- WebhooksManager.queue(
73
- shop_name,
74
- token,
75
- DuodealerApp.configuration.webhooks
76
- )
77
- end
78
-
79
- def install_scripttags
80
- return unless DuodealerApp.configuration.has_scripttags?
81
-
82
- ScripttagsManager.queue(
83
- shop_name,
84
- token,
85
- DuodealerApp.configuration.scripttags
86
- )
87
- end
88
-
89
- def perform_after_authenticate_job
90
- config = DuodealerApp.configuration.after_authenticate_job
91
-
92
- return unless config && config[:job].present?
93
-
94
- job = config[:job]
95
- job = job.constantize if job.is_a?(String)
96
-
97
- if config[:inline] == true
98
- job.perform_now(shop_domain: session[:duodealer_domain])
99
- else
100
- job.perform_later(shop_domain: session[:duodealer_domain])
101
- end
102
- end
103
- end
104
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DuodealerApp
4
- class ExtensionVerificationController < ApplicationController
5
- protect_from_forgery with: :null_session
6
- before_action :verify_request
7
-
8
- private
9
- def verify_request
10
- hmac_header = request.headers["HTTP_X_DUODEALER_HMAC_SHA256"]
11
- request_body = request.body.read
12
- secret = DuodealerApp.configuration.secret
13
- digest = OpenSSL::Digest.new("sha256")
14
-
15
- expected_hmac = Base64.strict_encode64(OpenSSL::HMAC.digest(digest, secret, request_body))
16
- head(:unauthorized) unless ActiveSupport::SecurityUtils.secure_compare(expected_hmac, hmac_header)
17
- end
18
- end
19
- end
@@ -1,159 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DuodealerApp
4
- class SessionsController < ApplicationController # rubocop:disable Metrics/ClassLength
5
- include DuodealerApp::LoginProtection
6
-
7
- layout false, only: :new
8
- after_action only: [:new, :create] do |controller|
9
- controller.response.headers.except!("X-Frame-Options")
10
- end
11
-
12
- def new
13
- authenticate if sanitized_shop_name.present?
14
- end
15
-
16
- def create
17
- authenticate
18
- end
19
-
20
- def enable_cookies
21
- return unless validate_shop
22
-
23
- render(:enable_cookies, layout: false, locals: {
24
- does_not_have_storage_access_url: top_level_interaction_path(
25
- shop: sanitized_shop_name,
26
- return_to: params[:return_to]
27
- ),
28
- has_storage_access_url: login_url_with_optional_shop(top_level: true),
29
- app_target_url: granted_storage_access_path(
30
- shop: sanitized_shop_name,
31
- return_to: params[:return_to]
32
- ),
33
- current_duodealer_domain: current_duodealer_domain
34
- })
35
- end
36
-
37
- def top_level_interaction
38
- @url = login_url_with_optional_shop(top_level: true)
39
- validate_shop
40
- end
41
-
42
- def granted_storage_access
43
- return unless validate_shop
44
-
45
- session["duodealer.granted_storage_access"] = true
46
-
47
- copy_return_to_param_to_session
48
-
49
- redirect_to(return_address_with_params({ shop: @shop }))
50
- end
51
-
52
- def destroy
53
- reset_session
54
- flash[:notice] = I18n.t(".logged_out")
55
- redirect_to(login_url_with_optional_shop)
56
- end
57
-
58
- private
59
- def authenticate
60
- return render_invalid_shop_error if sanitized_shop_name.blank?
61
- session["duodealer.omniauth_params"] = { shop: sanitized_shop_name }
62
-
63
- copy_return_to_param_to_session
64
-
65
- if user_agent_can_partition_cookies
66
- authenticate_with_partitioning
67
- else
68
- authenticate_normally
69
- end
70
- end
71
-
72
- def authenticate_normally
73
- if request_storage_access?
74
- redirect_to_request_storage_access
75
- elsif authenticate_in_context?
76
- authenticate_in_context
77
- else
78
- authenticate_at_top_level
79
- end
80
- end
81
-
82
- def authenticate_with_partitioning
83
- if session["duodealer.cookies_persist"]
84
- clear_top_level_oauth_cookie
85
- authenticate_in_context
86
- else
87
- set_top_level_oauth_cookie
88
- enable_cookie_access
89
- end
90
- end
91
-
92
- def validate_shop
93
- @shop = sanitized_shop_name
94
- unless @shop
95
- render_invalid_shop_error
96
- return false
97
- end
98
-
99
- true
100
- end
101
-
102
- def copy_return_to_param_to_session
103
- session[:return_to] = params[:return_to] if params[:return_to]
104
- end
105
-
106
- def render_invalid_shop_error
107
- flash[:error] = I18n.t("invalid_shop_url")
108
- redirect_to return_address
109
- end
110
-
111
- def enable_cookie_access
112
- fullpage_redirect_to(enable_cookies_path(
113
- shop: sanitized_shop_name,
114
- return_to: session[:return_to]
115
- ))
116
- end
117
-
118
- def authenticate_in_context
119
- redirect_to "#{main_app.root_path}auth/duodealer"
120
- end
121
-
122
- def authenticate_at_top_level
123
- fullpage_redirect_to(login_url_with_optional_shop(top_level: true))
124
- end
125
-
126
- def authenticate_in_context?
127
- return true unless DuodealerApp.configuration.embedded_app?
128
- params[:top_level]
129
- end
130
-
131
- def request_storage_access?
132
- return false unless DuodealerApp.configuration.embedded_app?
133
- return false if params[:top_level]
134
- return false if user_agent_is_mobile
135
- return false if user_agent_is_pos
136
-
137
- !session["duodealer.granted_storage_access"]
138
- end
139
-
140
- def redirect_to_request_storage_access
141
- render(
142
- :request_storage_access,
143
- layout: false,
144
- locals: {
145
- does_not_have_storage_access_url: top_level_interaction_path(
146
- shop: sanitized_shop_name,
147
- return_to: session[:return_to]
148
- ),
149
- has_storage_access_url: login_url_with_optional_shop(top_level: true),
150
- app_target_url: granted_storage_access_path(
151
- shop: sanitized_shop_name,
152
- return_to: session[:return_to]
153
- ),
154
- current_duodealer_domain: current_duodealer_domain
155
- }
156
- )
157
- end
158
- end
159
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DuodealerApp
4
- class WebhooksController < ApplicationController
5
- include DuodealerApp::WebhookVerification
6
-
7
- class DuodealerApp::MissingWebhookJobError < StandardError; end
8
-
9
- def receive
10
- params.permit!
11
- job_args = { shop_domain: shop_domain, webhook: webhook_params.to_h }
12
- webhook_job_klass.perform_later(job_args)
13
- head :no_content
14
- end
15
-
16
- private
17
- def webhook_params
18
- params.except(:controller, :action, :type)
19
- end
20
-
21
- def webhook_job_klass
22
- webhook_job_klass_name.safe_constantize || raise(DuodealerApp::MissingWebhookJobError)
23
- end
24
-
25
- def webhook_job_klass_name(type = webhook_type)
26
- [webhook_namespace, "#{type}_job"].compact.join("/").classify
27
- end
28
-
29
- def webhook_type
30
- params[:type]
31
- end
32
-
33
- def webhook_namespace
34
- DuodealerApp.configuration.webhook_jobs_namespace
35
- end
36
- end
37
- end