shopify_app 12.0.4 → 13.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +13 -6
  3. data/CHANGELOG.md +28 -0
  4. data/Gemfile +3 -0
  5. data/README.md +98 -20
  6. data/Rakefile +1 -0
  7. data/app/controllers/concerns/shopify_app/authenticated.rb +1 -1
  8. data/app/controllers/shopify_app/authenticated_controller.rb +1 -0
  9. data/app/controllers/shopify_app/callback_controller.rb +15 -11
  10. data/app/controllers/shopify_app/sessions_controller.rb +35 -9
  11. data/app/controllers/shopify_app/webhooks_controller.rb +6 -5
  12. data/config/locales/fi.yml +1 -1
  13. data/config/routes.rb +1 -0
  14. data/lib/generators/shopify_app/add_after_authenticate_job/add_after_authenticate_job_generator.rb +5 -3
  15. data/lib/generators/shopify_app/add_after_authenticate_job/templates/after_authenticate_job.rb +1 -0
  16. data/lib/generators/shopify_app/add_marketing_activity_extension/add_marketing_activity_extension_generator.rb +2 -1
  17. data/lib/generators/shopify_app/add_marketing_activity_extension/templates/marketing_activities_controller.rb +4 -4
  18. data/lib/generators/shopify_app/add_webhook/add_webhook_generator.rb +5 -4
  19. data/lib/generators/shopify_app/add_webhook/templates/webhook_job.rb +5 -0
  20. data/lib/generators/shopify_app/app_proxy_controller/app_proxy_controller_generator.rb +4 -3
  21. data/lib/generators/shopify_app/app_proxy_controller/templates/app_proxy_controller.rb +3 -3
  22. data/lib/generators/shopify_app/app_proxy_controller/templates/app_proxy_route.rb +10 -9
  23. data/lib/generators/shopify_app/controllers/controllers_generator.rb +1 -0
  24. data/lib/generators/shopify_app/home_controller/home_controller_generator.rb +4 -3
  25. data/lib/generators/shopify_app/home_controller/templates/index.html.erb +1 -1
  26. data/lib/generators/shopify_app/install/install_generator.rb +9 -8
  27. data/lib/generators/shopify_app/install/templates/embedded_app.html.erb +1 -1
  28. data/lib/generators/shopify_app/install/templates/omniauth.rb +2 -1
  29. data/lib/generators/shopify_app/install/templates/shopify_app.rb +1 -1
  30. data/lib/generators/shopify_app/install/templates/shopify_provider.rb +1 -1
  31. data/lib/generators/shopify_app/install/templates/user_agent.rb +2 -1
  32. data/lib/generators/shopify_app/routes/routes_generator.rb +1 -0
  33. data/lib/generators/shopify_app/routes/templates/routes.rb +10 -9
  34. data/lib/generators/shopify_app/shop_model/shop_model_generator.rb +5 -4
  35. data/lib/generators/shopify_app/shop_model/templates/shop.rb +2 -1
  36. data/lib/generators/shopify_app/shopify_app_generator.rb +4 -3
  37. data/lib/generators/shopify_app/user_model/templates/user.rb +2 -1
  38. data/lib/generators/shopify_app/user_model/user_model_generator.rb +5 -4
  39. data/lib/generators/shopify_app/views/views_generator.rb +1 -0
  40. data/lib/shopify_app.rb +9 -4
  41. data/lib/shopify_app/configuration.rb +20 -10
  42. data/lib/shopify_app/controller_concerns/app_proxy_verification.rb +3 -2
  43. data/lib/shopify_app/controller_concerns/embedded_app.rb +3 -2
  44. data/lib/shopify_app/controller_concerns/localization.rb +1 -0
  45. data/lib/shopify_app/controller_concerns/login_protection.rb +65 -25
  46. data/lib/shopify_app/controller_concerns/webhook_verification.rb +2 -1
  47. data/lib/shopify_app/engine.rb +1 -0
  48. data/lib/shopify_app/jobs/scripttags_manager_job.rb +1 -1
  49. data/lib/shopify_app/jobs/webhooks_manager_job.rb +1 -1
  50. data/lib/shopify_app/managers/scripttags_manager.rb +4 -3
  51. data/lib/shopify_app/managers/webhooks_manager.rb +4 -3
  52. data/lib/shopify_app/middleware/same_site_cookie_middleware.rb +5 -38
  53. data/lib/shopify_app/session/in_memory_session_store.rb +7 -3
  54. data/lib/shopify_app/session/in_memory_shop_session_store.rb +14 -0
  55. data/lib/shopify_app/session/in_memory_user_session_store.rb +14 -0
  56. data/lib/shopify_app/session/jwt.rb +48 -0
  57. data/lib/shopify_app/session/null_user_session_store.rb +22 -0
  58. data/lib/shopify_app/session/session_repository.rb +36 -14
  59. data/lib/shopify_app/session/session_storage.rb +1 -10
  60. data/lib/shopify_app/session/shop_session_storage.rb +42 -0
  61. data/lib/shopify_app/session/user_session_storage.rb +42 -0
  62. data/lib/shopify_app/test_helpers/all.rb +1 -0
  63. data/lib/shopify_app/test_helpers/webhook_verification_helper.rb +16 -0
  64. data/lib/shopify_app/utils.rb +6 -5
  65. data/lib/shopify_app/version.rb +2 -1
  66. data/package-lock.json +1231 -1210
  67. data/package.json +1 -1
  68. data/shopify_app.gemspec +12 -8
  69. data/yarn.lock +3 -3
  70. metadata +32 -11
  71. data/lib/shopify_app/session/storage_strategies/shop_storage_strategy.rb +0 -23
  72. data/lib/shopify_app/session/storage_strategies/user_storage_strategy.rb +0 -24
@@ -1,14 +1,15 @@
1
+ # frozen_string_literal: true
1
2
  module ShopifyApp
3
+ class MissingWebhookJobError < StandardError; end
4
+
2
5
  class WebhooksController < ActionController::Base
3
6
  include ShopifyApp::WebhookVerification
4
7
 
5
- class ShopifyApp::MissingWebhookJobError < StandardError; end
6
-
7
8
  def receive
8
9
  params.permit!
9
- job_args = {shop_domain: shop_domain, webhook: webhook_params.to_h}
10
+ job_args = { shop_domain: shop_domain, webhook: webhook_params.to_h }
10
11
  webhook_job_klass.perform_later(job_args)
11
- head :no_content
12
+ head(:no_content)
12
13
  end
13
14
 
14
15
  private
@@ -18,7 +19,7 @@ module ShopifyApp
18
19
  end
19
20
 
20
21
  def webhook_job_klass
21
- webhook_job_klass_name.safe_constantize or raise ShopifyApp::MissingWebhookJobError
22
+ webhook_job_klass_name.safe_constantize || raise(ShopifyApp::MissingWebhookJobError)
22
23
  end
23
24
 
24
25
  def webhook_job_klass_name(type = webhook_type)
@@ -15,6 +15,6 @@ fi:
15
15
  top_level_interaction_action: Jatka
16
16
  request_storage_access_heading: "%{app} edellyttää evästeiden käyttöä"
17
17
  request_storage_access_body: Näin sovellus voi todentaa sinut tallentamalla henkilötietosi
18
- tilapäisesti. Napsauta Jatka ja salli evästeet sovelluksen käyttämiseksi.
18
+ tilapäisesti. Klikkaa Jatka ja salli evästeet sovelluksen käyttämiseksi.
19
19
  request_storage_access_footer: Evästeet vanhenevat 30 päivän kuluttua.
20
20
  request_storage_access_action: Jatka
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  ShopifyApp::Engine.routes.draw do
2
3
  controller :sessions do
3
4
  get 'login' => :new, :as => :login
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'rails/generators/base'
2
3
 
3
4
  module ShopifyApp
@@ -6,7 +7,7 @@ module ShopifyApp
6
7
  source_root File.expand_path('../templates', __FILE__)
7
8
 
8
9
  hook_for :test_framework, as: :job, in: :rails do |instance, generator|
9
- instance.invoke generator, [ instance.send(:job_file_name) ]
10
+ instance.invoke(generator, [instance.send(:job_file_name)])
10
11
  end
11
12
 
12
13
  def init_after_authenticate_config
@@ -23,12 +24,13 @@ module ShopifyApp
23
24
  )
24
25
 
25
26
  unless initializer.include?(after_authenticate_job_config)
26
- shell.say("Error adding after_authenticate_job to config. Add this line manually: #{after_authenticate_job_config}", :red)
27
+ shell.say("Error adding after_authenticate_job to config. Add this line manually: "\
28
+ "#{after_authenticate_job_config}", :red)
27
29
  end
28
30
  end
29
31
 
30
32
  def add_after_authenticate_job
31
- template 'after_authenticate_job.rb', "app/jobs/#{job_file_name}_job.rb"
33
+ template('after_authenticate_job.rb', "app/jobs/#{job_file_name}_job.rb")
32
34
  end
33
35
 
34
36
  private
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shopify
2
3
  class AfterAuthenticateJob < ActiveJob::Base
3
4
  def perform(shop_domain:)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'rails/generators/base'
2
3
 
3
4
  module ShopifyApp
@@ -6,7 +7,7 @@ module ShopifyApp
6
7
  source_root File.expand_path('../templates', __FILE__)
7
8
 
8
9
  def generate_app_extension
9
- template "marketing_activities_controller.rb", "app/controllers/marketing_activities_controller.rb"
10
+ template("marketing_activities_controller.rb", "app/controllers/marketing_activities_controller.rb")
10
11
  generate_routes
11
12
  end
12
13
 
@@ -3,7 +3,7 @@
3
3
  class MarketingActivitiesController < ShopifyApp::ExtensionVerificationController
4
4
  def preload_form_data
5
5
  preload_data = {
6
- "form_data": {}
6
+ "form_data": {},
7
7
  }
8
8
  render(json: preload_data, status: :ok)
9
9
  end
@@ -31,14 +31,14 @@ class MarketingActivitiesController < ShopifyApp::ExtensionVerificationControlle
31
31
  "preview_url": placeholder_img,
32
32
  "content_type": "text/html",
33
33
  "width": 360,
34
- "height": 200
34
+ "height": 200,
35
35
  },
36
36
  "mobile": {
37
37
  "preview_url": placeholder_img,
38
38
  "content_type": "text/html",
39
39
  "width": 360,
40
- "height": 200
41
- }
40
+ "height": 200,
41
+ },
42
42
  }
43
43
  render(json: preview_response, status: :ok)
44
44
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'rails/generators/base'
2
3
 
3
4
  module ShopifyApp
@@ -8,7 +9,7 @@ module ShopifyApp
8
9
  class_option :address, type: :string, aliases: "-a", required: true
9
10
 
10
11
  hook_for :test_framework, as: :job, in: :rails do |instance, generator|
11
- instance.invoke generator, [ instance.send(:job_file_name) ]
12
+ instance.invoke(generator, [instance.send(:job_file_name)])
12
13
  end
13
14
 
14
15
  def init_webhook_config
@@ -32,14 +33,14 @@ module ShopifyApp
32
33
  initializer = load_initializer
33
34
 
34
35
  unless initializer.include?(webhook_config)
35
- shell.say "Error adding webhook to config. Add this line manually: #{webhook_config}", :red
36
+ shell.say("Error adding webhook to config. Add this line manually: #{webhook_config}", :red)
36
37
  end
37
38
  end
38
39
 
39
40
  def add_webhook_job
40
41
  @job_file_name = job_file_name + '_job'
41
- @job_class_name = @job_file_name.classify
42
- template 'webhook_job.rb', "app/jobs/#{@job_file_name}.rb"
42
+ @job_class_name = @job_file_name.classify
43
+ template('webhook_job.rb', "app/jobs/#{@job_file_name}.rb")
43
44
  end
44
45
 
45
46
  private
@@ -2,6 +2,11 @@ class <%= @job_class_name %> < ActiveJob::Base
2
2
  def perform(shop_domain:, webhook:)
3
3
  shop = Shop.find_by(shopify_domain: shop_domain)
4
4
 
5
+ if shop.nil?
6
+ logger.error("#{self.class} failed: cannot find shop with domain '#{shop_domain}'")
7
+ return
8
+ end
9
+
5
10
  shop.with_shopify_session do
6
11
  end
7
12
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'rails/generators/base'
2
3
 
3
4
  module ShopifyApp
@@ -6,11 +7,11 @@ module ShopifyApp
6
7
  source_root File.expand_path('../templates', __FILE__)
7
8
 
8
9
  def create_app_proxy_controller
9
- template 'app_proxy_controller.rb', 'app/controllers/app_proxy_controller.rb'
10
+ template('app_proxy_controller.rb', 'app/controllers/app_proxy_controller.rb')
10
11
  end
11
12
 
12
13
  def create_app_proxy_index_view
13
- copy_file 'index.html.erb', 'app/views/app_proxy/index.html.erb'
14
+ copy_file('index.html.erb', 'app/views/app_proxy/index.html.erb')
14
15
  end
15
16
 
16
17
  def add_app_proxy_route
@@ -18,7 +19,7 @@ module ShopifyApp
18
19
  'config/routes.rb',
19
20
  File.read(File.expand_path(find_in_source_paths('app_proxy_route.rb'))),
20
21
  after: "mount ShopifyApp::Engine, at: '/'\n"
21
- )
22
+ )
22
23
  end
23
24
  end
24
25
  end
@@ -1,8 +1,8 @@
1
+ # frozen_string_literal: true
1
2
  class AppProxyController < ApplicationController
2
- include ShopifyApp::AppProxyVerification
3
+ include ShopifyApp::AppProxyVerification
3
4
 
4
5
  def index
5
- render layout: false, content_type: 'application/liquid'
6
+ render(layout: false, content_type: 'application/liquid')
6
7
  end
7
-
8
8
  end
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
1
2
 
2
- namespace :app_proxy do
3
- root action: 'index'
4
- # simple routes without a specified controller will go to AppProxyController
5
-
6
- # more complex routes will go to controllers in the AppProxy namespace
7
- # resources :reviews
8
- # GET /app_proxy/reviews will now be routed to
9
- # AppProxy::ReviewsController#index, for example
10
- end
3
+ namespace :app_proxy do
4
+ root action: 'index'
5
+ # simple routes without a specified controller will go to AppProxyController
6
+
7
+ # more complex routes will go to controllers in the AppProxy namespace
8
+ # resources :reviews
9
+ # GET /app_proxy/reviews will now be routed to
10
+ # AppProxy::ReviewsController#index, for example
11
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'rails/generators/base'
2
3
 
3
4
  module ShopifyApp
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'rails/generators/base'
2
3
 
3
4
  module ShopifyApp
@@ -6,15 +7,15 @@ module ShopifyApp
6
7
  source_root File.expand_path('../templates', __FILE__)
7
8
 
8
9
  def create_home_controller
9
- template 'home_controller.rb', 'app/controllers/home_controller.rb'
10
+ template('home_controller.rb', 'app/controllers/home_controller.rb')
10
11
  end
11
12
 
12
13
  def create_home_index_view
13
- copy_file 'index.html.erb', 'app/views/home/index.html.erb'
14
+ copy_file('index.html.erb', 'app/views/home/index.html.erb')
14
15
  end
15
16
 
16
17
  def add_home_index_route
17
- route "root :to => 'home#index'"
18
+ route("root :to => 'home#index'")
18
19
  end
19
20
 
20
21
  def embedded_app?
@@ -2,7 +2,7 @@
2
2
 
3
3
  <ul>
4
4
  <% @products.each do |product| %>
5
- <li><%= link_to product.title, "https://#{@shop_session.domain}/admin/products/#{product.id}", target: "_top" %></li>
5
+ <li><%= link_to product.title, "https://#{@current_shopify_session.domain}/admin/products/#{product.id}", target: "_top" %></li>
6
6
  <% end %>
7
7
  </ul>
8
8
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'rails/generators/base'
2
3
 
3
4
  module ShopifyApp
@@ -16,7 +17,7 @@ module ShopifyApp
16
17
  @scope = format_array_argument(options['scope'])
17
18
  @api_version = options['api_version'] || ShopifyAPI::Meta.admin_versions.find(&:latest_supported).handle
18
19
 
19
- template 'shopify_app.rb', 'config/initializers/shopify_app.rb'
20
+ template('shopify_app.rb', 'config/initializers/shopify_app.rb')
20
21
  end
21
22
 
22
23
  def create_session_store_initializer
@@ -24,22 +25,22 @@ module ShopifyApp
24
25
  end
25
26
 
26
27
  def create_and_inject_into_omniauth_initializer
27
- unless File.exist? "config/initializers/omniauth.rb"
28
- copy_file 'omniauth.rb', 'config/initializers/omniauth.rb'
28
+ unless File.exist?("config/initializers/omniauth.rb")
29
+ copy_file('omniauth.rb', 'config/initializers/omniauth.rb')
29
30
  end
30
31
 
31
32
  inject_into_file(
32
33
  'config/initializers/omniauth.rb',
33
34
  File.read(File.expand_path(find_in_source_paths('shopify_provider.rb'))),
34
- after: "Rails.application.config.middleware.use OmniAuth::Builder do\n"
35
+ after: "Rails.application.config.middleware.use(OmniAuth::Builder) do\n"
35
36
  )
36
37
  end
37
38
 
38
39
  def create_embedded_app_layout
39
40
  return unless embedded_app?
40
41
 
41
- copy_file 'embedded_app.html.erb', 'app/views/layouts/embedded_app.html.erb'
42
- copy_file '_flash_messages.html.erb', 'app/views/layouts/_flash_messages.html.erb'
42
+ copy_file('embedded_app.html.erb', 'app/views/layouts/embedded_app.html.erb')
43
+ copy_file('_flash_messages.html.erb', 'app/views/layouts/_flash_messages.html.erb')
43
44
 
44
45
  if ShopifyApp.use_webpacker?
45
46
  copy_file('shopify_app.js', 'app/javascript/shopify_app/shopify_app.js')
@@ -53,11 +54,11 @@ module ShopifyApp
53
54
  end
54
55
 
55
56
  def create_user_agent_initializer
56
- template 'user_agent.rb', 'config/initializers/user_agent.rb'
57
+ template('user_agent.rb', 'config/initializers/user_agent.rb')
57
58
  end
58
59
 
59
60
  def mount_engine
60
- route "mount ShopifyApp::Engine, at: '/'"
61
+ route("mount ShopifyApp::Engine, at: '/'")
61
62
  end
62
63
 
63
64
  def insert_hosts_into_development_config
@@ -28,7 +28,7 @@
28
28
 
29
29
  <%= content_tag(:div, nil, id: 'shopify-app-init', data: {
30
30
  api_key: ShopifyApp.configuration.api_key,
31
- shop_origin: (@shop_session.domain if @shop_session),
31
+ shop_origin: (@current_shopify_session.domain if @current_shopify_session),
32
32
  debug: Rails.env.development?
33
33
  } ) %>
34
34
 
@@ -1,2 +1,3 @@
1
- Rails.application.config.middleware.use OmniAuth::Builder do
1
+ # frozen_string_literal: true
2
+ Rails.application.config.middleware.use(OmniAuth::Builder) do
2
3
  end
@@ -8,7 +8,7 @@ ShopifyApp.configure do |config|
8
8
  config.embedded_app = <%= embedded_app? %>
9
9
  config.after_authenticate_job = false
10
10
  config.api_version = "<%= @api_version %>"
11
- config.session_repository = 'ShopifyApp::InMemorySessionStore'
11
+ config.shop_session_repository = 'ShopifyApp::InMemoryShopSessionStore'
12
12
  end
13
13
 
14
14
  # ShopifyApp::Utils.fetch_known_api_versions # Uncomment to fetch known api versions from shopify servers on boot
@@ -4,7 +4,6 @@ provider :shopify,
4
4
  ShopifyApp.configuration.api_key,
5
5
  ShopifyApp.configuration.secret,
6
6
  scope: ShopifyApp.configuration.scope,
7
- per_user_permissions: ShopifyApp.configuration.per_user_tokens,
8
7
  setup: lambda { |env|
9
8
  strategy = env['omniauth.strategy']
10
9
 
@@ -17,4 +16,5 @@ provider :shopify,
17
16
 
18
17
  strategy.options[:client_options][:site] = shop
19
18
  strategy.options[:old_client_secret] = ShopifyApp.configuration.old_secret
19
+ strategy.options[:per_user_permissions] = strategy.session[:user_tokens]
20
20
  }
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  module ShopifyAPI
2
3
  class Base < ActiveResource::Base
3
- self.headers['User-Agent'] << " | ShopifyApp/#{ShopifyApp::VERSION}"
4
+ headers['User-Agent'] << " | ShopifyApp/#{ShopifyApp::VERSION}"
4
5
  end
5
6
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'rails/generators/base'
2
3
 
3
4
  module ShopifyApp
@@ -1,11 +1,12 @@
1
+ # frozen_string_literal: true
1
2
 
2
- controller :sessions do
3
- get 'login' => :new, :as => :login
4
- post 'login' => :create, :as => :authenticate
5
- get 'auth/shopify/callback' => :callback
6
- get 'logout' => :destroy, :as => :logout
7
- end
3
+ controller :sessions do
4
+ get 'login' => :new, :as => :login
5
+ post 'login' => :create, :as => :authenticate
6
+ get 'auth/shopify/callback' => :callback
7
+ get 'logout' => :destroy, :as => :logout
8
+ end
8
9
 
9
- namespace :webhooks do
10
- post ':type' => :receive
11
- end
10
+ namespace :webhooks do
11
+ post ':type' => :receive
12
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'rails/generators/base'
2
3
  require 'rails/generators/active_record'
3
4
 
@@ -8,19 +9,19 @@ module ShopifyApp
8
9
  source_root File.expand_path('../templates', __FILE__)
9
10
 
10
11
  def create_shop_model
11
- copy_file 'shop.rb', 'app/models/shop.rb'
12
+ copy_file('shop.rb', 'app/models/shop.rb')
12
13
  end
13
14
 
14
15
  def create_shop_migration
15
- migration_template 'db/migrate/create_shops.erb', 'db/migrate/create_shops.rb'
16
+ migration_template('db/migrate/create_shops.erb', 'db/migrate/create_shops.rb')
16
17
  end
17
18
 
18
19
  def update_shopify_app_initializer
19
- gsub_file 'config/initializers/shopify_app.rb', 'ShopifyApp::InMemorySessionStore', 'Shop'
20
+ gsub_file('config/initializers/shopify_app.rb', 'ShopifyApp::InMemoryShopSessionStore', 'Shop')
20
21
  end
21
22
 
22
23
  def create_shop_fixtures
23
- copy_file 'shops.yml', 'test/fixtures/shops.yml'
24
+ copy_file('shops.yml', 'test/fixtures/shops.yml')
24
25
  end
25
26
 
26
27
  private
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  class Shop < ActiveRecord::Base
2
- include ShopifyApp::SessionStorage
3
+ include ShopifyApp::ShopSessionStorage
3
4
 
4
5
  def api_version
5
6
  ShopifyApp.configuration.api_version
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module ShopifyApp
2
3
  module Generators
3
4
  class ShopifyAppGenerator < Rails::Generators::Base
@@ -7,10 +8,10 @@ module ShopifyApp
7
8
  end
8
9
 
9
10
  def run_all_generators
10
- generate "shopify_app:install #{@opts.join(' ')}"
11
- generate "shopify_app:shop_model"
11
+ generate("shopify_app:install #{@opts.join(' ')}")
12
+ generate("shopify_app:shop_model")
12
13
  generate("shopify_app:authenticated_controller")
13
- generate "shopify_app:home_controller"
14
+ generate("shopify_app:home_controller")
14
15
  end
15
16
  end
16
17
  end