disco_app 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Rakefile +37 -0
- data/app/assets/images/disco_app/icon.svg +1 -0
- data/app/assets/javascripts/disco_app/disco_app.js +7 -0
- data/app/assets/stylesheets/disco_app/bootstrap/_custom.scss +54 -0
- data/app/assets/stylesheets/disco_app/bootstrap/_variables.scss +872 -0
- data/app/assets/stylesheets/disco_app/disco/_buttons.scss +31 -0
- data/app/assets/stylesheets/disco_app/disco/_cards.scss +43 -0
- data/app/assets/stylesheets/disco_app/disco/_forms.scss +23 -0
- data/app/assets/stylesheets/disco_app/disco/_sections.scss +61 -0
- data/app/assets/stylesheets/disco_app/disco/_type.scss +21 -0
- data/app/assets/stylesheets/disco_app/disco/mixins/_flexbox.scss +394 -0
- data/app/assets/stylesheets/disco_app/disco_app.scss +13 -0
- data/app/controllers/disco_app/app_proxy_controller.rb +41 -0
- data/app/controllers/disco_app/authenticated_controller.rb +44 -0
- data/app/controllers/disco_app/carrier_request_controller.rb +28 -0
- data/app/controllers/disco_app/charges_controller.rb +30 -0
- data/app/controllers/disco_app/install_controller.rb +26 -0
- data/app/controllers/disco_app/webhooks_controller.rb +42 -0
- data/app/helpers/disco_app/application_helper.rb +4 -0
- data/app/jobs/disco_app/app_installed_job.rb +41 -0
- data/app/jobs/disco_app/app_uninstalled_job.rb +3 -0
- data/app/jobs/disco_app/concerns/app_uninstalled_job.rb +19 -0
- data/app/jobs/disco_app/shop_job.rb +29 -0
- data/app/jobs/disco_app/shop_update_job.rb +16 -0
- data/app/models/disco_app/concerns/plan.rb +14 -0
- data/app/models/disco_app/concerns/shop.rb +62 -0
- data/app/models/disco_app/concerns/subscription.rb +14 -0
- data/app/models/disco_app/plan.rb +3 -0
- data/app/models/disco_app/session_storage.rb +18 -0
- data/app/models/disco_app/shop.rb +3 -0
- data/app/models/disco_app/subscription.rb +3 -0
- data/app/services/disco_app/charges_service.rb +73 -0
- data/app/services/disco_app/subscription_service.rb +25 -0
- data/app/services/disco_app/webhook_service.rb +30 -0
- data/app/views/disco_app/charges/activate.html.erb +1 -0
- data/app/views/disco_app/charges/create.html.erb +1 -0
- data/app/views/disco_app/charges/new.html.erb +45 -0
- data/app/views/disco_app/install/installing.html.erb +7 -0
- data/app/views/disco_app/install/uninstalling.html.erb +1 -0
- data/app/views/disco_app/proxy_errors/404.html.erb +1 -0
- data/app/views/disco_app/shared/_card.html.erb +16 -0
- data/app/views/disco_app/shared/_section.html.erb +17 -0
- data/app/views/layouts/application.html.erb +18 -0
- data/app/views/layouts/embedded_app.html.erb +41 -0
- data/app/views/sessions/new.html.erb +26 -0
- data/config/routes.rb +19 -0
- data/db/migrate/20150525000000_create_shops_if_not_existent.rb +15 -0
- data/db/migrate/20150525162112_add_status_to_shops.rb +5 -0
- data/db/migrate/20150525171422_add_meta_to_shops.rb +11 -0
- data/db/migrate/20150629210346_add_charge_status_to_shop.rb +5 -0
- data/db/migrate/20150814214025_add_more_meta_to_shops.rb +15 -0
- data/db/migrate/20151017231302_create_disco_app_plans.rb +13 -0
- data/db/migrate/20151017232027_create_disco_app_subscriptions.rb +15 -0
- data/db/migrate/20151017234409_move_shop_to_disco_app_engine.rb +5 -0
- data/lib/disco_app/engine.rb +11 -0
- data/lib/disco_app/version.rb +3 -0
- data/lib/disco_app.rb +4 -0
- data/lib/generators/disco_app/USAGE +5 -0
- data/lib/generators/disco_app/disco_app_generator.rb +159 -0
- data/lib/generators/disco_app/mailify/mailify_generator.rb +55 -0
- data/lib/generators/disco_app/reactify/reactify_generator.rb +31 -0
- data/lib/generators/disco_app/templates/assets/javascripts/application.js +17 -0
- data/lib/generators/disco_app/templates/assets/stylesheets/application.scss +5 -0
- data/lib/generators/disco_app/templates/config/puma.rb +15 -0
- data/lib/generators/disco_app/templates/controllers/home_controller.rb +7 -0
- data/lib/generators/disco_app/templates/initializers/disco_app.rb +1 -0
- data/lib/generators/disco_app/templates/initializers/shopify_app.rb +7 -0
- data/lib/generators/disco_app/templates/initializers/shopify_session_repository.rb +7 -0
- data/lib/generators/disco_app/templates/root/Procfile +2 -0
- data/lib/generators/disco_app/templates/views/home/index.html.erb +2 -0
- data/test/controllers/disco_app/install_controller_test.rb +50 -0
- data/test/controllers/disco_app/webhooks_controller_test.rb +58 -0
- data/test/controllers/home_controller_test.rb +61 -0
- data/test/disco_app_test.rb +7 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +17 -0
- data/test/dummy/app/assets/stylesheets/application.scss +5 -0
- data/test/dummy/app/controllers/application_controller.rb +6 -0
- data/test/dummy/app/controllers/home_controller.rb +7 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/jobs/disco_app/app_uninstalled_job.rb +11 -0
- data/test/dummy/app/models/disco_app/shop.rb +15 -0
- data/test/dummy/app/views/home/index.html.erb +2 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config/application.rb +37 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +41 -0
- data/test/dummy/config/environments/production.rb +85 -0
- data/test/dummy/config/environments/test.rb +42 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/disco_app.rb +1 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/omniauth.rb +9 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/shopify_app.rb +7 -0
- data/test/dummy/config/initializers/shopify_session_repository.rb +7 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +8 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/schema.rb +70 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/fixtures/api/widget_store/shop.json +46 -0
- data/test/fixtures/disco_app/plans.yml +32 -0
- data/test/fixtures/disco_app/shops.yml +10 -0
- data/test/fixtures/disco_app/subscriptions.yml +26 -0
- data/test/fixtures/webhooks/app_uninstalled.json +46 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/jobs/disco_app/app_installed_job_test.rb +29 -0
- data/test/jobs/disco_app/app_uninstalled_job_test.rb +32 -0
- data/test/models/disco_app/plan_test.rb +5 -0
- data/test/models/disco_app/shop_test.rb +26 -0
- data/test/models/disco_app/subscription_test.rb +6 -0
- data/test/services/disco_app/subscription_service_test.rb +28 -0
- data/test/support/test_file_fixtures.rb +29 -0
- data/test/test_helper.rb +51 -0
- metadata +456 -0
data/config/routes.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
DiscoApp::Engine.routes.draw do
|
|
2
|
+
|
|
3
|
+
controller :webhooks do
|
|
4
|
+
post 'webhooks' => :process_webhook, as: :webhooks
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
controller :charges do
|
|
8
|
+
get 'charges/new' => :new, as: :new_charge
|
|
9
|
+
post 'charges/create' => :create, as: :create_charge
|
|
10
|
+
get 'charges/activate' => :activate, as: :activate_charge
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
controller :install do
|
|
14
|
+
get 'install' => :install, as: :install
|
|
15
|
+
get 'installing' => :installing, as: :installing
|
|
16
|
+
get 'uninstalling' => :uninstalling, as: :uninstalling
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class CreateShopsIfNotExistent < ActiveRecord::Migration
|
|
2
|
+
|
|
3
|
+
def change
|
|
4
|
+
unless table_exists? :shops or table_exists? :disco_app_shops
|
|
5
|
+
create_table :shops do |t|
|
|
6
|
+
t.string :shopify_domain, null: false
|
|
7
|
+
t.string :shopify_token, null: false
|
|
8
|
+
t.timestamps
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
add_index :shops, :shopify_domain, unique: true
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class AddMetaToShops < ActiveRecord::Migration
|
|
2
|
+
def change
|
|
3
|
+
add_column :shops, :email, :string
|
|
4
|
+
add_column :shops, :country_name, :string
|
|
5
|
+
add_column :shops, :currency, :string
|
|
6
|
+
add_column :shops, :money_format, :string
|
|
7
|
+
add_column :shops, :money_with_currency_format, :string
|
|
8
|
+
add_column :shops, :domain, :string
|
|
9
|
+
add_column :shops, :plan_name, :string
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class AddMoreMetaToShops < ActiveRecord::Migration
|
|
2
|
+
def change
|
|
3
|
+
add_column :shops, :plan_display_name, :string
|
|
4
|
+
add_column :shops, :latitude, :decimal
|
|
5
|
+
add_column :shops, :longitude, :decimal
|
|
6
|
+
add_column :shops, :customer_email, :string
|
|
7
|
+
add_column :shops, :password_enabled, :boolean
|
|
8
|
+
add_column :shops, :phone, :string
|
|
9
|
+
add_column :shops, :primary_locale, :string
|
|
10
|
+
add_column :shops, :ships_to_countries, :string
|
|
11
|
+
add_column :shops, :timezone, :string
|
|
12
|
+
add_column :shops, :iana_timezone, :string
|
|
13
|
+
add_column :shops, :has_storefront, :boolean
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class CreateDiscoAppPlans < ActiveRecord::Migration
|
|
2
|
+
def change
|
|
3
|
+
create_table :disco_app_plans do |t|
|
|
4
|
+
t.integer :status
|
|
5
|
+
t.string :name
|
|
6
|
+
t.integer :charge_type
|
|
7
|
+
t.decimal :default_price
|
|
8
|
+
t.integer :default_trial_days
|
|
9
|
+
|
|
10
|
+
t.timestamps null: false
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class CreateDiscoAppSubscriptions < ActiveRecord::Migration
|
|
2
|
+
def change
|
|
3
|
+
create_table :disco_app_subscriptions do |t|
|
|
4
|
+
t.belongs_to :shop, index: true
|
|
5
|
+
t.belongs_to :plan, index: true
|
|
6
|
+
t.integer :status
|
|
7
|
+
t.string :name
|
|
8
|
+
t.integer :charge_type
|
|
9
|
+
t.decimal :price
|
|
10
|
+
t.integer :trial_days
|
|
11
|
+
|
|
12
|
+
t.timestamps null: false
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/lib/disco_app.rb
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
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.sample 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.sample .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.2.0'
|
|
31
|
+
gem 'sidekiq', '~> 3.5.1'
|
|
32
|
+
gem 'puma', '~> 2.14.0'
|
|
33
|
+
gem 'bootstrap-sass', '~> 3.3.5.1'
|
|
34
|
+
|
|
35
|
+
# Add gems for development and testing only.
|
|
36
|
+
gem_group :development, :test do
|
|
37
|
+
gem 'sqlite3', '~> 1.3.11'
|
|
38
|
+
gem 'dotenv-rails', '~> 2.0.2'
|
|
39
|
+
gem 'minitest-reporters', '~> 1.0.19'
|
|
40
|
+
gem 'guard', '~> 2.13.0'
|
|
41
|
+
gem 'guard-minitest', '~> 2.4.4'
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Add gems for production only.
|
|
45
|
+
gem_group :production do
|
|
46
|
+
gem 'pg', '~> 0.18.3'
|
|
47
|
+
gem 'rails_12factor', '~> 0.0.3'
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Make any required adjustments to the application configuration.
|
|
52
|
+
def configure_application
|
|
53
|
+
# The force_ssl flag is commented by default for production.
|
|
54
|
+
# Uncomment to ensure config.force_ssl = true in production.
|
|
55
|
+
uncomment_lines 'config/environments/production.rb', /force_ssl/
|
|
56
|
+
|
|
57
|
+
# Set defaults for various charge attributes.
|
|
58
|
+
application "config.x.shopify_charges_default_trial_days = 14\n"
|
|
59
|
+
application "config.x.shopify_charges_default_price = 10.00"
|
|
60
|
+
application "config.x.shopify_charges_default_type = :recurring"
|
|
61
|
+
application "# Set defaults for charges created by the application"
|
|
62
|
+
|
|
63
|
+
# Set the "real charges" config variable to false explicitly by default.
|
|
64
|
+
# Only in production do we read from the environment variable and potentially have it become true.
|
|
65
|
+
application "config.x.shopify_charges_real = false\n"
|
|
66
|
+
application "# Explicitly prevent real charges being created by default"
|
|
67
|
+
application "config.x.shopify_charges_real = ENV['SHOPIFY_CHARGES_REAL'] == 'true'\n", env: :production
|
|
68
|
+
application "# Allow real charges in production with an ENV variable", env: :production
|
|
69
|
+
|
|
70
|
+
# Set Sidekiq as the queue adapter in production.
|
|
71
|
+
application "config.active_job.queue_adapter = :sidekiq\n", env: :production
|
|
72
|
+
application "# Use Sidekiq as the active job backend", env: :production
|
|
73
|
+
|
|
74
|
+
# Ensure the application configuration uses the DEFAULT_HOST environment variable to set up support for reverse
|
|
75
|
+
# routing absolute URLS (needed when generating Webhook URLs for example).
|
|
76
|
+
application "routes.default_url_options[:host] = ENV['DEFAULT_HOST']\n"
|
|
77
|
+
application "# Set the default host for absolute URL routing purposes"
|
|
78
|
+
|
|
79
|
+
application "config.x.shopify_app_name = ENV['SHOPIFY_APP_NAME']\n"
|
|
80
|
+
application "# Set the name of the application"
|
|
81
|
+
|
|
82
|
+
# Copy over the default puma configuration.
|
|
83
|
+
copy_file 'config/puma.rb', 'config/puma.rb'
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Create Rakefiles
|
|
87
|
+
def create_rakefiles
|
|
88
|
+
rakefile 'start.rake' do
|
|
89
|
+
<<-RAKEFILE.strip_heredoc
|
|
90
|
+
task start: :environment do
|
|
91
|
+
system 'bundle exec rails server -b 127.0.0.1 -p 3000'
|
|
92
|
+
end
|
|
93
|
+
RAKEFILE
|
|
94
|
+
end
|
|
95
|
+
rakefile 'console.rake' do
|
|
96
|
+
<<-RAKEFILE.strip_heredoc
|
|
97
|
+
task console: :environment do
|
|
98
|
+
system 'bundle exec rails console'
|
|
99
|
+
end
|
|
100
|
+
RAKEFILE
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Set up routes.
|
|
105
|
+
def setup_routes
|
|
106
|
+
route "mount DiscoApp::Engine, at: '/'"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Run shopify_app:install
|
|
110
|
+
def shopify_app_install
|
|
111
|
+
generate 'shopify_app:install'
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Copy template files to the appropriate location. In some cases, we'll be
|
|
115
|
+
# overwriting or removing existing files or those created by ShopifyApp.
|
|
116
|
+
def copy_and_remove_files
|
|
117
|
+
# Copy initializers
|
|
118
|
+
copy_file 'initializers/shopify_app.rb', 'config/initializers/shopify_app.rb'
|
|
119
|
+
copy_file 'initializers/disco_app.rb', 'config/initializers/disco_app.rb'
|
|
120
|
+
copy_file 'initializers/shopify_session_repository.rb', 'config/initializers/shopify_session_repository.rb'
|
|
121
|
+
|
|
122
|
+
# Copy default home controller and view
|
|
123
|
+
copy_file 'controllers/home_controller.rb', 'app/controllers/home_controller.rb'
|
|
124
|
+
copy_file 'views/home/index.html.erb', 'app/views/home/index.html.erb'
|
|
125
|
+
|
|
126
|
+
# Copy assets
|
|
127
|
+
copy_file 'assets/javascripts/application.js', 'app/assets/javascripts/application.js'
|
|
128
|
+
copy_file 'assets/stylesheets/application.scss', 'app/assets/stylesheets/application.scss'
|
|
129
|
+
|
|
130
|
+
# Remove application.css
|
|
131
|
+
remove_file 'app/assets/stylesheets/application.css'
|
|
132
|
+
|
|
133
|
+
# Remove the layout files created by ShopifyApp
|
|
134
|
+
remove_file 'app/views/layout/application.html.erb'
|
|
135
|
+
remove_file 'app/views/layout/embedded_app.html.erb'
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Copy engine migrations over.
|
|
139
|
+
def install_migrations
|
|
140
|
+
rake 'disco_app:install:migrations'
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Run migrations.
|
|
144
|
+
def migrate
|
|
145
|
+
rake 'db:migrate'
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Lock down the application to a specific Ruby version:
|
|
149
|
+
#
|
|
150
|
+
# - Via .ruby-version file for rbenv in development;
|
|
151
|
+
# - Via a Gemfile line in production.
|
|
152
|
+
#
|
|
153
|
+
# This should be the last operation, to allow all other operations to run in the initial Ruby version.
|
|
154
|
+
def set_ruby_version
|
|
155
|
+
copy_file 'root/.ruby-version', '.ruby-version'
|
|
156
|
+
prepend_to_file 'Gemfile', "ruby '2.2.2'\n"
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module DiscoApp
|
|
2
|
+
module Generators
|
|
3
|
+
class MailifyGenerator < 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 premailer gem to Gemfile.
|
|
10
|
+
gem 'premailer-rails', '~> 1.8.2'
|
|
11
|
+
|
|
12
|
+
# Add explicit dependency on Nokogiri
|
|
13
|
+
gem 'nokogiri', '~> 1.6.6.1'
|
|
14
|
+
|
|
15
|
+
# Add the Mailgun rails gem (production only)
|
|
16
|
+
gem_group :production do
|
|
17
|
+
gem 'mailgun_rails', '~> 0.7.0'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Install gem.
|
|
21
|
+
Bundler.with_clean_env do
|
|
22
|
+
run 'bundle install'
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Set application configuration
|
|
27
|
+
def configure_application
|
|
28
|
+
configuration = <<-CONFIG.strip_heredoc
|
|
29
|
+
|
|
30
|
+
# Configure ActionMailer to use MailGun
|
|
31
|
+
if ENV['MAILGUN_API_KEY']
|
|
32
|
+
config.action_mailer.delivery_method = :mailgun
|
|
33
|
+
config.action_mailer.mailgun_settings = {
|
|
34
|
+
api_key: ENV['MAILGUN_API_KEY'],
|
|
35
|
+
domain: ENV['MAILGUN_API_DOMAIN']
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
CONFIG
|
|
39
|
+
application configuration, env: :production
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Add entries to .env and .env.sample
|
|
43
|
+
def add_env_variables
|
|
44
|
+
configuration = <<-CONFIG.strip_heredoc
|
|
45
|
+
|
|
46
|
+
MAILGUN_API_KEY=
|
|
47
|
+
MAILGUN_API_DOMAIN=
|
|
48
|
+
CONFIG
|
|
49
|
+
append_to_file '.env', configuration
|
|
50
|
+
append_to_file '.env.sample', configuration
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
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.1.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
|
+
end
|
|
30
|
+
end
|
|
31
|
+
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,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 @@
|
|
|
1
|
+
DiscoApp::Engine.routes.default_url_options[:host] = ENV['DEFAULT_HOST']
|
|
@@ -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
|
data/test/dummy/Rakefile
ADDED