disco_app 0.10.4

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 (357) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +37 -0
  3. data/app/assets/images/disco_app/icon.svg +1 -0
  4. data/app/assets/images/disco_app/icons.svg +0 -0
  5. data/app/assets/javascripts/disco_app/components/custom/filterable_shop_list.js.jsx +61 -0
  6. data/app/assets/javascripts/disco_app/components/custom/inline-radio-options.es6.jsx +59 -0
  7. data/app/assets/javascripts/disco_app/components/custom/rules-editor.es6.jsx +432 -0
  8. data/app/assets/javascripts/disco_app/components/custom/shop_filter_query.js.jsx +13 -0
  9. data/app/assets/javascripts/disco_app/components/custom/shop_filter_tab.js.jsx +34 -0
  10. data/app/assets/javascripts/disco_app/components/custom/shop_filter_tabs.js.jsx +21 -0
  11. data/app/assets/javascripts/disco_app/components/custom/shop_list.js.jsx +142 -0
  12. data/app/assets/javascripts/disco_app/components/custom/shop_row.js.jsx +43 -0
  13. data/app/assets/javascripts/disco_app/components/custom/shopify_admin_link.js.jsx +29 -0
  14. data/app/assets/javascripts/disco_app/components/ui-kit/cards/card-footer.es6.jsx +11 -0
  15. data/app/assets/javascripts/disco_app/components/ui-kit/cards/card-header.es6.jsx +11 -0
  16. data/app/assets/javascripts/disco_app/components/ui-kit/cards/card-section.es6.jsx +30 -0
  17. data/app/assets/javascripts/disco_app/components/ui-kit/cards/card.es6.jsx +16 -0
  18. data/app/assets/javascripts/disco_app/components/ui-kit/cards/cart-section-title.es6.jsx +17 -0
  19. data/app/assets/javascripts/disco_app/components/ui-kit/forms/base_form.es6.jsx +72 -0
  20. data/app/assets/javascripts/disco_app/components/ui-kit/forms/base_input.es6.jsx +20 -0
  21. data/app/assets/javascripts/disco_app/components/ui-kit/forms/button.es6.jsx +15 -0
  22. data/app/assets/javascripts/disco_app/components/ui-kit/forms/input-checkbox.es6.jsx +30 -0
  23. data/app/assets/javascripts/disco_app/components/ui-kit/forms/input-radio.es6.jsx +30 -0
  24. data/app/assets/javascripts/disco_app/components/ui-kit/forms/input-select.es6.jsx +45 -0
  25. data/app/assets/javascripts/disco_app/components/ui-kit/forms/input-text.es6.jsx +69 -0
  26. data/app/assets/javascripts/disco_app/components/ui-kit/forms/input-textarea.es6.jsx +48 -0
  27. data/app/assets/javascripts/disco_app/components/ui-kit/forms/input-time.es6.jsx +7 -0
  28. data/app/assets/javascripts/disco_app/components/ui-kit/forms/ui-form__element.es6.jsx +17 -0
  29. data/app/assets/javascripts/disco_app/components/ui-kit/forms/ui-form__group.es6.jsx +11 -0
  30. data/app/assets/javascripts/disco_app/components/ui-kit/forms/ui-form__section.es6.jsx +11 -0
  31. data/app/assets/javascripts/disco_app/components/ui-kit/icons/icon-chevron.es6.jsx +33 -0
  32. data/app/assets/javascripts/disco_app/components/ui-kit/icons/next-icon.es6.jsx +18 -0
  33. data/app/assets/javascripts/disco_app/components/ui-kit/input_select.es6.jsx +21 -0
  34. data/app/assets/javascripts/disco_app/components/ui-kit/tables/table.es6.jsx +22 -0
  35. data/app/assets/javascripts/disco_app/components/ui-kit/ui-layout/ui-annotated-section.es6.jsx +29 -0
  36. data/app/assets/javascripts/disco_app/components/ui-kit/ui-layout/ui-empty-state.es6.jsx +35 -0
  37. data/app/assets/javascripts/disco_app/components/ui-kit/ui-layout/ui-footer-help.es6.jsx +13 -0
  38. data/app/assets/javascripts/disco_app/components/ui-kit/ui-layout/ui-layout-item.es6.jsx +11 -0
  39. data/app/assets/javascripts/disco_app/components/ui-kit/ui-layout/ui-layout-section.es6.jsx +19 -0
  40. data/app/assets/javascripts/disco_app/components/ui-kit/ui-layout/ui-layout-sections.es6.jsx +11 -0
  41. data/app/assets/javascripts/disco_app/components/ui-kit/ui-layout/ui-layout.es6.jsx +11 -0
  42. data/app/assets/javascripts/disco_app/components/ui-kit/ui-layout/ui-page-actions.es6.jsx +13 -0
  43. data/app/assets/javascripts/disco_app/components/ui-kit/ui-layout/ui-page-actions__buttons.es6.jsx +27 -0
  44. data/app/assets/javascripts/disco_app/components.js +2 -0
  45. data/app/assets/javascripts/disco_app/disco_app.js +9 -0
  46. data/app/assets/javascripts/disco_app/frame.js +152 -0
  47. data/app/assets/javascripts/disco_app/shopify-turbolinks.js +7 -0
  48. data/app/assets/javascripts/disco_app/ui-kit.js +1 -0
  49. data/app/assets/stylesheets/disco_app/admin/_header.scss +75 -0
  50. data/app/assets/stylesheets/disco_app/admin/_layout.scss +32 -0
  51. data/app/assets/stylesheets/disco_app/admin/_nav.scss +184 -0
  52. data/app/assets/stylesheets/disco_app/admin.scss +11 -0
  53. data/app/assets/stylesheets/disco_app/disco_app.scss +21 -0
  54. data/app/assets/stylesheets/disco_app/frame/_buttons.scss +54 -0
  55. data/app/assets/stylesheets/disco_app/frame/_forms.scss +26 -0
  56. data/app/assets/stylesheets/disco_app/frame/_layout.scss +77 -0
  57. data/app/assets/stylesheets/disco_app/frame/_type.scss +25 -0
  58. data/app/assets/stylesheets/disco_app/frame.scss +10 -0
  59. data/app/assets/stylesheets/disco_app/mixins/_flexbox.scss +400 -0
  60. data/app/assets/stylesheets/disco_app/ui-kit/_ui-empty-state.scss +121 -0
  61. data/app/assets/stylesheets/disco_app/ui-kit/_ui-footer-help.scss +28 -0
  62. data/app/assets/stylesheets/disco_app/ui-kit/_ui-forms.scss +69 -0
  63. data/app/assets/stylesheets/disco_app/ui-kit/_ui-icons.scss +28 -0
  64. data/app/assets/stylesheets/disco_app/ui-kit/_ui-kit.scss +5116 -0
  65. data/app/assets/stylesheets/disco_app/ui-kit/_ui-layout.scss +15 -0
  66. data/app/assets/stylesheets/disco_app/ui-kit/_ui-page-actions.scss +23 -0
  67. data/app/assets/stylesheets/disco_app/ui-kit/_ui-stack.scss +39 -0
  68. data/app/assets/stylesheets/disco_app/ui-kit/_ui-tabs.scss +75 -0
  69. data/app/assets/stylesheets/disco_app/ui-kit/_ui-type.scss +13 -0
  70. data/app/controllers/disco_app/admin/app_settings_controller.rb +3 -0
  71. data/app/controllers/disco_app/admin/application_controller.rb +3 -0
  72. data/app/controllers/disco_app/admin/concerns/app_settings_controller.rb +24 -0
  73. data/app/controllers/disco_app/admin/concerns/authenticated_controller.rb +20 -0
  74. data/app/controllers/disco_app/admin/concerns/plans_controller.rb +54 -0
  75. data/app/controllers/disco_app/admin/concerns/shops_controller.rb +7 -0
  76. data/app/controllers/disco_app/admin/concerns/subscriptions_controller.rb +29 -0
  77. data/app/controllers/disco_app/admin/plans_controller.rb +3 -0
  78. data/app/controllers/disco_app/admin/resources/shops_controller.rb +3 -0
  79. data/app/controllers/disco_app/admin/shops_controller.rb +3 -0
  80. data/app/controllers/disco_app/admin/subscriptions_controller.rb +3 -0
  81. data/app/controllers/disco_app/charges_controller.rb +47 -0
  82. data/app/controllers/disco_app/concerns/app_proxy_controller.rb +40 -0
  83. data/app/controllers/disco_app/concerns/authenticated_controller.rb +56 -0
  84. data/app/controllers/disco_app/concerns/carrier_request_controller.rb +35 -0
  85. data/app/controllers/disco_app/frame_controller.rb +9 -0
  86. data/app/controllers/disco_app/install_controller.rb +27 -0
  87. data/app/controllers/disco_app/subscriptions_controller.rb +32 -0
  88. data/app/controllers/disco_app/webhooks_controller.rb +46 -0
  89. data/app/controllers/sessions_controller.rb +28 -0
  90. data/app/helpers/disco_app/application_helper.rb +50 -0
  91. data/app/jobs/disco_app/app_installed_job.rb +3 -0
  92. data/app/jobs/disco_app/app_uninstalled_job.rb +3 -0
  93. data/app/jobs/disco_app/concerns/app_installed_job.rb +39 -0
  94. data/app/jobs/disco_app/concerns/app_uninstalled_job.rb +20 -0
  95. data/app/jobs/disco_app/concerns/render_asset_group_job.rb +8 -0
  96. data/app/jobs/disco_app/concerns/shop_update_job.rb +13 -0
  97. data/app/jobs/disco_app/concerns/subscription_changed_job.rb +7 -0
  98. data/app/jobs/disco_app/concerns/synchronise_carrier_service_job.rb +55 -0
  99. data/app/jobs/disco_app/concerns/synchronise_resources_job.rb +12 -0
  100. data/app/jobs/disco_app/concerns/synchronise_webhooks_job.rb +52 -0
  101. data/app/jobs/disco_app/render_asset_group_job.rb +3 -0
  102. data/app/jobs/disco_app/shop_job.rb +27 -0
  103. data/app/jobs/disco_app/shop_update_job.rb +3 -0
  104. data/app/jobs/disco_app/subscription_changed_job.rb +3 -0
  105. data/app/jobs/disco_app/synchronise_carrier_service_job.rb +3 -0
  106. data/app/jobs/disco_app/synchronise_resources_job.rb +3 -0
  107. data/app/jobs/disco_app/synchronise_webhooks_job.rb +3 -0
  108. data/app/models/disco_app/app_settings.rb +3 -0
  109. data/app/models/disco_app/application_charge.rb +18 -0
  110. data/app/models/disco_app/concerns/app_settings.rb +7 -0
  111. data/app/models/disco_app/concerns/can_be_liquified.rb +45 -0
  112. data/app/models/disco_app/concerns/has_metafields.rb +48 -0
  113. data/app/models/disco_app/concerns/plan.rb +26 -0
  114. data/app/models/disco_app/concerns/plan_code.rb +15 -0
  115. data/app/models/disco_app/concerns/renders_assets.rb +166 -0
  116. data/app/models/disco_app/concerns/shop.rb +78 -0
  117. data/app/models/disco_app/concerns/subscription.rb +60 -0
  118. data/app/models/disco_app/concerns/synchronises.rb +54 -0
  119. data/app/models/disco_app/concerns/taggable.rb +16 -0
  120. data/app/models/disco_app/plan.rb +3 -0
  121. data/app/models/disco_app/plan_code.rb +3 -0
  122. data/app/models/disco_app/recurring_application_charge.rb +18 -0
  123. data/app/models/disco_app/session_storage.rb +18 -0
  124. data/app/models/disco_app/shop.rb +3 -0
  125. data/app/models/disco_app/subscription.rb +3 -0
  126. data/app/resources/disco_app/admin/resources/concerns/shop_resource.rb +100 -0
  127. data/app/resources/disco_app/admin/resources/shop_resource.rb +4 -0
  128. data/app/services/disco_app/carrier_request_service.rb +15 -0
  129. data/app/services/disco_app/charges_service.rb +81 -0
  130. data/app/services/disco_app/proxy_service.rb +17 -0
  131. data/app/services/disco_app/subscription_service.rb +46 -0
  132. data/app/services/disco_app/webhook_service.rb +30 -0
  133. data/app/views/disco_app/admin/app_settings/edit.html.erb +5 -0
  134. data/app/views/disco_app/admin/plans/_form.html.erb +72 -0
  135. data/app/views/disco_app/admin/plans/_plan_code_fields.html.erb +15 -0
  136. data/app/views/disco_app/admin/plans/edit.html.erb +7 -0
  137. data/app/views/disco_app/admin/plans/index.html.erb +43 -0
  138. data/app/views/disco_app/admin/plans/new.html.erb +7 -0
  139. data/app/views/disco_app/admin/shops/index.html.erb +13 -0
  140. data/app/views/disco_app/admin/subscriptions/edit.html.erb +33 -0
  141. data/app/views/disco_app/charges/activate.html.erb +1 -0
  142. data/app/views/disco_app/charges/create.html.erb +1 -0
  143. data/app/views/disco_app/charges/new.html.erb +23 -0
  144. data/app/views/disco_app/frame/frame.html.erb +36 -0
  145. data/app/views/disco_app/install/installing.html.erb +7 -0
  146. data/app/views/disco_app/install/uninstalling.html.erb +1 -0
  147. data/app/views/disco_app/proxy_errors/404.html.erb +1 -0
  148. data/app/views/disco_app/shared/_card.html.erb +14 -0
  149. data/app/views/disco_app/shared/_icons.html.erb +1 -0
  150. data/app/views/disco_app/shared/_section.html.erb +17 -0
  151. data/app/views/disco_app/subscriptions/new.html.erb +25 -0
  152. data/app/views/layouts/admin/_nav_items.erb +20 -0
  153. data/app/views/layouts/admin.html.erb +67 -0
  154. data/app/views/layouts/application.html.erb +18 -0
  155. data/app/views/layouts/embedded_app.html.erb +44 -0
  156. data/app/views/layouts/embedded_app_modal.html.erb +28 -0
  157. data/app/views/sessions/new.html.erb +28 -0
  158. data/config/routes.rb +63 -0
  159. data/db/migrate/20150525000000_create_shops_if_not_existent.rb +15 -0
  160. data/db/migrate/20150525162112_add_status_to_shops.rb +5 -0
  161. data/db/migrate/20150525171422_add_meta_to_shops.rb +11 -0
  162. data/db/migrate/20150629210346_add_charge_status_to_shop.rb +5 -0
  163. data/db/migrate/20150814214025_add_more_meta_to_shops.rb +15 -0
  164. data/db/migrate/20151017231302_create_disco_app_plans.rb +13 -0
  165. data/db/migrate/20151017232027_create_disco_app_subscriptions.rb +15 -0
  166. data/db/migrate/20151017234409_move_shop_to_disco_app_engine.rb +5 -0
  167. data/db/migrate/20160112233706_create_disco_app_sessions.rb +12 -0
  168. data/db/migrate/20160113194418_add_shop_id_to_disco_app_sessions.rb +6 -0
  169. data/db/migrate/20160223111044_create_disco_app_settings.rb +8 -0
  170. data/db/migrate/20160301223215_update_plans.rb +22 -0
  171. data/db/migrate/20160301224558_update_subscriptions.rb +13 -0
  172. data/db/migrate/20160302104816_create_disco_app_recurring_application_charges.rb +14 -0
  173. data/db/migrate/20160302105259_create_disco_app_application_charges.rb +14 -0
  174. data/db/migrate/20160302134728_drop_charge_status_from_shops.rb +5 -0
  175. data/db/migrate/20160302142941_add_shopify_attributes_to_charges.rb +8 -0
  176. data/db/migrate/20160331093148_create_disco_app_plan_codes.rb +14 -0
  177. data/db/migrate/20160401044420_add_status_to_plan_codes.rb +5 -0
  178. data/db/migrate/20160401045551_add_amount_and_plan_code_to_disco_app_subscriptions.rb +7 -0
  179. data/db/migrate/20160425205211_add_source_to_disco_app_subscriptions.rb +5 -0
  180. data/db/migrate/20160426033520_add_trial_period_days_to_disco_app_subscriptions.rb +5 -0
  181. data/db/migrate/20160513140727_add_name_to_disco_app_shops.rb +5 -0
  182. data/db/migrate/20160521135510_move_shop_to_synchronises.rb +61 -0
  183. data/lib/disco_app/configuration.rb +45 -0
  184. data/lib/disco_app/constants.rb +4 -0
  185. data/lib/disco_app/engine.rb +26 -0
  186. data/lib/disco_app/session.rb +14 -0
  187. data/lib/disco_app/support/file_fixtures.rb +23 -0
  188. data/lib/disco_app/test_help.rb +11 -0
  189. data/lib/disco_app/version.rb +3 -0
  190. data/lib/disco_app.rb +7 -0
  191. data/lib/generators/disco_app/USAGE +5 -0
  192. data/lib/generators/disco_app/disco_app_generator.rb +239 -0
  193. data/lib/generators/disco_app/templates/assets/javascripts/application.js +17 -0
  194. data/lib/generators/disco_app/templates/assets/javascripts/components.js +3 -0
  195. data/lib/generators/disco_app/templates/assets/stylesheets/application.scss +5 -0
  196. data/lib/generators/disco_app/templates/config/database.yml.tt +20 -0
  197. data/lib/generators/disco_app/templates/config/newrelic.yml +26 -0
  198. data/lib/generators/disco_app/templates/config/puma.rb +15 -0
  199. data/lib/generators/disco_app/templates/controllers/home_controller.rb +7 -0
  200. data/lib/generators/disco_app/templates/initializers/disco_app.rb +28 -0
  201. data/lib/generators/disco_app/templates/initializers/rollbar.rb +19 -0
  202. data/lib/generators/disco_app/templates/initializers/session_store.rb +2 -0
  203. data/lib/generators/disco_app/templates/initializers/shopify_app.rb +7 -0
  204. data/lib/generators/disco_app/templates/initializers/shopify_session_repository.rb +7 -0
  205. data/lib/generators/disco_app/templates/root/CHECKS +4 -0
  206. data/lib/generators/disco_app/templates/root/Procfile +2 -0
  207. data/lib/generators/disco_app/templates/views/home/index.html.erb +2 -0
  208. data/lib/tasks/carrier_service.rake +10 -0
  209. data/lib/tasks/database.rake +8 -0
  210. data/lib/tasks/sessions.rake +9 -0
  211. data/lib/tasks/shops.rake +10 -0
  212. data/lib/tasks/start.rake +3 -0
  213. data/lib/tasks/webhooks.rake +10 -0
  214. data/test/controllers/disco_app/admin/shops_controller_test.rb +54 -0
  215. data/test/controllers/disco_app/charges_controller_test.rb +99 -0
  216. data/test/controllers/disco_app/install_controller_test.rb +50 -0
  217. data/test/controllers/disco_app/subscriptions_controller_test.rb +68 -0
  218. data/test/controllers/disco_app/webhooks_controller_test.rb +58 -0
  219. data/test/controllers/home_controller_test.rb +92 -0
  220. data/test/controllers/proxy_controller_test.rb +42 -0
  221. data/test/disco_app_test.rb +7 -0
  222. data/test/dummy/Rakefile +6 -0
  223. data/test/dummy/app/assets/javascripts/application.js +17 -0
  224. data/test/dummy/app/assets/stylesheets/application.scss +5 -0
  225. data/test/dummy/app/controllers/application_controller.rb +6 -0
  226. data/test/dummy/app/controllers/carrier_request_controller.rb +10 -0
  227. data/test/dummy/app/controllers/disco_app/admin/shops_controller.rb +8 -0
  228. data/test/dummy/app/controllers/home_controller.rb +7 -0
  229. data/test/dummy/app/controllers/proxy_controller.rb +8 -0
  230. data/test/dummy/app/helpers/application_helper.rb +2 -0
  231. data/test/dummy/app/jobs/disco_app/app_installed_job.rb +16 -0
  232. data/test/dummy/app/jobs/disco_app/app_uninstalled_job.rb +11 -0
  233. data/test/dummy/app/jobs/products_create_job.rb +7 -0
  234. data/test/dummy/app/jobs/products_delete_job.rb +7 -0
  235. data/test/dummy/app/jobs/products_update_job.rb +7 -0
  236. data/test/dummy/app/models/disco_app/shop.rb +15 -0
  237. data/test/dummy/app/models/js_configuration.rb +8 -0
  238. data/test/dummy/app/models/product.rb +9 -0
  239. data/test/dummy/app/models/widget_configuration.rb +10 -0
  240. data/test/dummy/app/views/assets/script_tag.js.erb +1 -0
  241. data/test/dummy/app/views/assets/test.js.erb +1 -0
  242. data/test/dummy/app/views/assets/widget.js.erb +2 -0
  243. data/test/dummy/app/views/assets/widget.scss.erb +3 -0
  244. data/test/dummy/app/views/home/index.html.erb +2 -0
  245. data/test/dummy/app/views/snippets/widget.liquid.erb +1 -0
  246. data/test/dummy/bin/bundle +3 -0
  247. data/test/dummy/bin/rails +4 -0
  248. data/test/dummy/bin/rake +4 -0
  249. data/test/dummy/bin/setup +29 -0
  250. data/test/dummy/config/application.rb +38 -0
  251. data/test/dummy/config/boot.rb +5 -0
  252. data/test/dummy/config/database.codeship.yml +23 -0
  253. data/test/dummy/config/database.gitlab-ci.yml +24 -0
  254. data/test/dummy/config/database.yml +20 -0
  255. data/test/dummy/config/environment.rb +5 -0
  256. data/test/dummy/config/environments/development.rb +41 -0
  257. data/test/dummy/config/environments/production.rb +85 -0
  258. data/test/dummy/config/environments/test.rb +42 -0
  259. data/test/dummy/config/initializers/assets.rb +11 -0
  260. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  261. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  262. data/test/dummy/config/initializers/disco_app.rb +28 -0
  263. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  264. data/test/dummy/config/initializers/inflections.rb +16 -0
  265. data/test/dummy/config/initializers/mime_types.rb +4 -0
  266. data/test/dummy/config/initializers/omniauth.rb +9 -0
  267. data/test/dummy/config/initializers/session_store.rb +2 -0
  268. data/test/dummy/config/initializers/shopify_app.rb +7 -0
  269. data/test/dummy/config/initializers/shopify_session_repository.rb +7 -0
  270. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  271. data/test/dummy/config/locales/en.yml +23 -0
  272. data/test/dummy/config/routes.rb +11 -0
  273. data/test/dummy/config/secrets.yml +22 -0
  274. data/test/dummy/config.ru +4 -0
  275. data/test/dummy/db/migrate/20160307182229_create_products.rb +11 -0
  276. data/test/dummy/db/migrate/20160530160739_create_asset_models.rb +19 -0
  277. data/test/dummy/db/schema.rb +141 -0
  278. data/test/dummy/public/404.html +67 -0
  279. data/test/dummy/public/422.html +67 -0
  280. data/test/dummy/public/500.html +66 -0
  281. data/test/dummy/public/favicon.ico +0 -0
  282. data/test/fixtures/api/widget_store/assets/create_script_tag_js_request.json +6 -0
  283. data/test/fixtures/api/widget_store/assets/create_script_tag_js_response.json +12 -0
  284. data/test/fixtures/api/widget_store/assets/create_script_tag_request.json +6 -0
  285. data/test/fixtures/api/widget_store/assets/create_script_tag_response.json +10 -0
  286. data/test/fixtures/api/widget_store/assets/create_test_js_request.json +6 -0
  287. data/test/fixtures/api/widget_store/assets/create_test_js_response.json +12 -0
  288. data/test/fixtures/api/widget_store/assets/create_widget_js_request.json +6 -0
  289. data/test/fixtures/api/widget_store/assets/create_widget_js_response.json +12 -0
  290. data/test/fixtures/api/widget_store/assets/create_widget_liquid_request.json +6 -0
  291. data/test/fixtures/api/widget_store/assets/create_widget_liquid_response.json +12 -0
  292. data/test/fixtures/api/widget_store/assets/create_widget_scss_request.json +6 -0
  293. data/test/fixtures/api/widget_store/assets/create_widget_scss_response.json +12 -0
  294. data/test/fixtures/api/widget_store/assets/get_script_tags_empty_request.json +1 -0
  295. data/test/fixtures/api/widget_store/assets/get_script_tags_empty_response.json +1 -0
  296. data/test/fixtures/api/widget_store/assets/get_script_tags_preexisting_request.json +1 -0
  297. data/test/fixtures/api/widget_store/assets/get_script_tags_preexisting_response.json +12 -0
  298. data/test/fixtures/api/widget_store/assets/update_script_tag_request.json +10 -0
  299. data/test/fixtures/api/widget_store/assets/update_script_tag_response.json +10 -0
  300. data/test/fixtures/api/widget_store/carrier_services.json +1 -0
  301. data/test/fixtures/api/widget_store/carrier_services_create.json +8 -0
  302. data/test/fixtures/api/widget_store/charges/activate_application_charge_request.json +16 -0
  303. data/test/fixtures/api/widget_store/charges/activate_application_charge_response.json +1 -0
  304. data/test/fixtures/api/widget_store/charges/activate_recurring_application_charge_request.json +20 -0
  305. data/test/fixtures/api/widget_store/charges/activate_recurring_application_charge_response.json +1 -0
  306. data/test/fixtures/api/widget_store/charges/create_application_charge_request.json +9 -0
  307. data/test/fixtures/api/widget_store/charges/create_application_charge_response.json +16 -0
  308. data/test/fixtures/api/widget_store/charges/create_recurring_application_charge_request.json +9 -0
  309. data/test/fixtures/api/widget_store/charges/create_recurring_application_charge_response.json +20 -0
  310. data/test/fixtures/api/widget_store/charges/create_second_recurring_application_charge_request.json +9 -0
  311. data/test/fixtures/api/widget_store/charges/create_second_recurring_application_charge_response.json +20 -0
  312. data/test/fixtures/api/widget_store/charges/get_accepted_application_charge_response.json +16 -0
  313. data/test/fixtures/api/widget_store/charges/get_accepted_recurring_application_charge_response.json +20 -0
  314. data/test/fixtures/api/widget_store/charges/get_declined_application_charge_response.json +16 -0
  315. data/test/fixtures/api/widget_store/charges/get_declined_recurring_application_charge_response.json +20 -0
  316. data/test/fixtures/api/widget_store/charges/get_pending_application_charge_response.json +16 -0
  317. data/test/fixtures/api/widget_store/charges/get_pending_recurring_application_charge_response.json +20 -0
  318. data/test/fixtures/api/widget_store/products/write_metafields_multiple_namespaces_request.json +31 -0
  319. data/test/fixtures/api/widget_store/products/write_metafields_multiple_namespaces_response.json +1 -0
  320. data/test/fixtures/api/widget_store/products/write_metafields_single_namespace_request.json +19 -0
  321. data/test/fixtures/api/widget_store/products/write_metafields_single_namespace_response.json +1 -0
  322. data/test/fixtures/api/widget_store/shop.json +46 -0
  323. data/test/fixtures/api/widget_store/webhooks.json +1 -0
  324. data/test/fixtures/assets/test.js +1 -0
  325. data/test/fixtures/assets/test.min.js +1 -0
  326. data/test/fixtures/disco_app/application_charges.yml +11 -0
  327. data/test/fixtures/disco_app/plan_codes.yml +13 -0
  328. data/test/fixtures/disco_app/plans.yml +37 -0
  329. data/test/fixtures/disco_app/recurring_application_charges.yml +11 -0
  330. data/test/fixtures/disco_app/shops.yml +10 -0
  331. data/test/fixtures/disco_app/subscriptions.yml +22 -0
  332. data/test/fixtures/js_configurations.yml +3 -0
  333. data/test/fixtures/liquid/model.liquid +8 -0
  334. data/test/fixtures/products.yml +4 -0
  335. data/test/fixtures/webhooks/app_uninstalled.json +46 -0
  336. data/test/fixtures/webhooks/product_created.json +167 -0
  337. data/test/fixtures/webhooks/product_deleted.json +3 -0
  338. data/test/fixtures/webhooks/product_updated.json +167 -0
  339. data/test/fixtures/widget_configurations.yml +4 -0
  340. data/test/integration/synchronises_test.rb +55 -0
  341. data/test/jobs/disco_app/app_installed_job_test.rb +57 -0
  342. data/test/jobs/disco_app/app_uninstalled_job_test.rb +30 -0
  343. data/test/jobs/disco_app/synchronise_carrier_service_job_test.rb +25 -0
  344. data/test/jobs/disco_app/synchronise_webhooks_job_test.rb +30 -0
  345. data/test/models/disco_app/can_be_liquified_test.rb +55 -0
  346. data/test/models/disco_app/has_metafields_test.rb +40 -0
  347. data/test/models/disco_app/plan_test.rb +5 -0
  348. data/test/models/disco_app/renders_assets_test.rb +109 -0
  349. data/test/models/disco_app/session_test.rb +31 -0
  350. data/test/models/disco_app/shop_test.rb +35 -0
  351. data/test/models/disco_app/subscription_test.rb +19 -0
  352. data/test/services/disco_app/charges_service_test.rb +112 -0
  353. data/test/services/disco_app/subscription_service_test.rb +60 -0
  354. data/test/support/test_file_fixtures.rb +29 -0
  355. data/test/support/test_shopify_api.rb +16 -0
  356. data/test/test_helper.rb +55 -0
  357. metadata +878 -0
@@ -0,0 +1,15 @@
1
+ //
2
+ // ui-layout.scss
3
+ // Styles for UI layout not provided by the Channel
4
+ // SDK UI Kit.
5
+ // --------------------------------------------------
6
+
7
+ body {
8
+ margin: 0;
9
+ padding: 0;
10
+ }
11
+
12
+ ul, ol, dl {
13
+ margin: 0;
14
+ padding: 0;
15
+ }
@@ -0,0 +1,23 @@
1
+ //
2
+ // ui-page-actions.scss
3
+ // Styles for UI page actions not provided by the
4
+ // Channel SDK UI Kit.
5
+ // --------------------------------------------------
6
+
7
+ .ui-page-actions {
8
+ @include flexbox();
9
+ margin: 0 auto;
10
+ max-width: 1036px;
11
+ padding: 20px 0;
12
+ border-top: 1px solid #d3dbe2;
13
+ }
14
+
15
+ .ui-page-actions__primary {
16
+ @include flex(1 1 auto);
17
+ padding-right: 20px;
18
+ }
19
+
20
+ .ui-page-actions__secondary {
21
+ @include flex(1 1 auto);
22
+ padding: 0 20px;
23
+ }
@@ -0,0 +1,39 @@
1
+ .ui-stack {
2
+ display: -webkit-flex;
3
+ display: -ms-flexbox;
4
+ display: flex;
5
+ margin-left: -1.42857rem;
6
+ margin-top: -1.42857rem;
7
+
8
+ > * {
9
+ margin-left: 1.42857rem;
10
+ margin-top: 1.42857rem;
11
+ -webkit-flex: 0 1 auto;
12
+ -ms-flex: 0 1 auto;
13
+ flex: 0 1 auto;
14
+ }
15
+ }
16
+
17
+ .ui-stack--wrap {
18
+ -webkit-flex-wrap: wrap;
19
+ -ms-flex-wrap: wrap;
20
+ flex-wrap: wrap;
21
+ }
22
+
23
+ .ui-stack--alignment-center {
24
+ -webkit-align-items: center;
25
+ -ms-flex-align: center;
26
+ -ms-grid-row-align: center;
27
+ align-items: center;
28
+ }
29
+
30
+ .ui-stack-item {
31
+ min-width: 0;
32
+ max-width: 100%;
33
+ }
34
+
35
+ .ui-stack-item--fill {
36
+ -webkit-flex: 1 1 auto;
37
+ -ms-flex: 1 1 auto;
38
+ flex: 1 1 auto;
39
+ }
@@ -0,0 +1,75 @@
1
+ //
2
+ // ui-tabs.scss
3
+ // Styles for tabs not provided by the Channel SDK UI
4
+ // Kit.
5
+ // --------------------------------------------------
6
+
7
+ .next-tab__list {
8
+ padding: 0;
9
+ margin: 0;
10
+ list-style: none;
11
+ background-color: #f5f6f7;
12
+ overflow: visible;
13
+ border-radius: 3px 3px 0 0;
14
+
15
+ flex-wrap: nowrap;
16
+ display: flex;
17
+ align-items: stretch;
18
+
19
+ > li {
20
+ position: relative;
21
+ flex-grow: 0;
22
+ flex-shrink: 0;
23
+ display: flex;
24
+ align-items: stretch;
25
+
26
+ &:first-child .next-tab {
27
+ border-top-left-radius: 3px;
28
+ }
29
+ }
30
+ }
31
+
32
+ .next-tab {
33
+ color: rgba(0,0,0,0.56);
34
+ padding: 15px 20px;
35
+ text-decoration: none;
36
+ border-right: 1px solid #ebeef0;
37
+ border-bottom: 1px solid #ebeef0;
38
+ text-align: center;
39
+ line-height: 1;
40
+ cursor: pointer;
41
+ position: relative;
42
+ -webkit-box-flex: 1;
43
+ -webkit-flex-grow: 1;
44
+ -ms-flex-positive: 1;
45
+ flex-grow: 1;
46
+ display: -webkit-box;
47
+ display: -webkit-flex;
48
+ display: -ms-flexbox;
49
+ display: flex;
50
+ -webkit-box-align: center;
51
+ -webkit-align-items: center;
52
+ -ms-flex-align: center;
53
+ align-items: center;
54
+ -webkit-box-pack: center;
55
+ -webkit-justify-content: center;
56
+ -ms-flex-pack: center;
57
+ justify-content: center;
58
+
59
+ &:focus,
60
+ &:hover {
61
+ outline: none;
62
+ background-color: #fafbfc;
63
+ color: #0078bd;
64
+ text-decoration: none;
65
+ }
66
+
67
+ &.next-tab--is-active {
68
+ font-weight: normal;
69
+ color: rgba(0,0,0,0.9);
70
+ background-color: #ffffff;
71
+ border-bottom-color: #ffffff;
72
+ cursor: default;
73
+ text-decoration: none;
74
+ }
75
+ }
@@ -0,0 +1,13 @@
1
+ //
2
+ // ui-type.scss
3
+ // Styles for type not provided by the Channel SDK UI
4
+ // Kit.
5
+ // --------------------------------------------------
6
+
7
+ hr {
8
+ color: #e6e6e6;
9
+ background-color: #e6e6e6;
10
+ height: 1px;
11
+ padding: 0;
12
+ border: 0;
13
+ }
@@ -0,0 +1,3 @@
1
+ class DiscoApp::Admin::AppSettingsController < DiscoApp::Admin::ApplicationController
2
+ include DiscoApp::Admin::Concerns::AppSettingsController
3
+ end
@@ -0,0 +1,3 @@
1
+ class DiscoApp::Admin::ApplicationController < ActionController::Base
2
+ include DiscoApp::Admin::Concerns::AuthenticatedController
3
+ end
@@ -0,0 +1,24 @@
1
+ module DiscoApp::Admin::Concerns::AppSettingsController
2
+ extend ActiveSupport::Concern
3
+
4
+ def edit
5
+ @app_settings = DiscoApp::AppSettings.instance
6
+ end
7
+
8
+ def update
9
+ @app_settings = DiscoApp::AppSettings.instance
10
+ if @app_settings.update_attributes(app_settings_params)
11
+ flash[:success] = 'Settings updated.'
12
+ redirect_to edit_admin_app_settings_path
13
+ else
14
+ render 'edit'
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def app_settings_params
21
+ params.require(:app_settings)
22
+ end
23
+
24
+ end
@@ -0,0 +1,20 @@
1
+ module DiscoApp::Admin::Concerns::AuthenticatedController
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+
6
+ protect_from_forgery with: :exception
7
+ before_action :authenticate_administrator
8
+ layout 'admin'
9
+
10
+ end
11
+
12
+ private
13
+
14
+ def authenticate_administrator
15
+ 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']
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,54 @@
1
+ module DiscoApp::Admin::Concerns::PlansController
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ before_action :find_plan, only: [:edit, :update, :destroy]
6
+ end
7
+
8
+ def index
9
+ @plans = DiscoApp::Plan.all
10
+ end
11
+
12
+ def new
13
+ @plan = DiscoApp::Plan.new
14
+ end
15
+
16
+ def create
17
+ @plan = DiscoApp::Plan.new(plan_params)
18
+ if @plan.save
19
+ redirect_to admin_plans_path
20
+ else
21
+ render 'new'
22
+ end
23
+ end
24
+
25
+ def edit
26
+ end
27
+
28
+ def update
29
+ if @plan.update_attributes(plan_params)
30
+ redirect_to edit_admin_plan_path(@plan)
31
+ else
32
+ render 'edit'
33
+ end
34
+ end
35
+
36
+ def destroy
37
+ @plan.destroy
38
+ redirect_to admin_plans_path
39
+ end
40
+
41
+ private
42
+
43
+ def find_plan
44
+ @plan = DiscoApp::Plan.find(params[:id])
45
+ end
46
+
47
+ def plan_params
48
+ params.require(:plan).permit(
49
+ :name, :status, :plan_type, :trial_period_days, :amount,
50
+ :plan_codes_attributes => [:id, :_destroy, :code, :trial_period_days, :amount]
51
+ )
52
+ end
53
+
54
+ end
@@ -0,0 +1,7 @@
1
+ module DiscoApp::Admin::Concerns::ShopsController
2
+ extend ActiveSupport::Concern
3
+
4
+ def index
5
+ end
6
+
7
+ end
@@ -0,0 +1,29 @@
1
+ module DiscoApp::Admin::Concerns::SubscriptionsController
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ before_action :find_subscription
6
+ end
7
+
8
+ def edit
9
+ end
10
+
11
+ def update
12
+ if @subscription.update_attributes(subscription_params)
13
+ redirect_to edit_admin_shop_subscription_path(@subscription.shop, @subscription)
14
+ else
15
+ render 'edit'
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def find_subscription
22
+ @subscription = DiscoApp::Subscription.find_by_id(params[:id])
23
+ end
24
+
25
+ def subscription_params
26
+ params.require(:subscription).permit(:amount, :trial_period_days)
27
+ end
28
+
29
+ end
@@ -0,0 +1,3 @@
1
+ class DiscoApp::Admin::PlansController < DiscoApp::Admin::ApplicationController
2
+ include DiscoApp::Admin::Concerns::PlansController
3
+ end
@@ -0,0 +1,3 @@
1
+ class DiscoApp::Admin::Resources::ShopsController < JSONAPI::ResourceController
2
+ include DiscoApp::Admin::Concerns::AuthenticatedController
3
+ end
@@ -0,0 +1,3 @@
1
+ class DiscoApp::Admin::ShopsController < DiscoApp::Admin::ApplicationController
2
+ include DiscoApp::Admin::Concerns::ShopsController
3
+ end
@@ -0,0 +1,3 @@
1
+ class DiscoApp::Admin::SubscriptionsController < DiscoApp::Admin::ApplicationController
2
+ include DiscoApp::Admin::Concerns::SubscriptionsController
3
+ end
@@ -0,0 +1,47 @@
1
+ class DiscoApp::ChargesController < ApplicationController
2
+ include DiscoApp::Concerns::AuthenticatedController
3
+
4
+ skip_before_action :check_active_charge
5
+ before_action :find_subscription
6
+
7
+ # Display a "pre-charge" page, giving the opportunity to explain why a charge
8
+ # needs to be made.
9
+ def new
10
+ end
11
+
12
+ # Attempt to create a new charge for the logged in shop and selected
13
+ # subscription. If successful, redirect to the (external) charge confirmation
14
+ # URL. If it fails, redirect back to the new charge page.
15
+ def create
16
+ if(charge = DiscoApp::ChargesService.create(@shop, @subscription)).nil?
17
+ redirect_to action: :new
18
+ else
19
+ redirect_to charge.confirmation_url
20
+ end
21
+ end
22
+
23
+ # Attempt to activate a charge after a user has accepted or declined it.
24
+ # Redirect to the main application's root URL immediately afterwards - if the
25
+ # charge wasn't accepted, the flow will start again.
26
+ def activate
27
+ # 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
30
+ end
31
+ if DiscoApp::ChargesService.activate(@shop, charge)
32
+ redirect_to main_app.root_url
33
+ else
34
+ redirect_to action: :new
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ 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
45
+ end
46
+
47
+ end
@@ -0,0 +1,40 @@
1
+ module DiscoApp::Concerns::AppProxyController
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ before_action :verify_proxy_signature
6
+ before_action :shopify_shop
7
+ after_action :add_liquid_header
8
+
9
+ rescue_from ActiveRecord::RecordNotFound do |exception|
10
+ render_error 404
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def verify_proxy_signature
17
+ unless proxy_signature_is_valid?
18
+ head :unauthorized
19
+ end
20
+ end
21
+
22
+ def proxy_signature_is_valid?
23
+ return true if Rails.env.development? and DiscoApp.configuration.skip_proxy_verification?
24
+ DiscoApp::ProxyService.proxy_signature_is_valid?(request.query_string, ShopifyApp.configuration.secret)
25
+ end
26
+
27
+ def shopify_shop
28
+ @shop = DiscoApp::Shop.find_by_shopify_domain!(params[:shop])
29
+ end
30
+
31
+ def add_liquid_header
32
+ response.headers['Content-Type'] = 'application/liquid'
33
+ end
34
+
35
+ def render_error(status)
36
+ add_liquid_header
37
+ render "disco_app/proxy_errors/#{status}", status: status
38
+ end
39
+
40
+ end
@@ -0,0 +1,56 @@
1
+ module DiscoApp::Concerns::AuthenticatedController
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ before_action :login_again_if_different_shop
6
+ before_action :shopify_shop
7
+ before_action :check_installed
8
+ before_action :check_current_subscription
9
+ before_action :check_active_charge
10
+ around_filter :shopify_session
11
+ layout 'embedded_app'
12
+ end
13
+
14
+ private
15
+
16
+ def shopify_shop
17
+ if shop_session
18
+ @shop = DiscoApp::Shop.find_by!(shopify_domain: @shop_session.url)
19
+ else
20
+ redirect_to_login
21
+ end
22
+ end
23
+
24
+ def check_installed
25
+ if @shop.awaiting_install? or @shop.installing?
26
+ redirect_if_not_current_path disco_app.installing_path
27
+ return
28
+ end
29
+ if @shop.awaiting_uninstall? or @shop.uninstalling?
30
+ redirect_if_not_current_path disco_app.uninstalling_path
31
+ return
32
+ end
33
+ unless @shop.installed?
34
+ redirect_if_not_current_path disco_app.install_path
35
+ end
36
+ end
37
+
38
+ def check_current_subscription
39
+ unless @shop.current_subscription?
40
+ redirect_if_not_current_path disco_app.new_subscription_path
41
+ end
42
+ end
43
+
44
+ def check_active_charge
45
+ if @shop.current_subscription? and @shop.current_subscription.requires_active_charge? and not @shop.development? and not @shop.current_subscription.active_charge?
46
+ redirect_if_not_current_path disco_app.new_subscription_charge_path(@shop.current_subscription)
47
+ end
48
+ end
49
+
50
+ def redirect_if_not_current_path(target)
51
+ if request.path != target
52
+ redirect_to target
53
+ end
54
+ end
55
+
56
+ end
@@ -0,0 +1,35 @@
1
+ module DiscoApp::Concerns::CarrierRequestController
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ before_action :verify_carrier_request
6
+ before_action :find_shop
7
+ before_action :validate_rate_params
8
+ end
9
+
10
+ private
11
+
12
+ def verify_carrier_request
13
+ unless carrier_request_signature_is_valid?
14
+ head :unauthorized
15
+ end
16
+ end
17
+
18
+ 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'])
21
+ end
22
+
23
+ def find_shop
24
+ unless (@shop = DiscoApp::Shop.find_by_shopify_domain(request.headers['HTTP_X_SHOPIFY_SHOP_DOMAIN']))
25
+ head :unauthorized
26
+ end
27
+ end
28
+
29
+ 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
33
+ end
34
+
35
+ end
@@ -0,0 +1,9 @@
1
+ class DiscoApp::FrameController < ActionController::Base
2
+
3
+ layout nil
4
+
5
+ def frame
6
+
7
+ end
8
+
9
+ end
@@ -0,0 +1,27 @@
1
+ class DiscoApp::InstallController < ApplicationController
2
+ include DiscoApp::Concerns::AuthenticatedController
3
+
4
+ skip_before_action :check_current_subscription
5
+ skip_before_action :check_active_charge
6
+
7
+ # Start the installation process for the current shop, then redirect to the installing screen.
8
+ def install
9
+ DiscoApp::AppInstalledJob.perform_later(@shop, cookies[DiscoApp::CODE_COOKIE_KEY], cookies[DiscoApp::SOURCE_COOKIE_KEY])
10
+ redirect_to action: :installing
11
+ end
12
+
13
+ # Display an "installing" page.
14
+ def installing
15
+ if @shop.installed?
16
+ redirect_to main_app.root_path
17
+ end
18
+ end
19
+
20
+ # Display an "uninstalling" page. Should be almost never used.
21
+ def uninstalling
22
+ if @shop.uninstalled?
23
+ redirect_to main_app.root_path
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,32 @@
1
+ class DiscoApp::SubscriptionsController < ApplicationController
2
+ include DiscoApp::Concerns::AuthenticatedController
3
+
4
+ skip_before_action :check_current_subscription
5
+
6
+ def new
7
+ @subscription = DiscoApp::Subscription.new
8
+ end
9
+
10
+ def create
11
+ # Get the selected plan. If it's not available or couldn't be found,
12
+ # redirect back to the plan selection page.
13
+ if(plan = DiscoApp::Plan.available.find_by_id(subscription_params[:plan])).nil?
14
+ redirect_to action: :new and return
15
+ end
16
+
17
+ # Subscribe the current shop to the selected plan. Pass along any cookied
18
+ # plan code and source code.
19
+ if(subscription = DiscoApp::SubscriptionService.subscribe(@shop, plan, cookies[DiscoApp::CODE_COOKIE_KEY], cookies[DiscoApp::SOURCE_COOKIE_KEY])).nil?
20
+ redirect_to action: :new
21
+ else
22
+ redirect_to main_app.root_path
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def subscription_params
29
+ params.require(:subscription).permit(:plan, :plan_code)
30
+ end
31
+
32
+ end
@@ -0,0 +1,46 @@
1
+ module DiscoApp
2
+ class WebhooksController < ActionController::Base
3
+
4
+ before_action :verify_webhook
5
+
6
+ def process_webhook
7
+ # Get the topic and domain for this webhook.
8
+ topic = request.headers['HTTP_X_SHOPIFY_TOPIC']
9
+ shopify_domain = request.headers['HTTP_X_SHOPIFY_SHOP_DOMAIN']
10
+
11
+ # Ensure a domain was provided in the headers.
12
+ unless shopify_domain
13
+ head :bad_request
14
+ end
15
+
16
+ # Try to find a matching background job task for the given topic using class name.
17
+ job_class = DiscoApp::WebhookService.find_job_class(topic)
18
+
19
+ # Return bad request if we couldn't match a job class.
20
+ unless job_class.present?
21
+ head :bad_request
22
+ end
23
+
24
+ # Decode the body data and enqueue the appropriate job.
25
+ data = ActiveSupport::JSON::decode(request.body.read).with_indifferent_access
26
+ job_class.perform_later(shopify_domain, data)
27
+
28
+ render nothing: true
29
+ end
30
+
31
+ private
32
+
33
+ def verify_webhook
34
+ unless webhook_is_valid?
35
+ head :unauthorized
36
+ end
37
+ request.body.rewind
38
+ end
39
+
40
+ def webhook_is_valid?
41
+ return true if Rails.env.development? and DiscoApp.configuration.skip_webhook_verification?
42
+ DiscoApp::WebhookService.is_valid_hmac?(request.body.read.to_s, ShopifyApp.configuration.secret, request.headers['HTTP_X_SHOPIFY_HMAC_SHA256'])
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,28 @@
1
+ class SessionsController < ApplicationController
2
+ include ShopifyApp::SessionsController
3
+
4
+ def referral
5
+ cookies[DiscoApp::SOURCE_COOKIE_KEY] = params[:source] if params[:source].present?
6
+ cookies[DiscoApp::CODE_COOKIE_KEY] = params[:code] if params[:code].present?
7
+ redirect_to root_path
8
+ end
9
+
10
+ protected
11
+
12
+ # Override the authenticate method to allow skipping OAuth in development
13
+ # mode. Skipping OAuth still requires a shop with Shopify domain specified
14
+ # by the `shop` parameter to be present in the local database.
15
+ def authenticate
16
+ if Rails.env.development? and DiscoApp.configuration.skip_oauth?
17
+ shop = DiscoApp::Shop.find_by_shopify_domain!(sanitized_shop_name)
18
+
19
+ sess = ShopifyAPI::Session.new(shop.shopify_domain, shop.shopify_token)
20
+ session[:shopify] = ShopifyApp::SessionRepository.store(sess)
21
+ session[:shopify_domain] = sanitized_shop_name
22
+
23
+ redirect_to disco_app.frame_path and return
24
+ end
25
+ super
26
+ end
27
+
28
+ end