duodealer_app 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (212) hide show
  1. checksums.yaml +7 -0
  2. data/.!66854!duodealer_app.gemspec +0 -0
  3. data/.babelrc +5 -0
  4. data/.gitignore +16 -0
  5. data/.nvmrc +1 -0
  6. data/.rubocop.yml +263 -0
  7. data/.ruby-version +1 -0
  8. data/.travis.yml +27 -0
  9. data/Gemfile +8 -0
  10. data/LICENSE +19 -0
  11. data/README.md +553 -0
  12. data/Rakefile +6 -0
  13. data/app/assets/images/storage_access.svg +2 -0
  14. data/app/assets/javascripts/duodealer_app/enable_cookies.js +3 -0
  15. data/app/assets/javascripts/duodealer_app/itp_helper.js +40 -0
  16. data/app/assets/javascripts/duodealer_app/partition_cookies.js +8 -0
  17. data/app/assets/javascripts/duodealer_app/redirect.js +33 -0
  18. data/app/assets/javascripts/duodealer_app/request_storage_access.js +3 -0
  19. data/app/assets/javascripts/duodealer_app/storage_access.js +153 -0
  20. data/app/assets/javascripts/duodealer_app/storage_access_redirect.js +17 -0
  21. data/app/assets/javascripts/duodealer_app/top_level.js +2 -0
  22. data/app/assets/javascripts/duodealer_app/top_level_interaction.js +11 -0
  23. data/app/controllers/concerns/duodealer_app/authenticated.rb +15 -0
  24. data/app/controllers/concerns/duodealer_app/authenticated.rb-e +15 -0
  25. data/app/controllers/duodealer_app/authenticated_controller.rb +9 -0
  26. data/app/controllers/duodealer_app/authenticated_controller.rb-e +9 -0
  27. data/app/controllers/duodealer_app/callback_controller.rb +104 -0
  28. data/app/controllers/duodealer_app/callback_controller.rb-e +104 -0
  29. data/app/controllers/duodealer_app/extension_verification_controller.rb +19 -0
  30. data/app/controllers/duodealer_app/extension_verification_controller.rb-e +19 -0
  31. data/app/controllers/duodealer_app/sessions_controller.rb +159 -0
  32. data/app/controllers/duodealer_app/sessions_controller.rb-e +159 -0
  33. data/app/controllers/duodealer_app/webhooks_controller.rb +37 -0
  34. data/app/controllers/duodealer_app/webhooks_controller.rb-e +37 -0
  35. data/app/views/duodealer_app/partials/_button_styles.html.erb +104 -0
  36. data/app/views/duodealer_app/partials/_button_styles.html.erb-e +104 -0
  37. data/app/views/duodealer_app/partials/_card_styles.html.erb +33 -0
  38. data/app/views/duodealer_app/partials/_card_styles.html.erb-e +33 -0
  39. data/app/views/duodealer_app/partials/_empty_state_styles.html.erb +129 -0
  40. data/app/views/duodealer_app/partials/_empty_state_styles.html.erb-e +129 -0
  41. data/app/views/duodealer_app/partials/_layout_styles.html.erb +167 -0
  42. data/app/views/duodealer_app/partials/_layout_styles.html.erb-e +167 -0
  43. data/app/views/duodealer_app/partials/_typography_styles.html.erb +35 -0
  44. data/app/views/duodealer_app/partials/_typography_styles.html.erb-e +35 -0
  45. data/app/views/duodealer_app/sessions/enable_cookies.html.erb +75 -0
  46. data/app/views/duodealer_app/sessions/enable_cookies.html.erb-e +75 -0
  47. data/app/views/duodealer_app/sessions/new.html.erb +123 -0
  48. data/app/views/duodealer_app/sessions/new.html.erb-e +123 -0
  49. data/app/views/duodealer_app/sessions/request_storage_access.html.erb +68 -0
  50. data/app/views/duodealer_app/sessions/request_storage_access.html.erb-e +68 -0
  51. data/app/views/duodealer_app/sessions/top_level_interaction.html.erb +64 -0
  52. data/app/views/duodealer_app/sessions/top_level_interaction.html.erb-e +64 -0
  53. data/app/views/duodealer_app/shared/redirect.html.erb +23 -0
  54. data/app/views/duodealer_app/shared/redirect.html.erb-e +23 -0
  55. data/config/locales/cs.yml +23 -0
  56. data/config/locales/da.yml +20 -0
  57. data/config/locales/de.yml +22 -0
  58. data/config/locales/en.yml +15 -0
  59. data/config/locales/es.yml +22 -0
  60. data/config/locales/fi.yml +20 -0
  61. data/config/locales/fr.yml +23 -0
  62. data/config/locales/hi.yml +23 -0
  63. data/config/locales/it.yml +21 -0
  64. data/config/locales/ja.yml +17 -0
  65. data/config/locales/ko.yml +19 -0
  66. data/config/locales/ms.yml +22 -0
  67. data/config/locales/nb.yml +21 -0
  68. data/config/locales/nl.yml +21 -0
  69. data/config/locales/pl.yml +21 -0
  70. data/config/locales/pt-BR.yml +21 -0
  71. data/config/locales/pt-PT.yml +22 -0
  72. data/config/locales/sv.yml +21 -0
  73. data/config/locales/th.yml +20 -0
  74. data/config/locales/tr.yml +22 -0
  75. data/config/locales/zh-CN.yml +16 -0
  76. data/config/locales/zh-TW.yml +16 -0
  77. data/config/routes.rb +22 -0
  78. data/docs/.!20385!test-your-app.png +0 -0
  79. data/docs/.!20388!install-on-dev-shop.png +0 -0
  80. data/docs/.!62511!test-your-app.png +0 -0
  81. data/docs/.!62512!install-on-dev-shop.png +0 -0
  82. data/docs/.!62763!test-your-app.png +0 -0
  83. data/docs/.!62765!install-on-dev-shop.png +0 -0
  84. data/docs/.!63018!test-your-app.png +0 -0
  85. data/docs/.!63020!install-on-dev-shop.png +0 -0
  86. data/docs/.!63289!test-your-app.png +0 -0
  87. data/docs/.!63291!install-on-dev-shop.png +0 -0
  88. data/docs/.!63562!test-your-app.png +0 -0
  89. data/docs/.!63564!install-on-dev-shop.png +0 -0
  90. data/docs/.!63872!test-your-app.png +0 -0
  91. data/docs/.!63874!install-on-dev-shop.png +0 -0
  92. data/docs/.!64151!test-your-app.png +0 -0
  93. data/docs/.!64153!install-on-dev-shop.png +0 -0
  94. data/docs/.!64428!test-your-app.png +0 -0
  95. data/docs/.!64431!install-on-dev-shop.png +0 -0
  96. data/docs/.!64737!test-your-app.png +0 -0
  97. data/docs/.!64740!install-on-dev-shop.png +0 -0
  98. data/docs/.!65025!test-your-app.png +0 -0
  99. data/docs/.!65028!install-on-dev-shop.png +0 -0
  100. data/docs/.!65324!test-your-app.png +0 -0
  101. data/docs/.!65327!install-on-dev-shop.png +0 -0
  102. data/docs/.!65626!test-your-app.png +0 -0
  103. data/docs/.!65629!install-on-dev-shop.png +0 -0
  104. data/docs/.!65942!test-your-app.png +0 -0
  105. data/docs/.!65945!install-on-dev-shop.png +0 -0
  106. data/docs/.!66760!test-your-app.png +0 -0
  107. data/docs/.!66763!install-on-dev-shop.png +0 -0
  108. data/docs/.!67028!test-your-app.png +0 -0
  109. data/docs/.!67031!install-on-dev-shop.png +0 -0
  110. data/docs/.!67657!test-your-app.png +0 -0
  111. data/docs/.!67660!install-on-dev-shop.png +0 -0
  112. data/docs/.!68031!test-your-app.png +0 -0
  113. data/docs/.!68034!install-on-dev-shop.png +0 -0
  114. data/docs/.!68363!test-your-app.png +0 -0
  115. data/docs/.!68366!install-on-dev-shop.png +0 -0
  116. data/docs/Quickstart.md +103 -0
  117. data/docs/Releasing.md +17 -0
  118. data/docs/Troubleshooting.md +16 -0
  119. data/docs/install-on-dev-shop.png +0 -0
  120. data/docs/test-your-app.png +0 -0
  121. data/duodealer_app.gemspec +34 -0
  122. data/images/.!20334!app-proxy-screenshot.png +0 -0
  123. data/images/.!62504!app-proxy-screenshot.png +0 -0
  124. data/images/.!62754!app-proxy-screenshot.png +0 -0
  125. data/images/.!63008!app-proxy-screenshot.png +0 -0
  126. data/images/.!63277!app-proxy-screenshot.png +0 -0
  127. data/images/.!63548!app-proxy-screenshot.png +0 -0
  128. data/images/.!63855!app-proxy-screenshot.png +0 -0
  129. data/images/.!64132!app-proxy-screenshot.png +0 -0
  130. data/images/.!64407!app-proxy-screenshot.png +0 -0
  131. data/images/.!64714!app-proxy-screenshot.png +0 -0
  132. data/images/.!65000!app-proxy-screenshot.png +0 -0
  133. data/images/.!65296!app-proxy-screenshot.png +0 -0
  134. data/images/.!65594!app-proxy-screenshot.png +0 -0
  135. data/images/.!65908!app-proxy-screenshot.png +0 -0
  136. data/images/.!66724!app-proxy-screenshot.png +0 -0
  137. data/images/.!66989!app-proxy-screenshot.png +0 -0
  138. data/images/.!67614!app-proxy-screenshot.png +0 -0
  139. data/images/.!67986!app-proxy-screenshot.png +0 -0
  140. data/images/.!68314!app-proxy-screenshot.png +0 -0
  141. data/images/app-proxy-screenshot.png +0 -0
  142. data/karma.conf.js +44 -0
  143. data/lib/duodealer_app.rb +54 -0
  144. data/lib/duodealer_app/configuration.rb +85 -0
  145. data/lib/duodealer_app/controller_concerns/app_proxy_verification.rb +39 -0
  146. data/lib/duodealer_app/controller_concerns/embedded_app.rb +20 -0
  147. data/lib/duodealer_app/controller_concerns/itp.rb +44 -0
  148. data/lib/duodealer_app/controller_concerns/localization.rb +23 -0
  149. data/lib/duodealer_app/controller_concerns/login_protection.rb +180 -0
  150. data/lib/duodealer_app/controller_concerns/webhook_verification.rb +39 -0
  151. data/lib/duodealer_app/engine.rb +22 -0
  152. data/lib/duodealer_app/jobs/scripttags_manager_job.rb +17 -0
  153. data/lib/duodealer_app/jobs/webhooks_manager_job.rb +17 -0
  154. data/lib/duodealer_app/managers/scripttags_manager.rb +78 -0
  155. data/lib/duodealer_app/managers/webhooks_manager.rb +62 -0
  156. data/lib/duodealer_app/middleware/same_site_cookie_middleware.rb +69 -0
  157. data/lib/duodealer_app/session/in_memory_session_store.rb +29 -0
  158. data/lib/duodealer_app/session/session_repository.rb +33 -0
  159. data/lib/duodealer_app/session/session_storage.rb +31 -0
  160. data/lib/duodealer_app/session/storage_strategies/shop_storage_strategy.rb +25 -0
  161. data/lib/duodealer_app/session/storage_strategies/user_storage_strategy.rb +26 -0
  162. data/lib/duodealer_app/utils.rb +24 -0
  163. data/lib/duodealer_app/version.rb +5 -0
  164. data/lib/generators/duodealer_app/add_after_authenticate_job/add_after_authenticate_job_generator.rb +46 -0
  165. data/lib/generators/duodealer_app/add_after_authenticate_job/templates/after_authenticate_job.rb +10 -0
  166. data/lib/generators/duodealer_app/add_marketing_activity_extension/add_marketing_activity_extension_generator.rb +40 -0
  167. data/lib/generators/duodealer_app/add_marketing_activity_extension/templates/marketing_activities_controller.rb +62 -0
  168. data/lib/generators/duodealer_app/add_webhook/add_webhook_generator.rb +69 -0
  169. data/lib/generators/duodealer_app/add_webhook/templates/webhook_job.rb +8 -0
  170. data/lib/generators/duodealer_app/app_proxy_controller/app_proxy_controller_generator.rb +27 -0
  171. data/lib/generators/duodealer_app/app_proxy_controller/templates/app_proxy_controller.rb +9 -0
  172. data/lib/generators/duodealer_app/app_proxy_controller/templates/app_proxy_route.rb +10 -0
  173. data/lib/generators/duodealer_app/app_proxy_controller/templates/index.html.erb +19 -0
  174. data/lib/generators/duodealer_app/authenticated_controller/authenticated_controller_generator.rb +15 -0
  175. data/lib/generators/duodealer_app/authenticated_controller/templates/authenticated_controller.rb +5 -0
  176. data/lib/generators/duodealer_app/controllers/controllers_generator.rb +30 -0
  177. data/lib/generators/duodealer_app/duodealer_app_generator.rb +19 -0
  178. data/lib/generators/duodealer_app/home_controller/home_controller_generator.rb +27 -0
  179. data/lib/generators/duodealer_app/home_controller/templates/home_controller.rb +8 -0
  180. data/lib/generators/duodealer_app/home_controller/templates/index.html.erb +21 -0
  181. data/lib/generators/duodealer_app/install/install_generator.rb +83 -0
  182. data/lib/generators/duodealer_app/install/templates/_flash_messages.html.erb +3 -0
  183. data/lib/generators/duodealer_app/install/templates/duodealer_app.js +15 -0
  184. data/lib/generators/duodealer_app/install/templates/duodealer_app.rb +15 -0
  185. data/lib/generators/duodealer_app/install/templates/duodealer_app_index.js +2 -0
  186. data/lib/generators/duodealer_app/install/templates/duodealer_provider.rb +20 -0
  187. data/lib/generators/duodealer_app/install/templates/embedded_app.html.erb +41 -0
  188. data/lib/generators/duodealer_app/install/templates/flash_messages.js +26 -0
  189. data/lib/generators/duodealer_app/install/templates/omniauth.rb +2 -0
  190. data/lib/generators/duodealer_app/install/templates/session_store.rb +4 -0
  191. data/lib/generators/duodealer_app/install/templates/user_agent.rb +5 -0
  192. data/lib/generators/duodealer_app/rotate_duodealer_token_job/rotate_duodealer_token_job_generator.rb +16 -0
  193. data/lib/generators/duodealer_app/rotate_duodealer_token_job/templates/rotate_duodealer_token.rake +17 -0
  194. data/lib/generators/duodealer_app/rotate_duodealer_token_job/templates/rotate_duodealer_token_job.rb +42 -0
  195. data/lib/generators/duodealer_app/routes/routes_generator.rb +32 -0
  196. data/lib/generators/duodealer_app/routes/templates/routes.rb +11 -0
  197. data/lib/generators/duodealer_app/shop_model/shop_model_generator.rb +39 -0
  198. data/lib/generators/duodealer_app/shop_model/templates/db/migrate/create_shops.erb +15 -0
  199. data/lib/generators/duodealer_app/shop_model/templates/shop.rb +7 -0
  200. data/lib/generators/duodealer_app/shop_model/templates/shops.yml +3 -0
  201. data/lib/generators/duodealer_app/user_model/templates/db/migrate/create_users.erb +16 -0
  202. data/lib/generators/duodealer_app/user_model/templates/user.rb +7 -0
  203. data/lib/generators/duodealer_app/user_model/templates/users.yml +4 -0
  204. data/lib/generators/duodealer_app/user_model/user_model_generator.rb +39 -0
  205. data/lib/generators/duodealer_app/views/views_generator.rb +30 -0
  206. data/package-lock.json +7224 -0
  207. data/package.json +28 -0
  208. data/shipit.rubygems.yml +4 -0
  209. data/translation.yml +7 -0
  210. data/webpack.config.js +24 -0
  211. data/yarn.lock +5263 -0
  212. metadata +447 -0
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ require File.expand_path("../test/dummy/config/application", __FILE__)
5
+
6
+ Rails.application.load_tasks
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg enable-background="new 0 0 1920 1080" version="1.1" viewBox="0 0 1920 1080" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><polygon points="1345 330.75 1345 437.24 1224.7 437.24 1224.7 676.56 873.52 676.56 874.04 643.85 1203.2 330.23" fill="#fff"/><path d="m1095.7 677.54c-18.553 0.074-37.107 0.163-55.66 0.126-18.553 0.056-37.107-0.188-55.66-0.233l-13.915-0.063-13.915 0.044-27.83 0.094c-18.553 0.128-37.107-5e-3 -55.66-0.056l-1.266-3e-3 3e-3 -1.259 0.047-22.532-0.093-22.532-0.068-11.266 6e-3 -11.266 0.019-22.532h2.703l0.111 22.532c0.053 7.511 0.06 15.022 0.038 22.532l-0.094 45.065-1.407-1.407c18.553 7e-3 37.107-0.041 55.66 0.086l27.83 0.131 13.915 0.066 13.915-0.028c18.553-8e-3 37.107-0.151 55.66-0.019 18.553 0.099 37.107 0.049 55.66-0.181v2.701z" fill="#0C1238"/><path d="m1225 677.54c-9.24 0.123-18.48 0.187-27.72 0.077l-13.86-0.213c-2.31-0.051-4.62-0.023-6.93 1e-3l-6.93 0.062c-9.24 0.156-18.48 0.076-27.72-0.054-2.31-0.034-4.62 1e-3 -6.93 2e-3l-6.93 0.121c-4.62 0.062-9.24-2e-3 -13.86 3e-3v-2.703c4.62-0.048 9.24-0.165 13.86-0.157l6.93 0.025c2.31 0.027 4.62 0.088 6.93 0.076 9.24-0.024 18.48-0.031 27.72 0.145 4.62 0.038 9.24 0.163 13.86 0.126l13.86-0.081c4.62-0.04 9.24 0.088 13.86 0.101 2.31 0.047 4.62-0.048 6.93-0.065 2.31-0.026 4.62-0.07 6.93-0.169v2.703z" fill="#0C1238"/><path d="m871.68 561.78l-0.13-115.72 0.07-115.72 1e-3 -1.414 1.411 3e-3 117.9 0.228 117.9-0.138 58.951-0.061 58.951 0.072 117.9 0.09 1.218 1e-3 4e-3 1.221 0.156 53.426-0.026 53.426h-2.703l-0.154-53.426 0.04-53.426 1.466 1.466-235.8-0.148-117.9-0.193-117.9 0.087 1.212-1.212-0.084 115.72c-0.058 19.286 0.032 38.573 0.074 57.859l0.15 57.859h-2.705z" fill="#0C1238"/><g fill="#E6E8F0"><circle cx="891.37" cy="344.49" r="6.812"/><circle cx="912.86" cy="345.01" r="6.812"/><circle cx="934.34" cy="345.54" r="6.812"/><path d="m1202.7 352.87h-186.64c-0.552 0-1-0.448-1-1v-11.624c0-0.552 0.448-1 1-1h186.64c0.552 0 1 0.448 1 1v11.624c0 0.552-0.448 1-1 1z" stroke="#F0F3F5" stroke-miterlimit="10"/><rect x="1288.6" y="339.25" width="17.816" height="13.624"/><path d="m1327.4 352.87h-15.816c-0.552 0-1-0.448-1-1v-11.624c0-0.552 0.448-1 1-1h15.816c0.552 0 1 0.448 1 1v11.624c0 0.552-0.447 1-1 1z"/></g><g fill="none" stroke="#8891EA" stroke-miterlimit="10" stroke-width="8"><path d="m1098.3 576.8c-24.295 0-43.99-19.695-43.99-43.99v-29.485c0-2.209 1.791-4 4-4h79.98c2.209 0 4 1.791 4 4v29.485c0 24.295-19.695 43.99-43.99 43.99z"/><path d="m1066 499.33v-12.41c0-17.804 14.433-32.237 32.237-32.237s32.237 14.433 32.237 32.237v12.41"/></g><circle cx="1098.3" cy="529.08" r="8.966" fill="#8891EA"/><line x1="1098.3" x2="1098.3" y1="529.08" y2="546.68" fill="#fff" stroke="#8891EA" stroke-linecap="round" stroke-miterlimit="10" stroke-width="8"/><polygon points="1416.1 676.19 1358 748.57 1416.1 749.77 1225 749.77 1225 659.42 1416.1 437.19" fill="#fff"/><path d="m1415.2 497.07l-0.12-59.83 1.472 1.472-95.89-0.052-47.945-0.135c-15.982-0.023-31.963-0.14-47.945-0.085l1.2-1.2 0.139 78.077c0.086 26.026 4e-3 52.052-0.039 78.077l-0.076 78.077c0.056 26.026 0.201 52.052 0.145 78.077l-1.368-1.368 38.25 0.017v2.703l-38.251 0.1-1.444 4e-3 -6e-3 -1.454c-0.102-26.026-0.045-52.052-0.026-78.077l0.068-78.077 0.067-78.077 0.191-78.077 3e-3 -1.15h1.147l47.945-0.013 47.945-0.051 95.89 0.089 1.121 1e-3 4e-3 1.125 0.226 59.83h-2.703z" fill="#0C1238"/><path d="m1417.9 518.33c0.051 19.268 0.165 38.536 0.128 57.804l-0.022 28.902-0.134 28.902-0.134 28.902 0.061 28.902 0.087 28.902 0.046 14.451-0.034 14.451-3e-3 1.353-1.347-3e-3c-22.64-0.042-45.28-0.192-67.919-0.118l-33.96 0.144-33.96-0.025v-2.703l33.96-0.143 33.96 0.01c11.32 0.049 22.64 0.1 33.96 0.078l33.96-2e-3 -1.409 1.409c-0.03-19.268 0.125-38.536 0.178-57.804l0.103-28.902-0.051-28.902-0.051-28.902 0.081-28.902c0.128-19.268-0.116-38.536-0.204-57.804h2.704z" fill="#0C1238"/><path d="m1400.3 458.72h-160.44c-0.552 0-1-0.448-1-1v-11.624c0-0.552 0.448-1 1-1h160.44c0.552 0 1 0.448 1 1v11.624c0 0.552-0.448 1-1 1z" fill="#E6E8F0" stroke="#F0F3F5" stroke-miterlimit="10"/><path d="m1238.5 467.44c13.587-0.084 27.173-0.121 40.76-0.055l20.38 0.141c6.793 0.061 13.587-0.03 20.38-0.038 13.587-0.116 27.173-0.022 40.76 0.038 6.793 0.029 13.587-0.022 20.38-0.082 6.793-0.046 13.587 0 20.38-5e-3v1.802c-13.587 0.111-27.173 0.144-40.76 0.036-13.587 2e-3 -27.173 0.027-40.76-0.09-6.793-0.025-13.587-0.117-20.38-0.088l-20.38 0.054c-6.793 0.022-13.587-0.048-20.38-0.067-6.793-7e-3 -13.587 0.107-20.38 0.154v-1.8z" fill="#E6E8F0"/><path d="m891.69 362.56c36.392-0.084 72.784-0.121 109.18-0.055l54.588 0.141c18.196 0.062 36.392-0.034 54.588-0.043l218.35-0.043v1.802c-36.392 0.111-72.784 0.144-109.18 0.036l-109.18-0.09-54.588-0.088-54.588 0.054-54.588-0.067-54.588 0.154v-1.801z" fill="#E6E8F0"/><g fill="none" stroke="#8891EA" stroke-miterlimit="10" stroke-width="6"><path d="m1320.6 638.41c-17.878 0-32.371-14.493-32.371-32.371v-21.697c0-1.626 1.318-2.943 2.943-2.943h58.854c1.626 0 2.943 1.318 2.943 2.943v21.697c1e-3 17.878-14.491 32.371-32.369 32.371z"/><path d="m1296.9 581.4v-9.132c0-13.101 10.62-23.722 23.722-23.722 13.101 0 23.722 10.621 23.722 23.722v9.132"/></g><circle cx="1320.6" cy="604.5" r="5.88" fill="#8891EA"/><line x1="1320.6" x2="1320.6" y1="603.3" y2="616.25" fill="#fff" stroke="#8891EA" stroke-linecap="round" stroke-miterlimit="10" stroke-width="6"/><path d="m966.35 697.36l-0.029 13.745c-0.01 1.145 0.011 2.291-0.023 3.436l-0.124 3.436c-0.103 2.291 0.022 4.582 0.121 6.872l-1.912-1.912c10.168-0.857 20.337-0.478 30.505-0.36 5.084 0.104 10.168 0.133 15.252 0.178 5.084 6e-3 10.168 0.199 15.252 0.287l7.626 0.168 7.626 0.264c2.542 0.09 5.084 0.032 7.626 0.023 2.542-0.035 5.084 0.047 7.626 0.065 10.168 0.377 20.337-0.052 30.505 0.201l7.626 0.04c2.542 6e-3 5.084-0.283 7.626-0.394 5.084-0.14 10.168-0.184 15.252-0.268 5.084-0.072 10.168-0.071 15.252-0.204 2.542-0.07 5.084-0.088 7.626-0.118 2.542-0.019 5.084 0.1 7.626 0.143 10.168 0.462 20.337-0.303 30.505 0.192 2.542 0.145 5.084 0.163 7.626 0.139 2.542 0 5.084-0.038 7.626-0.099l15.252-0.314v3.936l-15.252 0.106c-5.084 0.024-10.168 0.012-15.252 0.3-10.168 0.483-20.337-0.281-30.505-0.213-20.337-1.165-40.673 0.704-61.01-0.137-2.542 0.117-5.084 0.33-7.626 0.382-2.542 0.092-5.084 0.173-7.626-0.018s-5.084-0.219-7.626-0.183c-2.542-2e-3 -5.084 0.099-7.626 0.081-2.542-0.027-5.084 0.026-7.626-0.066-1.271-0.039-2.542-0.079-3.813-0.09-1.271-0.022-2.542-0.05-3.813 0.018-2.542 0.097-5.084 0.355-7.626 0.327-1.271-0.037-2.542-0.06-3.813-0.12l-3.813-0.238c-2.542-0.162-5.084-0.324-7.626-0.268-2.542 0.109-5.084-0.092-7.626-0.222-2.542-0.112-5.084-0.326-7.626-0.371-2.542-0.094-5.084-0.061-7.626-0.038-5.084 0.101-10.168 0.266-15.252 0.414-2.542 0.071-5.084 0.122-7.626 0.123l-7.626-0.19-1.598-0.04 0.032-1.527c0.047-2.291 0.153-4.582 9e-3 -6.872l-0.162-3.436c-0.047-1.145-0.04-2.291-0.062-3.436l-0.186-13.745h3.934z" fill="#E6E8F0"/><path d="m1434.8 722.88l16.096 0.019 8.048 0.01c2.683 0.018 5.365-0.029 8.048 0.05l-1.89 1.89c0.07-3.44 0.218-6.88 0.086-10.32l-0.312-10.32c-0.261-6.88-0.364-13.76-0.339-20.639l0.314-41.279c0.052-6.88 0.033-13.76 0.144-20.639l0.275-20.639c0.057-6.88 0.274-13.76 0.375-20.639 0.058-6.88-0.069-13.76 0.033-20.639l0.226-20.639-0.071-10.32-0.046-5.16 0.032-5.16 0.11-20.639c0.012-3.44 0.045-6.88-0.068-10.32-0.149-3.44-0.261-6.88-0.361-10.32l-0.328-41.279c-0.074-6.88-0.188-13.76-0.211-20.639 0.028-6.88 0.177-13.76 0.261-20.639l1.77 1.77c-4.37-0.095-8.74 1e-3 -13.111 1e-3l-13.111 0.063c-4.37 1e-3 -8.74 0.084-13.111 0.016l-13.111-0.231c-4.37-0.118-8.74-0.058-13.111-0.055-4.37-4e-3 -8.74 0.077-13.111 0.113l-26.221 0.29v-3.936l26.221-0.107 13.111-0.052c4.37-0.026 8.74 2e-3 13.111-0.14l13.111-0.262c4.37-0.066 8.74 0.04 13.111 0.051l26.221 0.283 2.211 0.024-0.016 2.172c-0.049 6.88-0.045 13.76-0.139 20.639-0.152 6.88-0.325 13.76-0.304 20.639l0.499 41.279c-0.024 1.72-0.037 3.44-0.138 5.16l-0.297 5.16c-0.137 3.44-0.045 6.88 0.01 10.32 0.12 6.88 0.479 13.76 0.59 20.639 0.273 6.88-0.127 13.76-0.227 20.639-0.014 6.88 0.146 13.76 0.091 20.639 0.051 6.88-0.202 13.76-0.162 20.639 0.04 3.44 0.226 6.88 0.324 10.32 0.061 3.44 4e-3 6.88-0.082 10.32l-0.356 10.32c-0.047 1.72-0.141 3.44-0.149 5.16l2e-3 5.16c-0.012 1.72 0.032 3.44-0.026 5.16l-0.164 5.16-0.335 10.32c-0.306 13.76 0.065 27.519 0.289 41.279 0.074 3.44 0.091 6.88 0.13 10.32 0.059 3.44-0.071 6.88-0.098 10.32l-0.153 10.32c-0.053 1.72 0.021 3.44 0.049 5.16l0.139 5.16 0.044 1.627-1.73 0.06c-2.683 0.093-5.365 0.065-8.048 0.1l-8.048 0.061-16.096 0.121v-3.941z" fill="#E6E8F0"/></svg>
@@ -0,0 +1,3 @@
1
+ //= require ./itp_helper.js
2
+ //= require ./storage_access.js
3
+ //= require ./partition_cookies.js
@@ -0,0 +1,40 @@
1
+ (function() {
2
+ function ITPHelper(opts) {
3
+ this.itpContent = document.getElementById('TopLevelInteractionContent');
4
+ this.itpAction = document.getElementById('TopLevelInteractionButton');
5
+ this.redirectUrl = opts.redirectUrl;
6
+ }
7
+
8
+ ITPHelper.prototype.redirect = function() {
9
+ sessionStorage.setItem('duodealer.top_level_interaction', true);
10
+ window.location.href = this.redirectUrl;
11
+ }
12
+
13
+ ITPHelper.prototype.userAgentIsAffected = function() {
14
+ return Boolean(document.hasStorageAccess);
15
+ }
16
+
17
+ ITPHelper.prototype.canPartitionCookies = function() {
18
+ var versionRegEx = /Version\/12\.0\.?\d? Safari/;
19
+ return versionRegEx.test(navigator.userAgent);
20
+ }
21
+
22
+ ITPHelper.prototype.setUpContent = function(onClick) {
23
+ this.itpContent.style.display = 'block';
24
+ this.itpAction.addEventListener('click', this.redirect.bind(this));
25
+ }
26
+
27
+ ITPHelper.prototype.execute = function() {
28
+ if (!this.itpContent) {
29
+ return;
30
+ }
31
+
32
+ if (this.userAgentIsAffected()) {
33
+ this.setUpContent();
34
+ } else {
35
+ this.redirect();
36
+ }
37
+ }
38
+
39
+ this.ITPHelper = ITPHelper;
40
+ })(window);
@@ -0,0 +1,8 @@
1
+ (function() {
2
+ document.addEventListener("DOMContentLoaded", function() {
3
+ var redirectTargetElement = document.getElementById("redirection-target");
4
+ var targetInfo = JSON.parse(redirectTargetElement.dataset.target)
5
+ var storageAccessHelper = new StorageAccessHelper(targetInfo);
6
+ storageAccessHelper.execute();
7
+ });
8
+ })();
@@ -0,0 +1,33 @@
1
+ (function() {
2
+ function redirect() {
3
+ var redirectTargetElement = document.getElementById("redirection-target");
4
+
5
+ if (!redirectTargetElement) {
6
+ return;
7
+ }
8
+
9
+ var targetInfo = JSON.parse(redirectTargetElement.dataset.target)
10
+
11
+ if (window.top == window.self) {
12
+ // If the current window is the 'parent', change the URL by setting location.href
13
+ window.top.location.href = targetInfo.url;
14
+ } else {
15
+ // If the current window is the 'child', change the parent's URL with postMessage
16
+ normalizedLink = document.createElement('a');
17
+ normalizedLink.href = targetInfo.url;
18
+
19
+ data = JSON.stringify({
20
+ message: 'Duodealer.API.remoteRedirect',
21
+ data: {location: normalizedLink.href}
22
+ });
23
+ window.parent.postMessage(data, targetInfo.duodealerUrl);
24
+ }
25
+ }
26
+
27
+ document.addEventListener("DOMContentLoaded", redirect);
28
+
29
+ // In the turbolinks context, neither DOMContentLoaded nor turbolinks:load
30
+ // consistently fires. This ensures that we at least attempt to fire in the
31
+ // turbolinks situation as well.
32
+ redirect();
33
+ })();
@@ -0,0 +1,3 @@
1
+ //= require ./itp_helper.js
2
+ //= require ./storage_access.js
3
+ //= require ./storage_access_redirect.js
@@ -0,0 +1,153 @@
1
+ (function() {
2
+ var ACCESS_GRANTED_STATUS = 'storage_access_granted';
3
+ var ACCESS_DENIED_STATUS = 'storage_access_denied';
4
+
5
+ function StorageAccessHelper(redirectData) {
6
+ this.redirectData = redirectData;
7
+ }
8
+
9
+ StorageAccessHelper.prototype.setNormalizedLink = function(storageAccessStatus) {
10
+ return storageAccessStatus === ACCESS_GRANTED_STATUS ? this.redirectData.hasStorageAccessUrl : this.redirectData.doesNotHaveStorageAccessUrl;
11
+ }
12
+
13
+ StorageAccessHelper.prototype.redirectToAppTLD = function(storageAccessStatus) {
14
+ var normalizedLink = document.createElement('a');
15
+
16
+ normalizedLink.href = this.setNormalizedLink(storageAccessStatus);
17
+
18
+ data = JSON.stringify({
19
+ message: 'Duodealer.API.remoteRedirect',
20
+ data: {
21
+ location: normalizedLink.href,
22
+ }
23
+ });
24
+ window.parent.postMessage(data, this.redirectData.duodealerUrl);
25
+ }
26
+
27
+ StorageAccessHelper.prototype.redirectToAppsIndex = function() {
28
+ window.parent.location.href = this.redirectData.duodealerUrl + '/admin/apps';
29
+ }
30
+
31
+ StorageAccessHelper.prototype.redirectToAppTargetUrl = function() {
32
+ window.location.href = this.redirectData.appTargetUrl;
33
+ }
34
+
35
+ StorageAccessHelper.prototype.sameSiteNoneIncompatible = function(ua) {
36
+ return ua.includes("iPhone OS 12_") || ua.includes("iPad; CPU OS 12_") || //iOS 12
37
+ (ua.includes("UCBrowser/")
38
+ ? this.isOlderUcBrowser(ua) //UC Browser < 12.13.2
39
+ : (ua.includes("Chrome/5") || ua.includes("Chrome/6"))) ||
40
+ ua.includes("Chromium/5") || ua.includes("Chromium/6") ||
41
+ (ua.includes(" OS X 10_14_") &&
42
+ ((ua.includes("Version/") && ua.includes("Safari")) || //Safari on MacOS 10.14
43
+ ua.endsWith("(KHTML, like Gecko)"))); //Web view on MacOS 10.14
44
+ }
45
+
46
+ StorageAccessHelper.prototype.isOlderUcBrowser = function(ua) {
47
+ var match = ua.match(/UCBrowser\/(\d+)\.(\d+)\.(\d+)\./);
48
+ if (!match) return false;
49
+ var major = parseInt(match[1]);
50
+ var minor = parseInt(match[2]);
51
+ var build = parseInt(match[3]);
52
+ if (major != 12) return major < 12;
53
+ if (minor != 13) return minor < 13;
54
+ return build < 2;
55
+ }
56
+
57
+ StorageAccessHelper.prototype.setCookie = function(value) {
58
+ if(!this.sameSiteNoneIncompatible(navigator.userAgent)) {
59
+ value += '; secure; SameSite=None'
60
+ }
61
+ document.cookie = value;
62
+ }
63
+
64
+ StorageAccessHelper.prototype.grantedStorageAccess = function() {
65
+ try {
66
+ sessionStorage.setItem('duodealer.granted_storage_access', true);
67
+ this.setCookie('duodealer.granted_storage_access=true');
68
+ if (!document.cookie) {
69
+ throw 'Cannot set third-party cookie.'
70
+ }
71
+ this.redirectToAppTargetUrl();
72
+ } catch (error) {
73
+ console.warn('Third party cookies may be blocked.', error);
74
+ this.redirectToAppTLD(ACCESS_DENIED_STATUS);
75
+ }
76
+ }
77
+
78
+ StorageAccessHelper.prototype.handleRequestStorageAccess = function() {
79
+ return document.requestStorageAccess().then(this.grantedStorageAccess.bind(this), this.redirectToAppsIndex.bind(this, ACCESS_DENIED_STATUS));
80
+ }
81
+
82
+ StorageAccessHelper.prototype.setupRequestStorageAccess = function() {
83
+ var requestContent = document.getElementById('RequestStorageAccess');
84
+ var requestButton = document.getElementById('TriggerAllowCookiesPrompt');
85
+
86
+ requestButton.addEventListener('click', this.handleRequestStorageAccess.bind(this));
87
+ requestContent.style.display = 'block';
88
+ }
89
+
90
+ StorageAccessHelper.prototype.handleHasStorageAccess = function() {
91
+ if (sessionStorage.getItem('duodealer.granted_storage_access')) {
92
+ // If app was classified by ITP and used Storage Access API to acquire access
93
+ this.redirectToAppTargetUrl();
94
+ } else {
95
+ // If app has not been classified by ITP and still has storage access
96
+ this.redirectToAppTLD(ACCESS_GRANTED_STATUS);
97
+ }
98
+ }
99
+
100
+ StorageAccessHelper.prototype.handleGetStorageAccess = function() {
101
+ if (sessionStorage.getItem('duodealer.top_level_interaction')) {
102
+ // If merchant has been redirected to interact with TLD (requirement for prompting request to gain storage access)
103
+ this.setupRequestStorageAccess();
104
+ } else {
105
+ // If merchant has not been redirected to interact with TLD (requirement for prompting request to gain storage access)
106
+ this.redirectToAppTLD(ACCESS_DENIED_STATUS);
107
+ }
108
+ }
109
+
110
+ StorageAccessHelper.prototype.manageStorageAccess = function() {
111
+ return document.hasStorageAccess().then(function(hasAccess) {
112
+ if (hasAccess) {
113
+ this.handleHasStorageAccess();
114
+ } else {
115
+ this.handleGetStorageAccess();
116
+ }
117
+ }.bind(this));
118
+ }
119
+
120
+ StorageAccessHelper.prototype.execute = function() {
121
+ if (ITPHelper.prototype.canPartitionCookies()) {
122
+ this.setUpCookiePartitioning();
123
+ return;
124
+ }
125
+
126
+ if (ITPHelper.prototype.userAgentIsAffected()) {
127
+ this.manageStorageAccess();
128
+ } else {
129
+ this.grantedStorageAccess();
130
+ }
131
+ }
132
+
133
+ /* ITP 2.0 solution: handles cookie partitioning */
134
+ StorageAccessHelper.prototype.setUpHelper = function() {
135
+ return new ITPHelper({redirectUrl: window.shopOrigin + "/admin/apps/" + window.apiKey + window.returnTo});
136
+ }
137
+
138
+ StorageAccessHelper.prototype.setCookieAndRedirect = function() {
139
+ this.setCookie('duodealer.cookies_persist=true');
140
+ var helper = this.setUpHelper();
141
+ helper.redirect();
142
+ }
143
+
144
+ StorageAccessHelper.prototype.setUpCookiePartitioning = function() {
145
+ var itpContent = document.getElementById('CookiePartitionPrompt');
146
+ itpContent.style.display = 'block';
147
+
148
+ var button = document.getElementById('AcceptCookies');
149
+ button.addEventListener('click', this.setCookieAndRedirect.bind(this));
150
+ }
151
+
152
+ this.StorageAccessHelper = StorageAccessHelper;
153
+ })(window);
@@ -0,0 +1,17 @@
1
+ (function() {
2
+ function redirect() {
3
+ var redirectTargetElement = document.getElementById("redirection-target");
4
+
5
+ var targetInfo = JSON.parse(redirectTargetElement.dataset.target)
6
+
7
+ if (window.top == window.self) {
8
+ // If the current window is the 'parent', change the URL by setting location.href
9
+ window.top.location.href = targetInfo.hasStorageAccessUrl;
10
+ } else {
11
+ var storageAccessHelper = new StorageAccessHelper(targetInfo);
12
+ storageAccessHelper.execute();
13
+ }
14
+ }
15
+
16
+ document.addEventListener("DOMContentLoaded", redirect);
17
+ })();
@@ -0,0 +1,2 @@
1
+ //= require ./itp_helper.js
2
+ //= require ./top_level_interaction.js
@@ -0,0 +1,11 @@
1
+ (function() {
2
+ function setUpTopLevelInteraction() {
3
+ var TopLevelInteraction = new ITPHelper({
4
+ redirectUrl: window.redirectUrl,
5
+ });
6
+
7
+ TopLevelInteraction.execute();
8
+ }
9
+
10
+ document.addEventListener("DOMContentLoaded", setUpTopLevelInteraction);
11
+ })();
@@ -0,0 +1,15 @@
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
@@ -0,0 +1,15 @@
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
@@ -0,0 +1,9 @@
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
@@ -0,0 +1,9 @@
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
@@ -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