disco_app 0.8.5

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 (173) 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/javascripts/disco_app/components/shopify_admin_link.js.jsx +29 -0
  5. data/app/assets/javascripts/disco_app/components.js +5 -0
  6. data/app/assets/javascripts/disco_app/disco_app.js +7 -0
  7. data/app/assets/javascripts/disco_app/frame.js +152 -0
  8. data/app/assets/javascripts/disco_app/shopify-turbolinks.js +7 -0
  9. data/app/assets/stylesheets/disco_app/bootstrap/_custom.scss +54 -0
  10. data/app/assets/stylesheets/disco_app/bootstrap/_variables.scss +872 -0
  11. data/app/assets/stylesheets/disco_app/disco/_buttons.scss +31 -0
  12. data/app/assets/stylesheets/disco_app/disco/_cards.scss +51 -0
  13. data/app/assets/stylesheets/disco_app/disco/_forms.scss +23 -0
  14. data/app/assets/stylesheets/disco_app/disco/_grid.scss +58 -0
  15. data/app/assets/stylesheets/disco_app/disco/_sections.scss +61 -0
  16. data/app/assets/stylesheets/disco_app/disco/_tables.scss +57 -0
  17. data/app/assets/stylesheets/disco_app/disco/_tabs.scss +61 -0
  18. data/app/assets/stylesheets/disco_app/disco/_type.scss +39 -0
  19. data/app/assets/stylesheets/disco_app/disco/mixins/_flexbox.scss +394 -0
  20. data/app/assets/stylesheets/disco_app/disco_app.scss +16 -0
  21. data/app/assets/stylesheets/disco_app/frame/_buttons.scss +54 -0
  22. data/app/assets/stylesheets/disco_app/frame/_forms.scss +26 -0
  23. data/app/assets/stylesheets/disco_app/frame/_layout.scss +77 -0
  24. data/app/assets/stylesheets/disco_app/frame/_type.scss +32 -0
  25. data/app/assets/stylesheets/disco_app/frame.scss +9 -0
  26. data/app/controllers/disco_app/app_proxy_controller.rb +42 -0
  27. data/app/controllers/disco_app/authenticated_controller.rb +44 -0
  28. data/app/controllers/disco_app/carrier_request_controller.rb +23 -0
  29. data/app/controllers/disco_app/charges_controller.rb +30 -0
  30. data/app/controllers/disco_app/frame_controller.rb +9 -0
  31. data/app/controllers/disco_app/install_controller.rb +26 -0
  32. data/app/controllers/disco_app/webhooks_controller.rb +46 -0
  33. data/app/helpers/disco_app/application_helper.rb +28 -0
  34. data/app/jobs/disco_app/app_installed_job.rb +3 -0
  35. data/app/jobs/disco_app/app_uninstalled_job.rb +3 -0
  36. data/app/jobs/disco_app/concerns/app_installed_job.rb +22 -0
  37. data/app/jobs/disco_app/concerns/app_uninstalled_job.rb +23 -0
  38. data/app/jobs/disco_app/concerns/shop_update_job.rb +16 -0
  39. data/app/jobs/disco_app/concerns/synchronise_carrier_service_job.rb +52 -0
  40. data/app/jobs/disco_app/concerns/synchronise_webhooks_job.rb +61 -0
  41. data/app/jobs/disco_app/shop_job.rb +27 -0
  42. data/app/jobs/disco_app/shop_update_job.rb +3 -0
  43. data/app/jobs/disco_app/synchronise_carrier_service_job.rb +3 -0
  44. data/app/jobs/disco_app/synchronise_webhooks_job.rb +3 -0
  45. data/app/models/disco_app/concerns/plan.rb +14 -0
  46. data/app/models/disco_app/concerns/shop.rb +70 -0
  47. data/app/models/disco_app/concerns/subscription.rb +14 -0
  48. data/app/models/disco_app/concerns/synchronises_with_shopify.rb +26 -0
  49. data/app/models/disco_app/plan.rb +3 -0
  50. data/app/models/disco_app/session_storage.rb +18 -0
  51. data/app/models/disco_app/shop.rb +3 -0
  52. data/app/models/disco_app/subscription.rb +3 -0
  53. data/app/services/disco_app/carrier_request_service.rb +15 -0
  54. data/app/services/disco_app/charges_service.rb +73 -0
  55. data/app/services/disco_app/proxy_service.rb +17 -0
  56. data/app/services/disco_app/subscription_service.rb +25 -0
  57. data/app/services/disco_app/webhook_service.rb +30 -0
  58. data/app/views/disco_app/charges/activate.html.erb +1 -0
  59. data/app/views/disco_app/charges/create.html.erb +1 -0
  60. data/app/views/disco_app/charges/new.html.erb +45 -0
  61. data/app/views/disco_app/frame/frame.html.erb +36 -0
  62. data/app/views/disco_app/install/installing.html.erb +7 -0
  63. data/app/views/disco_app/install/uninstalling.html.erb +1 -0
  64. data/app/views/disco_app/proxy_errors/404.html.erb +1 -0
  65. data/app/views/disco_app/shared/_card.html.erb +14 -0
  66. data/app/views/disco_app/shared/_section.html.erb +17 -0
  67. data/app/views/layouts/application.html.erb +18 -0
  68. data/app/views/layouts/embedded_app.html.erb +41 -0
  69. data/app/views/layouts/embedded_app_modal.html.erb +17 -0
  70. data/app/views/sessions/new.html.erb +26 -0
  71. data/config/routes.rb +26 -0
  72. data/db/migrate/20150525000000_create_shops_if_not_existent.rb +15 -0
  73. data/db/migrate/20150525162112_add_status_to_shops.rb +5 -0
  74. data/db/migrate/20150525171422_add_meta_to_shops.rb +11 -0
  75. data/db/migrate/20150629210346_add_charge_status_to_shop.rb +5 -0
  76. data/db/migrate/20150814214025_add_more_meta_to_shops.rb +15 -0
  77. data/db/migrate/20151017231302_create_disco_app_plans.rb +13 -0
  78. data/db/migrate/20151017232027_create_disco_app_subscriptions.rb +15 -0
  79. data/db/migrate/20151017234409_move_shop_to_disco_app_engine.rb +5 -0
  80. data/db/migrate/20160112233706_create_disco_app_sessions.rb +12 -0
  81. data/db/migrate/20160113194418_add_shop_id_to_disco_app_sessions.rb +6 -0
  82. data/lib/disco_app/configuration.rb +33 -0
  83. data/lib/disco_app/engine.rb +25 -0
  84. data/lib/disco_app/session.rb +14 -0
  85. data/lib/disco_app/support/file_fixtures.rb +23 -0
  86. data/lib/disco_app/test_help.rb +11 -0
  87. data/lib/disco_app/version.rb +3 -0
  88. data/lib/disco_app.rb +6 -0
  89. data/lib/generators/disco_app/USAGE +5 -0
  90. data/lib/generators/disco_app/disco_app_generator.rb +163 -0
  91. data/lib/generators/disco_app/mailify/mailify_generator.rb +54 -0
  92. data/lib/generators/disco_app/monitorify/monitorify_generator.rb +28 -0
  93. data/lib/generators/disco_app/monitorify/templates/config/newrelic.yml +26 -0
  94. data/lib/generators/disco_app/monitorify/templates/initializers/rollbar.rb +12 -0
  95. data/lib/generators/disco_app/reactify/reactify_generator.rb +45 -0
  96. data/lib/generators/disco_app/templates/assets/javascripts/application.js +17 -0
  97. data/lib/generators/disco_app/templates/assets/stylesheets/application.scss +5 -0
  98. data/lib/generators/disco_app/templates/config/puma.rb +15 -0
  99. data/lib/generators/disco_app/templates/controllers/home_controller.rb +7 -0
  100. data/lib/generators/disco_app/templates/initializers/disco_app.rb +14 -0
  101. data/lib/generators/disco_app/templates/initializers/session_store.rb +2 -0
  102. data/lib/generators/disco_app/templates/initializers/shopify_app.rb +7 -0
  103. data/lib/generators/disco_app/templates/initializers/shopify_session_repository.rb +7 -0
  104. data/lib/generators/disco_app/templates/root/Procfile +2 -0
  105. data/lib/generators/disco_app/templates/views/home/index.html.erb +2 -0
  106. data/lib/tasks/carrier_service.rake +10 -0
  107. data/lib/tasks/sessions.rake +9 -0
  108. data/lib/tasks/start.rake +3 -0
  109. data/lib/tasks/webhooks.rake +10 -0
  110. data/test/controllers/disco_app/install_controller_test.rb +50 -0
  111. data/test/controllers/disco_app/webhooks_controller_test.rb +58 -0
  112. data/test/controllers/home_controller_test.rb +61 -0
  113. data/test/controllers/proxy_controller_test.rb +42 -0
  114. data/test/disco_app_test.rb +7 -0
  115. data/test/dummy/Rakefile +6 -0
  116. data/test/dummy/app/assets/javascripts/application.js +17 -0
  117. data/test/dummy/app/assets/stylesheets/application.scss +5 -0
  118. data/test/dummy/app/controllers/application_controller.rb +6 -0
  119. data/test/dummy/app/controllers/home_controller.rb +7 -0
  120. data/test/dummy/app/controllers/proxy_controller.rb +8 -0
  121. data/test/dummy/app/helpers/application_helper.rb +2 -0
  122. data/test/dummy/app/jobs/disco_app/app_uninstalled_job.rb +11 -0
  123. data/test/dummy/app/models/disco_app/shop.rb +15 -0
  124. data/test/dummy/app/views/home/index.html.erb +2 -0
  125. data/test/dummy/bin/bundle +3 -0
  126. data/test/dummy/bin/rails +4 -0
  127. data/test/dummy/bin/rake +4 -0
  128. data/test/dummy/bin/setup +29 -0
  129. data/test/dummy/config/application.rb +38 -0
  130. data/test/dummy/config/boot.rb +5 -0
  131. data/test/dummy/config/database.yml +25 -0
  132. data/test/dummy/config/environment.rb +5 -0
  133. data/test/dummy/config/environments/development.rb +41 -0
  134. data/test/dummy/config/environments/production.rb +85 -0
  135. data/test/dummy/config/environments/test.rb +42 -0
  136. data/test/dummy/config/initializers/assets.rb +11 -0
  137. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  138. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  139. data/test/dummy/config/initializers/disco_app.rb +14 -0
  140. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  141. data/test/dummy/config/initializers/inflections.rb +16 -0
  142. data/test/dummy/config/initializers/mime_types.rb +4 -0
  143. data/test/dummy/config/initializers/omniauth.rb +9 -0
  144. data/test/dummy/config/initializers/session_store.rb +2 -0
  145. data/test/dummy/config/initializers/shopify_app.rb +7 -0
  146. data/test/dummy/config/initializers/shopify_session_repository.rb +7 -0
  147. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  148. data/test/dummy/config/locales/en.yml +23 -0
  149. data/test/dummy/config/routes.rb +10 -0
  150. data/test/dummy/config/secrets.yml +22 -0
  151. data/test/dummy/config.ru +4 -0
  152. data/test/dummy/db/schema.rb +81 -0
  153. data/test/dummy/public/404.html +67 -0
  154. data/test/dummy/public/422.html +67 -0
  155. data/test/dummy/public/500.html +66 -0
  156. data/test/dummy/public/favicon.ico +0 -0
  157. data/test/fixtures/api/widget_store/shop.json +46 -0
  158. data/test/fixtures/api/widget_store/webhooks.json +1 -0
  159. data/test/fixtures/disco_app/plans.yml +32 -0
  160. data/test/fixtures/disco_app/shops.yml +10 -0
  161. data/test/fixtures/disco_app/subscriptions.yml +26 -0
  162. data/test/fixtures/webhooks/app_uninstalled.json +46 -0
  163. data/test/integration/navigation_test.rb +10 -0
  164. data/test/jobs/disco_app/app_installed_job_test.rb +30 -0
  165. data/test/jobs/disco_app/app_uninstalled_job_test.rb +32 -0
  166. data/test/models/disco_app/plan_test.rb +5 -0
  167. data/test/models/disco_app/session_test.rb +31 -0
  168. data/test/models/disco_app/shop_test.rb +26 -0
  169. data/test/models/disco_app/subscription_test.rb +6 -0
  170. data/test/services/disco_app/subscription_service_test.rb +28 -0
  171. data/test/support/test_file_fixtures.rb +29 -0
  172. data/test/test_helper.rb +51 -0
  173. metadata +530 -0
@@ -0,0 +1,163 @@
1
+ class DiscoAppGenerator < Rails::Generators::Base
2
+
3
+ source_root File.expand_path('../templates', __FILE__)
4
+
5
+ # Copy a number of template files to the top-level directory of our application:
6
+ #
7
+ # - .env and .env.local for settings environment variables in development with dotenv-rails;
8
+ # - Slightly customised version of the default Rails .gitignore;
9
+ # - Default simple Procfile for Heroku.
10
+ #
11
+ def copy_root_files
12
+ %w(.env .env.local .gitignore Procfile).each do |file|
13
+ copy_file "root/#{file}", file
14
+ end
15
+ end
16
+
17
+ # Remove a number of root files.
18
+ def remove_root_files
19
+ %w(README.rdoc).each do |file|
20
+ remove_file file
21
+ end
22
+ end
23
+
24
+ # Configure the application's Gemfile.
25
+ def configure_gems
26
+ # Remove sqlite from the general Gemfile.
27
+ gsub_file 'Gemfile', /^# Use sqlite3 as the database for Active Record\ngem 'sqlite3'/m, ''
28
+
29
+ # Add gems common to all environments.
30
+ gem 'shopify_app', '~> 6.4.1'
31
+ gem 'sidekiq', '~> 4.0.2'
32
+ gem 'puma', '~> 2.14.0'
33
+ gem 'bootstrap-sass', '~> 3.3.5.1'
34
+ gem 'activerecord-session_store', '~> 0.1.2'
35
+ gem 'activeresource', github: 'shopify/activeresource', tag: '4.2-threadsafe'
36
+ gem 'rails-bigint-pk', '~> 1.2.0'
37
+
38
+ # Add gems for development and testing only.
39
+ gem_group :development, :test do
40
+ gem 'sqlite3', '~> 1.3.11'
41
+ gem 'dotenv-rails', '~> 2.0.2'
42
+ gem 'minitest-reporters', '~> 1.0.19'
43
+ gem 'guard', '~> 2.13.0'
44
+ gem 'guard-minitest', '~> 2.4.4'
45
+ end
46
+
47
+ # Add gems for production only.
48
+ gem_group :production do
49
+ gem 'pg', '~> 0.18.3'
50
+ gem 'rails_12factor', '~> 0.0.3'
51
+ end
52
+ end
53
+
54
+ # Run bundle install to add our new gems before running tasks.
55
+ def bundle_install
56
+ Bundler.with_clean_env do
57
+ run 'bundle install'
58
+ end
59
+ end
60
+
61
+ # Make any required adjustments to the application configuration.
62
+ def configure_application
63
+ # The force_ssl flag is commented by default for production.
64
+ # Uncomment to ensure config.force_ssl = true in production.
65
+ uncomment_lines 'config/environments/production.rb', /force_ssl/
66
+
67
+ # Set defaults for various charge attributes.
68
+ application "config.x.shopify_charges_default_trial_days = 14\n"
69
+ application "config.x.shopify_charges_default_price = 10.00"
70
+ application "config.x.shopify_charges_default_type = :recurring"
71
+ application "# Set defaults for charges created by the application"
72
+
73
+ # Set the "real charges" config variable to false explicitly by default.
74
+ # Only in production do we read from the environment variable and
75
+ # potentially have it become true.
76
+ application "config.x.shopify_charges_real = false\n"
77
+ application "# Explicitly prevent real charges being created by default"
78
+ application "config.x.shopify_charges_real = ENV['SHOPIFY_CHARGES_REAL'] == 'true'\n", env: :production
79
+ application "# Allow real charges in production with an ENV variable", env: :production
80
+
81
+ # Configure session storage.
82
+ application "ActiveRecord::SessionStore::Session.table_name = 'disco_app_sessions'"
83
+ application "ActionDispatch::Session::ActiveRecordStore.session_class = DiscoApp::Session"
84
+ application "# Configure custom session storage"
85
+
86
+ # Set Sidekiq as the queue adapter in production.
87
+ application "config.active_job.queue_adapter = :sidekiq\n", env: :production
88
+ application "# Use Sidekiq as the active job backend", env: :production
89
+
90
+ # Ensure the application configuration uses the DEFAULT_HOST environment
91
+ # variable to set up support for reverse routing absolute URLS (needed when
92
+ # generating Webhook URLs for example).
93
+ application "routes.default_url_options[:host] = ENV['DEFAULT_HOST']\n"
94
+ application "# Set the default host for absolute URL routing purposes"
95
+
96
+ # Copy over the default puma configuration.
97
+ copy_file 'config/puma.rb', 'config/puma.rb'
98
+ end
99
+
100
+ # Set up routes.
101
+ def setup_routes
102
+ route "mount DiscoApp::Engine, at: '/'"
103
+ end
104
+
105
+ # Run generators.
106
+ def run_generators
107
+ generate 'shopify_app:install'
108
+ generate 'shopify_app:home_controller'
109
+ generate 'bigint_pk:install'
110
+ end
111
+
112
+ # Copy template files to the appropriate location. In some cases, we'll be
113
+ # overwriting or removing existing files or those created by ShopifyApp.
114
+ def copy_and_remove_files
115
+ # Copy initializers
116
+ copy_file 'initializers/shopify_app.rb', 'config/initializers/shopify_app.rb'
117
+ copy_file 'initializers/disco_app.rb', 'config/initializers/disco_app.rb'
118
+ copy_file 'initializers/shopify_session_repository.rb', 'config/initializers/shopify_session_repository.rb'
119
+ copy_file 'initializers/session_store.rb', 'config/initializers/session_store.rb'
120
+
121
+ # Copy default home controller and view
122
+ copy_file 'controllers/home_controller.rb', 'app/controllers/home_controller.rb'
123
+ copy_file 'views/home/index.html.erb', 'app/views/home/index.html.erb'
124
+
125
+ # Copy assets
126
+ copy_file 'assets/javascripts/application.js', 'app/assets/javascripts/application.js'
127
+ copy_file 'assets/stylesheets/application.scss', 'app/assets/stylesheets/application.scss'
128
+
129
+ # Remove application.css
130
+ remove_file 'app/assets/stylesheets/application.css'
131
+
132
+ # Remove the layout files created by ShopifyApp
133
+ remove_file 'app/views/layouts/application.html.erb'
134
+ remove_file 'app/views/layouts/embedded_app.html.erb'
135
+ end
136
+
137
+ # Add the Disco App test helper to test/test_helper.rb
138
+ def add_test_helper
139
+ inject_into_file 'test/test_helper.rb', "require 'disco_app/test_help'\n", { after: "require 'rails/test_help'\n" }
140
+ end
141
+
142
+ # Copy engine migrations over.
143
+ def install_migrations
144
+ rake 'disco_app:install:migrations'
145
+ end
146
+
147
+ # Run migrations.
148
+ def migrate
149
+ rake 'db:migrate'
150
+ end
151
+
152
+ # Lock down the application to a specific Ruby version:
153
+ #
154
+ # - Via .ruby-version file for rbenv in development;
155
+ # - Via a Gemfile line in production.
156
+ #
157
+ # This should be the last operation, to allow all other operations to run in the initial Ruby version.
158
+ def set_ruby_version
159
+ copy_file 'root/.ruby-version', '.ruby-version'
160
+ prepend_to_file 'Gemfile', "ruby '2.3.0'\n"
161
+ end
162
+
163
+ end
@@ -0,0 +1,54 @@
1
+ module DiscoApp
2
+ module Generators
3
+ class MailifyGenerator < Rails::Generators::Base
4
+
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ def install_gem
8
+ # Add premailer gem to Gemfile.
9
+ gem 'premailer-rails', '~> 1.8.2'
10
+
11
+ # Add explicit dependency on Nokogiri
12
+ gem 'nokogiri', '~> 1.6.6.1'
13
+
14
+ # Add the Mailgun rails gem (production only)
15
+ gem_group :production do
16
+ gem 'mailgun_rails', '~> 0.7.0'
17
+ end
18
+
19
+ # Install gem.
20
+ Bundler.with_clean_env do
21
+ run 'bundle install'
22
+ end
23
+ end
24
+
25
+ # Set application configuration
26
+ def configure_application
27
+ configuration = <<-CONFIG.strip_heredoc
28
+
29
+ # Configure ActionMailer to use MailGun
30
+ if ENV['MAILGUN_API_KEY']
31
+ config.action_mailer.delivery_method = :mailgun
32
+ config.action_mailer.mailgun_settings = {
33
+ api_key: ENV['MAILGUN_API_KEY'],
34
+ domain: ENV['MAILGUN_API_DOMAIN']
35
+ }
36
+ end
37
+ CONFIG
38
+ application configuration, env: :production
39
+ end
40
+
41
+ # Add entries to .env and .env.local
42
+ def add_env_variables
43
+ configuration = <<-CONFIG.strip_heredoc
44
+
45
+ MAILGUN_API_KEY=
46
+ MAILGUN_API_DOMAIN=
47
+ CONFIG
48
+ append_to_file '.env', configuration
49
+ append_to_file '.env.local', configuration
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,28 @@
1
+ module DiscoApp
2
+ module Generators
3
+ class MonitorifyGenerator < Rails::Generators::Base
4
+
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ # Install the Rollbar, OJ and New Relic gems.
8
+ def install_gems
9
+ # Add gem to Gemfile
10
+ gem 'rollbar', '~> 2.8.0'
11
+ gem 'oj', '~> 2.14.5'
12
+ gem 'newrelic_rpm', '~> 3.14.1.314'
13
+
14
+ # Install gem.
15
+ Bundler.with_clean_env do
16
+ run 'bundle install'
17
+ end
18
+ end
19
+
20
+ # Copy Rollbar initializer and New Relic config file.
21
+ def configure
22
+ copy_file 'initializers/rollbar.rb', 'config/initializers/rollbar.rb'
23
+ copy_file 'config/newrelic.yml', 'config/newrelic.yml'
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,26 @@
1
+ # This file configures the New Relic Agent.
2
+ #
3
+ # For full documentation of agent configuration options, please refer to
4
+ # https://docs.newrelic.com/docs/agents/ruby-agent/installation-configuration/ruby-agent-configuration
5
+
6
+ common: &default_settings
7
+ license_key: <%= ENV['NEW_RELIC_LICENSE_KEY'] %>
8
+ app_name: <%= ENV['SHOPIFY_APP_NAME'] || 'Unknown App' %>
9
+
10
+ # To disable the agent regardless of other settings, uncomment the following:
11
+ # agent_enabled: false
12
+
13
+ # Logging level for log/newrelic_agent.log
14
+ log_level: info
15
+
16
+ development:
17
+ <<: *default_settings
18
+ app_name: <%= ENV['SHOPIFY_APP_NAME'] || 'Unknown App' %> (Development)
19
+ developer_mode: true
20
+
21
+ test:
22
+ <<: *default_settings
23
+ monitor_mode: false
24
+
25
+ production:
26
+ <<: *default_settings
@@ -0,0 +1,12 @@
1
+ Rollbar.configure do |config|
2
+ # Fetch the access token from the environment.
3
+ config.access_token = ENV['ROLLBAR_ACCESS_TOKEN']
4
+
5
+ # Only use Rollbar in production when there's a token configured.
6
+ unless config.access_token and Rails.env.production?
7
+ config.enabled = false
8
+ end
9
+
10
+ # Enable delayed reporting (using Sidekiq)
11
+ config.use_sidekiq
12
+ end
@@ -0,0 +1,45 @@
1
+ module DiscoApp
2
+ module Generators
3
+ class ReactifyGenerator < Rails::Generators::Base
4
+
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ # Install the react-rails gem and run its setup.
8
+ def install_gem
9
+ # Add gem to Gemfile
10
+ gem 'react-rails', '~> 1.5.0'
11
+
12
+ # Install gem.
13
+ Bundler.with_clean_env do
14
+ run 'bundle install'
15
+ end
16
+
17
+ # Run the gem's generator.
18
+ generate 'react:install'
19
+ end
20
+
21
+ # Set application configuration
22
+ def configure_application
23
+ application "config.react.variant = :development", env: :development
24
+ application "# Use development variant of React in development.", env: :development
25
+ application "config.react.variant = :production", env: :production
26
+ application "# Use production variant of React in production.", env: :production
27
+ end
28
+
29
+ # Include the DiscoApp component library in the application.js manifest.
30
+ def add_to_manifest
31
+ inject_into_file manifest, "//= require disco_app/components\n", { before: "//= require components\n" }
32
+ end
33
+
34
+ private
35
+
36
+ # This method of finding the application.js manifest taken from the
37
+ # install generator in react-rails.
38
+ # See https://github.com/reactjs/react-rails/blob/3f0af13fa755d6e95969c17728d0354c234f3a37/lib/generators/react/install_generator.rb#L53-L55
39
+ def manifest
40
+ Pathname.new(destination_root).join('app/assets/javascripts', 'application.js')
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,17 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ //= require turbolinks
16
+ //= require disco_app/disco_app
17
+ //= require_tree .
@@ -0,0 +1,5 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ */
5
+ @import "disco_app/disco_app";
@@ -0,0 +1,15 @@
1
+ workers Integer(ENV['WEB_CONCURRENCY'] || 2)
2
+ threads_count = Integer(ENV['MAX_THREADS'] || 5)
3
+ threads threads_count, threads_count
4
+
5
+ preload_app!
6
+
7
+ rackup DefaultRackup
8
+ port ENV['PORT'] || 3000
9
+ environment ENV['RACK_ENV'] || 'development'
10
+
11
+ on_worker_boot do
12
+ # Worker specific setup for Rails 4.1+
13
+ # See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot
14
+ ActiveRecord::Base.establish_connection
15
+ end
@@ -0,0 +1,7 @@
1
+ class HomeController < ApplicationController
2
+ include DiscoApp::AuthenticatedController
3
+
4
+ def index
5
+ end
6
+
7
+ end
@@ -0,0 +1,14 @@
1
+ DiscoApp::Engine.routes.default_url_options[:host] = ENV['DEFAULT_HOST']
2
+
3
+ DiscoApp.configure do |config|
4
+ # Required configuration.
5
+ config.app_name = ENV['SHOPIFY_APP_NAME']
6
+
7
+ # Set the below if using an application proxy.
8
+ config.app_proxy_prefix = ENV['SHOPIFY_APP_PROXY_PREFIX']
9
+
10
+ # Optional configuration, usually useful for development environments.
11
+ config.skip_proxy_verification = ENV['SKIP_PROXY_VERIFICATION']
12
+ config.skip_webhook_verification = ENV['SKIP_WEBHOOK_VERIFICATION']
13
+ config.skip_carrier_request_verification = ENV['SKIP_CARRIER_REQUEST_VERIFICATION']
14
+ end
@@ -0,0 +1,2 @@
1
+ # Use an ActiveRecord-based session store.
2
+ Rails.application.config.session_store :active_record_store, :key => '_disco_app_session'
@@ -0,0 +1,7 @@
1
+ ShopifyApp.configure do |config|
2
+ config.api_key = ENV['SHOPIFY_APP_API_KEY']
3
+ config.secret = ENV['SHOPIFY_APP_SECRET']
4
+ config.redirect_uri = ENV['SHOPIFY_APP_REDIRECT_URI']
5
+ config.scope = ENV['SHOPIFY_APP_SCOPE']
6
+ config.embedded_app = true
7
+ end
@@ -0,0 +1,7 @@
1
+ if Rails.configuration.cache_classes
2
+ ShopifyApp::SessionRepository.storage = DiscoApp::SessionStorage
3
+ else
4
+ ActionDispatch::Reloader.to_prepare do
5
+ ShopifyApp::SessionRepository.storage = DiscoApp::SessionStorage
6
+ end
7
+ end
@@ -0,0 +1,2 @@
1
+ web: bundle exec puma -C ./config/puma.rb
2
+ worker: bundle exec sidekiq -c 5 -v -q default -q mailers -q rollbar
@@ -0,0 +1,2 @@
1
+ <% provide(:title, 'Welcome') %>
2
+ <h1>Welcome</h1>
@@ -0,0 +1,10 @@
1
+ namespace :carrier_service do
2
+
3
+ desc 'Synchronise carrier service across all installed shops.'
4
+ task sync: :environment do
5
+ DiscoApp::Shop.installed.has_active_shopify_plan.each do |shop|
6
+ DiscoApp::SynchroniseCarrierServiceJob.perform_later(shop.shopify_domain)
7
+ end
8
+ end
9
+
10
+ end
@@ -0,0 +1,9 @@
1
+ namespace :sessions do
2
+
3
+ desc 'Clean out any stale sessions.'
4
+ task clean: [:environment, 'db:load_config'] do
5
+ threshold = (ENV['SESSIONS_CLEAN_THRESHOLD_DAYS'] || 30).to_i.days.ago
6
+ ActiveRecord::Base.connection.execute("DELETE FROM #{ActiveRecord::SessionStore::Session.table_name} WHERE updated_at < '#{threshold}'")
7
+ end
8
+
9
+ end
@@ -0,0 +1,3 @@
1
+ task start: :environment do
2
+ system 'bundle exec rails server -b 127.0.0.1 -p 3000'
3
+ end
@@ -0,0 +1,10 @@
1
+ namespace :webhooks do
2
+
3
+ desc 'Synchronise webhooks across all installed shops.'
4
+ task sync: :environment do
5
+ DiscoApp::Shop.installed.has_active_shopify_plan.each do |shop|
6
+ DiscoApp::SynchroniseWebhooksJob.perform_later(shop.shopify_domain)
7
+ end
8
+ end
9
+
10
+ end
@@ -0,0 +1,50 @@
1
+ require 'test_helper'
2
+
3
+ class DiscoApp::InstallControllerTest < ActionController::TestCase
4
+ include ActiveJob::TestHelper
5
+
6
+ def setup
7
+ @shop = disco_app_shops(:widget_store)
8
+ @routes = DiscoApp::Engine.routes
9
+ log_in_as(@shop)
10
+ end
11
+
12
+ def teardown
13
+ @shop = nil
14
+ end
15
+
16
+ test 'logged-in but uninstalled user triggers installation from install page' do
17
+ get(:install)
18
+ assert_redirected_to :installing
19
+ assert_enqueued_jobs 1
20
+ @shop.reload
21
+ assert @shop.awaiting_install?
22
+ end
23
+
24
+ test 'logged-in and installed user is redirected to installing url for install/uninstalling actions' do
25
+ @shop.installed!
26
+ [:install, :uninstalling].each do |action|
27
+ get(:install)
28
+ assert_redirected_to :installing
29
+ end
30
+ end
31
+
32
+ test 'logged-in and installed user is redirected to root url for installing' do
33
+ @shop.installed!
34
+ get(:installing)
35
+ assert_redirected_to Rails.application.routes.url_helpers.root_path
36
+ end
37
+
38
+ test 'logged-in and uninstalling user sees uninstalling page' do
39
+ @shop.uninstalling!
40
+ get(:uninstalling)
41
+ assert_response :success
42
+ end
43
+
44
+ test 'logged-in and uninstalled user starts install process again' do
45
+ @shop.uninstalled!
46
+ get(:uninstalling)
47
+ assert_redirected_to :install
48
+ end
49
+
50
+ end
@@ -0,0 +1,58 @@
1
+ require 'test_helper'
2
+
3
+ class DiscoApp::WebhooksControllerTest < ActionController::TestCase
4
+ include ActiveJob::TestHelper
5
+
6
+ def setup
7
+ @shop = disco_app_shops(:widget_store)
8
+ @routes = DiscoApp::Engine.routes
9
+ end
10
+
11
+ def teardown
12
+ @shop = nil
13
+ end
14
+
15
+ test 'webhook request without authentication information returns unauthorized' do
16
+ body = webhook_fixture('app_uninstalled')
17
+ post(:process_webhook, body)
18
+ assert_response :unauthorized
19
+ end
20
+
21
+ test 'webhook request with no HMAC returns unauthorized' do
22
+ body = webhook_fixture('app_uninstalled')
23
+ @request.headers['HTTP_X_SHOPIFY_TOPIC'] = :'app/uninstalled'
24
+ @request.headers['HTTP_X_SHOPIFY_SHOP_DOMAIN'] = @shop.shopify_domain
25
+ post(:process_webhook, body)
26
+ assert_response :unauthorized
27
+ end
28
+
29
+ test 'webhook request with invalid HMAC returns unauthorized' do
30
+ body = webhook_fixture('app_uninstalled')
31
+ @request.headers['HTTP_X_SHOPIFY_TOPIC'] = :'app/uninstalled'
32
+ @request.headers['HTTP_X_SHOPIFY_SHOP_DOMAIN'] = @shop.shopify_domain
33
+ @request.headers['HTTP_X_SHOPIFY_HMAC_SHA256'] = '0000'
34
+ post(:process_webhook, body)
35
+ assert_response :unauthorized
36
+ end
37
+
38
+ test 'webhook request with valid HMAC returns OK' do
39
+ body = webhook_fixture('app_uninstalled')
40
+ @request.headers['HTTP_X_SHOPIFY_TOPIC'] = :'app/uninstalled'
41
+ @request.headers['HTTP_X_SHOPIFY_SHOP_DOMAIN'] = @shop.shopify_domain
42
+ @request.headers['HTTP_X_SHOPIFY_HMAC_SHA256'] = DiscoApp::WebhookService.calculated_hmac(body, ShopifyApp.configuration.secret)
43
+ post(:process_webhook, body)
44
+ assert_response :ok
45
+ end
46
+
47
+ test 'app uninstalled job queued when app/uninstalled webhook arrives' do
48
+ body = webhook_fixture('app_uninstalled')
49
+ @request.headers['HTTP_X_SHOPIFY_TOPIC'] = :'app/uninstalled'
50
+ @request.headers['HTTP_X_SHOPIFY_SHOP_DOMAIN'] = @shop.shopify_domain
51
+ @request.headers['HTTP_X_SHOPIFY_HMAC_SHA256'] = DiscoApp::WebhookService.calculated_hmac(body, ShopifyApp.configuration.secret)
52
+
53
+ assert_enqueued_with(job: DiscoApp::AppUninstalledJob) do
54
+ post(:process_webhook, body)
55
+ end
56
+ end
57
+
58
+ end
@@ -0,0 +1,61 @@
1
+ require 'test_helper'
2
+
3
+ class HomeControllerTest < ActionController::TestCase
4
+
5
+ def setup
6
+ @shop = disco_app_shops(:widget_store)
7
+ log_in_as(@shop)
8
+ end
9
+
10
+ def teardown
11
+ @shop = nil
12
+ end
13
+
14
+ test 'non-logged in user is redirected to the login page' do
15
+ log_out
16
+ get(:index)
17
+ assert_redirected_to ShopifyApp::Engine.routes.url_helpers.login_path
18
+ end
19
+
20
+ test 'logged-in, never installed user is redirected to the install page' do
21
+ get(:index)
22
+ assert_redirected_to DiscoApp::Engine.routes.url_helpers.install_path
23
+ end
24
+
25
+ test 'logged-in, awaiting install user is redirected to the installing page' do
26
+ @shop.awaiting_install!
27
+ get(:index)
28
+ assert_redirected_to DiscoApp::Engine.routes.url_helpers.installing_path
29
+ end
30
+
31
+ test 'logged-in, installing user is redirected to the installing page' do
32
+ @shop.installing!
33
+ get(:index)
34
+ assert_redirected_to DiscoApp::Engine.routes.url_helpers.installing_path
35
+ end
36
+
37
+ test 'logged-in, installed user is able to access the page' do
38
+ @shop.installed!
39
+ get(:index)
40
+ assert_response :success
41
+ end
42
+
43
+ test 'logged-in, awaiting uninstall user is redirected to the uninstalling page' do
44
+ @shop.awaiting_uninstall!
45
+ get(:index)
46
+ assert_redirected_to DiscoApp::Engine.routes.url_helpers.uninstalling_path
47
+ end
48
+
49
+ test 'logged-in, uninstalling user is redirected to the uninstalling page' do
50
+ @shop.uninstalling!
51
+ get(:index)
52
+ assert_redirected_to DiscoApp::Engine.routes.url_helpers.uninstalling_path
53
+ end
54
+
55
+ test 'logged-in, uninstalled user is redirected to the install page' do
56
+ @shop.uninstalled!
57
+ get(:index)
58
+ assert_redirected_to DiscoApp::Engine.routes.url_helpers.install_path
59
+ end
60
+
61
+ end