disco_app 0.14.4 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (429) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -5
  3. data/app/clients/disco_app/api_client.rb +5 -4
  4. data/app/clients/disco_app/graphql_client.rb +85 -0
  5. data/app/controllers/disco_app/admin/app_settings_controller.rb +2 -0
  6. data/app/controllers/disco_app/admin/application_controller.rb +1 -0
  7. data/app/controllers/disco_app/admin/concerns/app_settings_controller.rb +2 -1
  8. data/app/controllers/disco_app/admin/concerns/authenticated_controller.rb +5 -3
  9. data/app/controllers/disco_app/admin/concerns/plans_controller.rb +3 -2
  10. data/app/controllers/disco_app/admin/concerns/shops_controller.rb +1 -0
  11. data/app/controllers/disco_app/admin/concerns/sources_controller.rb +2 -1
  12. data/app/controllers/disco_app/admin/concerns/subscriptions_controller.rb +3 -2
  13. data/app/controllers/disco_app/admin/plans_controller.rb +2 -0
  14. data/app/controllers/disco_app/admin/resources/shops_controller.rb +2 -0
  15. data/app/controllers/disco_app/admin/shops_controller.rb +2 -0
  16. data/app/controllers/disco_app/admin/sources_controller.rb +2 -0
  17. data/app/controllers/disco_app/admin/subscriptions_controller.rb +2 -0
  18. data/app/controllers/disco_app/charges_controller.rb +6 -7
  19. data/app/controllers/disco_app/concerns/app_proxy_controller.rb +6 -6
  20. data/app/controllers/disco_app/concerns/authenticated_controller.rb +24 -25
  21. data/app/controllers/disco_app/concerns/carrier_request_controller.rb +22 -11
  22. data/app/controllers/disco_app/concerns/user_authenticated_controller.rb +1 -0
  23. data/app/controllers/disco_app/concerns/webhooks_controller.rb +49 -0
  24. data/app/controllers/disco_app/flow/actions_controller.rb +9 -0
  25. data/app/controllers/disco_app/flow/concerns/actions_controller.rb +50 -0
  26. data/app/controllers/disco_app/frame_controller.rb +0 -1
  27. data/app/controllers/disco_app/install_controller.rb +3 -6
  28. data/app/controllers/disco_app/subscriptions_controller.rb +12 -4
  29. data/app/controllers/disco_app/user_sessions_controller.rb +1 -0
  30. data/app/controllers/disco_app/webhooks_controller.rb +2 -44
  31. data/app/controllers/sessions_controller.rb +4 -3
  32. data/app/helpers/disco_app/application_helper.rb +7 -7
  33. data/app/jobs/disco_app/app_installed_job.rb +2 -0
  34. data/app/jobs/disco_app/app_uninstalled_job.rb +2 -0
  35. data/app/jobs/disco_app/concerns/app_installed_job.rb +2 -3
  36. data/app/jobs/disco_app/concerns/app_uninstalled_job.rb +2 -1
  37. data/app/jobs/disco_app/concerns/render_asset_group_job.rb +1 -0
  38. data/app/jobs/disco_app/concerns/shop_update_job.rb +9 -2
  39. data/app/jobs/disco_app/concerns/subscription_changed_job.rb +2 -1
  40. data/app/jobs/disco_app/concerns/synchronise_carrier_service_job.rb +8 -7
  41. data/app/jobs/disco_app/concerns/synchronise_resources_job.rb +1 -0
  42. data/app/jobs/disco_app/concerns/synchronise_users_job.rb +6 -3
  43. data/app/jobs/disco_app/concerns/synchronise_webhooks_job.rb +4 -5
  44. data/app/jobs/disco_app/flow/process_action_job.rb +11 -0
  45. data/app/jobs/disco_app/flow/process_trigger_job.rb +11 -0
  46. data/app/jobs/disco_app/render_asset_group_job.rb +2 -0
  47. data/app/jobs/disco_app/shop_job.rb +10 -10
  48. data/app/jobs/disco_app/shop_update_job.rb +2 -0
  49. data/app/jobs/disco_app/subscription_changed_job.rb +2 -0
  50. data/app/jobs/disco_app/synchronise_carrier_service_job.rb +2 -0
  51. data/app/jobs/disco_app/synchronise_resources_job.rb +2 -0
  52. data/app/jobs/disco_app/synchronise_users_job.rb +2 -0
  53. data/app/jobs/disco_app/synchronise_webhooks_job.rb +2 -0
  54. data/app/models/application_record.rb +2 -0
  55. data/app/models/disco_app/app_settings.rb +2 -0
  56. data/app/models/disco_app/application_charge.rb +1 -1
  57. data/app/models/disco_app/concerns/app_settings.rb +2 -0
  58. data/app/models/disco_app/concerns/can_be_liquified.rb +29 -14
  59. data/app/models/disco_app/concerns/has_metafields.rb +1 -2
  60. data/app/models/disco_app/concerns/plan.rb +3 -4
  61. data/app/models/disco_app/concerns/plan_code.rb +1 -2
  62. data/app/models/disco_app/concerns/renders_assets.rb +14 -18
  63. data/app/models/disco_app/concerns/shop.rb +11 -12
  64. data/app/models/disco_app/concerns/source.rb +2 -3
  65. data/app/models/disco_app/concerns/subscription.rb +3 -3
  66. data/app/models/disco_app/concerns/synchronises.rb +10 -15
  67. data/app/models/disco_app/concerns/taggable.rb +1 -0
  68. data/app/models/disco_app/concerns/user.rb +3 -2
  69. data/app/models/disco_app/flow/action.rb +9 -0
  70. data/app/models/disco_app/flow/concerns/action.rb +27 -0
  71. data/app/models/disco_app/flow/concerns/trigger.rb +27 -0
  72. data/app/models/disco_app/flow/trigger.rb +9 -0
  73. data/app/models/disco_app/plan.rb +2 -0
  74. data/app/models/disco_app/plan_code.rb +2 -0
  75. data/app/models/disco_app/session_storage.rb +3 -0
  76. data/app/models/disco_app/shop.rb +2 -0
  77. data/app/models/disco_app/source.rb +2 -0
  78. data/app/models/disco_app/subscription.rb +2 -0
  79. data/app/models/disco_app/user.rb +2 -0
  80. data/app/resources/disco_app/admin/resources/concerns/shop_resource.rb +12 -15
  81. data/app/resources/disco_app/admin/resources/shop_resource.rb +1 -0
  82. data/app/services/disco_app/carrier_request_service.rb +3 -3
  83. data/app/services/disco_app/charges_service.rb +26 -34
  84. data/app/services/disco_app/flow/create_action.rb +35 -0
  85. data/app/services/disco_app/flow/create_trigger.rb +34 -0
  86. data/app/services/disco_app/flow/process_action.rb +50 -0
  87. data/app/services/disco_app/flow/process_trigger.rb +52 -0
  88. data/app/services/disco_app/partner_app_service.rb +1 -1
  89. data/app/services/disco_app/proxy_service.rb +2 -2
  90. data/app/services/disco_app/request_validation_service.rb +2 -2
  91. data/app/services/disco_app/subscription_service.rb +60 -32
  92. data/app/services/disco_app/webhook_service.rb +9 -11
  93. data/config/routes.rb +7 -3
  94. data/db/migrate/20150525000000_create_shops_if_not_existent.rb +80 -80
  95. data/db/migrate/20170315062548_create_disco_app_sources.rb +2 -0
  96. data/db/migrate/20170315062629_add_sources_to_shop_subscriptions.rb +3 -1
  97. data/db/migrate/20170327214540_create_disco_app_users.rb +2 -1
  98. data/db/migrate/20170606160751_fix_disco_app_users_index.rb +2 -0
  99. data/db/migrate/20181229100327_create_flow_actions_and_triggers.rb +32 -0
  100. data/lib/disco_app/configuration.rb +9 -5
  101. data/lib/disco_app/constants.rb +4 -2
  102. data/lib/disco_app/engine.rb +1 -1
  103. data/lib/disco_app/session.rb +1 -0
  104. data/lib/disco_app/support/file_fixtures.rb +2 -1
  105. data/lib/disco_app/version.rb +3 -1
  106. data/lib/generators/disco_app/install/USAGE +5 -0
  107. data/lib/generators/disco_app/install/install_generator.rb +287 -0
  108. data/lib/generators/disco_app/{templates → install/templates}/assets/javascripts/application.js +0 -0
  109. data/lib/generators/disco_app/{templates → install/templates}/assets/javascripts/components.js +0 -0
  110. data/lib/generators/disco_app/{templates → install/templates}/assets/stylesheets/application.scss +0 -0
  111. data/lib/generators/disco_app/install/templates/config/appsignal.yml +12 -0
  112. data/lib/generators/disco_app/install/templates/config/cable.yml.tt +11 -0
  113. data/lib/generators/disco_app/{templates → install/templates}/config/database.yml.tt +6 -3
  114. data/lib/generators/disco_app/install/templates/config/environments/staging.rb +108 -0
  115. data/lib/generators/disco_app/{templates → install/templates}/config/puma.rb +0 -0
  116. data/lib/generators/disco_app/{templates → install/templates}/controllers/home_controller.rb +1 -0
  117. data/lib/generators/disco_app/{templates → install/templates}/initializers/disco_app.rb +0 -0
  118. data/lib/generators/disco_app/install/templates/initializers/session_store.rb +2 -0
  119. data/lib/generators/disco_app/{templates → install/templates}/initializers/shopify_app.rb +0 -0
  120. data/lib/generators/disco_app/{templates → install/templates}/initializers/shopify_session_repository.rb +0 -0
  121. data/lib/generators/disco_app/install/templates/initializers/timber.rb +6 -0
  122. data/lib/generators/disco_app/{templates → install/templates}/root/.editorconfig +0 -0
  123. data/lib/generators/disco_app/{templates → install/templates}/root/.env +3 -0
  124. data/lib/generators/disco_app/{templates → install/templates}/root/.env.local +3 -0
  125. data/lib/generators/disco_app/install/templates/root/.github/PULL_REQUEST_TEMPLATE.md +18 -0
  126. data/lib/generators/disco_app/{templates → install/templates}/root/.gitignore +10 -0
  127. data/lib/generators/disco_app/install/templates/root/.rspec +1 -0
  128. data/lib/generators/disco_app/{templates → install/templates}/root/.rubocop.yml +263 -170
  129. data/lib/generators/disco_app/{templates → install/templates}/root/.ruby-version +0 -0
  130. data/lib/generators/disco_app/{templates → install/templates}/root/CHECKS +0 -0
  131. data/lib/generators/disco_app/{templates → install/templates}/root/Procfile +0 -0
  132. data/lib/generators/disco_app/{templates → install/templates}/root/README.md +0 -0
  133. data/lib/generators/disco_app/install/templates/spec/rails_helper.rb +40 -0
  134. data/lib/generators/disco_app/install/templates/spec/spec_helper.rb +24 -0
  135. data/lib/generators/disco_app/install/templates/spec/support/active_job.rb +13 -0
  136. data/lib/generators/disco_app/install/templates/spec/support/coveralls.rb +3 -0
  137. data/lib/generators/disco_app/install/templates/spec/support/database_cleaner.rb +17 -0
  138. data/lib/generators/disco_app/install/templates/spec/support/factory_bot.rb +3 -0
  139. data/lib/generators/disco_app/install/templates/spec/support/helpers/json_helper.rb +13 -0
  140. data/lib/generators/disco_app/install/templates/spec/support/shared_examples/a_synchronise_job.rb +12 -0
  141. data/lib/generators/disco_app/install/templates/spec/support/shoulda.rb +6 -0
  142. data/lib/generators/disco_app/install/templates/spec/support/vcr.rb +14 -0
  143. data/lib/generators/disco_app/install/templates/spec/support/webmock.rb +8 -0
  144. data/lib/generators/disco_app/{templates → install/templates}/views/home/index.html.erb +0 -0
  145. data/lib/generators/disco_app/react/USAGE +5 -0
  146. data/lib/generators/disco_app/react/react_generator.rb +108 -0
  147. data/lib/generators/disco_app/react/templates/app/controllers/embedded/api/base_controller.rb +18 -0
  148. data/lib/generators/disco_app/react/templates/app/controllers/embedded/api/home_controller.rb +10 -0
  149. data/lib/generators/disco_app/react/templates/app/controllers/embedded/api/shops_controller.rb +11 -0
  150. data/lib/generators/disco_app/react/templates/app/controllers/embedded/api/users_controller.rb +11 -0
  151. data/lib/generators/disco_app/react/templates/app/controllers/embedded/home_controller.rb +13 -0
  152. data/lib/generators/disco_app/react/templates/app/models/api_response.rb +107 -0
  153. data/lib/generators/disco_app/react/templates/app/serializers/disco_app/shop_serializer.rb +13 -0
  154. data/lib/generators/disco_app/react/templates/app/serializers/disco_app/user_serializer.rb +13 -0
  155. data/lib/generators/disco_app/react/templates/app/serializers/empty_serializer.rb +5 -0
  156. data/lib/generators/disco_app/react/templates/app/serializers/error_serializer.rb +76 -0
  157. data/lib/generators/disco_app/react/templates/app/views/embedded/home/index.html.erb +12 -0
  158. data/lib/generators/disco_app/react/templates/app/views/layouts/embedded.html.erb +10 -0
  159. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/App.jsx +77 -0
  160. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/HomePage.jsx +34 -0
  161. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/Shared/EmbeddedPage.jsx +70 -0
  162. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/Shared/ErrorBanner.jsx +58 -0
  163. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/Shared/PaginationWrapper.jsx +10 -0
  164. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/Shared/ScrollToTop.jsx +23 -0
  165. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/withApi.jsx +125 -0
  166. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/index.jsx +39 -0
  167. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/utils.js +19 -0
  168. data/lib/generators/disco_app/react/templates/app/webpack/packs/embedded.js +2 -0
  169. data/lib/generators/disco_app/react/templates/app/webpack/stylesheets/embedded/shared/banners.scss +7 -0
  170. data/lib/generators/disco_app/react/templates/app/webpack/stylesheets/embedded/shared/busy.scss +3 -0
  171. data/lib/generators/disco_app/react/templates/app/webpack/stylesheets/embedded/shared/index.scss +3 -0
  172. data/lib/generators/disco_app/react/templates/app/webpack/stylesheets/embedded/shared/pagination.scss +5 -0
  173. data/lib/generators/disco_app/react/templates/app/webpack/stylesheets/embedded.scss +2 -0
  174. data/lib/generators/disco_app/react/templates/config/initializers/mime_types.rb +13 -0
  175. data/lib/generators/disco_app/react/templates/config/initializers/omniauth.rb +27 -0
  176. data/lib/generators/disco_app/react/templates/config/initializers/version.rb.tt +7 -0
  177. data/lib/generators/disco_app/react/templates/config/webpack/staging.js +5 -0
  178. data/lib/generators/disco_app/react/templates/config/webpack/test.js +5 -0
  179. data/lib/generators/disco_app/react/templates/config/webpacker.yml +96 -0
  180. data/lib/generators/disco_app/react/templates/root/.eslintignore +5 -0
  181. data/lib/generators/disco_app/react/templates/root/.eslintrc +69 -0
  182. data/lib/generators/disco_app/react/templates/root/.prettierrc +3 -0
  183. data/lib/generators/disco_app/react/templates/root/VERSION +1 -0
  184. data/lib/generators/disco_app/react/templates/root/babel.config.js +72 -0
  185. data/lib/generators/disco_app/react/templates/root/package.json.tt +84 -0
  186. data/lib/generators/disco_app/react/templates/root/postcss.config.js +14 -0
  187. data/lib/tasks/api.rake +0 -2
  188. data/lib/tasks/carrier_service.rake +0 -2
  189. data/lib/tasks/database.rake +1 -1
  190. data/lib/tasks/sessions.rake +0 -2
  191. data/lib/tasks/shops.rake +0 -2
  192. data/lib/tasks/users.rake +0 -2
  193. data/lib/tasks/webhooks.rake +0 -2
  194. data/test/clients/disco_app/api_client_test.rb +3 -3
  195. data/test/controllers/disco_app/admin/shops_controller_test.rb +1 -0
  196. data/test/controllers/disco_app/charges_controller_test.rb +7 -8
  197. data/test/controllers/disco_app/install_controller_test.rb +2 -1
  198. data/test/controllers/disco_app/subscriptions_controller_test.rb +1 -0
  199. data/test/controllers/disco_app/webhooks_controller_test.rb +1 -0
  200. data/test/controllers/home_controller_test.rb +1 -1
  201. data/test/disco_app_test.rb +3 -1
  202. data/test/dummy/Rakefile +1 -1
  203. data/test/dummy/app/controllers/application_controller.rb +2 -0
  204. data/test/dummy/app/controllers/carrier_request_controller.rb +1 -0
  205. data/test/dummy/app/controllers/disco_app/admin/shops_controller.rb +1 -0
  206. data/test/dummy/app/controllers/home_controller.rb +1 -0
  207. data/test/dummy/app/controllers/proxy_controller.rb +1 -0
  208. data/test/dummy/app/jobs/disco_app/app_installed_job.rb +2 -3
  209. data/test/dummy/app/jobs/disco_app/app_uninstalled_job.rb +1 -0
  210. data/test/dummy/app/models/application_record.rb +2 -0
  211. data/test/dummy/app/models/cart.rb +4 -3
  212. data/test/dummy/app/models/disco_app/shop.rb +4 -5
  213. data/test/dummy/app/models/js_configuration.rb +1 -0
  214. data/test/dummy/app/models/product.rb +3 -2
  215. data/test/dummy/app/models/widget_configuration.rb +1 -0
  216. data/test/dummy/bin/bundle +1 -1
  217. data/test/dummy/bin/rails +1 -1
  218. data/test/dummy/bin/setup +8 -8
  219. data/test/dummy/config/application.rb +4 -3
  220. data/test/dummy/config/boot.rb +2 -2
  221. data/test/dummy/config/database.yml +3 -0
  222. data/test/dummy/config/environment.rb +1 -1
  223. data/test/dummy/config/environments/staging.rb +85 -0
  224. data/test/dummy/config/initializers/disco_app.rb +1 -1
  225. data/test/dummy/config/initializers/omniauth.rb +3 -4
  226. data/test/dummy/config/initializers/session_store.rb +1 -1
  227. data/test/dummy/config/routes.rb +0 -2
  228. data/test/dummy/config/secrets.yml +3 -0
  229. data/test/dummy/db/migrate/20160307182229_create_products.rb +3 -1
  230. data/test/dummy/db/migrate/20160530160739_create_asset_models.rb +3 -1
  231. data/test/dummy/db/migrate/20161105054746_create_carts.rb +2 -1
  232. data/test/dummy/db/schema.rb +179 -152
  233. data/test/dummy/log/development.log +123 -0
  234. data/test/dummy/log/test.log +22884 -0
  235. data/test/dummy/tmp/cache/assets/sprockets/v3.0/-p/-p4kkBudGSkrc-Hs2yVEjJfJGuf9E8MY-5Huo4W9iZ0.cache +3 -0
  236. data/test/dummy/tmp/cache/assets/sprockets/v3.0/02/02ODr719GA9zZyrA_CgJwh5Vg-Pq_dHkMMbUvRIygtA.cache +3 -0
  237. data/test/dummy/tmp/cache/assets/sprockets/v3.0/0y/0yiARCmpEBX_JoExohBEcHFx0vv-nWUcjHbxtQbEA3w.cache +1 -0
  238. data/test/dummy/tmp/cache/assets/sprockets/v3.0/12/12KLSO9fSADQ-vGWrYiIRQqP1yFoPcxxZfCvm6paqnE.cache +1 -0
  239. data/test/dummy/tmp/cache/assets/sprockets/v3.0/1h/1ho8ca9C4lfKF780RN8l2MHAActK0WYWa_5I_LQO_ag.cache +1 -0
  240. data/test/dummy/tmp/cache/assets/sprockets/v3.0/2E/2E5jz5DyydbByixysW06PLr06e_FQdg9TtbY_LxsRo8.cache +0 -0
  241. data/test/dummy/tmp/cache/assets/sprockets/v3.0/2J/2JdcXeYI4Ed1DoLpSzLbKAvxbzMjrdwRoNICGVN45dU.cache +0 -0
  242. data/test/dummy/tmp/cache/assets/sprockets/v3.0/2X/2X74oB94L9QPqDYRPZkVEcbdsec1wp6qB_y7h3qwYp4.cache +1 -0
  243. data/test/dummy/tmp/cache/assets/sprockets/v3.0/32/32y6lFrrvtuqVj8A3uafoeX0iA_l4YhD5PJS1JvQIfk.cache +0 -0
  244. data/test/dummy/tmp/cache/assets/sprockets/v3.0/35/35LlNk3lHMnnozK9qRT4mpTbnAtOnjBpfHIybikbcfo.cache +0 -0
  245. data/test/dummy/tmp/cache/assets/sprockets/v3.0/3X/3Xl5kEo1hpRF6kHX2lvLp2kUaNDYGuAkylPqJsOLKXQ.cache +0 -0
  246. data/test/dummy/tmp/cache/assets/sprockets/v3.0/4H/4HXBYKkHtI3ZmDZncAS7pdUwtVhzmwt8XWQMGH1R5xo.cache +0 -0
  247. data/test/dummy/tmp/cache/assets/sprockets/v3.0/4H/4hR2zE1hAnLGpPIQS2v71qG-jmiWb2SHAbGiQjxijck.cache +1 -0
  248. data/test/dummy/tmp/cache/assets/sprockets/v3.0/4O/4OJh4kuEsZJ7ok8p5Wd0wui5pwAE46AFCurNgp2gSmk.cache +1 -0
  249. data/test/dummy/tmp/cache/assets/sprockets/v3.0/4Q/4Qe1126dQRjtMngpBX8SwgKoZu8tQFMDj6XxRU8h4TM.cache +1 -0
  250. data/test/dummy/tmp/cache/assets/sprockets/v3.0/4a/4aPQ7FUdl3IqfTnkIvvU_TbAQVz9rEuUbGQk4YMlFHc.cache +4 -0
  251. data/test/dummy/tmp/cache/assets/sprockets/v3.0/4t/4t0ZbDDyABeGi5MqrX0f4_dHY4BEtHc_zGRi1rkQRog.cache +3 -0
  252. data/test/dummy/tmp/cache/assets/sprockets/v3.0/5e/5efYNzR4038HZsit1p-T65aXkUBH4ZVleUZb9hEvXIw.cache +1 -0
  253. data/test/dummy/tmp/cache/assets/sprockets/v3.0/5f/5fTS4gj7gRDTvcAIYd46ZVrIJqJxQXrLVHhxzWoSJnw.cache +0 -0
  254. data/test/dummy/tmp/cache/assets/sprockets/v3.0/6B/6B5j5ojbS7-L49BW-pNvcpI-SvSgiwvMtK7cKz9UnVE.cache +1 -0
  255. data/test/dummy/tmp/cache/assets/sprockets/v3.0/87/87o1fQc0-Zza8i-HNr9IqA4HYu8ePoAOkIJKIKf8Z6c.cache +0 -0
  256. data/test/dummy/tmp/cache/assets/sprockets/v3.0/8G/8Gp6gCGqi_pI4TmiSRkdhdWznz8tSvZmez3YdyJLNDk.cache +1 -0
  257. data/test/dummy/tmp/cache/assets/sprockets/v3.0/8Z/8Z6fieaymg-zBK1iKgH2xBNnbfeA8Or1VfihnmwZfDc.cache +1 -0
  258. data/test/dummy/tmp/cache/assets/sprockets/v3.0/95/95puf81N4E8lDxbeI9yL09DueyWMUjfsUJ9IAP5jOOM.cache +1 -0
  259. data/test/dummy/tmp/cache/assets/sprockets/v3.0/9E/9E3lx2-LKkXgLWP5jG38B5uCsGiSeWq2po03Die5KF4.cache +3 -0
  260. data/test/dummy/tmp/cache/assets/sprockets/v3.0/9m/9m2H02fp4A1UDiXojyy9sl9NgiiNhAbWFL99jKLSUXQ.cache +1 -0
  261. data/test/dummy/tmp/cache/assets/sprockets/v3.0/A-/A-NmGmyyn0mjkLyKGGU0KRIZalJ2fZNyOkgZt5e910I.cache +3 -0
  262. data/test/dummy/tmp/cache/assets/sprockets/v3.0/AF/AFq71LdWk8T3oJ3clzVzZV--uw0vgLDhG7eMv-RzXWQ.cache +0 -0
  263. data/test/dummy/tmp/cache/assets/sprockets/v3.0/AV/AVaNyVl3EijOrYMZaI7oNgwVbsBIxZHrTKLar1ze83A.cache +0 -0
  264. data/test/dummy/tmp/cache/assets/sprockets/v3.0/B-/B-Qo2b4ZsaxV28WasrCQxMuvqER0D7WhzdE4ydvu6bs.cache +1 -0
  265. data/test/dummy/tmp/cache/assets/sprockets/v3.0/BC/BCGc2X3UiMM53c7SecA7o8rP8PnnWI-msrib8ngDCzU.cache +1 -0
  266. data/test/dummy/tmp/cache/assets/sprockets/v3.0/B_/B_Zzsw0s5HhMI_CS94zPqXl1CdI5oR2CksO7cRDTQKk.cache +0 -0
  267. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Bk/BkOwynwXRQOTj1eL9WyhTbRj-UqFPIrWaIpShoHs9Ck.cache +1 -0
  268. data/test/dummy/tmp/cache/assets/sprockets/v3.0/CP/CPGMneZZYKfNQIQfykCtq6C_kPvs-Q_5IT7-62sQig8.cache +0 -0
  269. data/test/dummy/tmp/cache/assets/sprockets/v3.0/D4/D4FYk677edDaB59dMMpaLK_laiH2ExaAoNfQ3tckUe0.cache +0 -0
  270. data/test/dummy/tmp/cache/assets/sprockets/v3.0/D9/D9O72M_cglvDAMJDjtzio3B6-aC_mmcbI4mLvvKnBX8.cache +1 -0
  271. data/test/dummy/tmp/cache/assets/sprockets/v3.0/DM/DMgq30X20--UWPvaAZ5Cf4oEvG4tBBHF4gLe5mnePRI.cache +1 -0
  272. data/test/dummy/tmp/cache/assets/sprockets/v3.0/E0/E03lez839JRYKgxWxjIrCnVdXJ26UoZDCSHUmR4ojdc.cache +0 -0
  273. data/test/dummy/tmp/cache/assets/sprockets/v3.0/E4/E4Pb3S8O5ZHVIkRSm6c-VFO-17tIFqQzHVloIC9yVQQ.cache +2 -0
  274. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Ep/Eph4FRIXVEgT6ofe0aGn6s-8A-Q0jsyxstY422Btwgk.cache +0 -0
  275. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Eq/Eq6J05FaAYDioPfJRie-I5fIzVt8N8Cc9fFrum3R0kU.cache +2 -0
  276. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Ev/EvGs2l1aBK0RXGSw8osKl01fEOHn6RuiWkR55TIZADE.cache +0 -0
  277. data/test/dummy/tmp/cache/assets/sprockets/v3.0/F3/F3sM5VHZOb3PYnt59S-zBWfWtU_HMpihPI61bBdqtPo.cache +0 -0
  278. data/test/dummy/tmp/cache/assets/sprockets/v3.0/FV/FVpKiOBNCAznp4Ya_eMnQ38K-xO3tK46uPBg-mFB4v4.cache +0 -0
  279. data/test/dummy/tmp/cache/assets/sprockets/v3.0/G5/G5aZsL6LP4HC_Of4i2yYsPaOm8dEOLIXkYdZ6tfuYH4.cache +1 -0
  280. data/test/dummy/tmp/cache/assets/sprockets/v3.0/GP/GPc2gCWO8la32JX3fK1ArDYv3QM63WVQ4S0iwpyJinA.cache +1 -0
  281. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Hg/Hgo9RBfSwY8h8vBNKW38aTRYrA2POVwE2v0ZUs4H4iY.cache +1 -0
  282. data/test/dummy/tmp/cache/assets/sprockets/v3.0/I2/I2iRIXHbnG_vgyhptOqXgQHRe8AIPfa34zmkDL06ibY.cache +2 -0
  283. data/test/dummy/tmp/cache/assets/sprockets/v3.0/IT/ITu-bZPOSBI44uFwzG-2bXQvYQvlsjFhIzQtA6FjpzI.cache +0 -0
  284. data/test/dummy/tmp/cache/assets/sprockets/v3.0/IU/IUU7_XlyzslBC48YPBBx35oNruWg9vN906B_uV4GiDg.cache +0 -0
  285. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Jt/JtSpiYSuQ7CjfmgQNb7_FLI2Bls3o7yLZf-2Yn3Tp2U.cache +1 -0
  286. data/test/dummy/tmp/cache/assets/sprockets/v3.0/KA/KA1WZHj-tCh9wJTjQ82C6RW2abPAHfPbczUvt3U0tBA.cache +1 -0
  287. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Kr/KrbYQRjOQilz5PwngxqljeBbo7gnho2oNCzt9xeostM.cache +2 -0
  288. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Kv/KvrosnOxWBhs2jdBY359Jd_PuPgvRxTEhknjpLZI2J4.cache +1 -0
  289. data/test/dummy/tmp/cache/assets/sprockets/v3.0/LB/LBKCbI8U7auhpX6SCBMuQUyESeMLr90SUzMlnB2u9K0.cache +0 -0
  290. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Lx/LxvZGzkKI0YLuIZB1jBioj31ElpU3JOmhzZrQIqu6f4.cache +2 -0
  291. data/test/dummy/tmp/cache/assets/sprockets/v3.0/MA/MAY9X_jK8UHgcT3acJjAPNRR1io9S2E5KXFZjk9BVoc.cache +0 -0
  292. data/test/dummy/tmp/cache/assets/sprockets/v3.0/MA/MAjMl63wcw2lt9F7Fu0Aml-DdcReV0Op4kCwLLkgZzE.cache +1 -0
  293. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Mb/MbUcsjDehlhHnLqP_sU8IKStNYDZEz09Ga5gk4psMZU.cache +1 -0
  294. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Mf/Mfdr1mda4l8eqbsSlL2hylksXaiTeYfwU-fq4ko_F_s.cache +1 -0
  295. data/test/dummy/tmp/cache/assets/sprockets/v3.0/ND/NDwUm11hTOtktv5tkuUYsrSYAA911qwhO2acqloyxas.cache +0 -0
  296. data/test/dummy/tmp/cache/assets/sprockets/v3.0/ND/ndYRNd1Jv1ESobiH7xjHCJXHooPNdUPSxG8OUoCVi40.cache +1 -0
  297. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Nu/NuS-wdnyjTJSg7hUaprtYh_3hQyvNGTTaRSmK0tUNiU.cache +3 -0
  298. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Nz/NzUGztrNqSgb4WfJOviqI6mjmx1g1L9T6V7BdOgZs3A.cache +0 -0
  299. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Oo/Oox1vL8lRd_YME1JHrD8fTh4Osz1njTWieFpIZ0_G2Y.cache +1 -0
  300. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Pj/PjFSX3ELsmK13-CVKc39OnguIcUMb4EbMV6s0lspCps.cache +1 -0
  301. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Qa/Qa6iUyiZsHRjXGz39RPFnBoVYB2YNZJRlihJjDXm1Bk.cache +0 -0
  302. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Qa/qA0PpX9EMQtQoiP0QbK5bYMUX9OkK1OKTIKwGLtqEMw.cache +0 -0
  303. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Qv/Qvrsp8Of-JGCe25QvfmdH--wQL5vGbLtKiKb921jFq4.cache +1 -0
  304. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Qx/QxOtw5pSMh_dcbeU_FmhURV2lEsclOCcFfNrk2EoSRA.cache +0 -0
  305. data/test/dummy/tmp/cache/assets/sprockets/v3.0/RB/RBgpR6mjFySj9-G4E_qadgKjQbF7G_pAA6D_iRDUk1k.cache +0 -0
  306. data/test/dummy/tmp/cache/assets/sprockets/v3.0/RY/RYr7AxgrTd-Qg2KQa84E8ph9qmA7YFrdrVHMRxMxh_w.cache +0 -0
  307. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Re/ReX-_166hRZykFAwmvCQ19NZEbV6Wa82TEZyyIJna4I.cache +3 -0
  308. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Rk/Rk2lt4VSCTBJ_5w3zwlezlAymCnCIrj-u4hkGrphzDM.cache +1 -0
  309. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Rl/RlgTK-oa7AfiImaIV0ABJ7Gfbg0PdFMeQitXJ-wgKA4.cache +1 -0
  310. data/test/dummy/tmp/cache/assets/sprockets/v3.0/SG/SGGTeEpmk20e5GZV4hcfdbmHMbsQgC8C1VhYlrrQ66M.cache +0 -0
  311. data/test/dummy/tmp/cache/assets/sprockets/v3.0/SK/SKaaVqp6uc_kLTIG2y22QaCGc6g3O4GhL8G4LwJJB8s.cache +1 -0
  312. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Sw/SwRQFgc8QgHfYpyQ7yxe3tPOoP2VJ4Gg6hNH1-fS7LQ.cache +0 -0
  313. data/test/dummy/tmp/cache/assets/sprockets/v3.0/TF/TFzMURDWcxBdkePR_mAtaTIrdc4vWlLJuL48b_xiOxQ.cache +0 -0
  314. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Ul/Ulgt7E1quzZA4FaG37lmxJCoTzG74eHZg-dpjniHHYw.cache +0 -0
  315. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Vr/Vr3hv8nrf3Q9kTPp7bZK9GzGVXU77Yrd_iW4QjMda08.cache +0 -0
  316. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Wg/WgJ8nC_59fjWlE7iFIGPD94i3QCNLt1kR9gcAFkou_4.cache +1 -0
  317. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Wi/WiufxFw0JHFbFUn_8t_eC06A3pMN-vHT-Bs-bxXLsJk.cache +1 -0
  318. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Wx/WxK5JQ5Syi4DSTgcxH3k0-PfF_g7eeb7qW1z5EEqEkY.cache +1 -0
  319. data/test/dummy/tmp/cache/assets/sprockets/v3.0/XB/XBj30cQH2Bw6KE9wpF6ylqczHNtz1rvailJi85_aXFY.cache +0 -0
  320. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Xf/XfRpHm7iz1vW_wpIEZRO4i4dFQLBLzmdP3UPg1tcf-E.cache +0 -0
  321. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Xt/Xtcw2vyNc82l8ChsSieO0h0kbELj9P2Tw9TxjmttoEw.cache +1 -0
  322. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Y0/Y0IFckg4LNe1fBvLBTvZct2gfX_g_1MpAMoTBU8qfLg.cache +0 -0
  323. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Y0/y0SkzhEQe_b3MQq69A2KH5LjHUB7vPYj6wp4neZzf6Q.cache +1 -0
  324. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Y4/Y4jdKVp7dOOcuMaUutQ1s4NmmLXq47L1LWhyXZXEaLg.cache +3 -0
  325. data/test/dummy/tmp/cache/assets/sprockets/v3.0/YE/YEjjWfxdNXU6i_3BklG7anaVrOdu-5jksfoL9GufaGU.cache +0 -0
  326. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Yi/YitmSGSMIDji4aC0llOHl0AS6taxqjRk6e_SYw-V1Is.cache +1 -0
  327. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Zb/Zbler-n-7XzOneefutPvH2Cu1UsS967fqjldXwVuStU.cache +0 -0
  328. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Zs/Zs5ig01Gu3Y1thnsToaKQbOIFKAQPCQm0HEEec_vblE.cache +1 -0
  329. data/test/dummy/tmp/cache/assets/sprockets/v3.0/_C/_C10TQWkrfsm41Aaav86lCOkEcLdO7fX8yojbphLRbE.cache +1 -0
  330. data/test/dummy/tmp/cache/assets/sprockets/v3.0/_G/_GCN7qhLkwrwMKEGcBZ9ITsu0QC1l9HD9XaViXBlNQM.cache +0 -0
  331. data/test/dummy/tmp/cache/assets/sprockets/v3.0/_H/_HRU4CZPSyJ4PEUvsGMJSiIVZqSkNIvU3PoQGUB4l2I.cache +3 -0
  332. data/test/dummy/tmp/cache/assets/sprockets/v3.0/_T/_TQROPFCUq0STw2BzbGITspAWA8dF_WvVa7aR02nXAE.cache +2 -0
  333. data/test/dummy/tmp/cache/assets/sprockets/v3.0/_d/_dgNuvKh1O-ss5yC3qg8KPo3anB_pzCXJw3sphxrAFI.cache +0 -0
  334. data/test/dummy/tmp/cache/assets/sprockets/v3.0/_p/_pqVJRc7OZRexEiqcsNQKd5ip8aNkUW9mKQc6OpAp8I.cache +0 -0
  335. data/test/dummy/tmp/cache/assets/sprockets/v3.0/a1/a1P7jCwGayzCGMYDX1CYCSvT7-pi0eiRewg9KbC-6mI.cache +2 -0
  336. data/test/dummy/tmp/cache/assets/sprockets/v3.0/ao/aoPwSmt5N3P9MyBoWUSbkg8F3_b0jhvKuZ6GlBbwRw0.cache +1 -0
  337. data/test/dummy/tmp/cache/assets/sprockets/v3.0/au/au5wohs0fb0VW1crV3GXkqZs18247x-hRKniPTdRqRM.cache +3 -0
  338. data/test/dummy/tmp/cache/assets/sprockets/v3.0/bW/bWiegRudr21oJdzrS11Fu6RMJ9hjYELHp5F94RA6zRI.cache +1 -0
  339. data/test/dummy/tmp/cache/assets/sprockets/v3.0/c1/c1tUtq98JfLhITxPjfdj6g0Ys9pCpneLHq6wBa9v4co.cache +1 -0
  340. data/test/dummy/tmp/cache/assets/sprockets/v3.0/cC/cCneJUl-S3YnUyRCXIUSQxORgSrNf3K24tBhWxLceo4.cache +0 -0
  341. data/test/dummy/tmp/cache/assets/sprockets/v3.0/cK/cK54mTNBuCdAdDEaSzhZ43uo00XDN8FDTMcsViGpmUc.cache +0 -0
  342. data/test/dummy/tmp/cache/assets/sprockets/v3.0/cy/cydtDFqB_RwfVSEq7ACddUz8us2dp3h4WtZnAJTukfU.cache +0 -0
  343. data/test/dummy/tmp/cache/assets/sprockets/v3.0/dY/dYKoKcEw2XuaSJKsyIixsGilwIzRPtXACDh0e-w3PAM.cache +1 -0
  344. data/test/dummy/tmp/cache/assets/sprockets/v3.0/eY/eYr7xslMqmPqzIH5i1RCZ-XnPoU9owIbQ-hnrsR9SFk.cache +1 -0
  345. data/test/dummy/tmp/cache/assets/sprockets/v3.0/ec/ecxUdWV-k6NvipoXNVXRmH32mnDSwr-ZeNVGhBlpYQQ.cache +0 -0
  346. data/test/dummy/tmp/cache/assets/sprockets/v3.0/ej/ejTWaTrHa-76kUnlqc-EfP1NfTPMyHyqS00NMupK9WQ.cache +0 -0
  347. data/test/dummy/tmp/cache/assets/sprockets/v3.0/f7/f7tLgf7D2qMZcsHSt8R97kFvH30wBYGkeLz9-8U6uhc.cache +1 -0
  348. data/test/dummy/tmp/cache/assets/sprockets/v3.0/fX/fXmxRq4KBzpEegCEzFlkLnWGxPMakZmprlIYMFbQJ1E.cache +0 -0
  349. data/test/dummy/tmp/cache/assets/sprockets/v3.0/g7/g7UL8J5-FXcqK8YQM_ghdj_iEx4xnApvwAaWbgBV0TY.cache +1 -0
  350. data/test/dummy/tmp/cache/assets/sprockets/v3.0/gV/gVz5L3gA5w0S8o3yZpVZF-mP-TreyN5iepl1RRZ-R-E.cache +0 -0
  351. data/test/dummy/tmp/cache/assets/sprockets/v3.0/hI/hIpGOQMTq1d2_3DlNrPG4Q7MfO1WPpkjtd7RFyBWu3A.cache +1 -0
  352. data/test/dummy/tmp/cache/assets/sprockets/v3.0/hI/hiDKOMo7TGsMf1DyunEb03ce439H742gxAM3mgi6Ihg.cache +0 -0
  353. data/test/dummy/tmp/cache/assets/sprockets/v3.0/iG/iGaY16bCJiW0AwP1GzM9Uwad-mZCe1Q937irWUgiI9c.cache +0 -0
  354. data/test/dummy/tmp/cache/assets/sprockets/v3.0/iy/iyzEFHfDRV_piHvWtrdYZuaKMqScr_j4oPKDNHfsDjU.cache +1 -0
  355. data/test/dummy/tmp/cache/assets/sprockets/v3.0/kn/knb5R_X55aCiFz3vJWuSUSQPM4CHSNnp0iae5UMECcw.cache +1 -0
  356. data/test/dummy/tmp/cache/assets/sprockets/v3.0/lJ/lJBk3thZoWRjF0s__eDJF7w6qLdkFpA4eAbwgxH_Dho.cache +1 -0
  357. data/test/dummy/tmp/cache/assets/sprockets/v3.0/lY/lYQpdxF4JQIu4RN2ECazZRXa2r04cIJxhUIa05qojZE.cache +3 -0
  358. data/test/dummy/tmp/cache/assets/sprockets/v3.0/m4/m4QRh4VcQWkjLezj3he7eCiAI-NzVhXPeLzAAcIlYxU.cache +3 -0
  359. data/test/dummy/tmp/cache/assets/sprockets/v3.0/mH/mHZUE9U2nO5Wpi1_6ZOvKorTK0DB1XAgAy8vCzKwPUE.cache +3 -0
  360. data/test/dummy/tmp/cache/assets/sprockets/v3.0/mM/mMFR0RXDB_d00Q-DWF3raKUOK_pKIoLKWe8sbByIbmA.cache +2 -0
  361. data/test/dummy/tmp/cache/assets/sprockets/v3.0/mj/mjHlIUoMbdf3_s3E3yHmx6cD3XBpNw44VkLuszduuQU.cache +2 -0
  362. data/test/dummy/tmp/cache/assets/sprockets/v3.0/mj/mjVM7LYY8IA7tuNN3xA7teC_8er8vfGYt2yIlZtm9ss.cache +1 -0
  363. data/test/dummy/tmp/cache/assets/sprockets/v3.0/my/myTGA5_heGVdkdReWuRE40AphRvs-JEHfS14DVL5pIk.cache +1 -0
  364. data/test/dummy/tmp/cache/assets/sprockets/v3.0/nb/nbBwrQkAIneOVTkIGBCdsMtZIT4043SIOR6sXJP_LHU.cache +0 -0
  365. data/test/dummy/tmp/cache/assets/sprockets/v3.0/nq/nqJAnHctHKNe0jSpv19MqPf8BB_w495YOe2rzF_ehos.cache +1 -0
  366. data/test/dummy/tmp/cache/assets/sprockets/v3.0/nq/nqj0Mk3m_97LBVDR7MZgIC80X4_mAeL6ZwDdqgtI1Gw.cache +0 -0
  367. data/test/dummy/tmp/cache/assets/sprockets/v3.0/od/odSXqZl0ZH48zGt8AMIRhQkDU-YtstjobbS5e7ZkN3k.cache +0 -0
  368. data/test/dummy/tmp/cache/assets/sprockets/v3.0/pO/pOygnjQeOv1F__tZVlOBgQIns_FPOY0Hg8jD24Q1MzQ.cache +0 -0
  369. data/test/dummy/tmp/cache/assets/sprockets/v3.0/pZ/pZ0SU1EHDUQqCK7f8encuHCG6TMsPQBoRaMFxy5vqfo.cache +1 -0
  370. data/test/dummy/tmp/cache/assets/sprockets/v3.0/pp/ppVvwCOmFUDtfjoiXcUyRCdjSHm90PXKtkb4qnuRXco.cache +3 -0
  371. data/test/dummy/tmp/cache/assets/sprockets/v3.0/pu/puTfP5YER7biq4Y4_EFFbcfDeYmOSuBt6z0CGzwFGkA.cache +2 -0
  372. data/test/dummy/tmp/cache/assets/sprockets/v3.0/q1/q1F3pWmX7ZJXbKtQUuNQE2PWTRGmvfAySjo0yHBS_BM.cache +1 -0
  373. data/test/dummy/tmp/cache/assets/sprockets/v3.0/q8/q8rvNJwHhh0RwP_ggTBQX15sVQfAGmHVkhopI3IPsHY.cache +0 -0
  374. data/test/dummy/tmp/cache/assets/sprockets/v3.0/q9/q9Mvo1FFlvxT_LCt7H3xYwBY1V5h3Jpe0eEXH8fv5Wk.cache +1 -0
  375. data/test/dummy/tmp/cache/assets/sprockets/v3.0/qG/qGfHn3hSyl2R1i-xwZDvumLbhV-cFIv5USU0_1iehb4.cache +1 -0
  376. data/test/dummy/tmp/cache/assets/sprockets/v3.0/qS/qSUOLK2mlX6Qg4pb39vYusg3MMB-5KqC4PqOt3qqU_I.cache +0 -0
  377. data/test/dummy/tmp/cache/assets/sprockets/v3.0/qZ/qZ7PeULj1cXaHw1RbEoymDg9vVEWoqR7b2tfe6Bjc-g.cache +1 -0
  378. data/test/dummy/tmp/cache/assets/sprockets/v3.0/ql/qldoyykCYdfXs4qvYwGJiKYSq-r0R1Hlw6cjY8IUfmk.cache +3 -0
  379. data/test/dummy/tmp/cache/assets/sprockets/v3.0/s9/s91U__cBvKPCirRM_cTGjn2d8Iv3KUJ2NbC6HeITxbg.cache +0 -0
  380. data/test/dummy/tmp/cache/assets/sprockets/v3.0/sI/sINrJvpYJWwxFKLJbhUC7OAf7ZuyUP888wzWFOlBPts.cache +3 -0
  381. data/test/dummy/tmp/cache/assets/sprockets/v3.0/sI/sIyfH9Z6L3jrjvuKCFI7EqiQOZ2AETT6OvpnumLpjQg.cache +1 -0
  382. data/test/dummy/tmp/cache/assets/sprockets/v3.0/sU/sU13DKNwa_RkHnSkgjrhcBWQed7kETAwwikJRsAU00M.cache +1 -0
  383. data/test/dummy/tmp/cache/assets/sprockets/v3.0/sq/sqx5Hs0Pydu-MUCvGvLJVo9B2Q3rFkn88DuIz9KSkaU.cache +1 -0
  384. data/test/dummy/tmp/cache/assets/sprockets/v3.0/tp/tpDl_cHg-S7_NzWixr_IxfubDy8a3sRY9mOfB_eDu_0.cache +0 -0
  385. data/test/dummy/tmp/cache/assets/sprockets/v3.0/tt/tthgO-QyL3rkOmOxkriE3s0lD3m_en6g7IVBmP6WfpQ.cache +1 -0
  386. data/test/dummy/tmp/cache/assets/sprockets/v3.0/tu/tuvygi0c8-7HYCnG21mYtnMbRq3byGoC-v0EPr_rcqw.cache +1 -0
  387. data/test/dummy/tmp/cache/assets/sprockets/v3.0/u7/u7Ba9DdA5Y5nYCATAuCiIkwdzV8uFn2mIAz6uIKQGCY.cache +1 -0
  388. data/test/dummy/tmp/cache/assets/sprockets/v3.0/u9/u9kCUfXtoYIqW4g4MTByGD589fmczyYmfBSV1aBwKlA.cache +1 -0
  389. data/test/dummy/tmp/cache/assets/sprockets/v3.0/vo/vo2bQsrDyQHltM8J3UVYBos-ex4ksUlyS_JaAXL9gp8.cache +0 -0
  390. data/test/dummy/tmp/cache/assets/sprockets/v3.0/wN/wNuzOUQkHcNtINLMu5i-oArMVgYINdApTU3CTGrBcr0.cache +1 -0
  391. data/test/dummy/tmp/cache/assets/sprockets/v3.0/xH/xHIb5G7OYHTA8bRoeHgv0B_-ttn9qrt7X8tNzWmBOSw.cache +0 -0
  392. data/test/dummy/tmp/cache/assets/sprockets/v3.0/yG/yGybriOHUct9EJuL4y_xiTsDmXYhzyhtdyjMl_bdnyA.cache +0 -0
  393. data/test/dummy/tmp/cache/assets/sprockets/v3.0/yH/yHWDEeVRq__H83jsasoRVfR13AGZqz3-ljrem37eYhA.cache +1 -0
  394. data/test/dummy/tmp/cache/assets/sprockets/v3.0/yJ/yJOgszuKdJlo777tz6syyQBm-5U9m92DdtWG80FyLrk.cache +1 -0
  395. data/test/dummy/tmp/cache/assets/sprockets/v3.0/zN/zN6nRw3aNJhIaKnykNJFXsCpDZNJhoeGEh6OC0YmBEQ.cache +0 -0
  396. data/test/dummy/tmp/cache/assets/sprockets/v3.0/zZ/zZz-dhRhZqpFP0QbFY4EnkgUw5okSYV61DC3u-Uo_Lg.cache +1 -0
  397. data/test/dummy/tmp/cache/assets/sprockets/v3.0/zy/zyV8aFlgWhLDl1dtI6PHd8CiddDhYL9jpZTc6f00L2Y.cache +0 -0
  398. data/test/integration/synchronises_test.rb +2 -1
  399. data/test/jobs/disco_app/app_installed_job_test.rb +27 -8
  400. data/test/jobs/disco_app/app_uninstalled_job_test.rb +5 -2
  401. data/test/jobs/disco_app/send_subscription_job_test.rb +3 -2
  402. data/test/jobs/disco_app/synchronise_carrier_service_job_test.rb +1 -0
  403. data/test/jobs/disco_app/synchronise_users_job_test.rb +1 -0
  404. data/test/jobs/disco_app/synchronise_webhooks_job_test.rb +31 -14
  405. data/test/models/disco_app/can_be_liquified_test.rb +3 -1
  406. data/test/models/disco_app/has_metafields_test.rb +37 -18
  407. data/test/models/disco_app/renders_assets_test.rb +2 -1
  408. data/test/models/disco_app/session_test.rb +2 -2
  409. data/test/services/disco_app/charges_service_test.rb +7 -8
  410. data/test/services/disco_app/flow/create_action_test.rb +51 -0
  411. data/test/services/disco_app/flow/create_trigger_test.rb +56 -0
  412. data/test/services/disco_app/flow/process_action_test.rb +68 -0
  413. data/test/services/disco_app/flow/process_trigger_test.rb +61 -0
  414. data/test/services/disco_app/subscription_service_test.rb +3 -2
  415. data/test/support/test_file_fixtures.rb +2 -2
  416. data/test/support/test_shopify_api.rb +1 -1
  417. data/test/test_helper.rb +7 -7
  418. data/test/vcr/flow_trigger_invalid_title.yml +35 -0
  419. data/test/vcr/flow_trigger_valid.yml +38 -0
  420. metadata +732 -250
  421. data/app/clients/disco_app/rollbar_client.rb +0 -53
  422. data/app/clients/disco_app/rollbar_client_error.rb +0 -2
  423. data/lib/generators/disco_app/USAGE +0 -5
  424. data/lib/generators/disco_app/disco_app_generator.rb +0 -236
  425. data/lib/generators/disco_app/templates/config/newrelic.yml +0 -26
  426. data/lib/generators/disco_app/templates/initializers/rollbar.rb +0 -23
  427. data/lib/generators/disco_app/templates/initializers/session_store.rb +0 -2
  428. data/lib/generators/disco_app/templates/root/.codeclimate.yml +0 -7
  429. data/lib/tasks/rollbar.rake +0 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 201255aa9e92f2967fb8583ad43e2d13b4aea475d0222337d8956bf14df70841
4
- data.tar.gz: ab97fc9e8f149f70baaaa35addb08ea96f3dea8f203789fd04bd585b0f4f8557
3
+ metadata.gz: 3670b5ea98be3f2a8e647127ed8e626c662f73be43ee8ad4b9bd9568aa66e692
4
+ data.tar.gz: 671d21dacbe00712492025c7e00bb93ec155e467ad42cec53af52a95844471ea
5
5
  SHA512:
6
- metadata.gz: 6d7ccecfce96e4bac63df8153c9ef0931c34a8d6387fa77bc3a734669a44639ef76634527f0d74d8f0ae2ffd516aeb7b6a84e59fdf98c14eaaae1a86145baaa8
7
- data.tar.gz: 98a2e1d47d2fc19bb798a5579eac1f98b75ecdfcf645039dafe8cc5bb3dd39ee1845b780215fca0855d66fc9dbf429dede6f87ad962d3006c293941f3fec3562
6
+ metadata.gz: c2afb706e6acc5fc7db22d19820da1e7f2776f8e73e77a647583666be0628796018632c7d733b6e74dd7758823f940f5d4a773ad7992f1536dd632f2dbc9a910
7
+ data.tar.gz: 24cc7017987d849d378acaae7720bbd8c3efdb4a442d5a4a29cdf604ab0278e396978a44dbabe36bc4d0e953c28f5e5881f63dab9da9f8f5cf3ad6c20b7bbae1
data/Rakefile CHANGED
@@ -14,14 +14,11 @@ RDoc::Task.new(:rdoc) do |rdoc|
14
14
  rdoc.rdoc_files.include('lib/**/*.rb')
15
15
  end
16
16
 
17
- APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
17
+ APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
18
18
  load 'rails/tasks/engine.rake'
19
19
 
20
-
21
20
  load 'rails/tasks/statistics.rake'
22
21
 
23
-
24
-
25
22
  Bundler::GemHelper.install_tasks
26
23
 
27
24
  require 'rake/testtask'
@@ -33,5 +30,4 @@ Rake::TestTask.new(:test) do |t|
33
30
  t.verbose = false
34
31
  end
35
32
 
36
-
37
33
  task default: :test
@@ -2,7 +2,7 @@ require 'rest-client'
2
2
 
3
3
  class DiscoApp::ApiClient
4
4
 
5
- SUBSCRIPTION_ENDPOINT = 'app_subscriptions.json'
5
+ SUBSCRIPTION_ENDPOINT = 'app_subscriptions.json'.freeze
6
6
 
7
7
  def initialize(shop, url)
8
8
  @shop = shop
@@ -10,17 +10,18 @@ class DiscoApp::ApiClient
10
10
  end
11
11
 
12
12
  def create_app_subscription
13
- return unless @url.present?
13
+ return if @url.blank?
14
+
14
15
  url = @url + SUBSCRIPTION_ENDPOINT
15
16
  begin
16
- response = RestClient::Request.execute(
17
+ RestClient::Request.execute(
17
18
  method: :post,
18
19
  headers: { content_type: :json },
19
20
  url: url,
20
21
  payload: { shop: @shop, subscription: @shop.current_subscription }.to_json
21
22
  )
22
23
  rescue RestClient::BadRequest, RestClient::ResourceNotFound => e
23
- raise DiscoApiError.new(e.message)
24
+ raise DiscoApiError, e.message
24
25
  end
25
26
  end
26
27
 
@@ -0,0 +1,85 @@
1
+ require 'rest-client'
2
+
3
+ ##
4
+ # This file defines a very simple GraphQL API client to support a single type
5
+ # of GraphQL API call for a Shopify store - sending a Shopify Flow trigger.
6
+ #
7
+ # We use this simple approach rather than using an existing GraphQL client
8
+ # library such as https://github.com/github/graphql-client (either standalone
9
+ # or as bundled with the Shopify API gem) for a couple of reasons:
10
+ #
11
+ # - These libraries tend to presume that a single client instance is
12
+ # instantiated once and then reused across the application, which isn't the
13
+ # case when we're making API calls once per trigger for each background
14
+ # job.
15
+ # - These libraries make an API call to fetch the Shopify GraphQL schema on
16
+ # initialisation. The schema is very large, so the API call takes a number
17
+ # of seconds to complete and when parsed consumes a large amount of memory.
18
+ # - These libraries do not natively work well with the idea of a dynamic API
19
+ # endpoint (ie, changing the request URL frequently), which is required
20
+ # when making many requests to different Shopify stores.
21
+ #
22
+ module DiscoApp
23
+ class GraphqlClient
24
+
25
+ def initialize(shop)
26
+ @shop = shop
27
+ end
28
+
29
+ ##
30
+ # Fire a Shopify Flow Trigger.
31
+ # Returns a tuple {Boolean, Array} representing {success, errors}.
32
+ def create_flow_trigger(title, resource_name, resource_url, properties)
33
+ body = {
34
+ trigger_title: title,
35
+ resources: [
36
+ {
37
+ name: resource_name,
38
+ url: resource_url
39
+ }
40
+ ],
41
+ properties: properties
42
+ }
43
+
44
+ # The double .to_json.to_json below looks odd but is required to properly escape the JSON hash
45
+ # when inserting it into the GraphQL mutation call.
46
+ response = execute(%(
47
+ mutation {
48
+ flowTriggerReceive(body: #{body.to_json.to_json}) {
49
+ userErrors {
50
+ field,
51
+ message
52
+ }
53
+ }
54
+ }
55
+ ))
56
+
57
+ errors = response.dig(:data, :flowTriggerReceive, :userErrors)
58
+ [errors.empty?, errors]
59
+ end
60
+
61
+ private
62
+
63
+ def execute(query)
64
+ response = RestClient::Request.execute(
65
+ method: :post,
66
+ headers: headers,
67
+ url: url,
68
+ payload: { query: query }.to_json
69
+ )
70
+ JSON.parse(response.body).with_indifferent_access
71
+ end
72
+
73
+ def headers
74
+ {
75
+ 'Content-Type' => 'application/json',
76
+ 'X-Shopify-Access-Token' => @shop.shopify_token
77
+ }
78
+ end
79
+
80
+ def url
81
+ "https://#{@shop.shopify_domain}/admin/api/graphql.json"
82
+ end
83
+
84
+ end
85
+ end
@@ -1,3 +1,5 @@
1
1
  class DiscoApp::Admin::AppSettingsController < DiscoApp::Admin::ApplicationController
2
+
2
3
  include DiscoApp::Admin::Concerns::AppSettingsController
4
+
3
5
  end
@@ -1,4 +1,5 @@
1
1
  class DiscoApp::Admin::ApplicationController < ActionController::Base
2
+
2
3
  include DiscoApp::Admin::Concerns::AuthenticatedController
3
4
 
4
5
  private
@@ -1,4 +1,5 @@
1
1
  module DiscoApp::Admin::Concerns::AppSettingsController
2
+
2
3
  extend ActiveSupport::Concern
3
4
 
4
5
  def edit
@@ -7,7 +8,7 @@ module DiscoApp::Admin::Concerns::AppSettingsController
7
8
 
8
9
  def update
9
10
  @app_settings = DiscoApp::AppSettings.instance
10
- if @app_settings.update_attributes(app_settings_params)
11
+ if @app_settings.update(app_settings_params)
11
12
  flash[:success] = 'Settings updated.'
12
13
  redirect_to edit_admin_app_settings_path
13
14
  else
@@ -1,19 +1,21 @@
1
1
  module DiscoApp::Admin::Concerns::AuthenticatedController
2
+
2
3
  extend ActiveSupport::Concern
3
4
 
4
5
  included do
5
-
6
6
  protect_from_forgery with: :exception
7
7
  before_action :authenticate_administrator
8
8
  layout 'admin'
9
-
10
9
  end
11
10
 
12
11
  private
13
12
 
14
13
  def authenticate_administrator
15
14
  authenticate_or_request_with_http_basic do |username, password|
16
- (not username.blank?) && (not password.blank?) && username == ENV['ADMIN_APP_USERNAME'] && password == ENV['ADMIN_APP_PASSWORD']
15
+ username.present? &&
16
+ password.present? &&
17
+ username == ENV['ADMIN_APP_USERNAME'] &&
18
+ password == ENV['ADMIN_APP_PASSWORD']
17
19
  end
18
20
  end
19
21
 
@@ -1,4 +1,5 @@
1
1
  module DiscoApp::Admin::Concerns::PlansController
2
+
2
3
  extend ActiveSupport::Concern
3
4
 
4
5
  included do
@@ -26,7 +27,7 @@ module DiscoApp::Admin::Concerns::PlansController
26
27
  end
27
28
 
28
29
  def update
29
- if @plan.update_attributes(plan_params)
30
+ if @plan.update(plan_params)
30
31
  redirect_to edit_admin_plan_path(@plan)
31
32
  else
32
33
  render 'edit'
@@ -47,7 +48,7 @@ module DiscoApp::Admin::Concerns::PlansController
47
48
  def plan_params
48
49
  params.require(:plan).permit(
49
50
  :name, :status, :plan_type, :trial_period_days, :amount,
50
- :plan_codes_attributes => [:id, :_destroy, :code, :trial_period_days, :amount]
51
+ plan_codes_attributes: %i[id _destroy code trial_period_days amount]
51
52
  )
52
53
  end
53
54
 
@@ -1,4 +1,5 @@
1
1
  module DiscoApp::Admin::Concerns::ShopsController
2
+
2
3
  extend ActiveSupport::Concern
3
4
 
4
5
  def index
@@ -1,4 +1,5 @@
1
1
  module DiscoApp::Admin::Concerns::SourcesController
2
+
2
3
  extend ActiveSupport::Concern
3
4
 
4
5
  included do
@@ -26,7 +27,7 @@ module DiscoApp::Admin::Concerns::SourcesController
26
27
  end
27
28
 
28
29
  def update
29
- if @source.update_attributes(source_params)
30
+ if @source.update(source_params)
30
31
  redirect_to edit_admin_plan_path(@source)
31
32
  else
32
33
  render 'edit'
@@ -1,4 +1,5 @@
1
1
  module DiscoApp::Admin::Concerns::SubscriptionsController
2
+
2
3
  extend ActiveSupport::Concern
3
4
 
4
5
  included do
@@ -9,7 +10,7 @@ module DiscoApp::Admin::Concerns::SubscriptionsController
9
10
  end
10
11
 
11
12
  def update
12
- if @subscription.update_attributes(subscription_params)
13
+ if @subscription.update(subscription_params)
13
14
  redirect_to edit_admin_shop_subscription_path(@subscription.shop, @subscription)
14
15
  else
15
16
  render 'edit'
@@ -19,7 +20,7 @@ module DiscoApp::Admin::Concerns::SubscriptionsController
19
20
  private
20
21
 
21
22
  def find_subscription
22
- @subscription = DiscoApp::Subscription.find_by_id(params[:id])
23
+ @subscription = DiscoApp::Subscription.find_by(id: params[:id])
23
24
  end
24
25
 
25
26
  def subscription_params
@@ -1,3 +1,5 @@
1
1
  class DiscoApp::Admin::PlansController < DiscoApp::Admin::ApplicationController
2
+
2
3
  include DiscoApp::Admin::Concerns::PlansController
4
+
3
5
  end
@@ -1,3 +1,5 @@
1
1
  class DiscoApp::Admin::Resources::ShopsController < JSONAPI::ResourceController
2
+
2
3
  include DiscoApp::Admin::Concerns::AuthenticatedController
4
+
3
5
  end
@@ -1,3 +1,5 @@
1
1
  class DiscoApp::Admin::ShopsController < DiscoApp::Admin::ApplicationController
2
+
2
3
  include DiscoApp::Admin::Concerns::ShopsController
4
+
3
5
  end
@@ -1,3 +1,5 @@
1
1
  class DiscoApp::Admin::SourcesController < DiscoApp::Admin::ApplicationController
2
+
2
3
  include DiscoApp::Admin::Concerns::SourcesController
4
+
3
5
  end
@@ -1,3 +1,5 @@
1
1
  class DiscoApp::Admin::SubscriptionsController < DiscoApp::Admin::ApplicationController
2
+
2
3
  include DiscoApp::Admin::Concerns::SubscriptionsController
4
+
3
5
  end
@@ -1,4 +1,5 @@
1
1
  class DiscoApp::ChargesController < ApplicationController
2
+
2
3
  include DiscoApp::Concerns::AuthenticatedController
3
4
 
4
5
  skip_before_action :check_active_charge
@@ -13,7 +14,7 @@ class DiscoApp::ChargesController < ApplicationController
13
14
  # subscription. If successful, redirect to the (external) charge confirmation
14
15
  # URL. If it fails, redirect back to the new charge page.
15
16
  def create
16
- if(charge = DiscoApp::ChargesService.create(@shop, @subscription)).nil?
17
+ if (charge = DiscoApp::ChargesService.create(@shop, @subscription)).nil?
17
18
  redirect_to action: :new
18
19
  else
19
20
  redirect_to charge.confirmation_url
@@ -25,8 +26,8 @@ class DiscoApp::ChargesController < ApplicationController
25
26
  # charge wasn't accepted, the flow will start again.
26
27
  def activate
27
28
  # First attempt to find a matching charge.
28
- if(charge = @subscription.charges.find_by(id: params[:id], shopify_id: params[:charge_id])).nil?
29
- redirect_to action: :new and return
29
+ if (charge = @subscription.charges.find_by(id: params[:id], shopify_id: params[:charge_id])).nil?
30
+ redirect_to(action: :new) && return
30
31
  end
31
32
  if DiscoApp::ChargesService.activate(@shop, charge)
32
33
  redirect_to main_app.root_url
@@ -38,10 +39,8 @@ class DiscoApp::ChargesController < ApplicationController
38
39
  private
39
40
 
40
41
  def find_subscription
41
- @subscription = @shop.subscriptions.find_by_id!(params[:subscription_id])
42
- unless @subscription.requires_active_charge? and not @subscription.active_charge?
43
- redirect_to main_app.root_url
44
- end
42
+ @subscription = @shop.subscriptions.find_by!(id: params[:subscription_id])
43
+ redirect_to main_app.root_url unless @subscription.requires_active_charge? && !@subscription.active_charge?
45
44
  end
46
45
 
47
46
  end
@@ -1,4 +1,5 @@
1
1
  module DiscoApp::Concerns::AppProxyController
2
+
2
3
  extend ActiveSupport::Concern
3
4
 
4
5
  included do
@@ -6,7 +7,7 @@ module DiscoApp::Concerns::AppProxyController
6
7
  before_action :shopify_shop
7
8
  after_action :add_liquid_header
8
9
 
9
- rescue_from ActiveRecord::RecordNotFound do |exception|
10
+ rescue_from ActiveRecord::RecordNotFound do |_exception|
10
11
  render_error 404
11
12
  end
12
13
  end
@@ -14,18 +15,17 @@ module DiscoApp::Concerns::AppProxyController
14
15
  private
15
16
 
16
17
  def verify_proxy_signature
17
- unless proxy_signature_is_valid?
18
- head :unauthorized
19
- end
18
+ head :unauthorized unless proxy_signature_is_valid?
20
19
  end
21
20
 
22
21
  def proxy_signature_is_valid?
23
- return true if (Rails.env.development? || Rails.env.test?) and DiscoApp.configuration.skip_proxy_verification?
22
+ return true if (Rails.env.development? || Rails.env.test?) && DiscoApp.configuration.skip_proxy_verification?
23
+
24
24
  DiscoApp::ProxyService.proxy_signature_is_valid?(request.query_string, ShopifyApp.configuration.secret)
25
25
  end
26
26
 
27
27
  def shopify_shop
28
- @shop = DiscoApp::Shop.find_by_shopify_domain!(params[:shop])
28
+ @shop = DiscoApp::Shop.find_by!(shopify_domain: params[:shop])
29
29
  end
30
30
 
31
31
  def add_liquid_header
@@ -1,4 +1,5 @@
1
1
  module DiscoApp::Concerns::AuthenticatedController
2
+
2
3
  extend ActiveSupport::Concern
3
4
  include ShopifyApp::LoginProtection
4
5
 
@@ -17,12 +18,13 @@ module DiscoApp::Concerns::AuthenticatedController
17
18
  private
18
19
 
19
20
  def auto_login
20
- if shop_session.nil? and request_hmac_valid?
21
- if(shop = DiscoApp::Shop.find_by_shopify_domain(sanitized_shop_name)).present?
22
- session[:shopify] = shop.id
23
- session[:shopify_domain] = sanitized_shop_name
24
- end
25
- end
21
+ return unless shop_session.nil? && request_hmac_valid?
22
+
23
+ shop = DiscoApp::Shop.find_by(shopify_domain: sanitized_shop_name)
24
+ return if shop.blank?
25
+
26
+ session[:shopify] = shop.id
27
+ session[:shopify_domain] = sanitized_shop_name
26
28
  end
27
29
 
28
30
  def shopify_shop
@@ -34,35 +36,32 @@ module DiscoApp::Concerns::AuthenticatedController
34
36
  end
35
37
 
36
38
  def check_installed
37
- if @shop.awaiting_install? or @shop.installing?
39
+ if @shop.awaiting_install? || @shop.installing?
38
40
  redirect_if_not_current_path disco_app.installing_path
39
41
  return
40
42
  end
41
- if @shop.awaiting_uninstall? or @shop.uninstalling?
43
+ if @shop.awaiting_uninstall? || @shop.uninstalling?
42
44
  redirect_if_not_current_path disco_app.uninstalling_path
43
45
  return
44
46
  end
45
- unless @shop.installed?
46
- redirect_if_not_current_path disco_app.install_path
47
- end
47
+ redirect_if_not_current_path disco_app.install_path unless @shop.installed?
48
48
  end
49
49
 
50
50
  def check_current_subscription
51
- unless @shop.current_subscription?
52
- redirect_if_not_current_path disco_app.new_subscription_path
53
- end
51
+ redirect_if_not_current_path disco_app.new_subscription_path unless @shop.current_subscription?
54
52
  end
55
53
 
56
54
  def check_active_charge
57
- if @shop.current_subscription? and @shop.current_subscription.requires_active_charge? and not @shop.development? and not @shop.current_subscription.active_charge?
58
- redirect_if_not_current_path disco_app.new_subscription_charge_path(@shop.current_subscription)
59
- end
55
+ return unless @shop.current_subscription?
56
+ return unless @shop.current_subscription.requires_active_charge?
57
+ return if @shop.development?
58
+ return if @shop.current_subscription.active_charge?
59
+
60
+ redirect_if_not_current_path disco_app.new_subscription_charge_path(@shop.current_subscription)
60
61
  end
61
62
 
62
63
  def redirect_if_not_current_path(target)
63
- if request.path != target
64
- redirect_to target
65
- end
64
+ redirect_to target if request.path != target
66
65
  end
67
66
 
68
67
  def request_hmac_valid?
@@ -70,11 +69,11 @@ module DiscoApp::Concerns::AuthenticatedController
70
69
  end
71
70
 
72
71
  def check_shop_whitelist
73
- if shop_session
74
- if ENV['WHITELISTED_DOMAINS'].present? && !ENV['WHITELISTED_DOMAINS'].include?(shop_session.url)
75
- redirect_to_login
76
- end
77
- end
72
+ return unless shop_session
73
+ return if ENV['WHITELISTED_DOMAINS'].blank?
74
+ return if ENV['WHITELISTED_DOMAINS'].include?(shop_session.url)
75
+
76
+ redirect_to_login
78
77
  end
79
78
 
80
79
  end
@@ -1,4 +1,5 @@
1
1
  module DiscoApp::Concerns::CarrierRequestController
2
+
2
3
  extend ActiveSupport::Concern
3
4
 
4
5
  included do
@@ -10,26 +11,36 @@ module DiscoApp::Concerns::CarrierRequestController
10
11
  private
11
12
 
12
13
  def verify_carrier_request
13
- unless carrier_request_signature_is_valid?
14
- head :unauthorized
15
- end
14
+ head :unauthorized unless carrier_request_signature_is_valid?
16
15
  end
17
16
 
18
17
  def carrier_request_signature_is_valid?
19
- return true if Rails.env.development? and DiscoApp.configuration.skip_carrier_request_verification?
20
- DiscoApp::CarrierRequestService.is_valid_hmac?(request.body.read.to_s, ShopifyApp.configuration.secret, request.headers['HTTP_X_SHOPIFY_HMAC_SHA256'])
18
+ return true if Rails.env.development? && DiscoApp.configuration.skip_carrier_request_verification?
19
+
20
+ DiscoApp::CarrierRequestService.valid_hmac?(
21
+ request.body.read.to_s,
22
+ ShopifyApp.configuration.secret,
23
+ request.headers['HTTP_X_SHOPIFY_HMAC_SHA256']
24
+ )
21
25
  end
22
26
 
23
27
  def find_shop
24
- unless (@shop = DiscoApp::Shop.find_by_shopify_domain(request.headers['HTTP_X_SHOPIFY_SHOP_DOMAIN']))
25
- head :unauthorized
26
- end
28
+ @shop = DiscoApp::Shop.find_by(shopify_domain: request.headers['HTTP_X_SHOPIFY_SHOP_DOMAIN'])
29
+
30
+ head :unauthorized unless @shop
27
31
  end
28
32
 
29
33
  def validate_rate_params
30
- unless params[:rate].present? and params[:rate][:origin].present? and params[:rate][:destination].present? and params[:rate][:items].present?
31
- head :bad_request
32
- end
34
+ head :bad_request unless request_is_valid?
35
+ end
36
+
37
+ def request_is_valid?
38
+ return false if params[:rate].blank?
39
+ return false if params[:rate][:origin].blank?
40
+ return false if params[:rate][:destination].blank?
41
+ return false if params[:rate][:items].blank?
42
+
43
+ true
33
44
  end
34
45
 
35
46
  end
@@ -1,4 +1,5 @@
1
1
  module DiscoApp::Concerns::UserAuthenticatedController
2
+
2
3
  extend ActiveSupport::Concern
3
4
  include ShopifyApp::LoginProtection
4
5
 
@@ -0,0 +1,49 @@
1
+ module DiscoApp::Concerns::WebhooksController
2
+
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ before_action :verify_webhook
7
+ protect_from_forgery with: :null_session
8
+ end
9
+
10
+ def process_webhook
11
+ # Get the topic and domain for this webhook.
12
+ topic = request.headers['HTTP_X_SHOPIFY_TOPIC']
13
+ shopify_domain = request.headers['HTTP_X_SHOPIFY_SHOP_DOMAIN']
14
+
15
+ # Ensure a domain was provided in the headers.
16
+ return head :bad_request unless shopify_domain
17
+
18
+ # Try to find a matching background job task for the given topic using class name.
19
+ job_class = DiscoApp::WebhookService.find_job_class(topic)
20
+
21
+ # Return bad request if we couldn't match a job class.
22
+ return head :bad_request if job_class.blank?
23
+
24
+ # Decode the body data and enqueue the appropriate job.
25
+ data = JSON.parse(request.body.read).with_indifferent_access
26
+ job_class.perform_later(shopify_domain, data)
27
+
28
+ render body: nil
29
+ end
30
+
31
+ private
32
+
33
+ def verify_webhook
34
+ return head :unauthorized unless webhook_is_valid?
35
+
36
+ request.body.rewind
37
+ end
38
+
39
+ def webhook_is_valid?
40
+ return true if Rails.env.development? && DiscoApp.configuration.skip_webhook_verification?
41
+
42
+ DiscoApp::WebhookService.valid_hmac?(
43
+ request.body.read.to_s,
44
+ ShopifyApp.configuration.secret,
45
+ request.headers['HTTP_X_SHOPIFY_HMAC_SHA256']
46
+ )
47
+ end
48
+
49
+ end
@@ -0,0 +1,9 @@
1
+ module DiscoApp
2
+ module Flow
3
+ class ActionsController < ActionController::Base
4
+
5
+ include DiscoApp::Flow::Concerns::ActionsController
6
+
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,50 @@
1
+ module DiscoApp
2
+ module Flow
3
+ module Concerns
4
+ module ActionsController
5
+
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ before_action :verify_flow_action
10
+ before_action :find_shop
11
+ protect_from_forgery with: :null_session
12
+ end
13
+
14
+ def create_flow_action
15
+ DiscoApp::Flow::CreateAction.call(
16
+ shop: @shop,
17
+ action_id: params[:id],
18
+ action_run_id: params[:action_run_id],
19
+ properties: params[:properties]
20
+ )
21
+
22
+ head :ok
23
+ end
24
+
25
+ private
26
+
27
+ def verify_flow_action
28
+ return head :unauthorized unless flow_action_is_valid?
29
+
30
+ request.body.rewind
31
+ end
32
+
33
+ # Shopify Flow action endpoints use the same verification method as webhooks, which is why we reuse this
34
+ # service method here.
35
+ def flow_action_is_valid?
36
+ DiscoApp::WebhookService.valid_hmac?(
37
+ request.body.read.to_s,
38
+ ShopifyApp.configuration.secret,
39
+ request.headers['HTTP_X_SHOPIFY_HMAC_SHA256']
40
+ )
41
+ end
42
+
43
+ def find_shop
44
+ @shop = DiscoApp::Shop.find_by!(shopify_domain: params[:shopify_domain])
45
+ end
46
+
47
+ end
48
+ end
49
+ end
50
+ end
@@ -3,7 +3,6 @@ class DiscoApp::FrameController < ActionController::Base
3
3
  layout nil
4
4
 
5
5
  def frame
6
-
7
6
  end
8
7
 
9
8
  end