disco_app 0.13.6.pre.puma.pre.3 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
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