duodealer_app 1.0.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 +7 -0
- data/.!66854!duodealer_app.gemspec +0 -0
- data/.babelrc +5 -0
- data/.gitignore +16 -0
- data/.nvmrc +1 -0
- data/.rubocop.yml +263 -0
- data/.ruby-version +1 -0
- data/.travis.yml +27 -0
- data/Gemfile +8 -0
- data/LICENSE +19 -0
- data/README.md +553 -0
- data/Rakefile +6 -0
- data/app/assets/images/storage_access.svg +2 -0
- data/app/assets/javascripts/duodealer_app/enable_cookies.js +3 -0
- data/app/assets/javascripts/duodealer_app/itp_helper.js +40 -0
- data/app/assets/javascripts/duodealer_app/partition_cookies.js +8 -0
- data/app/assets/javascripts/duodealer_app/redirect.js +33 -0
- data/app/assets/javascripts/duodealer_app/request_storage_access.js +3 -0
- data/app/assets/javascripts/duodealer_app/storage_access.js +153 -0
- data/app/assets/javascripts/duodealer_app/storage_access_redirect.js +17 -0
- data/app/assets/javascripts/duodealer_app/top_level.js +2 -0
- data/app/assets/javascripts/duodealer_app/top_level_interaction.js +11 -0
- data/app/controllers/concerns/duodealer_app/authenticated.rb +15 -0
- data/app/controllers/concerns/duodealer_app/authenticated.rb-e +15 -0
- data/app/controllers/duodealer_app/authenticated_controller.rb +9 -0
- data/app/controllers/duodealer_app/authenticated_controller.rb-e +9 -0
- data/app/controllers/duodealer_app/callback_controller.rb +104 -0
- data/app/controllers/duodealer_app/callback_controller.rb-e +104 -0
- data/app/controllers/duodealer_app/extension_verification_controller.rb +19 -0
- data/app/controllers/duodealer_app/extension_verification_controller.rb-e +19 -0
- data/app/controllers/duodealer_app/sessions_controller.rb +159 -0
- data/app/controllers/duodealer_app/sessions_controller.rb-e +159 -0
- data/app/controllers/duodealer_app/webhooks_controller.rb +37 -0
- data/app/controllers/duodealer_app/webhooks_controller.rb-e +37 -0
- data/app/views/duodealer_app/partials/_button_styles.html.erb +104 -0
- data/app/views/duodealer_app/partials/_button_styles.html.erb-e +104 -0
- data/app/views/duodealer_app/partials/_card_styles.html.erb +33 -0
- data/app/views/duodealer_app/partials/_card_styles.html.erb-e +33 -0
- data/app/views/duodealer_app/partials/_empty_state_styles.html.erb +129 -0
- data/app/views/duodealer_app/partials/_empty_state_styles.html.erb-e +129 -0
- data/app/views/duodealer_app/partials/_layout_styles.html.erb +167 -0
- data/app/views/duodealer_app/partials/_layout_styles.html.erb-e +167 -0
- data/app/views/duodealer_app/partials/_typography_styles.html.erb +35 -0
- data/app/views/duodealer_app/partials/_typography_styles.html.erb-e +35 -0
- data/app/views/duodealer_app/sessions/enable_cookies.html.erb +75 -0
- data/app/views/duodealer_app/sessions/enable_cookies.html.erb-e +75 -0
- data/app/views/duodealer_app/sessions/new.html.erb +123 -0
- data/app/views/duodealer_app/sessions/new.html.erb-e +123 -0
- data/app/views/duodealer_app/sessions/request_storage_access.html.erb +68 -0
- data/app/views/duodealer_app/sessions/request_storage_access.html.erb-e +68 -0
- data/app/views/duodealer_app/sessions/top_level_interaction.html.erb +64 -0
- data/app/views/duodealer_app/sessions/top_level_interaction.html.erb-e +64 -0
- data/app/views/duodealer_app/shared/redirect.html.erb +23 -0
- data/app/views/duodealer_app/shared/redirect.html.erb-e +23 -0
- data/config/locales/cs.yml +23 -0
- data/config/locales/da.yml +20 -0
- data/config/locales/de.yml +22 -0
- data/config/locales/en.yml +15 -0
- data/config/locales/es.yml +22 -0
- data/config/locales/fi.yml +20 -0
- data/config/locales/fr.yml +23 -0
- data/config/locales/hi.yml +23 -0
- data/config/locales/it.yml +21 -0
- data/config/locales/ja.yml +17 -0
- data/config/locales/ko.yml +19 -0
- data/config/locales/ms.yml +22 -0
- data/config/locales/nb.yml +21 -0
- data/config/locales/nl.yml +21 -0
- data/config/locales/pl.yml +21 -0
- data/config/locales/pt-BR.yml +21 -0
- data/config/locales/pt-PT.yml +22 -0
- data/config/locales/sv.yml +21 -0
- data/config/locales/th.yml +20 -0
- data/config/locales/tr.yml +22 -0
- data/config/locales/zh-CN.yml +16 -0
- data/config/locales/zh-TW.yml +16 -0
- data/config/routes.rb +22 -0
- data/docs/.!20385!test-your-app.png +0 -0
- data/docs/.!20388!install-on-dev-shop.png +0 -0
- data/docs/.!62511!test-your-app.png +0 -0
- data/docs/.!62512!install-on-dev-shop.png +0 -0
- data/docs/.!62763!test-your-app.png +0 -0
- data/docs/.!62765!install-on-dev-shop.png +0 -0
- data/docs/.!63018!test-your-app.png +0 -0
- data/docs/.!63020!install-on-dev-shop.png +0 -0
- data/docs/.!63289!test-your-app.png +0 -0
- data/docs/.!63291!install-on-dev-shop.png +0 -0
- data/docs/.!63562!test-your-app.png +0 -0
- data/docs/.!63564!install-on-dev-shop.png +0 -0
- data/docs/.!63872!test-your-app.png +0 -0
- data/docs/.!63874!install-on-dev-shop.png +0 -0
- data/docs/.!64151!test-your-app.png +0 -0
- data/docs/.!64153!install-on-dev-shop.png +0 -0
- data/docs/.!64428!test-your-app.png +0 -0
- data/docs/.!64431!install-on-dev-shop.png +0 -0
- data/docs/.!64737!test-your-app.png +0 -0
- data/docs/.!64740!install-on-dev-shop.png +0 -0
- data/docs/.!65025!test-your-app.png +0 -0
- data/docs/.!65028!install-on-dev-shop.png +0 -0
- data/docs/.!65324!test-your-app.png +0 -0
- data/docs/.!65327!install-on-dev-shop.png +0 -0
- data/docs/.!65626!test-your-app.png +0 -0
- data/docs/.!65629!install-on-dev-shop.png +0 -0
- data/docs/.!65942!test-your-app.png +0 -0
- data/docs/.!65945!install-on-dev-shop.png +0 -0
- data/docs/.!66760!test-your-app.png +0 -0
- data/docs/.!66763!install-on-dev-shop.png +0 -0
- data/docs/.!67028!test-your-app.png +0 -0
- data/docs/.!67031!install-on-dev-shop.png +0 -0
- data/docs/.!67657!test-your-app.png +0 -0
- data/docs/.!67660!install-on-dev-shop.png +0 -0
- data/docs/.!68031!test-your-app.png +0 -0
- data/docs/.!68034!install-on-dev-shop.png +0 -0
- data/docs/.!68363!test-your-app.png +0 -0
- data/docs/.!68366!install-on-dev-shop.png +0 -0
- data/docs/Quickstart.md +103 -0
- data/docs/Releasing.md +17 -0
- data/docs/Troubleshooting.md +16 -0
- data/docs/install-on-dev-shop.png +0 -0
- data/docs/test-your-app.png +0 -0
- data/duodealer_app.gemspec +34 -0
- data/images/.!20334!app-proxy-screenshot.png +0 -0
- data/images/.!62504!app-proxy-screenshot.png +0 -0
- data/images/.!62754!app-proxy-screenshot.png +0 -0
- data/images/.!63008!app-proxy-screenshot.png +0 -0
- data/images/.!63277!app-proxy-screenshot.png +0 -0
- data/images/.!63548!app-proxy-screenshot.png +0 -0
- data/images/.!63855!app-proxy-screenshot.png +0 -0
- data/images/.!64132!app-proxy-screenshot.png +0 -0
- data/images/.!64407!app-proxy-screenshot.png +0 -0
- data/images/.!64714!app-proxy-screenshot.png +0 -0
- data/images/.!65000!app-proxy-screenshot.png +0 -0
- data/images/.!65296!app-proxy-screenshot.png +0 -0
- data/images/.!65594!app-proxy-screenshot.png +0 -0
- data/images/.!65908!app-proxy-screenshot.png +0 -0
- data/images/.!66724!app-proxy-screenshot.png +0 -0
- data/images/.!66989!app-proxy-screenshot.png +0 -0
- data/images/.!67614!app-proxy-screenshot.png +0 -0
- data/images/.!67986!app-proxy-screenshot.png +0 -0
- data/images/.!68314!app-proxy-screenshot.png +0 -0
- data/images/app-proxy-screenshot.png +0 -0
- data/karma.conf.js +44 -0
- data/lib/duodealer_app.rb +54 -0
- data/lib/duodealer_app/configuration.rb +85 -0
- data/lib/duodealer_app/controller_concerns/app_proxy_verification.rb +39 -0
- data/lib/duodealer_app/controller_concerns/embedded_app.rb +20 -0
- data/lib/duodealer_app/controller_concerns/itp.rb +44 -0
- data/lib/duodealer_app/controller_concerns/localization.rb +23 -0
- data/lib/duodealer_app/controller_concerns/login_protection.rb +180 -0
- data/lib/duodealer_app/controller_concerns/webhook_verification.rb +39 -0
- data/lib/duodealer_app/engine.rb +22 -0
- data/lib/duodealer_app/jobs/scripttags_manager_job.rb +17 -0
- data/lib/duodealer_app/jobs/webhooks_manager_job.rb +17 -0
- data/lib/duodealer_app/managers/scripttags_manager.rb +78 -0
- data/lib/duodealer_app/managers/webhooks_manager.rb +62 -0
- data/lib/duodealer_app/middleware/same_site_cookie_middleware.rb +69 -0
- data/lib/duodealer_app/session/in_memory_session_store.rb +29 -0
- data/lib/duodealer_app/session/session_repository.rb +33 -0
- data/lib/duodealer_app/session/session_storage.rb +31 -0
- data/lib/duodealer_app/session/storage_strategies/shop_storage_strategy.rb +25 -0
- data/lib/duodealer_app/session/storage_strategies/user_storage_strategy.rb +26 -0
- data/lib/duodealer_app/utils.rb +24 -0
- data/lib/duodealer_app/version.rb +5 -0
- data/lib/generators/duodealer_app/add_after_authenticate_job/add_after_authenticate_job_generator.rb +46 -0
- data/lib/generators/duodealer_app/add_after_authenticate_job/templates/after_authenticate_job.rb +10 -0
- data/lib/generators/duodealer_app/add_marketing_activity_extension/add_marketing_activity_extension_generator.rb +40 -0
- data/lib/generators/duodealer_app/add_marketing_activity_extension/templates/marketing_activities_controller.rb +62 -0
- data/lib/generators/duodealer_app/add_webhook/add_webhook_generator.rb +69 -0
- data/lib/generators/duodealer_app/add_webhook/templates/webhook_job.rb +8 -0
- data/lib/generators/duodealer_app/app_proxy_controller/app_proxy_controller_generator.rb +27 -0
- data/lib/generators/duodealer_app/app_proxy_controller/templates/app_proxy_controller.rb +9 -0
- data/lib/generators/duodealer_app/app_proxy_controller/templates/app_proxy_route.rb +10 -0
- data/lib/generators/duodealer_app/app_proxy_controller/templates/index.html.erb +19 -0
- data/lib/generators/duodealer_app/authenticated_controller/authenticated_controller_generator.rb +15 -0
- data/lib/generators/duodealer_app/authenticated_controller/templates/authenticated_controller.rb +5 -0
- data/lib/generators/duodealer_app/controllers/controllers_generator.rb +30 -0
- data/lib/generators/duodealer_app/duodealer_app_generator.rb +19 -0
- data/lib/generators/duodealer_app/home_controller/home_controller_generator.rb +27 -0
- data/lib/generators/duodealer_app/home_controller/templates/home_controller.rb +8 -0
- data/lib/generators/duodealer_app/home_controller/templates/index.html.erb +21 -0
- data/lib/generators/duodealer_app/install/install_generator.rb +83 -0
- data/lib/generators/duodealer_app/install/templates/_flash_messages.html.erb +3 -0
- data/lib/generators/duodealer_app/install/templates/duodealer_app.js +15 -0
- data/lib/generators/duodealer_app/install/templates/duodealer_app.rb +15 -0
- data/lib/generators/duodealer_app/install/templates/duodealer_app_index.js +2 -0
- data/lib/generators/duodealer_app/install/templates/duodealer_provider.rb +20 -0
- data/lib/generators/duodealer_app/install/templates/embedded_app.html.erb +41 -0
- data/lib/generators/duodealer_app/install/templates/flash_messages.js +26 -0
- data/lib/generators/duodealer_app/install/templates/omniauth.rb +2 -0
- data/lib/generators/duodealer_app/install/templates/session_store.rb +4 -0
- data/lib/generators/duodealer_app/install/templates/user_agent.rb +5 -0
- data/lib/generators/duodealer_app/rotate_duodealer_token_job/rotate_duodealer_token_job_generator.rb +16 -0
- data/lib/generators/duodealer_app/rotate_duodealer_token_job/templates/rotate_duodealer_token.rake +17 -0
- data/lib/generators/duodealer_app/rotate_duodealer_token_job/templates/rotate_duodealer_token_job.rb +42 -0
- data/lib/generators/duodealer_app/routes/routes_generator.rb +32 -0
- data/lib/generators/duodealer_app/routes/templates/routes.rb +11 -0
- data/lib/generators/duodealer_app/shop_model/shop_model_generator.rb +39 -0
- data/lib/generators/duodealer_app/shop_model/templates/db/migrate/create_shops.erb +15 -0
- data/lib/generators/duodealer_app/shop_model/templates/shop.rb +7 -0
- data/lib/generators/duodealer_app/shop_model/templates/shops.yml +3 -0
- data/lib/generators/duodealer_app/user_model/templates/db/migrate/create_users.erb +16 -0
- data/lib/generators/duodealer_app/user_model/templates/user.rb +7 -0
- data/lib/generators/duodealer_app/user_model/templates/users.yml +4 -0
- data/lib/generators/duodealer_app/user_model/user_model_generator.rb +39 -0
- data/lib/generators/duodealer_app/views/views_generator.rb +30 -0
- data/package-lock.json +7224 -0
- data/package.json +28 -0
- data/shipit.rubygems.yml +4 -0
- data/translation.yml +7 -0
- data/webpack.config.js +24 -0
- data/yarn.lock +5263 -0
- metadata +447 -0
|
@@ -0,0 +1,104 @@
|
|
|
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
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
|
@@ -0,0 +1,159 @@
|
|
|
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
|
|
@@ -0,0 +1,159 @@
|
|
|
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
|