disco_app 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Rakefile +37 -0
- data/app/assets/images/disco_app/icon.svg +1 -0
- data/app/assets/javascripts/disco_app/components/shopify_admin_link.js.jsx +29 -0
- data/app/assets/javascripts/disco_app/components.js +5 -0
- data/app/assets/javascripts/disco_app/disco_app.js +7 -0
- data/app/assets/javascripts/disco_app/frame.js +152 -0
- data/app/assets/javascripts/disco_app/shopify-turbolinks.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 +51 -0
- data/app/assets/stylesheets/disco_app/disco/_forms.scss +23 -0
- data/app/assets/stylesheets/disco_app/disco/_grid.scss +58 -0
- data/app/assets/stylesheets/disco_app/disco/_sections.scss +61 -0
- data/app/assets/stylesheets/disco_app/disco/_tables.scss +57 -0
- data/app/assets/stylesheets/disco_app/disco/_tabs.scss +61 -0
- data/app/assets/stylesheets/disco_app/disco/_type.scss +39 -0
- data/app/assets/stylesheets/disco_app/disco/mixins/_flexbox.scss +394 -0
- data/app/assets/stylesheets/disco_app/disco_app.scss +16 -0
- data/app/assets/stylesheets/disco_app/frame/_buttons.scss +54 -0
- data/app/assets/stylesheets/disco_app/frame/_forms.scss +26 -0
- data/app/assets/stylesheets/disco_app/frame/_layout.scss +77 -0
- data/app/assets/stylesheets/disco_app/frame/_type.scss +32 -0
- data/app/assets/stylesheets/disco_app/frame.scss +9 -0
- data/app/controllers/disco_app/app_proxy_controller.rb +42 -0
- data/app/controllers/disco_app/authenticated_controller.rb +44 -0
- data/app/controllers/disco_app/carrier_request_controller.rb +23 -0
- data/app/controllers/disco_app/charges_controller.rb +30 -0
- data/app/controllers/disco_app/frame_controller.rb +9 -0
- data/app/controllers/disco_app/install_controller.rb +26 -0
- data/app/controllers/disco_app/webhooks_controller.rb +46 -0
- data/app/helpers/disco_app/application_helper.rb +28 -0
- data/app/jobs/disco_app/app_installed_job.rb +3 -0
- data/app/jobs/disco_app/app_uninstalled_job.rb +3 -0
- data/app/jobs/disco_app/concerns/app_installed_job.rb +22 -0
- data/app/jobs/disco_app/concerns/app_uninstalled_job.rb +23 -0
- data/app/jobs/disco_app/concerns/shop_update_job.rb +16 -0
- data/app/jobs/disco_app/concerns/synchronise_carrier_service_job.rb +52 -0
- data/app/jobs/disco_app/concerns/synchronise_webhooks_job.rb +61 -0
- data/app/jobs/disco_app/shop_job.rb +27 -0
- data/app/jobs/disco_app/shop_update_job.rb +3 -0
- data/app/jobs/disco_app/synchronise_carrier_service_job.rb +3 -0
- data/app/jobs/disco_app/synchronise_webhooks_job.rb +3 -0
- data/app/models/disco_app/concerns/plan.rb +14 -0
- data/app/models/disco_app/concerns/shop.rb +70 -0
- data/app/models/disco_app/concerns/subscription.rb +14 -0
- data/app/models/disco_app/concerns/synchronises_with_shopify.rb +26 -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/carrier_request_service.rb +15 -0
- data/app/services/disco_app/charges_service.rb +73 -0
- data/app/services/disco_app/proxy_service.rb +17 -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/frame/frame.html.erb +36 -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 +14 -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/layouts/embedded_app_modal.html.erb +17 -0
- data/app/views/sessions/new.html.erb +26 -0
- data/config/routes.rb +26 -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/db/migrate/20160112233706_create_disco_app_sessions.rb +12 -0
- data/db/migrate/20160113194418_add_shop_id_to_disco_app_sessions.rb +6 -0
- data/lib/disco_app/configuration.rb +33 -0
- data/lib/disco_app/engine.rb +25 -0
- data/lib/disco_app/session.rb +14 -0
- data/lib/disco_app/support/file_fixtures.rb +23 -0
- data/lib/disco_app/test_help.rb +11 -0
- data/lib/disco_app/version.rb +3 -0
- data/lib/disco_app.rb +6 -0
- data/lib/generators/disco_app/USAGE +5 -0
- data/lib/generators/disco_app/disco_app_generator.rb +163 -0
- data/lib/generators/disco_app/mailify/mailify_generator.rb +54 -0
- data/lib/generators/disco_app/monitorify/monitorify_generator.rb +28 -0
- data/lib/generators/disco_app/monitorify/templates/config/newrelic.yml +26 -0
- data/lib/generators/disco_app/monitorify/templates/initializers/rollbar.rb +12 -0
- data/lib/generators/disco_app/reactify/reactify_generator.rb +45 -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 +14 -0
- data/lib/generators/disco_app/templates/initializers/session_store.rb +2 -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/lib/tasks/carrier_service.rake +10 -0
- data/lib/tasks/sessions.rake +9 -0
- data/lib/tasks/start.rake +3 -0
- data/lib/tasks/webhooks.rake +10 -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/controllers/proxy_controller_test.rb +42 -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/controllers/proxy_controller.rb +8 -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 +38 -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 +14 -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 +2 -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 +10 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/schema.rb +81 -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/api/widget_store/webhooks.json +1 -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 +30 -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/session_test.rb +31 -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 +530 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
class DiscoApp::SubscriptionService
|
|
2
|
+
|
|
3
|
+
# Subscribe the given shop to the given plan.
|
|
4
|
+
def self.subscribe(shop, plan)
|
|
5
|
+
# Mark all existing active subscriptions as replaced.
|
|
6
|
+
shop.subscriptions.active.update_all(status: DiscoApp::Subscription.statuses[:replaced])
|
|
7
|
+
|
|
8
|
+
# Add the new subscription.
|
|
9
|
+
DiscoApp::Subscription.create!(
|
|
10
|
+
shop: shop,
|
|
11
|
+
plan: plan,
|
|
12
|
+
status: DiscoApp::Subscription.statuses[:active],
|
|
13
|
+
name: plan.name,
|
|
14
|
+
charge_type: plan.charge_type,
|
|
15
|
+
price: plan.default_price,
|
|
16
|
+
trial_days: plan.default_trial_days
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Cancel any active subscription for the given shop.
|
|
21
|
+
def self.cancel(shop)
|
|
22
|
+
shop.subscriptions.active.update_all(status: DiscoApp::Subscription.statuses[:cancelled])
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
class DiscoApp::WebhookService
|
|
2
|
+
|
|
3
|
+
# Return true iff the provided hmac_to_verify matches that calculated from the
|
|
4
|
+
# given data and secret.
|
|
5
|
+
def self.is_valid_hmac?(body, secret, hmac_to_verify)
|
|
6
|
+
ActiveSupport::SecurityUtils.secure_compare(self.calculated_hmac(body, secret), hmac_to_verify.to_s)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Calculate the HMAC for the given data and secret.
|
|
10
|
+
def self.calculated_hmac(body, secret)
|
|
11
|
+
digest = OpenSSL::Digest.new('sha256')
|
|
12
|
+
Base64.encode64(OpenSSL::HMAC.digest(digest, secret, body)).strip
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Try to find a job class for the given webhook topic.
|
|
16
|
+
def self.find_job_class(topic)
|
|
17
|
+
begin
|
|
18
|
+
# First try to find a top-level matching job class.
|
|
19
|
+
"#{topic}_job".gsub('/', '_').classify.constantize
|
|
20
|
+
rescue NameError
|
|
21
|
+
# If that fails, try to find a DiscoApp:: prefixed job class.
|
|
22
|
+
begin
|
|
23
|
+
%Q{DiscoApp::#{"#{topic}_job".gsub('/', '_').classify}}.constantize
|
|
24
|
+
rescue NameError
|
|
25
|
+
nil
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
activate_charge
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
create_charge
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<% provide(:title, 'Thankyou') %>
|
|
2
|
+
|
|
3
|
+
<div class="row">
|
|
4
|
+
<% if @shop.charge_declined? %>
|
|
5
|
+
<div class="alert alert-warning">
|
|
6
|
+
<p>
|
|
7
|
+
Oops! Looks like you declined the charge.
|
|
8
|
+
Unfortunately, you'll have to accept the charge on the next screen in order to continue installing the application.
|
|
9
|
+
</p>
|
|
10
|
+
</div>
|
|
11
|
+
<% elsif @shop.charge_cancelled? %>
|
|
12
|
+
<div class="alert alert-warning">
|
|
13
|
+
<p>
|
|
14
|
+
Your authorized charge for this application has expired.
|
|
15
|
+
This could have occurred if:
|
|
16
|
+
</p>
|
|
17
|
+
<ul>
|
|
18
|
+
<li>You uninstalled and reinstalled the application; or</li>
|
|
19
|
+
<li>Your plan level has changed.</li>
|
|
20
|
+
</ul>
|
|
21
|
+
<p>
|
|
22
|
+
In either case, it's no problem!
|
|
23
|
+
Simply click okay and you'll be asked to authorize a new charge.
|
|
24
|
+
Don't worry - you *wont'* be billed twice.
|
|
25
|
+
</p>
|
|
26
|
+
</div>
|
|
27
|
+
<% else %>
|
|
28
|
+
<div class="alert alert-success">
|
|
29
|
+
<p>
|
|
30
|
+
Thanks for installing <%= DiscoApp.configuration.app_name %>!
|
|
31
|
+
</p>
|
|
32
|
+
<p>
|
|
33
|
+
Before we start setting things up, we need you to authorize a charge for the application.
|
|
34
|
+
</p>
|
|
35
|
+
</div>
|
|
36
|
+
<% end %>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<div class="row">
|
|
40
|
+
<%= form_tag disco_app.create_charge_path, method: 'POST', target: '_parent' do %>
|
|
41
|
+
<div class="form-group">
|
|
42
|
+
<%= submit_tag 'Okay', class: 'form-input' %>
|
|
43
|
+
</div>
|
|
44
|
+
<% end %>
|
|
45
|
+
</div>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Dev Frame</title>
|
|
5
|
+
<%= stylesheet_link_tag 'disco_app/frame', media: 'all' %>
|
|
6
|
+
<%= javascript_include_tag 'disco_app/frame' %>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<!-- Left Sidebar -->
|
|
10
|
+
<aside id="sidebar"></aside>
|
|
11
|
+
|
|
12
|
+
<!-- Header Bar -->
|
|
13
|
+
<header id="header">
|
|
14
|
+
<h1 id="header-title">
|
|
15
|
+
<img id="header-title-icon" src="<%= image_path('disco_app/icon.svg') %>" width="20" height="20" />
|
|
16
|
+
Shopify Dev Frame
|
|
17
|
+
</h1>
|
|
18
|
+
<div id="header-actions">
|
|
19
|
+
<!-- No action. -->
|
|
20
|
+
</div>
|
|
21
|
+
</header>
|
|
22
|
+
|
|
23
|
+
<!-- Content iFrame -->
|
|
24
|
+
<section id="content-wrapper">
|
|
25
|
+
<iframe id="content" src="/"></iframe>
|
|
26
|
+
</section>
|
|
27
|
+
|
|
28
|
+
<!-- Setup FrameApp. -->
|
|
29
|
+
<script type="text/javascript">
|
|
30
|
+
FrameApp.init({
|
|
31
|
+
debug: true,
|
|
32
|
+
iframe: document.getElementById('content')
|
|
33
|
+
});
|
|
34
|
+
</script>
|
|
35
|
+
</body>
|
|
36
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
uninstalling
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
404 Not Found
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<% disabled ||= false %>
|
|
2
|
+
<div class="next-card <% if disabled %>next-card--disabled<% end %>">
|
|
3
|
+
<% if content_for?(:card_header) %>
|
|
4
|
+
<header class="next-card__header">
|
|
5
|
+
<%= content_for :card_header %>
|
|
6
|
+
</header>
|
|
7
|
+
<% end %>
|
|
8
|
+
<%= content_for :card_content %>
|
|
9
|
+
<% if content_for?(:card_footer) %>
|
|
10
|
+
<footer class="next-card__footer">
|
|
11
|
+
<%= content_for :card_footer %>
|
|
12
|
+
</footer>
|
|
13
|
+
<% end %>
|
|
14
|
+
</div>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<section class="section">
|
|
2
|
+
<div class="layout-content">
|
|
3
|
+
|
|
4
|
+
<aside class="layout-content__sidebar layout-content__first">
|
|
5
|
+
<% if content_for?(:section_summary) %>
|
|
6
|
+
<div class="section-summary">
|
|
7
|
+
<%= content_for :section_summary %>
|
|
8
|
+
</div>
|
|
9
|
+
<% end %>
|
|
10
|
+
</aside>
|
|
11
|
+
|
|
12
|
+
<section class="layout-content__main">
|
|
13
|
+
<%= content_for :section_content %>
|
|
14
|
+
</section>
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
</section>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title><%= yield(:title) %></title>
|
|
5
|
+
|
|
6
|
+
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
|
|
7
|
+
|
|
8
|
+
<%= csrf_meta_tags %>
|
|
9
|
+
|
|
10
|
+
<%= yield :extra_head %>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
|
|
14
|
+
<%= yield %>
|
|
15
|
+
|
|
16
|
+
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
|
|
17
|
+
</body>
|
|
18
|
+
</html>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title><%= yield(:title) %></title>
|
|
5
|
+
|
|
6
|
+
<script src="//cdn.shopify.com/s/assets/external/app.js?<%= Time.now.strftime('%Y%m%d%H') %>"></script>
|
|
7
|
+
<script type="text/javascript">
|
|
8
|
+
// Initialise the Shopify App.
|
|
9
|
+
ShopifyApp.init({
|
|
10
|
+
"apiKey": "<%= ShopifyApp.configuration.api_key %>",
|
|
11
|
+
"shopOrigin": "<%= "https://#{ @shop_session.url }" if @shop_session %>",
|
|
12
|
+
"debug": <%= Rails.env.development? ? 'true' : 'false' %>
|
|
13
|
+
});
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
|
|
17
|
+
|
|
18
|
+
<%= csrf_meta_tags %>
|
|
19
|
+
|
|
20
|
+
<%= yield :extra_head %>
|
|
21
|
+
</head>
|
|
22
|
+
<body>
|
|
23
|
+
<script type="text/javascript">
|
|
24
|
+
ShopifyApp.Bar.initialize({
|
|
25
|
+
title: "<%= yield(:title) %>",
|
|
26
|
+
icon: "<%= image_url("disco_app/icon.svg") %>",
|
|
27
|
+
buttons: <%= content_for?(:buttons) ? content_for(:buttons) : '{}' %>
|
|
28
|
+
});
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<%= yield %>
|
|
32
|
+
|
|
33
|
+
<% flash.each do |key, message| %>
|
|
34
|
+
<script type="text/javascript">
|
|
35
|
+
ShopifyApp.flash<%= (key == 'error') ? 'Error' : 'Notice' %>('<%= message %>');
|
|
36
|
+
</script>
|
|
37
|
+
<% end %>
|
|
38
|
+
|
|
39
|
+
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true, 'data-turbolinks-eval' => false %>
|
|
40
|
+
</body>
|
|
41
|
+
</html>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title><%= yield(:title) %></title>
|
|
5
|
+
|
|
6
|
+
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
|
|
7
|
+
|
|
8
|
+
<%= csrf_meta_tags %>
|
|
9
|
+
|
|
10
|
+
<%= yield :extra_head %>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
|
|
14
|
+
<%= yield %>
|
|
15
|
+
|
|
16
|
+
</body>
|
|
17
|
+
</html>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<% provide(:title, 'Install') %>
|
|
2
|
+
|
|
3
|
+
<%= form_tag shopify_app.login_path do %>
|
|
4
|
+
<div class="modal-dialog">
|
|
5
|
+
<div class="modal-content">
|
|
6
|
+
<div class="modal-body">
|
|
7
|
+
|
|
8
|
+
<% flash.each do |message_type, message| %>
|
|
9
|
+
<div class="alert alert-<%= message_type %>"><%= message %></div>
|
|
10
|
+
<% end %>
|
|
11
|
+
|
|
12
|
+
<div class="form-group">
|
|
13
|
+
<div class="input-group">
|
|
14
|
+
<div class="input-group-addon">http://</div>
|
|
15
|
+
<input type="text" class="form-control" id="shop" name="shop" placeholder="your-store" autocomplete="off" autofocus="on" />
|
|
16
|
+
<div class="input-group-addon">.myshopify.com</div>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
</div>
|
|
21
|
+
<div class="modal-footer">
|
|
22
|
+
<button type="submit" class="btn btn-primary">Install</button>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
<% end %>
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
# Make the embedded app frame emulator available in development.
|
|
20
|
+
if Rails.env.development?
|
|
21
|
+
controller :frame do
|
|
22
|
+
get 'frame' => :frame, as: :frame
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
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
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class CreateDiscoAppSessions < ActiveRecord::Migration
|
|
2
|
+
def change
|
|
3
|
+
create_table :disco_app_sessions do |t|
|
|
4
|
+
t.string :session_id, :null => false
|
|
5
|
+
t.text :data
|
|
6
|
+
t.timestamps
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
add_index :disco_app_sessions, :session_id, :unique => true
|
|
10
|
+
add_index :disco_app_sessions, :updated_at
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module DiscoApp
|
|
2
|
+
|
|
3
|
+
class Configuration
|
|
4
|
+
|
|
5
|
+
# Required configuration.
|
|
6
|
+
attr_accessor :app_name
|
|
7
|
+
|
|
8
|
+
# Set the below if using an application proxy.
|
|
9
|
+
attr_accessor :app_proxy_prefix
|
|
10
|
+
|
|
11
|
+
# Optional configuration, usually useful for development environments.
|
|
12
|
+
attr_accessor :skip_proxy_verification
|
|
13
|
+
alias_method :skip_proxy_verification?, :skip_proxy_verification
|
|
14
|
+
attr_accessor :skip_webhook_verification
|
|
15
|
+
alias_method :skip_webhook_verification?, :skip_webhook_verification
|
|
16
|
+
attr_accessor :skip_carrier_request_verification
|
|
17
|
+
alias_method :skip_carrier_request_verification?, :skip_carrier_request_verification
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.configuration
|
|
22
|
+
@configuration ||= Configuration.new
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.configuration=(config)
|
|
26
|
+
@configuration = config
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.configure
|
|
30
|
+
yield configuration
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'shopify_app'
|
|
2
|
+
require 'bootstrap-sass'
|
|
3
|
+
require 'jquery-rails'
|
|
4
|
+
require 'turbolinks'
|
|
5
|
+
require 'activerecord/session_store'
|
|
6
|
+
require 'disco_app/session'
|
|
7
|
+
|
|
8
|
+
module DiscoApp
|
|
9
|
+
class Engine < ::Rails::Engine
|
|
10
|
+
|
|
11
|
+
isolate_namespace DiscoApp
|
|
12
|
+
engine_name 'disco_app'
|
|
13
|
+
|
|
14
|
+
# Ensure DiscoApp helpers are available throughout application.
|
|
15
|
+
config.to_prepare do
|
|
16
|
+
ApplicationController.helper(DiscoApp::ApplicationHelper)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Ensure our frame assets are included for precompilation.
|
|
20
|
+
initializer 'disco_app.assets.precompile' do |app|
|
|
21
|
+
app.config.assets.precompile += %w(disco_app/icon.svg disco_app/frame.css disco_app/frame.js)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module DiscoApp::Test
|
|
2
|
+
module FileFixtures
|
|
3
|
+
|
|
4
|
+
# Return an XML fixture as an XML string.
|
|
5
|
+
def xml_fixture(path)
|
|
6
|
+
filename = Rails.root.join('test', 'fixtures', 'xml', "#{path}.xml")
|
|
7
|
+
File.read(filename)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Return a JSON fixture as an indifferent hash.
|
|
11
|
+
def json_fixture(path, dir: 'json', parse: true)
|
|
12
|
+
filename = Rails.root.join('test', 'fixtures', dir, "#{path}.json")
|
|
13
|
+
return File.read(filename) unless parse
|
|
14
|
+
HashWithIndifferentAccess.new(ActiveSupport::JSON.decode(File.read(filename)))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Webhook fixtures are special-case JSON fixtures.
|
|
18
|
+
def webhook_fixture(path, parse: true)
|
|
19
|
+
json_fixture(path, dir: 'webhooks', parse: parse)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require 'disco_app/support/file_fixtures'
|
|
2
|
+
|
|
3
|
+
# Make our helper modules available inside fixtures.
|
|
4
|
+
ActiveRecord::FixtureSet.context_class.send :include, DiscoApp::Test::FileFixtures
|
|
5
|
+
|
|
6
|
+
# Include FileFixture helpers in base TestCase class.
|
|
7
|
+
class ActiveSupport::TestCase
|
|
8
|
+
|
|
9
|
+
include DiscoApp::Test::FileFixtures
|
|
10
|
+
|
|
11
|
+
end
|
data/lib/disco_app.rb
ADDED