shopify_app_lrb3 5.0.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 (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/CHANGELOG +5 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +19 -0
  6. data/README.md +182 -0
  7. data/RELEASING +16 -0
  8. data/Rakefile +11 -0
  9. data/install.rb +25 -0
  10. data/lib/generators/shopify_app/README +23 -0
  11. data/lib/generators/shopify_app/USAGE +22 -0
  12. data/lib/generators/shopify_app/shopify_app_generator.rb +69 -0
  13. data/lib/generators/shopify_app/templates/app/assets/images/favicon.png +0 -0
  14. data/lib/generators/shopify_app/templates/app/assets/images/grid-18px.png +0 -0
  15. data/lib/generators/shopify_app/templates/app/assets/images/shopify-114.png +0 -0
  16. data/lib/generators/shopify_app/templates/app/assets/images/shopify-57.png +0 -0
  17. data/lib/generators/shopify_app/templates/app/assets/images/shopify-72.png +0 -0
  18. data/lib/generators/shopify_app/templates/app/assets/images/shopify.png +0 -0
  19. data/lib/generators/shopify_app/templates/app/assets/javascripts/application.js +15 -0
  20. data/lib/generators/shopify_app/templates/app/assets/stylesheets/application.css +10 -0
  21. data/lib/generators/shopify_app/templates/app/assets/stylesheets/imports.css.less +5 -0
  22. data/lib/generators/shopify_app/templates/app/assets/stylesheets/shopify_app.css.scss +150 -0
  23. data/lib/generators/shopify_app/templates/app/assets/stylesheets/shopify_app_buttons.css.less +77 -0
  24. data/lib/generators/shopify_app/templates/app/controllers/application_controller.rb +13 -0
  25. data/lib/generators/shopify_app/templates/app/controllers/home_controller.rb +18 -0
  26. data/lib/generators/shopify_app/templates/app/controllers/sessions_controller.rb +52 -0
  27. data/lib/generators/shopify_app/templates/app/helpers/home_helper.rb +9 -0
  28. data/lib/generators/shopify_app/templates/app/helpers/login_helper.rb +3 -0
  29. data/lib/generators/shopify_app/templates/app/helpers/tabs_helper.rb +11 -0
  30. data/lib/generators/shopify_app/templates/app/views/home/design.html.erb +3542 -0
  31. data/lib/generators/shopify_app/templates/app/views/home/index.html.erb +168 -0
  32. data/lib/generators/shopify_app/templates/app/views/home/welcome.html.erb +110 -0
  33. data/lib/generators/shopify_app/templates/app/views/layouts/application.html.erb +79 -0
  34. data/lib/generators/shopify_app/templates/app/views/sessions/new.html.erb +21 -0
  35. data/lib/generators/shopify_app/templates/config/initializers/omniauth.rb +14 -0
  36. data/lib/generators/shopify_app/templates/config/initializers/shopify_session_repository.rb +21 -0
  37. data/lib/generators/shopify_app/templates/public/404.html +40 -0
  38. data/lib/generators/shopify_app/templates/public/422.html +40 -0
  39. data/lib/generators/shopify_app/templates/public/500.html +40 -0
  40. data/lib/generators/shopify_app/templates/public/favicon.png +0 -0
  41. data/lib/generators/shopify_app/templates/public/shopify-114.png +0 -0
  42. data/lib/generators/shopify_app/templates/public/shopify-57.png +0 -0
  43. data/lib/generators/shopify_app/templates/public/shopify-72.png +0 -0
  44. data/lib/shopify_app.rb +20 -0
  45. data/lib/shopify_app/configuration.rb +46 -0
  46. data/lib/shopify_app/in_memory_session_store.rb +25 -0
  47. data/lib/shopify_app/login_protection.rb +39 -0
  48. data/lib/shopify_app/railtie.rb +17 -0
  49. data/lib/shopify_app/shopify_session_repository.rb +22 -0
  50. data/lib/shopify_app/version.rb +3 -0
  51. data/shipit.rubygems.yml +1 -0
  52. data/shopify_app.gemspec +30 -0
  53. data/test/config/development_config_file.yml +7 -0
  54. data/test/config/empty_config_file.yml +1 -0
  55. data/test/config/other_config_file.yml +3 -0
  56. data/test/config/shopify_app.yml +3 -0
  57. data/test/lib/shopify_app/configuration_test.rb +78 -0
  58. data/test/lib/shopify_app/in_memory_session_store_test.rb +35 -0
  59. data/test/lib/shopify_app/shopify_session_repository_test.rb +57 -0
  60. data/test/test_helper.rb +5 -0
  61. metadata +214 -0
@@ -0,0 +1,40 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>422 Error: Your change was rejected</title>
5
+
6
+ <style>
7
+ .container { text-align:center;}
8
+ .navbar .brand { float:none;}
9
+ </style>
10
+ </head>
11
+
12
+ <body>
13
+ <div class="navbar navbar-fixed-top">
14
+ <div class="navbar-inner">
15
+ <div class="container">
16
+ <a href="/" class="brand">Shopify Demo App</a>
17
+ </div>
18
+ </div>
19
+ </div>
20
+
21
+ <div class="container">
22
+ <div class="content">
23
+
24
+ <div class="page-header">
25
+ <h1>422 Error</h1>
26
+ </div>
27
+
28
+ <h3><i class="icon-warning-sign" style="margin-top:6px; opacity:.5;"></i> Sorry, the change you requested was rejected.</h3>
29
+ <p class="muted">Did you try to change something you don't have access to?</p>
30
+
31
+ <p><button type="button" value ="back" onClick="window.history.back();" class='btn btn-primary'><i class="icon-chevron-left" style="opacity:.25"></i> Back to the app</button></p>
32
+
33
+ </div>
34
+
35
+ <footer>
36
+ <p>A Shopify app by (company name here)</p>
37
+ </footer>
38
+ </div> <!-- /container -->
39
+ </body>
40
+ </html>
@@ -0,0 +1,40 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>500 Error: Something went horribly wrong</title>
5
+
6
+ <style>
7
+ .container { text-align:center;}
8
+ .navbar .brand { float:none;}
9
+ </style>
10
+ </head>
11
+
12
+ <body>
13
+ <div class="navbar navbar-fixed-top">
14
+ <div class="navbar-inner">
15
+ <div class="container">
16
+ <a href="/" class="brand">Shopify Demo App</a>
17
+ </div>
18
+ </div>
19
+ </div>
20
+
21
+ <div class="container">
22
+ <div class="content">
23
+
24
+ <div class="page-header">
25
+ <h1>AH! 500 Error!</h1>
26
+ </div>
27
+
28
+ <h3><i class="icon-warning-sign" style="margin-top:6px; opacity:.5;"></i> We're sorry, but something went wrong.</h3>
29
+ <p class="muted">The developer of this app has been notified.</p>
30
+
31
+ <p><button type="button" value ="back" onClick="window.history.back();" class='btn btn-primary'><i class="icon-chevron-left" style="opacity:.25"></i> Back to the app</button></p>
32
+
33
+ </div>
34
+
35
+ <footer>
36
+ <p>A Shopify app by (company name here)</p>
37
+ </footer>
38
+ </div> <!-- /container -->
39
+ </body>
40
+ </html>
@@ -0,0 +1,20 @@
1
+ require 'shopify_api'
2
+ require 'omniauth-shopify-oauth2'
3
+
4
+ module ShopifyApp
5
+
6
+ def self.configuration
7
+ @configuration ||= ShopifyApp::Configuration.new
8
+ end
9
+
10
+ def self.setup_session
11
+ ShopifyAPI::Session.setup(:api_key => ShopifyApp.configuration.api_key, :secret => ShopifyApp.configuration.secret)
12
+ end
13
+ end
14
+
15
+ require 'shopify_app/shopify_session_repository'
16
+ require 'shopify_app/in_memory_session_store'
17
+ require 'shopify_app/login_protection'
18
+ require 'shopify_app/configuration'
19
+ require 'shopify_app/railtie'
20
+ require 'shopify_app/version'
@@ -0,0 +1,46 @@
1
+ class ShopifyApp::Configuration
2
+ VALID_KEYS = [:api_key, :secret]
3
+ attr_writer *VALID_KEYS
4
+
5
+ def initialize(params={})
6
+ self.params = default_params.merge(params)
7
+ end
8
+
9
+ VALID_KEYS.each do |meth|
10
+ define_method meth do
11
+ meth = meth.to_s
12
+ config_from_env(meth) || config_from_rails(meth) || config_from_file(meth) || ''
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ attr_accessor :params
19
+
20
+ def config_from_env(meth)
21
+ ENV["SHOPIFY_APP_#{meth.upcase}"]
22
+ end
23
+
24
+ def config_from_rails(meth)
25
+ instance_variable_get("@#{meth}")
26
+ end
27
+
28
+ def config_from_file(meth)
29
+ @config_file ||= load_config
30
+ @config_file[Rails.env].try(:[], meth) || @config_file['common'].try(:[], meth)
31
+ end
32
+
33
+ def load_config
34
+ File.exist?(config_filepath) ? YAML.load_file(config_filepath) : {}
35
+ end
36
+
37
+ def config_filepath
38
+ params[:config_file]
39
+ end
40
+
41
+ def default_params
42
+ {
43
+ config_file: File.join(Rails.root, 'config', 'shopify_app.yml')
44
+ }
45
+ end
46
+ end
@@ -0,0 +1,25 @@
1
+ # WARNING - This really only works for development, see README for more details
2
+ class InMemorySessionStore
3
+ class EnvironmentError < StandardError; end
4
+
5
+ def self.retrieve(id)
6
+ repo[id]
7
+ end
8
+
9
+ def self.store(session)
10
+ id = SecureRandom.uuid
11
+ repo[id] = session
12
+ id
13
+ end
14
+
15
+ def self.clear
16
+ @@repo = nil
17
+ end
18
+
19
+ def self.repo
20
+ if Rails.env.production?
21
+ raise EnvironmentError.new("Cannot use InMemorySessionStore in a Production environment")
22
+ end
23
+ @@repo ||= {}
24
+ end
25
+ end
@@ -0,0 +1,39 @@
1
+ module ShopifyApp::LoginProtection
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ rescue_from ActiveResource::UnauthorizedAccess, :with => :close_session
6
+ end
7
+
8
+ def shopify_session
9
+ if shop_session
10
+ begin
11
+ # session[:shopify] set in LoginController#show
12
+ ShopifyAPI::Base.activate_session(shop_session)
13
+ yield
14
+ ensure
15
+ ShopifyAPI::Base.clear_session
16
+ end
17
+ else
18
+ session[:return_to] = request.fullpath if request.get?
19
+ redirect_to login_path(shop: params[:shop])
20
+ end
21
+ end
22
+
23
+ def shop_session
24
+ ShopifySessionRepository.retrieve(session[:shopify])
25
+ end
26
+
27
+ def login_again_if_different_shop
28
+ if shop_session && params[:shop] && params[:shop].is_a?(String) && shop_session.url != params[:shop]
29
+ redirect_to login_path(shop: params[:shop])
30
+ end
31
+ end
32
+
33
+ protected
34
+
35
+ def close_session
36
+ session[:shopify] = nil
37
+ redirect_to login_path
38
+ end
39
+ end
@@ -0,0 +1,17 @@
1
+ require 'rails'
2
+
3
+ class ShopifyApp::Railtie < ::Rails::Railtie
4
+
5
+ config.before_configuration do
6
+ config.shopify = ShopifyApp.configuration
7
+ end
8
+
9
+ initializer "shopify_app.action_controller_integration" do
10
+ ActionController::Base.send :include, ShopifyApp::LoginProtection
11
+ ActionController::Base.send :helper_method, :shop_session
12
+ end
13
+
14
+ initializer "shopify_app.setup_session" do
15
+ ShopifyApp.setup_session
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ class ShopifySessionRepository
2
+ class ConfigurationError < StandardError; end
3
+
4
+ def self.storage=(storage)
5
+ @@storage = storage
6
+ end
7
+
8
+ def self.retrieve(id)
9
+ validate
10
+ @@storage.retrieve(id)
11
+ end
12
+
13
+ def self.store(session)
14
+ validate
15
+ @@storage.store(session)
16
+ end
17
+
18
+ def self.validate
19
+ raise ConfigurationError.new("ShopifySessionRepository.store is not configured!") unless @@storage
20
+ end
21
+
22
+ end
@@ -0,0 +1,3 @@
1
+ module ShopifyApp
2
+ VERSION = "5.0.0"
3
+ end
@@ -0,0 +1 @@
1
+ # using the default shipit config
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "shopify_app/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "shopify_app_lrb3"
7
+ s.version = ShopifyApp::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.author = "Shopify"
10
+ s.email = ["gareth@bencrudo.com"]
11
+ s.homepage = "http://www.shopify.com/developers"
12
+ s.summary = %q{Fork of shopify_app upgrade to Less Rails Bootstrap 3.1.1}
13
+ s.description = %q{Required Boostrap 3 so cloned and upgraded to Less Rails Bootstrap 3.1.1}
14
+
15
+ s.rubyforge_project = "shopify-api"
16
+
17
+ s.add_runtime_dependency('rails', '>= 3.1', '< 5.0')
18
+ s.add_runtime_dependency('shopify_api', '~> 3.2.0')
19
+ s.add_runtime_dependency('omniauth-shopify-oauth2', '~> 1.1.4')
20
+ s.add_runtime_dependency('less-rails-bootstrap', '~> 3.1.1')
21
+
22
+ s.add_development_dependency('rake')
23
+ s.add_development_dependency('minitest')
24
+ s.add_development_dependency('mocha')
25
+
26
+ s.files = `git ls-files`.split("\n")
27
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
28
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
29
+ s.require_paths = ["lib"]
30
+ end
@@ -0,0 +1,7 @@
1
+ common:
2
+ api_key: should never see this api key value
3
+ secret: should never see this secret value
4
+
5
+ development:
6
+ api_key: development key
7
+ secret: development secret
@@ -0,0 +1 @@
1
+ common:
@@ -0,0 +1,3 @@
1
+ common:
2
+ api_key: api key from other file
3
+ secret: secret from other file
@@ -0,0 +1,3 @@
1
+ common:
2
+ api_key: api key from default file
3
+ secret: secret from default file
@@ -0,0 +1,78 @@
1
+ require 'test_helper'
2
+
3
+ class ConfigurationTest < Minitest::Test
4
+ def setup
5
+ Rails.stubs(:env).returns('development')
6
+ Rails.stubs(:root).returns(File.expand_path('../..', File.dirname(__FILE__)))
7
+ end
8
+
9
+ def config_file(filename)
10
+ filepath = File.expand_path("../../config/#{filename}", File.dirname(__FILE__))
11
+ end
12
+
13
+ def test_define_method_creates_readers
14
+ config = ShopifyApp::Configuration.new
15
+ config.respond_to?(:api_key)
16
+ config.respond_to?(:secret)
17
+ end
18
+
19
+ def test_defaults_to_empty_string
20
+ config = ShopifyApp::Configuration.new(config_file: config_file('empty_config_file.yml'))
21
+
22
+ assert_equal '', config.api_key
23
+ assert_equal '', config.secret
24
+ end
25
+
26
+ def test_environment_has_precedence_over_common
27
+ config = ShopifyApp::Configuration.new(config_file: config_file('development_config_file.yml'))
28
+
29
+ assert_equal 'development key', config.api_key
30
+ assert_equal 'development secret', config.secret
31
+ end
32
+
33
+ def test_rails_has_precedence_over_environment
34
+ config = ShopifyApp::Configuration.new(config_file: config_file('development_config_file.yml'))
35
+
36
+ assert_equal 'development key', config.api_key
37
+ assert_equal 'development secret', config.secret
38
+
39
+ config.api_key = 'rails key'
40
+ config.secret = 'rails secret'
41
+
42
+ assert_equal 'rails key', config.api_key
43
+ assert_equal 'rails secret', config.secret
44
+ end
45
+
46
+ def test_env_has_precedence_over_rails
47
+ config = ShopifyApp::Configuration.new
48
+ config.api_key = 'rails key'
49
+ config.secret = 'rails secret'
50
+
51
+ assert_equal 'rails key', config.api_key
52
+ assert_equal 'rails secret', config.secret
53
+
54
+ ENV.expects(:[]).with('SHOPIFY_APP_API_KEY').returns('env key')
55
+ ENV.expects(:[]).with('SHOPIFY_APP_SECRET').returns('env secret')
56
+
57
+ assert_equal 'env key', config.api_key
58
+ assert_equal 'env secret', config.secret
59
+ end
60
+
61
+ def test_reads_config_from_default_config_file
62
+ config = ShopifyApp::Configuration.new
63
+ assert_equal 'api key from default file', config.api_key
64
+ assert_equal 'secret from default file', config.secret
65
+ end
66
+
67
+ def test_reads_config_from_specified_config_file
68
+ config = ShopifyApp::Configuration.new(config_file: config_file('other_config_file.yml'))
69
+ assert_equal 'api key from other file', config.api_key
70
+ assert_equal 'secret from other file', config.secret
71
+ end
72
+
73
+ def test_handles_missing_config_file
74
+ config = ShopifyApp::Configuration.new(config_file: config_file('missing_config_file.yml'))
75
+ assert_equal '', config.api_key
76
+ assert_equal '', config.secret
77
+ end
78
+ end
@@ -0,0 +1,35 @@
1
+ require 'test_helper'
2
+
3
+ class InMemorySessionStoreTest < Minitest::Test
4
+ def teardown
5
+ InMemorySessionStore.clear
6
+ end
7
+
8
+ def test_storing_a_session
9
+ uuid = InMemorySessionStore.store('something')
10
+ assert_equal 'something', InMemorySessionStore.repo[uuid]
11
+ end
12
+
13
+ def test_retrieving_a_session
14
+ InMemorySessionStore.repo['abra'] = 'something'
15
+ assert_equal 'something', InMemorySessionStore.retrieve('abra')
16
+ end
17
+
18
+ def test_clearing_the_store
19
+ uuid = InMemorySessionStore.store('data')
20
+ assert_equal 'data', InMemorySessionStore.retrieve(uuid)
21
+ InMemorySessionStore.clear
22
+ assert !InMemorySessionStore.retrieve(uuid), 'The sessions should have been removed'
23
+ end
24
+
25
+ def test_it_should_raise_when_the_environment_is_not_valid
26
+ Rails.env.stubs(:production?).returns(true)
27
+ assert_raises InMemorySessionStore::EnvironmentError do
28
+ InMemorySessionStore.store('data')
29
+ end
30
+
31
+ assert_raises InMemorySessionStore::EnvironmentError do
32
+ InMemorySessionStore.retrieve('abracadabra')
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,57 @@
1
+ require 'test_helper'
2
+
3
+ class TestSessionStore
4
+ attr_reader :storage
5
+ def initialize
6
+ @storage = []
7
+ end
8
+
9
+ def retrieve(id)
10
+ storage[id]
11
+ end
12
+
13
+ def store(session)
14
+ id = storage.length
15
+ storage[id] = session
16
+ id
17
+ end
18
+ end
19
+
20
+ class ShopifySessionRepositoryTest < Minitest::Test
21
+ attr_reader :session_store, :session
22
+ def setup
23
+ @session_store = TestSessionStore.new
24
+ @session = ShopifyAPI::Session.new('shop.myshopify.com', 'abracadabra')
25
+ ShopifySessionRepository.storage = session_store
26
+ end
27
+
28
+ def teardown
29
+ ShopifySessionRepository.storage = nil
30
+ end
31
+
32
+ def test_adding_a_session_to_the_repository
33
+ assert_equal 0, ShopifySessionRepository.store(session)
34
+ assert_equal session, session_store.retrieve(0)
35
+ end
36
+
37
+ def test_retrieving_a_session_from_the_repository
38
+ session_store.storage[9] = session
39
+ assert_equal session, ShopifySessionRepository.retrieve(9)
40
+ end
41
+
42
+ def test_retrieving_a_session_for_an_id_that_does_not_exist
43
+ ShopifySessionRepository.store(session)
44
+ assert !ShopifySessionRepository.retrieve(100), "The session with id 100 should not exist in the Repository"
45
+ end
46
+
47
+ def test_retrieving_a_session_for_a_misconfigured_shops_repository
48
+ ShopifySessionRepository.storage = nil
49
+ assert_raises ShopifySessionRepository::ConfigurationError do
50
+ ShopifySessionRepository.retrieve(0)
51
+ end
52
+
53
+ assert_raises ShopifySessionRepository::ConfigurationError do
54
+ ShopifySessionRepository.store(session)
55
+ end
56
+ end
57
+ end