disco_app 0.15.2 → 0.18.1

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 (310) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -5
  3. data/app/clients/disco_app/api_client.rb +25 -19
  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 +26 -27
  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 +13 -12
  24. data/app/controllers/disco_app/flow/actions_controller.rb +9 -0
  25. data/app/controllers/disco_app/flow/concerns/actions_controller.rb +23 -0
  26. data/app/controllers/disco_app/flow/concerns/trigger_usage_controller.rb +29 -0
  27. data/app/controllers/disco_app/flow/concerns/verifies_flow_payload.rb +39 -0
  28. data/app/controllers/disco_app/flow/trigger_usage_controller.rb +9 -0
  29. data/app/controllers/disco_app/frame_controller.rb +0 -1
  30. data/app/controllers/disco_app/install_controller.rb +3 -6
  31. data/app/controllers/disco_app/subscriptions_controller.rb +12 -4
  32. data/app/controllers/disco_app/user_sessions_controller.rb +1 -0
  33. data/app/controllers/disco_app/webhooks_controller.rb +2 -0
  34. data/app/controllers/sessions_controller.rb +5 -6
  35. data/app/helpers/disco_app/application_helper.rb +7 -7
  36. data/app/jobs/disco_app/app_installed_job.rb +2 -0
  37. data/app/jobs/disco_app/app_uninstalled_job.rb +2 -0
  38. data/app/jobs/disco_app/concerns/app_installed_job.rb +2 -3
  39. data/app/jobs/disco_app/concerns/app_uninstalled_job.rb +2 -1
  40. data/app/jobs/disco_app/concerns/customers_data_request_job.rb +13 -0
  41. data/app/jobs/disco_app/concerns/customers_redact_job.rb +13 -0
  42. data/app/jobs/disco_app/concerns/render_asset_group_job.rb +1 -0
  43. data/app/jobs/disco_app/concerns/shop_redact_job.rb +13 -0
  44. data/app/jobs/disco_app/concerns/shop_update_job.rb +9 -2
  45. data/app/jobs/disco_app/concerns/subscription_changed_job.rb +2 -1
  46. data/app/jobs/disco_app/concerns/synchronise_carrier_service_job.rb +8 -7
  47. data/app/jobs/disco_app/concerns/synchronise_resources_job.rb +1 -0
  48. data/app/jobs/disco_app/concerns/synchronise_users_job.rb +6 -3
  49. data/app/jobs/disco_app/concerns/synchronise_webhooks_job.rb +24 -11
  50. data/app/jobs/disco_app/customers_data_request_job.rb +5 -0
  51. data/app/jobs/disco_app/customers_redact_job.rb +5 -0
  52. data/app/jobs/disco_app/flow/process_action_job.rb +11 -0
  53. data/app/jobs/disco_app/flow/process_trigger_job.rb +11 -0
  54. data/app/jobs/disco_app/render_asset_group_job.rb +2 -0
  55. data/app/jobs/disco_app/shop_job.rb +10 -10
  56. data/app/jobs/disco_app/shop_redact_job.rb +5 -0
  57. data/app/jobs/disco_app/shop_update_job.rb +2 -0
  58. data/app/jobs/disco_app/subscription_changed_job.rb +2 -0
  59. data/app/jobs/disco_app/synchronise_carrier_service_job.rb +2 -0
  60. data/app/jobs/disco_app/synchronise_resources_job.rb +2 -0
  61. data/app/jobs/disco_app/synchronise_users_job.rb +2 -0
  62. data/app/jobs/disco_app/synchronise_webhooks_job.rb +2 -0
  63. data/app/models/application_record.rb +2 -0
  64. data/app/models/disco_app/app_settings.rb +2 -0
  65. data/app/models/disco_app/application_charge.rb +1 -1
  66. data/app/models/disco_app/concerns/app_settings.rb +2 -0
  67. data/app/models/disco_app/concerns/can_be_liquified.rb +29 -14
  68. data/app/models/disco_app/concerns/has_metafields.rb +1 -2
  69. data/app/models/disco_app/concerns/plan.rb +3 -4
  70. data/app/models/disco_app/concerns/plan_code.rb +1 -2
  71. data/app/models/disco_app/concerns/renders_assets.rb +15 -21
  72. data/app/models/disco_app/concerns/shop.rb +20 -14
  73. data/app/models/disco_app/concerns/source.rb +2 -3
  74. data/app/models/disco_app/concerns/subscription.rb +3 -3
  75. data/app/models/disco_app/concerns/synchronises.rb +10 -15
  76. data/app/models/disco_app/concerns/taggable.rb +1 -0
  77. data/app/models/disco_app/concerns/user.rb +3 -2
  78. data/app/models/disco_app/flow/action.rb +9 -0
  79. data/app/models/disco_app/flow/concerns/action.rb +27 -0
  80. data/app/models/disco_app/flow/concerns/trigger.rb +28 -0
  81. data/app/models/disco_app/flow/concerns/trigger_usage.rb +17 -0
  82. data/app/models/disco_app/flow/trigger.rb +9 -0
  83. data/app/models/disco_app/flow/trigger_usage.rb +9 -0
  84. data/app/models/disco_app/plan.rb +2 -0
  85. data/app/models/disco_app/plan_code.rb +2 -0
  86. data/app/models/disco_app/session_storage.rb +5 -2
  87. data/app/models/disco_app/shop.rb +2 -0
  88. data/app/models/disco_app/source.rb +2 -0
  89. data/app/models/disco_app/subscription.rb +2 -0
  90. data/app/models/disco_app/user.rb +2 -0
  91. data/app/resources/disco_app/admin/resources/concerns/shop_resource.rb +12 -15
  92. data/app/resources/disco_app/admin/resources/shop_resource.rb +1 -0
  93. data/app/services/disco_app/carrier_request_service.rb +3 -3
  94. data/app/services/disco_app/charges_service.rb +26 -34
  95. data/app/services/disco_app/flow/create_action.rb +35 -0
  96. data/app/services/disco_app/flow/create_trigger.rb +34 -0
  97. data/app/services/disco_app/flow/process_action.rb +50 -0
  98. data/app/services/disco_app/flow/process_trigger.rb +72 -0
  99. data/app/services/disco_app/flow/update_trigger_usage.rb +42 -0
  100. data/app/services/disco_app/partner_app_service.rb +1 -1
  101. data/app/services/disco_app/proxy_service.rb +2 -2
  102. data/app/services/disco_app/request_validation_service.rb +2 -2
  103. data/app/services/disco_app/subscription_service.rb +60 -32
  104. data/app/services/disco_app/webhook_service.rb +9 -11
  105. data/app/views/layouts/admin.html.erb +1 -2
  106. data/app/views/layouts/application.html.erb +1 -2
  107. data/app/views/layouts/embedded_app.html.erb +2 -4
  108. data/app/views/layouts/embedded_app_modal.html.erb +2 -3
  109. data/app/views/shopify_app/sessions/new.html.erb +2 -4
  110. data/config/routes.rb +11 -3
  111. data/db/migrate/20150525000000_create_shops_if_not_existent.rb +80 -80
  112. data/db/migrate/20170315062548_create_disco_app_sources.rb +2 -0
  113. data/db/migrate/20170315062629_add_sources_to_shop_subscriptions.rb +3 -1
  114. data/db/migrate/20170327214540_create_disco_app_users.rb +2 -1
  115. data/db/migrate/20170606160751_fix_disco_app_users_index.rb +2 -0
  116. data/db/migrate/20181229100327_create_flow_actions_and_triggers.rb +32 -0
  117. data/db/migrate/20200405000000_create_flow_trigger_usages.rb +16 -0
  118. data/lib/disco_app/configuration.rb +12 -5
  119. data/lib/disco_app/constants.rb +4 -2
  120. data/lib/disco_app/engine.rb +1 -1
  121. data/lib/disco_app/session.rb +1 -0
  122. data/lib/disco_app/support/file_fixtures.rb +2 -1
  123. data/lib/disco_app/version.rb +3 -1
  124. data/lib/generators/disco_app/install/USAGE +5 -0
  125. data/lib/generators/disco_app/install/install_generator.rb +297 -0
  126. data/lib/generators/disco_app/{templates → install/templates}/assets/javascripts/application.js +0 -0
  127. data/lib/generators/disco_app/{templates → install/templates}/assets/javascripts/components.js +0 -0
  128. data/lib/generators/disco_app/{templates → install/templates}/assets/stylesheets/application.scss +0 -0
  129. data/lib/generators/disco_app/install/templates/config/appsignal.yml +12 -0
  130. data/lib/generators/disco_app/install/templates/config/cable.yml.tt +11 -0
  131. data/lib/generators/disco_app/{templates → install/templates}/config/database.yml.tt +6 -3
  132. data/lib/generators/disco_app/install/templates/config/environments/staging.rb +108 -0
  133. data/lib/generators/disco_app/{templates → install/templates}/config/puma.rb +0 -0
  134. data/lib/generators/disco_app/{templates → install/templates}/controllers/home_controller.rb +1 -0
  135. data/lib/generators/disco_app/{templates → install/templates}/initializers/disco_app.rb +5 -0
  136. data/lib/generators/disco_app/install/templates/initializers/session_store.rb +2 -0
  137. data/lib/generators/disco_app/install/templates/initializers/shopify_app.rb +11 -0
  138. data/lib/generators/disco_app/{templates → install/templates}/initializers/shopify_session_repository.rb +0 -0
  139. data/lib/generators/disco_app/install/templates/initializers/timber.rb +4 -0
  140. data/lib/generators/disco_app/{templates → install/templates}/root/.editorconfig +0 -0
  141. data/lib/generators/disco_app/{templates → install/templates}/root/.env +7 -0
  142. data/lib/generators/disco_app/{templates → install/templates}/root/.env.local +4 -0
  143. data/lib/generators/disco_app/{templates → install/templates}/root/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  144. data/lib/generators/disco_app/{templates → install/templates}/root/.gitignore +6 -0
  145. data/lib/generators/disco_app/install/templates/root/.rspec +1 -0
  146. data/lib/generators/disco_app/{templates → install/templates}/root/.rubocop.yml +315 -217
  147. data/lib/generators/disco_app/install/templates/root/.tool-versions +2 -0
  148. data/lib/generators/disco_app/{templates → install/templates}/root/CHECKS +0 -0
  149. data/lib/generators/disco_app/{templates → install/templates}/root/Procfile +0 -0
  150. data/lib/generators/disco_app/{templates → install/templates}/root/README.md +0 -0
  151. data/lib/generators/disco_app/install/templates/root/package.json.tt +17 -0
  152. data/lib/generators/disco_app/install/templates/spec/rails_helper.rb +40 -0
  153. data/lib/generators/disco_app/install/templates/spec/spec_helper.rb +24 -0
  154. data/lib/generators/disco_app/install/templates/spec/support/active_job.rb +13 -0
  155. data/lib/generators/disco_app/install/templates/spec/support/coveralls.rb +3 -0
  156. data/lib/generators/disco_app/install/templates/spec/support/database_cleaner.rb +17 -0
  157. data/lib/generators/disco_app/install/templates/spec/support/factory_bot.rb +3 -0
  158. data/lib/generators/disco_app/install/templates/spec/support/helpers/json_helper.rb +13 -0
  159. data/lib/generators/disco_app/install/templates/spec/support/shared_examples/a_synchronise_job.rb +12 -0
  160. data/lib/generators/disco_app/install/templates/spec/support/shoulda.rb +6 -0
  161. data/lib/generators/disco_app/install/templates/spec/support/vcr.rb +14 -0
  162. data/lib/generators/disco_app/install/templates/spec/support/webmock.rb +8 -0
  163. data/lib/generators/disco_app/{templates → install/templates}/views/home/index.html.erb +0 -0
  164. data/lib/generators/disco_app/react/USAGE +5 -0
  165. data/lib/generators/disco_app/react/react_generator.rb +108 -0
  166. data/lib/generators/disco_app/react/templates/app/controllers/embedded/api/base_controller.rb +18 -0
  167. data/lib/generators/disco_app/react/templates/app/controllers/embedded/api/home_controller.rb +10 -0
  168. data/lib/generators/disco_app/react/templates/app/controllers/embedded/api/shops_controller.rb +11 -0
  169. data/lib/generators/disco_app/react/templates/app/controllers/embedded/api/users_controller.rb +11 -0
  170. data/lib/generators/disco_app/react/templates/app/controllers/embedded/home_controller.rb +13 -0
  171. data/lib/generators/disco_app/react/templates/app/models/api_response.rb +107 -0
  172. data/lib/generators/disco_app/react/templates/app/serializers/disco_app/shop_serializer.rb +13 -0
  173. data/lib/generators/disco_app/react/templates/app/serializers/disco_app/user_serializer.rb +13 -0
  174. data/lib/generators/disco_app/react/templates/app/serializers/empty_serializer.rb +5 -0
  175. data/lib/generators/disco_app/react/templates/app/serializers/error_serializer.rb +76 -0
  176. data/lib/generators/disco_app/react/templates/app/views/embedded/home/index.html.erb +12 -0
  177. data/lib/generators/disco_app/react/templates/app/views/layouts/embedded.html.erb +10 -0
  178. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/App.jsx +77 -0
  179. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/HomePage.jsx +34 -0
  180. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/Shared/EmbeddedPage.jsx +70 -0
  181. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/Shared/ErrorBanner.jsx +58 -0
  182. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/Shared/PaginationWrapper.jsx +10 -0
  183. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/Shared/ScrollToTop.jsx +23 -0
  184. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/withApi.jsx +125 -0
  185. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/index.jsx +39 -0
  186. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/utils.js +19 -0
  187. data/lib/generators/disco_app/react/templates/app/webpack/packs/embedded.js +2 -0
  188. data/lib/generators/disco_app/react/templates/app/webpack/stylesheets/embedded/shared/banners.scss +7 -0
  189. data/lib/generators/disco_app/react/templates/app/webpack/stylesheets/embedded/shared/busy.scss +3 -0
  190. data/lib/generators/disco_app/react/templates/app/webpack/stylesheets/embedded/shared/index.scss +3 -0
  191. data/lib/generators/disco_app/react/templates/app/webpack/stylesheets/embedded/shared/pagination.scss +5 -0
  192. data/lib/generators/disco_app/react/templates/app/webpack/stylesheets/embedded.scss +2 -0
  193. data/lib/generators/disco_app/react/templates/config/initializers/mime_types.rb +13 -0
  194. data/lib/generators/disco_app/react/templates/config/initializers/omniauth.rb +27 -0
  195. data/lib/generators/disco_app/react/templates/config/initializers/version.rb.tt +7 -0
  196. data/lib/generators/disco_app/react/templates/config/webpack/staging.js +5 -0
  197. data/lib/generators/disco_app/react/templates/config/webpack/test.js +5 -0
  198. data/lib/generators/disco_app/react/templates/config/webpacker.yml +96 -0
  199. data/lib/generators/disco_app/react/templates/root/.eslintignore +5 -0
  200. data/lib/generators/disco_app/react/templates/root/.eslintrc +69 -0
  201. data/lib/generators/disco_app/react/templates/root/.prettierrc +3 -0
  202. data/lib/generators/disco_app/react/templates/root/VERSION +1 -0
  203. data/lib/generators/disco_app/react/templates/root/babel.config.js +72 -0
  204. data/lib/generators/disco_app/react/templates/root/package.json.tt +84 -0
  205. data/lib/generators/disco_app/react/templates/root/postcss.config.js +14 -0
  206. data/lib/tasks/api.rake +0 -2
  207. data/lib/tasks/carrier_service.rake +0 -2
  208. data/lib/tasks/database.rake +1 -1
  209. data/lib/tasks/sessions.rake +0 -2
  210. data/lib/tasks/shops.rake +0 -2
  211. data/lib/tasks/users.rake +0 -2
  212. data/lib/tasks/webhooks.rake +0 -2
  213. data/test/clients/disco_app/api_client_test.rb +3 -3
  214. data/test/controllers/disco_app/admin/shops_controller_test.rb +1 -0
  215. data/test/controllers/disco_app/charges_controller_test.rb +8 -9
  216. data/test/controllers/disco_app/flow/trigger_usage_controller_test.rb +41 -0
  217. data/test/controllers/disco_app/install_controller_test.rb +2 -1
  218. data/test/controllers/disco_app/subscriptions_controller_test.rb +2 -1
  219. data/test/controllers/disco_app/webhooks_controller_test.rb +1 -0
  220. data/test/controllers/home_controller_test.rb +1 -1
  221. data/test/disco_app_test.rb +3 -1
  222. data/test/dummy/Rakefile +1 -1
  223. data/test/dummy/app/assets/config/manifest.js +2 -0
  224. data/test/dummy/app/controllers/application_controller.rb +2 -0
  225. data/test/dummy/app/controllers/carrier_request_controller.rb +1 -0
  226. data/test/dummy/app/controllers/disco_app/admin/shops_controller.rb +1 -0
  227. data/test/dummy/app/controllers/home_controller.rb +1 -0
  228. data/test/dummy/app/controllers/proxy_controller.rb +1 -0
  229. data/test/dummy/app/javascript/packs/application.js +18 -0
  230. data/test/dummy/app/jobs/disco_app/app_installed_job.rb +2 -3
  231. data/test/dummy/app/jobs/disco_app/app_uninstalled_job.rb +1 -0
  232. data/test/dummy/app/models/application_record.rb +2 -0
  233. data/test/dummy/app/models/cart.rb +4 -3
  234. data/test/dummy/app/models/disco_app/shop.rb +4 -5
  235. data/test/dummy/app/models/js_configuration.rb +1 -0
  236. data/test/dummy/app/models/product.rb +3 -2
  237. data/test/dummy/app/models/widget_configuration.rb +1 -0
  238. data/test/dummy/babel.config.js +72 -0
  239. data/test/dummy/bin/bundle +1 -1
  240. data/test/dummy/bin/rails +1 -1
  241. data/test/dummy/bin/setup +8 -8
  242. data/test/dummy/bin/webpack +19 -0
  243. data/test/dummy/bin/webpack-dev-server +19 -0
  244. data/test/dummy/config/application.rb +4 -3
  245. data/test/dummy/config/boot.rb +2 -2
  246. data/test/dummy/config/database.yml +3 -0
  247. data/test/dummy/config/environment.rb +1 -1
  248. data/test/dummy/config/environments/staging.rb +85 -0
  249. data/test/dummy/config/initializers/disco_app.rb +8 -1
  250. data/test/dummy/config/initializers/omniauth.rb +3 -4
  251. data/test/dummy/config/initializers/session_store.rb +1 -1
  252. data/test/dummy/config/initializers/shopify_app.rb +1 -0
  253. data/test/dummy/config/routes.rb +0 -2
  254. data/test/dummy/config/secrets.yml +3 -0
  255. data/test/dummy/config/webpack/development.js +5 -0
  256. data/test/dummy/config/webpack/environment.js +3 -0
  257. data/test/dummy/config/webpack/production.js +5 -0
  258. data/test/dummy/config/webpack/test.js +5 -0
  259. data/test/dummy/config/webpacker.yml +95 -0
  260. data/test/dummy/db/migrate/20160307182229_create_products.rb +3 -1
  261. data/test/dummy/db/migrate/20160530160739_create_asset_models.rb +3 -1
  262. data/test/dummy/db/migrate/20161105054746_create_carts.rb +2 -1
  263. data/test/dummy/db/schema.rb +45 -6
  264. data/test/dummy/package.json +8 -0
  265. data/test/dummy/postcss.config.js +12 -0
  266. data/test/dummy/yarn.lock +7244 -0
  267. data/test/fixtures/api/subscriptions/valid_request.json +1 -1
  268. data/test/fixtures/api/widget_store/empty_webhooks.json +3 -0
  269. data/test/fixtures/api/widget_store/existing_webhooks.json +43 -0
  270. data/test/fixtures/disco_app/shops.yml +3 -0
  271. data/test/fixtures/webhooks/flow/trigger_usage.json +7 -0
  272. data/test/integration/synchronises_test.rb +2 -1
  273. data/test/jobs/disco_app/app_installed_job_test.rb +28 -9
  274. data/test/jobs/disco_app/app_uninstalled_job_test.rb +5 -2
  275. data/test/jobs/disco_app/send_subscription_job_test.rb +3 -2
  276. data/test/jobs/disco_app/synchronise_carrier_service_job_test.rb +1 -0
  277. data/test/jobs/disco_app/synchronise_users_job_test.rb +1 -0
  278. data/test/jobs/disco_app/synchronise_webhooks_job_test.rb +70 -13
  279. data/test/models/disco_app/can_be_liquified_test.rb +3 -1
  280. data/test/models/disco_app/has_metafields_test.rb +37 -18
  281. data/test/models/disco_app/renders_assets_test.rb +2 -1
  282. data/test/models/disco_app/session_test.rb +2 -2
  283. data/test/models/disco_app/shop_test.rb +1 -1
  284. data/test/services/disco_app/charges_service_test.rb +7 -8
  285. data/test/services/disco_app/flow/create_action_test.rb +51 -0
  286. data/test/services/disco_app/flow/create_trigger_test.rb +56 -0
  287. data/test/services/disco_app/flow/process_action_test.rb +68 -0
  288. data/test/services/disco_app/flow/process_trigger_test.rb +94 -0
  289. data/test/services/disco_app/flow/update_trigger_usage_test.rb +87 -0
  290. data/test/services/disco_app/subscription_service_test.rb +3 -2
  291. data/test/support/test_file_fixtures.rb +2 -2
  292. data/test/support/test_shopify_api.rb +1 -1
  293. data/test/test_helper.rb +10 -7
  294. data/test/vcr/flow_trigger_invalid_title.yml +35 -0
  295. data/test/vcr/flow_trigger_valid.yml +38 -0
  296. data/test/vcr/webhook_failure.yml +13 -13
  297. metadata +282 -148
  298. data/app/clients/disco_app/disco_api_error.rb +0 -2
  299. data/app/clients/disco_app/rollbar_client.rb +0 -53
  300. data/app/clients/disco_app/rollbar_client_error.rb +0 -2
  301. data/lib/generators/disco_app/USAGE +0 -5
  302. data/lib/generators/disco_app/disco_app_generator.rb +0 -236
  303. data/lib/generators/disco_app/templates/config/newrelic.yml +0 -26
  304. data/lib/generators/disco_app/templates/initializers/rollbar.rb +0 -23
  305. data/lib/generators/disco_app/templates/initializers/session_store.rb +0 -2
  306. data/lib/generators/disco_app/templates/initializers/shopify_app.rb +0 -6
  307. data/lib/generators/disco_app/templates/root/.codeclimate.yml +0 -7
  308. data/lib/generators/disco_app/templates/root/.ruby-version +0 -1
  309. data/lib/tasks/rollbar.rake +0 -24
  310. data/test/fixtures/api/widget_store/webhooks.json +0 -1
@@ -0,0 +1,29 @@
1
+ module DiscoApp
2
+ module Flow
3
+ module Concerns
4
+ module TriggerUsageController
5
+
6
+ extend ActiveSupport::Concern
7
+ include DiscoApp::Flow::Concerns::VerifiesFlowPayload
8
+
9
+ def update_trigger_usage
10
+ DiscoApp::Flow::UpdateTriggerUsage.call(
11
+ shop: @shop,
12
+ flow_trigger_definition_id: params[:flow_trigger_definition_id],
13
+ has_enabled_flow: params[:has_enabled_flow],
14
+ timestamp: parsed_timestamp
15
+ )
16
+
17
+ head :ok
18
+ end
19
+
20
+ private
21
+
22
+ def parsed_timestamp
23
+ Time.parse(params[:timestamp])
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,39 @@
1
+ module DiscoApp
2
+ module Flow
3
+ module Concerns
4
+ module VerifiesFlowPayload
5
+
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ before_action :verify_flow_payload
10
+ before_action :find_shop
11
+ protect_from_forgery with: :null_session
12
+ end
13
+
14
+ private
15
+
16
+ def verify_flow_payload
17
+ return head :unauthorized unless flow_payload_is_valid?
18
+
19
+ request.body.rewind
20
+ end
21
+
22
+ # Shopify Flow action and trigger usage update endpoints use the same
23
+ # verification as webhooks, which is why we reuse this service method here.
24
+ def flow_payload_is_valid?
25
+ DiscoApp::WebhookService.valid_hmac?(
26
+ request.body.read.to_s,
27
+ ShopifyApp.configuration.secret,
28
+ request.headers['HTTP_X_SHOPIFY_HMAC_SHA256']
29
+ )
30
+ end
31
+
32
+ def find_shop
33
+ @shop = DiscoApp::Shop.find_by!(shopify_domain: params[:shopify_domain])
34
+ end
35
+
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,9 @@
1
+ module DiscoApp
2
+ module Flow
3
+ class TriggerUsageController < ActionController::Base
4
+
5
+ include DiscoApp::Flow::Concerns::TriggerUsageController
6
+
7
+ end
8
+ end
9
+ 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
@@ -1,4 +1,5 @@
1
1
  class DiscoApp::InstallController < ApplicationController
2
+
2
3
  include DiscoApp::Concerns::AuthenticatedController
3
4
 
4
5
  skip_before_action :check_current_subscription
@@ -12,16 +13,12 @@ class DiscoApp::InstallController < ApplicationController
12
13
 
13
14
  # Display an "installing" page.
14
15
  def installing
15
- if @shop.installed?
16
- redirect_to main_app.root_path
17
- end
16
+ redirect_to main_app.root_path if @shop.installed?
18
17
  end
19
18
 
20
19
  # Display an "uninstalling" page. Should be almost never used.
21
20
  def uninstalling
22
- if @shop.uninstalled?
23
- redirect_to main_app.root_path
24
- end
21
+ redirect_to main_app.root_path if @shop.uninstalled?
25
22
  end
26
23
 
27
24
  end
@@ -1,4 +1,5 @@
1
1
  class DiscoApp::SubscriptionsController < ApplicationController
2
+
2
3
  include DiscoApp::Concerns::AuthenticatedController
3
4
 
4
5
  skip_before_action :check_current_subscription
@@ -10,13 +11,20 @@ class DiscoApp::SubscriptionsController < ApplicationController
10
11
  def create
11
12
  # Get the selected plan. If it's not available or couldn't be found,
12
13
  # 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
14
+ plan = DiscoApp::Plan.available.find_by(id: subscription_params[:plan])
15
+
16
+ redirect_to(action: :new) && return unless plan
16
17
 
17
18
  # Subscribe the current shop to the selected plan. Pass along any cookied
18
19
  # 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
+ subscription = DiscoApp::SubscriptionService.subscribe(
21
+ @shop,
22
+ plan,
23
+ cookies[DiscoApp::CODE_COOKIE_KEY],
24
+ cookies[DiscoApp::SOURCE_COOKIE_KEY]
25
+ )
26
+
27
+ if subscription.nil?
20
28
  redirect_to action: :new
21
29
  else
22
30
  redirect_to main_app.root_path
@@ -1,4 +1,5 @@
1
1
  class DiscoApp::UserSessionsController < ApplicationController
2
+
2
3
  include DiscoApp::Concerns::AuthenticatedController
3
4
 
4
5
  def new
@@ -1,3 +1,5 @@
1
1
  class DiscoApp::WebhooksController < ActionController::Base
2
+
2
3
  include DiscoApp::Concerns::WebhooksController
4
+
3
5
  end
@@ -1,5 +1,4 @@
1
- class SessionsController < ActionController::Base
2
- include ShopifyApp::SessionsConcern
1
+ class SessionsController < ShopifyApp::SessionsController
3
2
 
4
3
  def referral
5
4
  cookies[DiscoApp::SOURCE_COOKIE_KEY] = params[:source] if params[:source].present?
@@ -18,14 +17,14 @@ class SessionsController < ActionController::Base
18
17
  # mode. Skipping OAuth still requires a shop with Shopify domain specified
19
18
  # by the `shop` parameter to be present in the local database.
20
19
  def authenticate
21
- if Rails.env.development? and DiscoApp.configuration.skip_oauth?
22
- shop = DiscoApp::Shop.find_by_shopify_domain!(sanitized_shop_name)
20
+ if Rails.env.development? && DiscoApp.configuration.skip_oauth?
21
+ shop = DiscoApp::Shop.find_by!(shopify_domain: sanitized_shop_name)
23
22
 
24
- sess = ShopifyAPI::Session.new(shop.shopify_domain, shop.shopify_token)
23
+ sess = ShopifyAPI::Session.new(domain: shop.shopify_domain, token: shop.shopify_token, api_version: shop.api_version)
25
24
  session[:shopify] = ShopifyApp::SessionRepository.store(sess)
26
25
  session[:shopify_domain] = sanitized_shop_name
27
26
 
28
- redirect_to disco_app.frame_path and return
27
+ redirect_to(disco_app.frame_path) && return
29
28
  end
30
29
  super
31
30
  end
@@ -18,7 +18,7 @@ module DiscoApp::ApplicationHelper
18
18
  title: options.delete(:modal_title),
19
19
  width: options.delete(:modal_width),
20
20
  height: options.delete(:modal_height),
21
- buttons: options.delete(:modal_buttons),
21
+ buttons: options.delete(:modal_buttons)
22
22
  }
23
23
  options[:onclick] = "ShopifyApp.Modal.open(#{modal_options.to_json}); return false;"
24
24
  options[:onclick].gsub!(/"function(.*?)"/, 'function\1')
@@ -32,14 +32,14 @@ module DiscoApp::ApplicationHelper
32
32
  react_component(name, args, options)
33
33
  end
34
34
 
35
- # Provide link to dynamically add a new nested fields association
36
- def link_to_add_fields(name, f, association)
37
- new_object = f.object.send(association).klass.new
35
+ # Provide link to dynamically add a new nested fields association
36
+ def link_to_add_fields(name, form, association)
37
+ new_object = form.object.send(association).klass.new
38
38
  id = new_object.object_id
39
- fields = f.fields_for(association, new_object, child_index: id) do |builder|
40
- render(association.to_s.singularize + "_fields", f: builder)
39
+ fields = form.fields_for(association, new_object, child_index: id) do |builder|
40
+ render(association.to_s.singularize + '_fields', f: builder)
41
41
  end
42
- link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
42
+ link_to(name, '#', class: 'add_fields', data: { id: id, fields: fields.delete("\n") })
43
43
  end
44
44
 
45
45
  # Return the props required to instantiate a React ModelForm component for the
@@ -1,3 +1,5 @@
1
1
  class DiscoApp::AppInstalledJob < DiscoApp::ShopJob
2
+
2
3
  include DiscoApp::Concerns::AppInstalledJob
4
+
3
5
  end
@@ -1,3 +1,5 @@
1
1
  class DiscoApp::AppUninstalledJob < DiscoApp::ShopJob
2
+
2
3
  include DiscoApp::Concerns::AppUninstalledJob
4
+
3
5
  end
@@ -1,4 +1,5 @@
1
1
  module DiscoApp::Concerns::AppInstalledJob
2
+
2
3
  extend ActiveSupport::Concern
3
4
 
4
5
  included do
@@ -21,9 +22,7 @@ module DiscoApp::Concerns::AppInstalledJob
21
22
 
22
23
  @shop.reload
23
24
 
24
- if default_plan.present?
25
- DiscoApp::SubscriptionService.subscribe(@shop, default_plan, plan_code, source)
26
- end
25
+ DiscoApp::SubscriptionService.subscribe(@shop, default_plan, plan_code, source) if default_plan.present?
27
26
  end
28
27
 
29
28
  # Provide an overridable hook for applications to examine the @shop object
@@ -1,4 +1,5 @@
1
1
  module DiscoApp::Concerns::AppUninstalledJob
2
+
2
3
  extend ActiveSupport::Concern
3
4
 
4
5
  included do
@@ -12,7 +13,7 @@ module DiscoApp::Concerns::AppUninstalledJob
12
13
  # - Mark any recurring application charges as cancelled.
13
14
  # - Remove any stored sessions for the shop.
14
15
  #
15
- def perform(_shop, shop_data)
16
+ def perform(_shop, _shop_data)
16
17
  DiscoApp::ChargesService.cancel_recurring_charges(@shop)
17
18
  DiscoApp::SendSubscriptionJob.perform_later(@shop)
18
19
  @shop.sessions.delete_all
@@ -0,0 +1,13 @@
1
+ module DiscoApp
2
+ module Concerns
3
+ module CustomersDataRequestJob
4
+
5
+ extend ActiveSupport::Concern
6
+
7
+ def perform(_shop, data_request_data)
8
+ # See https://shopify.dev/tutorials/add-gdpr-webhooks-to-your-app#customers-data_request
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module DiscoApp
2
+ module Concerns
3
+ module CustomersRedactJob
4
+
5
+ extend ActiveSupport::Concern
6
+
7
+ def perform(_shop, redaction_request)
8
+ # See https://shopify.dev/tutorials/add-gdpr-webhooks-to-your-app#customers-redact
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -1,4 +1,5 @@
1
1
  module DiscoApp::Concerns::RenderAssetGroupJob
2
+
2
3
  extend ActiveSupport::Concern
3
4
 
4
5
  def perform(_shop, instance, asset_group)
@@ -0,0 +1,13 @@
1
+ module DiscoApp
2
+ module Concerns
3
+ module ShopRedactJob
4
+
5
+ extend ActiveSupport::Concern
6
+
7
+ def perform(_shop, redaction_request)
8
+ # See https://shopify.dev/tutorials/add-gdpr-webhooks-to-your-app#shop-redact
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -1,13 +1,20 @@
1
1
  module DiscoApp::Concerns::ShopUpdateJob
2
+
2
3
  extend ActiveSupport::Concern
3
4
 
4
5
  # Perform an update of the current shop's information.
5
6
  def perform(_shop, shop_data = nil)
6
7
  # If we weren't provided with shop data (eg from a webhook), fetch it.
7
- shop_data ||= ActiveSupport::JSON::decode(ShopifyAPI::Shop.current.to_json)
8
+ shop_data ||= JSON.parse(ShopifyAPI::Shop.current.to_json)
8
9
 
9
10
  # Update attributes stored directly on the Shop model, along with the data hash itself.
10
- @shop.update(shop_data.with_indifferent_access.slice(*DiscoApp::Shop.column_names).except(:id, :created_at).merge(data: shop_data))
11
+ @shop.update(
12
+ shop_data
13
+ .with_indifferent_access
14
+ .slice(*DiscoApp::Shop.column_names)
15
+ .except(:id, :created_at)
16
+ .merge(data: shop_data)
17
+ )
11
18
  end
12
19
 
13
20
  end
@@ -1,7 +1,8 @@
1
1
  module DiscoApp::Concerns::SubscriptionChangedJob
2
+
2
3
  extend ActiveSupport::Concern
3
4
 
4
- def perform(_shop, subscription)
5
+ def perform(_shop, _subscription)
5
6
  DiscoApp::SendSubscriptionJob.perform_later(@shop)
6
7
  end
7
8
 
@@ -1,10 +1,11 @@
1
1
  module DiscoApp::Concerns::SynchroniseCarrierServiceJob
2
+
2
3
  extend ActiveSupport::Concern
3
4
 
4
5
  # Ensure that any carrier service required by our app is registered.
5
6
  def perform(_shop)
6
7
  # Don't proceed unless we have a name and callback url.
7
- return unless carrier_service_name and callback_url
8
+ return unless carrier_service_name && callback_url
8
9
 
9
10
  # Registered the carrier service if it hasn't been registered yet.
10
11
  unless current_carrier_service_names.include?(carrier_service_name)
@@ -19,11 +20,11 @@ module DiscoApp::Concerns::SynchroniseCarrierServiceJob
19
20
  # Ensure any existing carrier services (with the correct name) are active
20
21
  # and have a current callback URL.
21
22
  current_carrier_services.each do |carrier_service|
22
- if carrier_service.name == carrier_service_name
23
- carrier_service.callback_url = callback_url
24
- carrier_service.active = true
25
- carrier_service.save
26
- end
23
+ next unless carrier_service.name == carrier_service_name
24
+
25
+ carrier_service.callback_url = callback_url
26
+ carrier_service.active = true
27
+ carrier_service.save
27
28
  end
28
29
  end
29
30
 
@@ -49,7 +50,7 @@ module DiscoApp::Concerns::SynchroniseCarrierServiceJob
49
50
 
50
51
  # Return a list of currently registered carrier services.
51
52
  def current_carrier_services
52
- @current_carrier_service ||= ShopifyAPI::CarrierService.find(:all)
53
+ @current_carrier_services ||= ShopifyAPI::CarrierService.find(:all)
53
54
  end
54
55
 
55
56
  end
@@ -1,4 +1,5 @@
1
1
  module DiscoApp::Concerns::SynchroniseResourcesJob
2
+
2
3
  extend ActiveSupport::Concern
3
4
 
4
5
  def perform(_shop, class_name, params)
@@ -1,14 +1,17 @@
1
1
  module DiscoApp::Concerns::SynchroniseUsersJob
2
+
2
3
  extend ActiveSupport::Concern
3
4
 
4
5
  def perform(_shop)
5
6
  begin
6
- users = @shop.with_api_context {
7
+ users = @shop.with_api_context do
7
8
  ShopifyAPI::User.all
8
- }
9
+ end
9
10
  rescue ActiveResource::UnauthorizedAccess => e
10
- Rollbar.error(e) and return
11
+ Appsignal.set_error(e)
12
+ return
11
13
  end
14
+
12
15
  users.each { |user| DiscoApp::User.create_user(user, @shop) }
13
16
  end
14
17
 
@@ -1,7 +1,8 @@
1
1
  module DiscoApp::Concerns::SynchroniseWebhooksJob
2
+
2
3
  extend ActiveSupport::Concern
3
4
 
4
- COMMON_WEBHOOKS = [:'app/uninstalled', :'shop/update']
5
+ COMMON_WEBHOOKS = %i[app/uninstalled shop/update]
5
6
 
6
7
  # Ensure the webhooks registered with our shop are the same as those listed
7
8
  # in our application configuration.
@@ -11,25 +12,27 @@ module DiscoApp::Concerns::SynchroniseWebhooksJob
11
12
  with_verbose_output(topic) do
12
13
  ShopifyAPI::Webhook.create(
13
14
  topic: topic,
15
+ fields: topic_fields(topic),
14
16
  address: webhooks_url,
15
- format: 'json',
17
+ format: 'json'
16
18
  )
17
19
  end
18
20
  end
19
21
 
20
22
  # Remove any extraneous topics.
21
23
  current_webhooks.each do |webhook|
22
- unless expected_topics.include?(webhook.topic.to_sym)
23
- ShopifyAPI::Webhook.delete(webhook.id)
24
- end
24
+ ShopifyAPI::Webhook.delete(webhook.id) unless expected_topics.include?(webhook.topic.to_sym)
25
25
  end
26
26
 
27
27
  # Ensure webhook addresses are current.
28
28
  current_webhooks.each do |webhook|
29
- unless webhook.address == webhooks_url
30
- webhook.address = webhooks_url
31
- webhook.save
32
- end
29
+ expected_fields = topic_fields(webhook.topic.to_sym).map(&:to_s)
30
+
31
+ next if webhook.address == webhooks_url && webhook.fields == expected_fields
32
+
33
+ webhook.address = webhooks_url
34
+ webhook.fields = expected_fields
35
+ webhook.save
33
36
  end
34
37
  end
35
38
 
@@ -37,12 +40,12 @@ module DiscoApp::Concerns::SynchroniseWebhooksJob
37
40
 
38
41
  # Get the full list of expected webhook topics.
39
42
  def expected_topics
40
- COMMON_WEBHOOKS + (DiscoApp.configuration.webhook_topics || [])
43
+ @expected_topics ||= (COMMON_WEBHOOKS + (DiscoApp.configuration.webhook_topics || [])).map(&:to_sym)
41
44
  end
42
45
 
43
46
  # Return a list of currently registered topics.
44
47
  def current_topics
45
- current_webhooks.map(&:topic).map(&:to_sym)
48
+ @current_topics ||= current_webhooks.map(&:topic).map(&:to_sym)
46
49
  end
47
50
 
48
51
  # Return a list of current registered webhooks.
@@ -50,6 +53,16 @@ module DiscoApp::Concerns::SynchroniseWebhooksJob
50
53
  @current_webhooks ||= ShopifyAPI::Webhook.find(:all)
51
54
  end
52
55
 
56
+ # Return a list of requested fields for the given topic.
57
+ def topic_fields(topic)
58
+ webhook_fields[topic] || []
59
+ end
60
+
61
+ # Return a list of topic-to-field mappings.
62
+ def webhook_fields
63
+ @webhook_fields ||= (DiscoApp.configuration.webhook_fields || {}).symbolize_keys
64
+ end
65
+
53
66
  # Return the absolute URL to the webhooks endpoint.
54
67
  def webhooks_url
55
68
  DiscoApp::Engine.routes.url_helpers.webhooks_url
@@ -0,0 +1,5 @@
1
+ class DiscoApp::CustomersDataRequestJob < DiscoApp::ShopJob
2
+
3
+ include DiscoApp::Concerns::CustomersDataRequestJob
4
+
5
+ end
@@ -0,0 +1,5 @@
1
+ class DiscoApp::CustomersRedactJob < DiscoApp::ShopJob
2
+
3
+ include DiscoApp::Concerns::CustomersRedactJob
4
+
5
+ end
@@ -0,0 +1,11 @@
1
+ module DiscoApp
2
+ module Flow
3
+ class ProcessActionJob < DiscoApp::ShopJob
4
+
5
+ def perform(_shop, action)
6
+ ProcessAction.call(action: action)
7
+ end
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module DiscoApp
2
+ module Flow
3
+ class ProcessTriggerJob < DiscoApp::ShopJob
4
+
5
+ def perform(_shop, trigger)
6
+ ProcessTrigger.call(trigger: trigger)
7
+ end
8
+
9
+ end
10
+ end
11
+ end
@@ -1,3 +1,5 @@
1
1
  class DiscoApp::RenderAssetGroupJob < DiscoApp::ShopJob
2
+
2
3
  include DiscoApp::Concerns::RenderAssetGroupJob
4
+
3
5
  end
@@ -1,10 +1,10 @@
1
+ require 'appsignal'
2
+
1
3
  # The base class for all jobs that should be performed in the context of a
2
4
  # particular Shop's API session. The first argument to any job inheriting from
3
5
  # this class must be the domain of the relevant store, so that the appropriate
4
6
  # Shop model can be fetched and the temporary API session created.
5
7
 
6
- require 'rollbar'
7
-
8
8
  class DiscoApp::ShopJob < ApplicationJob
9
9
 
10
10
  queue_as :default
@@ -18,17 +18,17 @@ class DiscoApp::ShopJob < ApplicationJob
18
18
  private
19
19
 
20
20
  def find_shop(job)
21
- @shop ||= job.arguments.first.is_a?(DiscoApp::Shop) ? job.arguments.first : DiscoApp::Shop.find_by!(shopify_domain: job.arguments.first)
22
- end
21
+ return @shop if @shop
23
22
 
24
- def shop_context(job, block)
25
- Rollbar.scoped(rollbar_scope) do
26
- @shop.with_api_context { block.call(job.arguments) }
27
- end
23
+ @shop = job.arguments.first.is_a?(DiscoApp::Shop) ? job.arguments.first : DiscoApp::Shop.find_by!(shopify_domain: job.arguments.first)
28
24
  end
29
25
 
30
- def rollbar_scope
31
- { person: { id: @shop.id, username: @shop.shopify_domain } }
26
+ def shop_context(job, block)
27
+ Appsignal.tag_request(
28
+ shop_id: @shop.id,
29
+ shopify_domain: @shop.shopify_domain
30
+ )
31
+ @shop.with_api_context { block.call(job.arguments) }
32
32
  end
33
33
 
34
34
  end
@@ -0,0 +1,5 @@
1
+ class DiscoApp::ShopRedactJob < DiscoApp::ShopJob
2
+
3
+ include DiscoApp::Concerns::ShopRedactJob
4
+
5
+ end
@@ -1,3 +1,5 @@
1
1
  class DiscoApp::ShopUpdateJob < DiscoApp::ShopJob
2
+
2
3
  include DiscoApp::Concerns::ShopUpdateJob
4
+
3
5
  end
@@ -1,3 +1,5 @@
1
1
  class DiscoApp::SubscriptionChangedJob < DiscoApp::ShopJob
2
+
2
3
  include DiscoApp::Concerns::SubscriptionChangedJob
4
+
3
5
  end
@@ -1,3 +1,5 @@
1
1
  class DiscoApp::SynchroniseCarrierServiceJob < DiscoApp::ShopJob
2
+
2
3
  include DiscoApp::Concerns::SynchroniseCarrierServiceJob
4
+
3
5
  end
@@ -1,3 +1,5 @@
1
1
  class DiscoApp::SynchroniseResourcesJob < DiscoApp::ShopJob
2
+
2
3
  include DiscoApp::Concerns::SynchroniseResourcesJob
4
+
3
5
  end
@@ -1,3 +1,5 @@
1
1
  class DiscoApp::SynchroniseUsersJob < DiscoApp::ShopJob
2
+
2
3
  include DiscoApp::Concerns::SynchroniseUsersJob
4
+
3
5
  end
@@ -1,3 +1,5 @@
1
1
  class DiscoApp::SynchroniseWebhooksJob < DiscoApp::ShopJob
2
+
2
3
  include DiscoApp::Concerns::SynchroniseWebhooksJob
4
+
3
5
  end
@@ -1,3 +1,5 @@
1
1
  class ApplicationRecord < ActiveRecord::Base
2
+
2
3
  self.abstract_class = true
4
+
3
5
  end
@@ -1,3 +1,5 @@
1
1
  class DiscoApp::AppSettings < ApplicationRecord
2
+
2
3
  include DiscoApp::Concerns::AppSettings
4
+
3
5
  end
@@ -8,7 +8,7 @@ class DiscoApp::ApplicationCharge < ApplicationRecord
8
8
  accepted: 1,
9
9
  declined: 2,
10
10
  expired: 3,
11
- active: 4,
11
+ active: 4
12
12
  }
13
13
 
14
14
  scope :active, -> { where status: statuses[:active] }