disco_app 0.13.6.pre.puma.pre.3 → 0.14.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.
Files changed (69) hide show
  1. checksums.yaml +5 -5
  2. data/app/assets/images/disco_app/logo.png +0 -0
  3. data/app/clients/disco_app/rollbar_client.rb +53 -0
  4. data/app/clients/disco_app/rollbar_client_error.rb +2 -0
  5. data/app/controllers/disco_app/concerns/app_proxy_controller.rb +1 -1
  6. data/app/controllers/disco_app/concerns/authenticated_controller.rb +10 -1
  7. data/app/controllers/disco_app/concerns/user_authenticated_controller.rb +2 -2
  8. data/app/controllers/disco_app/user_sessions_controller.rb +1 -1
  9. data/app/controllers/disco_app/webhooks_controller.rb +1 -1
  10. data/app/controllers/sessions_controller.rb +1 -1
  11. data/app/jobs/application_job.rb +2 -0
  12. data/app/jobs/disco_app/concerns/synchronise_webhooks_job.rb +26 -9
  13. data/app/jobs/disco_app/shop_job.rb +1 -1
  14. data/app/models/application_record.rb +3 -0
  15. data/app/models/disco_app/app_settings.rb +1 -1
  16. data/app/models/disco_app/application_charge.rb +8 -2
  17. data/app/models/disco_app/concerns/can_be_liquified.rb +5 -4
  18. data/app/models/disco_app/concerns/plan.rb +12 -3
  19. data/app/models/disco_app/concerns/plan_code.rb +4 -1
  20. data/app/models/disco_app/concerns/shop.rb +9 -1
  21. data/app/models/disco_app/concerns/subscription.rb +11 -4
  22. data/app/models/disco_app/concerns/synchronises.rb +1 -1
  23. data/app/models/disco_app/plan.rb +1 -1
  24. data/app/models/disco_app/plan_code.rb +1 -1
  25. data/app/models/disco_app/recurring_application_charge.rb +9 -2
  26. data/app/models/disco_app/shop.rb +1 -1
  27. data/app/models/disco_app/source.rb +1 -1
  28. data/app/models/disco_app/subscription.rb +1 -1
  29. data/app/models/disco_app/user.rb +1 -1
  30. data/app/services/disco_app/partner_app_service.rb +151 -0
  31. data/db/migrate/20150525000000_create_shops_if_not_existent.rb +1 -1
  32. data/db/migrate/20170315062548_create_disco_app_sources.rb +1 -1
  33. data/db/migrate/20170315062629_add_sources_to_shop_subscriptions.rb +1 -1
  34. data/db/migrate/20170327214540_create_disco_app_users.rb +1 -1
  35. data/db/migrate/20170606160751_fix_disco_app_users_index.rb +1 -1
  36. data/lib/disco_app/version.rb +1 -1
  37. data/lib/generators/disco_app/disco_app_generator.rb +17 -18
  38. data/lib/generators/disco_app/templates/initializers/shopify_session_repository.rb +2 -1
  39. data/lib/generators/disco_app/templates/root/README.md +26 -0
  40. data/lib/tasks/partner_app.rake +26 -0
  41. data/lib/tasks/rollbar.rake +24 -0
  42. data/test/controllers/disco_app/charges_controller_test.rb +11 -11
  43. data/test/controllers/disco_app/subscriptions_controller_test.rb +4 -4
  44. data/test/controllers/disco_app/webhooks_controller_test.rb +5 -5
  45. data/test/controllers/home_controller_test.rb +1 -1
  46. data/test/controllers/proxy_controller_test.rb +3 -3
  47. data/test/dummy/app/controllers/disco_app/admin/shops_controller.rb +1 -1
  48. data/test/dummy/app/controllers/proxy_controller.rb +1 -1
  49. data/test/dummy/app/jobs/application_job.rb +2 -0
  50. data/test/dummy/app/models/application_record.rb +3 -0
  51. data/test/dummy/app/models/cart.rb +1 -1
  52. data/test/dummy/app/models/disco_app/shop.rb +1 -1
  53. data/test/dummy/app/models/js_configuration.rb +1 -1
  54. data/test/dummy/app/models/product.rb +1 -1
  55. data/test/dummy/app/models/widget_configuration.rb +1 -1
  56. data/test/dummy/config/application.rb +0 -3
  57. data/test/dummy/config/environments/test.rb +2 -2
  58. data/test/dummy/config/initializers/shopify_session_repository.rb +1 -1
  59. data/test/dummy/db/migrate/20160307182229_create_products.rb +2 -2
  60. data/test/dummy/db/migrate/20160530160739_create_asset_models.rb +2 -2
  61. data/test/dummy/db/migrate/20161105054746_create_carts.rb +3 -2
  62. data/test/dummy/db/schema.rb +89 -96
  63. data/test/fixtures/disco_app/shops.yml +6 -2
  64. data/test/fixtures/liquid/model.liquid +8 -8
  65. data/test/integration/synchronises_test.rb +15 -9
  66. data/test/jobs/disco_app/synchronise_webhooks_job_test.rb +16 -4
  67. data/test/test_helper.rb +13 -0
  68. data/test/vcr/webhook_failure.yml +640 -0
  69. metadata +81 -38
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: bf27c28d441f98e6eefdc7809f69daca79c75604
4
- data.tar.gz: 9686a13bb881a26dd0185eb5f7673c211c8eebb5
2
+ SHA256:
3
+ metadata.gz: 970c527220c6ea8c650c51f80c6b1e68eee859d86d5652330eb9577d4a4ce2ad
4
+ data.tar.gz: ac39e32ed7ec03b2244b8efdcfb9e32f9ee8c0fdcfbeb60d186e80785e390cce
5
5
  SHA512:
6
- metadata.gz: f4a2afea46cb6cbbf4e33baf5cbeb2b533ba6f9b9032b40f6a76d984a18977179fedf1fc656c1f750fc383e54906cb824f633447b7481f42267950c7ad921d16
7
- data.tar.gz: 8f90a604e1a61b4b9b5f617dbd7d77a0406ccca51d82d6ab46638b2ab1293b3b1483031a2e33051cf0770a46dbf8b44bc33ab7aaf79fd947bf9c034064ca474b
6
+ metadata.gz: 1ca38662339da5af03b15600f934cafd63c9335a07394af5f813fb17cec8005e30f20d2c204754573bdbd44705175e5e04c1164b89fa9b3eacab47d4f567aee2
7
+ data.tar.gz: 3804a7bd20cbf1eec6012af974b4dc91fac66b1cd219a86cc005b799f3d88b2d611ea208c9c39c118fcf88aab846895aab6fe408bb560668246d2ee5b715776d
@@ -0,0 +1,53 @@
1
+ require 'rest-client'
2
+
3
+ class DiscoApp::RollbarClient
4
+
5
+ API_URL = 'https://api.rollbar.com/api/1'
6
+ CREATE_PROJECT_ENDPOINT = '/projects'
7
+ ACCESS_TOKEN_ENDPOINT = '/project'
8
+ ACCESS_TOKEN_SCOPE = 'post_server_item'
9
+
10
+ def initialize(params)
11
+ @write_access_token = params[:write_account_access_token]
12
+ @read_access_token = params[:read_account_access_token]
13
+ end
14
+
15
+ # Create project on Rollbar, returns it new post server side access token
16
+ def create_project(name)
17
+ begin
18
+ response = RestClient::Request.execute(
19
+ method: :post,
20
+ headers: { content_type: :json },
21
+ url: create_api_url,
22
+ payload: { name: name.parameterize }.to_json
23
+ )
24
+ request_access_token(ActiveSupport::JSON.decode(response).dig('result', 'id'))
25
+ rescue RestClient::BadRequest => e
26
+ raise RollbarClientError.new(e.message)
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def request_access_token(project_id)
33
+ begin
34
+ response = RestClient.get(access_tokens_api_url(project_id))
35
+ # Only return post_server_item server side access token
36
+ post_server_access_token(ActiveSupport::JSON.decode(response)['result'])
37
+ rescue RestClient::BadRequest => e
38
+ raise RollbarClientError.new(e.message)
39
+ end
40
+ end
41
+
42
+ def create_api_url
43
+ API_URL + CREATE_PROJECT_ENDPOINT + "?access_token=#{@write_access_token}"
44
+ end
45
+
46
+ def access_tokens_api_url(project_id)
47
+ API_URL + ACCESS_TOKEN_ENDPOINT + "/#{project_id}/access_tokens?access_token=#{@read_access_token}"
48
+ end
49
+
50
+ def post_server_access_token(results)
51
+ results.select { |x| x['name'] == ACCESS_TOKEN_SCOPE }.first['access_token']
52
+ end
53
+ end
@@ -0,0 +1,2 @@
1
+ class RollbarClientError < StandardError
2
+ end
@@ -20,7 +20,7 @@ module DiscoApp::Concerns::AppProxyController
20
20
  end
21
21
 
22
22
  def proxy_signature_is_valid?
23
- return true if Rails.env.development? and DiscoApp.configuration.skip_proxy_verification?
23
+ return true if (Rails.env.development? || Rails.env.test?) and DiscoApp.configuration.skip_proxy_verification?
24
24
  DiscoApp::ProxyService.proxy_signature_is_valid?(request.query_string, ShopifyApp.configuration.secret)
25
25
  end
26
26
 
@@ -4,12 +4,13 @@ module DiscoApp::Concerns::AuthenticatedController
4
4
 
5
5
  included do
6
6
  before_action :auto_login
7
+ before_action :check_shop_whitelist
7
8
  before_action :login_again_if_different_shop
8
9
  before_action :shopify_shop
9
10
  before_action :check_installed
10
11
  before_action :check_current_subscription
11
12
  before_action :check_active_charge
12
- around_filter :shopify_session
13
+ around_action :shopify_session
13
14
  layout 'embedded_app'
14
15
  end
15
16
 
@@ -68,4 +69,12 @@ module DiscoApp::Concerns::AuthenticatedController
68
69
  DiscoApp::RequestValidationService.hmac_valid?(request.query_string, ShopifyApp.configuration.secret)
69
70
  end
70
71
 
72
+ def check_shop_whitelist
73
+ if shop_session
74
+ if ENV['WHITELISTED_DOMAINS'].present? && !ENV['WHITELISTED_DOMAINS'].include?(shop_session.url)
75
+ redirect_to_login
76
+ end
77
+ end
78
+ end
79
+
71
80
  end
@@ -10,8 +10,8 @@ module DiscoApp::Concerns::UserAuthenticatedController
10
10
 
11
11
  def shopify_user
12
12
  @user = DiscoApp::User.find(session[:shopify_user])
13
- rescue ActiveRecord::RecordNotFound
14
- redirect_to disco_app.new_user_session_path
13
+ rescue ActiveRecord::RecordNotFound
14
+ redirect_to disco_app.new_user_session_path
15
15
  end
16
16
 
17
17
  end
@@ -51,7 +51,7 @@ class DiscoApp::UserSessionsController < ApplicationController
51
51
  end
52
52
 
53
53
  def sanitized_shop_name
54
- @shop.shopify_domain
54
+ @shop.present? ? @shop.shopify_domain : super
55
55
  end
56
56
 
57
57
  end
@@ -25,7 +25,7 @@ module DiscoApp
25
25
  data = ActiveSupport::JSON::decode(request.body.read).with_indifferent_access
26
26
  job_class.perform_later(shopify_domain, data)
27
27
 
28
- render nothing: true
28
+ render body: nil
29
29
  end
30
30
 
31
31
  private
@@ -1,4 +1,4 @@
1
- class SessionsController < ApplicationController
1
+ class SessionsController < ActionController::Base
2
2
  include ShopifyApp::SessionsConcern
3
3
 
4
4
  def referral
@@ -0,0 +1,2 @@
1
+ class ApplicationJob < ActiveJob::Base
2
+ end
@@ -1,19 +1,20 @@
1
1
  module DiscoApp::Concerns::SynchroniseWebhooksJob
2
2
  extend ActiveSupport::Concern
3
3
 
4
+ COMMON_WEBHOOKS = [:'app/uninstalled', :'shop/update']
5
+
4
6
  # Ensure the webhooks registered with our shop are the same as those listed
5
7
  # in our application configuration.
6
8
  def perform(_shop)
7
- # Get the full list of expected webhook topics.
8
- expected_topics = [:'app/uninstalled', :'shop/update'] + (DiscoApp.configuration.webhook_topics || [])
9
-
10
- # Registered any webhooks that haven't been registered yet.
9
+ # Register any webhooks that haven't been registered yet.
11
10
  (expected_topics - current_topics).each do |topic|
12
- ShopifyAPI::Webhook.create(
13
- topic: topic,
14
- address: webhooks_url,
15
- format: 'json'
16
- )
11
+ with_verbose_output(topic) do
12
+ ShopifyAPI::Webhook.create(
13
+ topic: topic,
14
+ address: webhooks_url,
15
+ format: 'json',
16
+ )
17
+ end
17
18
  end
18
19
 
19
20
  # Remove any extraneous topics.
@@ -34,6 +35,11 @@ module DiscoApp::Concerns::SynchroniseWebhooksJob
34
35
 
35
36
  private
36
37
 
38
+ # Get the full list of expected webhook topics.
39
+ def expected_topics
40
+ COMMON_WEBHOOKS + (DiscoApp.configuration.webhook_topics || [])
41
+ end
42
+
37
43
  # Return a list of currently registered topics.
38
44
  def current_topics
39
45
  current_webhooks.map(&:topic).map(&:to_sym)
@@ -49,4 +55,15 @@ module DiscoApp::Concerns::SynchroniseWebhooksJob
49
55
  DiscoApp::Engine.routes.url_helpers.webhooks_url
50
56
  end
51
57
 
58
+ def with_verbose_output(topic)
59
+ print "\n#{topic}"
60
+ shopify_response = yield
61
+ if shopify_response.errors.blank?
62
+ print " - registered successfully\n"
63
+ else
64
+ print " - not registered\n"
65
+ puts shopify_response.errors.messages
66
+ end
67
+ end
68
+
52
69
  end
@@ -5,7 +5,7 @@
5
5
 
6
6
  require 'rollbar'
7
7
 
8
- class DiscoApp::ShopJob < ActiveJob::Base
8
+ class DiscoApp::ShopJob < ApplicationJob
9
9
 
10
10
  queue_as :default
11
11
 
@@ -0,0 +1,3 @@
1
+ class ApplicationRecord < ActiveRecord::Base
2
+ self.abstract_class = true
3
+ end
@@ -1,3 +1,3 @@
1
- class DiscoApp::AppSettings < ActiveRecord::Base
1
+ class DiscoApp::AppSettings < ApplicationRecord
2
2
  include DiscoApp::Concerns::AppSettings
3
3
  end
@@ -1,9 +1,15 @@
1
- class DiscoApp::ApplicationCharge < ActiveRecord::Base
1
+ class DiscoApp::ApplicationCharge < ApplicationRecord
2
2
 
3
3
  belongs_to :shop
4
4
  belongs_to :subscription
5
5
 
6
- enum status: [:pending, :accepted, :declined, :expired, :active]
6
+ enum status: {
7
+ pending: 0,
8
+ accepted: 1,
9
+ declined: 2,
10
+ expired: 3,
11
+ active: 4,
12
+ }
7
13
 
8
14
  scope :active, -> { where status: statuses[:active] }
9
15
 
@@ -5,14 +5,15 @@ module DiscoApp::Concerns::CanBeLiquified
5
5
 
6
6
  included do
7
7
 
8
- # Return this model as an array of Liquid {% assign %} statements.
8
+ # Return this model as a hash for use with `to_liquid`. Returns `as_json` by default but is provided here as a hook
9
+ # for potential overrides.
9
10
  def as_liquid
10
- as_json.map { |k, v| "{% assign #{liquid_model_name}_#{k} = #{as_liquid_value(k, v)} %}" }
11
+ as_json
11
12
  end
12
13
 
13
- # Render this model as a series of concatenated Liquid {% assign %} statements.
14
+ # Render this model as a series of concatenated Liquid {%- assign -%} statements.
14
15
  def to_liquid
15
- as_liquid.join("\n")
16
+ as_liquid.map { |k, v| "{%- assign #{liquid_model_name}_#{k} = #{as_liquid_value(k, v)} -%}" }.join("\n")
16
17
  end
17
18
 
18
19
  # Method to allow override of the model name in Liquid. Useful for models
@@ -9,9 +9,18 @@ module DiscoApp::Concerns::Plan
9
9
 
10
10
  accepts_nested_attributes_for :plan_codes, allow_destroy: true
11
11
 
12
- enum status: [:available, :unavailable]
13
- enum plan_type: [:recurring, :one_time]
14
- enum interval: [:month, :year]
12
+ enum status: {
13
+ available: 0,
14
+ unavailable: 1
15
+ }
16
+ enum plan_type: {
17
+ recurring: 0,
18
+ one_time: 1
19
+ }
20
+ enum interval: {
21
+ month: 0,
22
+ year: 1
23
+ }
15
24
 
16
25
  scope :available, -> { where status: statuses[:available] }
17
26
 
@@ -5,7 +5,10 @@ module DiscoApp::Concerns::PlanCode
5
5
 
6
6
  belongs_to :plan
7
7
 
8
- enum status: [:available, :unavailable]
8
+ enum status: {
9
+ available: 0,
10
+ unavailable: 1
11
+ }
9
12
 
10
13
  validates_presence_of :code
11
14
  validates_presence_of :amount
@@ -16,7 +16,15 @@ module DiscoApp::Concerns::Shop
16
16
  has_many :sessions, class_name: 'DiscoApp::Session', dependent: :destroy
17
17
 
18
18
  # Define possible installation statuses as an enum.
19
- enum status: [:never_installed, :awaiting_install, :installing, :installed, :awaiting_uninstall, :uninstalling, :uninstalled]
19
+ enum status: {
20
+ never_installed: 0,
21
+ awaiting_install: 1,
22
+ installing: 2,
23
+ installed: 3,
24
+ awaiting_uninstall: 4,
25
+ uninstalling: 5,
26
+ uninstalled: 6
27
+ }
20
28
 
21
29
  # Define some useful scopes.
22
30
  scope :status, -> (status) { where status: status }
@@ -5,13 +5,20 @@ module DiscoApp::Concerns::Subscription
5
5
 
6
6
  belongs_to :shop
7
7
  belongs_to :plan
8
- belongs_to :plan_code
9
- belongs_to :source
8
+ belongs_to :plan_code, optional: true
9
+ belongs_to :source, optional: true
10
10
  has_many :one_time_charges, class_name: 'DiscoApp::ApplicationCharge', dependent: :destroy
11
11
  has_many :recurring_charges, class_name: 'DiscoApp::RecurringApplicationCharge', dependent: :destroy
12
12
 
13
- enum status: [:trial, :active, :cancelled]
14
- enum subscription_type: [:recurring, :one_time]
13
+ enum status: {
14
+ trial: 0,
15
+ active: 1,
16
+ cancelled: 2
17
+ }
18
+ enum subscription_type: {
19
+ recurring: 0,
20
+ one_time: 1
21
+ }
15
22
 
16
23
  scope :current, -> { where status: [statuses[:trial], statuses[:active]] }
17
24
 
@@ -45,7 +45,7 @@ module DiscoApp::Concerns::Synchronises
45
45
 
46
46
  return unless should_synchronise_deletion?(shop, data)
47
47
 
48
- self.destroy_all(shop: shop, id: data[:id])
48
+ self.where(shop: shop, id: data[:id]).destroy_all
49
49
  end
50
50
 
51
51
  def synchronise_all(shop, params = {})
@@ -1,3 +1,3 @@
1
- class DiscoApp::Plan < ActiveRecord::Base
1
+ class DiscoApp::Plan < ApplicationRecord
2
2
  include DiscoApp::Concerns::Plan
3
3
  end
@@ -1,3 +1,3 @@
1
- class DiscoApp::PlanCode < ActiveRecord::Base
1
+ class DiscoApp::PlanCode < ApplicationRecord
2
2
  include DiscoApp::Concerns::PlanCode
3
3
  end
@@ -1,9 +1,16 @@
1
- class DiscoApp::RecurringApplicationCharge < ActiveRecord::Base
1
+ class DiscoApp::RecurringApplicationCharge < ApplicationRecord
2
2
 
3
3
  belongs_to :shop
4
4
  belongs_to :subscription
5
5
 
6
- enum status: [:pending, :accepted, :declined, :active, :cancelled, :expired]
6
+ enum status: {
7
+ pending: 0,
8
+ accepted: 1,
9
+ declined: 2,
10
+ active: 3,
11
+ cancelled: 4,
12
+ expired: 5
13
+ }
7
14
 
8
15
  scope :active, -> { where status: statuses[:active] }
9
16
 
@@ -1,3 +1,3 @@
1
- class DiscoApp::Shop < ActiveRecord::Base
1
+ class DiscoApp::Shop < ApplicationRecord
2
2
  include DiscoApp::Concerns::Shop
3
3
  end
@@ -1,3 +1,3 @@
1
- class DiscoApp::Source < ActiveRecord::Base
1
+ class DiscoApp::Source < ApplicationRecord
2
2
  include DiscoApp::Concerns::Source
3
3
  end
@@ -1,3 +1,3 @@
1
- class DiscoApp::Subscription < ActiveRecord::Base
1
+ class DiscoApp::Subscription < ApplicationRecord
2
2
  include DiscoApp::Concerns::Subscription
3
3
  end
@@ -1,3 +1,3 @@
1
- class DiscoApp::User < ActiveRecord::Base
1
+ class DiscoApp::User < ApplicationRecord
2
2
  include DiscoApp::Concerns::User
3
3
  end
@@ -0,0 +1,151 @@
1
+ module DiscoApp
2
+ class PartnerAppService
3
+
4
+ def initialize(params)
5
+ @email = params[:email]
6
+ @password = params[:password]
7
+ @app_name = params[:app_name]
8
+ @app_url = params[:app_url]
9
+ @organization = params[:organization]
10
+
11
+ @agent = Mechanize.new do |a|
12
+ a.user_agent_alias = 'Mac Safari'
13
+ a.follow_meta_refresh = true
14
+ a.keep_alive = false
15
+ a.pre_connect_hooks << lambda do |_agent, request|
16
+ request['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
17
+ end
18
+ end
19
+ end
20
+
21
+ def generate_partner_app
22
+ begin
23
+ # Login to Shopify Partners
24
+ login
25
+ # Access Partner dashboard
26
+ org_link = organizations
27
+ dashboard = dashboard_page(org_link)
28
+ # Create App
29
+ apps_page = refresh_page(dashboard)
30
+ create_partner_app(apps_page)
31
+ # Configure newly created app with embedded app use
32
+ apps_page = refresh_page(dashboard)
33
+ embedded_admin_app(apps_page)
34
+ # Add Disco App icon
35
+ apps_page = refresh_page(dashboard)
36
+ add_disco_icon(apps_page)
37
+ # Fetch API credentials
38
+ apps_page = refresh_page(dashboard)
39
+ api_key, secret = api_credentials(apps_page)
40
+ rescue Mechanize::Error => e
41
+ puts 'Error while trying to create partner app'
42
+ puts "Error #{e}, message : #{e.message}"
43
+ return
44
+ end
45
+ # Add them to .env.local file
46
+ append_credentials(api_key, secret)
47
+ puts '#' * 80
48
+ puts 'New Partner App successfully created!'
49
+ puts 'API Credentials have been pasted to your .env.local file'
50
+ puts '#' * 80
51
+ end
52
+
53
+ private
54
+
55
+ def login
56
+ @agent.get('https://accounts.shopify.com/login') do |page|
57
+ page.form do |form|
58
+ form['account[email]'] = @email
59
+ form['account[password]'] = @password
60
+ end.submit
61
+ end
62
+ end
63
+
64
+ def organizations
65
+ organizations = @agent.get('https://partners.shopify.com/organizations/')
66
+ organizations.links.select { |link| link.text[/#{@organization}/] }.first.href
67
+ end
68
+
69
+ def dashboard_page(org_link)
70
+ @agent.get('https://partners.shopify.com' + org_link)
71
+ end
72
+
73
+ def create_partner_app(apps_page)
74
+ apps_page.form do |form|
75
+ # App name
76
+ form['create_form[title]'] = @app_name
77
+
78
+ # App URL
79
+ form['create_form[application_url]'] = @app_url
80
+
81
+ # Accept TOS
82
+ unless form['create_form[accepted]'].blank?
83
+ form['create_form[accepted]'] = '1'
84
+ form.hiddens.last.value = 1
85
+ end
86
+ end.submit
87
+ end
88
+
89
+ def api_credentials(apps_page)
90
+ app = apps_page.link_with(text: @app_name).click
91
+ app_info = app.link_with(text: 'App info').click
92
+ add_whitelist_url(app_info)
93
+ api_key = app_info.search('#api_key').first.values[3]
94
+ secret = app_info.search('#settings_form_secrets').first.values[3]
95
+ [api_key, secret]
96
+ end
97
+
98
+ def embedded_admin_app(apps_page)
99
+ app = apps_page.link_with(text: @app_name).click
100
+ extensions = app.link_with(text: 'Extensions').click
101
+ extensions.form do |form|
102
+ form['extensions_form[embedded]'] = '1'
103
+ end.submit
104
+ end
105
+
106
+ def add_disco_icon(apps_page)
107
+ app = apps_page.link_with(text: @app_name).click
108
+ app_info = app.link_with(text: 'App info').click
109
+ logo = DiscoApp::Engine.root.join('app', 'assets', 'images', 'disco_app', 'logo.png').to_s
110
+ app_info.form do |form|
111
+ form.file_uploads.first.file_name = logo
112
+ end.submit
113
+ end
114
+
115
+ # Write credentials of newly created app to .env.local file
116
+ def append_credentials(api_key, secret)
117
+ original_file = '.env.local'
118
+ new_file = original_file + '.new'
119
+ File.open(new_file, 'w') do |file|
120
+ File.foreach(original_file) do |line|
121
+ if line.include?('SHOPIFY_APP_API_KEY')
122
+ file.puts "SHOPIFY_APP_API_KEY=#{api_key}"
123
+ elsif line.include?('SHOPIFY_APP_SECRET')
124
+ file.puts "SHOPIFY_APP_SECRET=#{secret}"
125
+ else
126
+ file.puts line
127
+ end
128
+ end
129
+ end
130
+ File.delete(original_file)
131
+ File.rename(new_file, original_file)
132
+ end
133
+
134
+ def add_whitelist_url(app_info)
135
+ app_info.form do |form|
136
+ form['info_form[redirect_url_whitelist]'] = callback_url
137
+ end.submit
138
+ end
139
+
140
+ # Access the "Apps" section of the dashboard, also used to reload the dashboard
141
+ # When an action has been taken
142
+ def refresh_page(dashboard)
143
+ dashboard.link_with(text: ' Apps').click
144
+ end
145
+
146
+ def callback_url
147
+ [@app_url + '/auth/shopify/callback', @app_url + '/auth/shopify_user/callback'].join("\n")
148
+ end
149
+
150
+ end
151
+ end
@@ -1,7 +1,7 @@
1
1
  ##
2
2
  # While this migration file is called "create shops if not existent", it's actually a reset of all `disco_app`
3
3
  # migrations up until 23 January 2017. It's kept its name like this to ensure compatibility across upgraded apps.
4
- class CreateShopsIfNotExistent < ActiveRecord::Migration
4
+ class CreateShopsIfNotExistent < ActiveRecord::Migration[5.1]
5
5
 
6
6
  def change
7
7
  return if table_exists? :disco_app_shops
@@ -1,4 +1,4 @@
1
- class CreateDiscoAppSources < ActiveRecord::Migration
1
+ class CreateDiscoAppSources < ActiveRecord::Migration[5.1]
2
2
  def change
3
3
  create_table :disco_app_sources do |t|
4
4
  t.string :source, null: true
@@ -1,4 +1,4 @@
1
- class AddSourcesToShopSubscriptions < ActiveRecord::Migration
1
+ class AddSourcesToShopSubscriptions < ActiveRecord::Migration[5.1]
2
2
  def change
3
3
  add_column :disco_app_subscriptions, :source_id, :integer, limit: 8, index: true
4
4
  add_foreign_key :disco_app_subscriptions, :disco_app_sources, column: :source_id
@@ -1,4 +1,4 @@
1
- class CreateDiscoAppUsers < ActiveRecord::Migration
1
+ class CreateDiscoAppUsers < ActiveRecord::Migration[5.1]
2
2
  def change
3
3
  create_table :disco_app_users do |t|
4
4
  t.integer :shop_id, limit: 8
@@ -1,4 +1,4 @@
1
- class FixDiscoAppUsersIndex < ActiveRecord::Migration
1
+ class FixDiscoAppUsersIndex < ActiveRecord::Migration[5.1]
2
2
  def change
3
3
  remove_index :disco_app_users, :shop_id
4
4
  add_index :disco_app_users, [:id, :shop_id], unique: true
@@ -1,3 +1,3 @@
1
1
  module DiscoApp
2
- VERSION = '0.13.6-puma-3'
2
+ VERSION = '0.14.0'
3
3
  end