shopify_theme 0.0.22 → 0.0.23

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2223be5c2de93ee62bfd2c4534e94407f10a4b59
4
- data.tar.gz: d0d57181fa9d5e9aa9128c55a423e108e58cb70a
3
+ metadata.gz: 6971fe42d85d617b5d0a95de3c9e34279dac2199
4
+ data.tar.gz: d3ca43ec6f1b2ed28266e67a6036d748709a0f85
5
5
  SHA512:
6
- metadata.gz: 909b624021715432d39077e4a15bbf03de67f996cb3994176b1ee49409d3f7b16ab17842d939804bc5f2d3c5cbd0220b42058e3b1c3c8234f6faa5bf67ea127e
7
- data.tar.gz: ae1a012f19bc8a16bb7ca1d3ea142cb91bd13d7ff5d9c8071d7abd0f1e8ee7ef13dd7ddd21db1f642fdcb4dcbc9e688bfecff93533bf1ce305553fa119ef635f
6
+ metadata.gz: 994ba6ea158f91729a131200ebc778c72467234febfa8716e72f829156c75fd028e6d9c085ba80bc6fa0bd7e9a5d6c11a7778db69d1bd42c06e37134abfb87e2
7
+ data.tar.gz: 94ee9d1a1266d99e6b9a0f762e8bfe0e8cfa50bf09f2651a58d070e5de1c42e73020bfdadcfd3d45e1e51b8cbcb0ee54e2e83a9863dc8f1ad0f5a844c6e72592
data/.gitignore CHANGED
@@ -2,4 +2,5 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
- .project
5
+ .project
6
+ .idea
@@ -1,4 +1,5 @@
1
1
  langauge: ruby
2
+ sudo: false
2
3
  rvm:
3
4
  - 1.9.3
4
5
  - 2.0.0
@@ -1,3 +1,12 @@
1
+ # v0.0.23 (Unreleased)
2
+
3
+ * Adds support for OAuth access token based authentication -- gavinballard
4
+
5
+ # v0.0.22
6
+
7
+ * Parsing of Timber release feed to always retrieve latest release
8
+ * Minor documentation improvements
9
+
1
10
  # v0.0.21
2
11
 
3
12
  * Adds Locale support
data/README.md CHANGED
@@ -10,7 +10,7 @@ The Shopify theme gem is a command line tool that allows you to manage and edit
10
10
  ## Requirements
11
11
  This gem works with OS X or Windows with Ruby 1.9.
12
12
 
13
- First time installing Ruby on Windows? Try [Rubyinstaller](http://http://rubyinstaller.org/).
13
+ First time installing Ruby on Windows? Try [Rubyinstaller](http://rubyinstaller.org/).
14
14
 
15
15
 
16
16
  ## Configuration
@@ -24,9 +24,9 @@ Click on “Create a Private App” to generate the credentials for a new app. Y
24
24
 
25
25
  Navigate to the directory where you theme files live, or where you'd like them to be, and execute the following command:
26
26
 
27
- `theme configure api_key password store_name`
27
+ `theme configure api_key password store_domain`
28
28
 
29
- **Important:** enter the `store_name` with no `http://`.
29
+ **Important:** enter the `store_domain` with no `http://`.
30
30
 
31
31
  In your directory you should see a file named config.yml with your credentials. If you want, you may also edit the config.yml file directly and paste your API Key and Password in the appropriate area.
32
32
 
@@ -74,6 +74,17 @@ Specifies which files and directories should be responding to changes. If nothin
74
74
 
75
75
  Specifies which files should be explicitly ignored and not affected by any commands entered.
76
76
 
77
+ ### Alternative OAuth configuration (for advanced users)
78
+ As of v0.0.23, you can use a Shopify application's OAuth access token to authenticate with a store and manipulate theme files.
79
+
80
+ Once your application has obtained an access token through Shopify's regular OAuth authentication flow, run the following command to configure the gem:
81
+
82
+ `theme configure_oauth access_token store_domain`
83
+
84
+ The gem can then be used in exactly the same way as if you were authenticating via a Private App.
85
+
86
+ Note that the access token your Application has obtained ***must*** be valid for the `write_themes` scope in order to use the theme gem in this way.
87
+
77
88
 
78
89
  ## Commands
79
90
 
data/bin/theme CHANGED
@@ -20,6 +20,7 @@ fallback_load_path(File.join(File.dirname(__FILE__), '..', 'lib')) do
20
20
  require 'shopify_theme'
21
21
  require 'shopify_theme/cli'
22
22
  require 'shopify_theme/releases'
23
+ require 'shopify_theme/api_checker'
23
24
  end
24
25
 
25
26
  ShopifyTheme::Cli.start(ARGV)
@@ -132,9 +132,13 @@ module ShopifyTheme
132
132
  shopify.get(path).code == 200
133
133
  end
134
134
 
135
+ def self.get_index
136
+ shopify.get(path)
137
+ end
138
+
135
139
  private
136
140
  def self.shopify
137
- basic_auth config[:api_key], config[:password]
141
+ headers 'X-Shopify-Access-Token' => config[:password] || config[:access_token]
138
142
  base_uri "https://#{config[:store]}"
139
143
  ShopifyTheme
140
144
  end
@@ -0,0 +1,41 @@
1
+ module ShopifyTheme
2
+ class APIChecker
3
+ class APIResult
4
+ OK = 200
5
+ UNAUTHORIZED = 401
6
+ SERVER_ERROR_CODES = (500..599)
7
+
8
+ attr_reader :response
9
+ def initialize(http_response)
10
+ @response = http_response
11
+ end
12
+
13
+ def accessed_api?
14
+ response.code == OK
15
+ end
16
+
17
+ def cannot_access_api?
18
+ !accessed_api?
19
+ end
20
+
21
+ def invalid_config?
22
+ response.code == UNAUTHORIZED
23
+ end
24
+
25
+ def api_down?
26
+ SERVER_ERROR_CODES.include?(response.code)
27
+ end
28
+ end
29
+
30
+ def initialize(client)
31
+ @client = client
32
+ end
33
+
34
+ def test_connectivity
35
+ return APIResult.new(client.get_index)
36
+ end
37
+
38
+ private
39
+ attr_reader :client
40
+ end
41
+ end
@@ -36,18 +36,36 @@ module ShopifyTheme
36
36
  end
37
37
 
38
38
  desc "check", "check configuration"
39
- def check
40
- if ShopifyTheme.check_config
41
- say("Configuration [OK]", :green)
39
+ def check(exit_on_failure=false)
40
+ result = APIChecker.new(ShopifyTheme).test_connectivity
41
+
42
+ if result.api_down?
43
+ say("Cannot connect to Shopify. API appears to be down", :red)
44
+ say("Visit http://status.shopify.com for more details", :yello)
45
+ elsif result.invalid_config?
46
+ say("Cannot connect to Shopify. Configuration is invalid.", :red)
47
+ say("Verify that your API key, password and domain are correct.", :yellow)
48
+ say("Visit https://github.com/shopify/shopify_theme#configuration for more details", :yellow)
49
+ say("If your shop domain is correct, the following URL should take you to the Private Apps page for the shop:", :yellow)
50
+ say(" https://#{config[:store]}/admin/apps/private", :yellow)
42
51
  else
43
- say("Configuration [FAIL]", :red)
52
+ say("Shopify API is accessible and configuration is valid", :green) unless exit_on_failure
44
53
  end
54
+
55
+ exit(1) if result.cannot_access_api? && exit_on_failure
45
56
  end
46
57
 
47
58
  desc "configure API_KEY PASSWORD STORE THEME_ID", "generate a config file for the store to connect to"
48
59
  def configure(api_key=nil, password=nil, store=nil, theme_id=nil)
49
60
  config = {:api_key => api_key, :password => password, :store => store, :theme_id => theme_id}
50
61
  create_file('config.yml', config.to_yaml)
62
+ check(true)
63
+ end
64
+
65
+ desc "configure_oauth ACCESS_TOKEN STORE THEME_ID", "generate a config file for the store to connect to using an OAuth access token"
66
+ def configure_oauth(access_token=nil, store=nil, theme_id=nil)
67
+ config = {:access_token => access_token, :store => store, :theme_id => theme_id}
68
+ create_file('config.yml', config.to_yaml)
51
69
  end
52
70
 
53
71
  desc "bootstrap API_KEY PASSWORD STORE THEME_NAME", "bootstrap with Timber to shop and configure local directory."
@@ -55,6 +73,7 @@ module ShopifyTheme
55
73
  method_option :version, :type => :string, :default => "latest"
56
74
  def bootstrap(api_key=nil, password=nil, store=nil, theme_name=nil)
57
75
  ShopifyTheme.config = {:api_key => api_key, :password => password, :store => store}
76
+ check(true)
58
77
 
59
78
  theme_name ||= 'Timber'
60
79
  say("Registering #{theme_name} theme on #{store}", :green)
@@ -78,6 +97,7 @@ module ShopifyTheme
78
97
  method_option :quiet, :type => :boolean, :default => false
79
98
  method_option :exclude
80
99
  def download(*keys)
100
+ check(true)
81
101
  assets = keys.empty? ? ShopifyTheme.asset_list : keys
82
102
 
83
103
  if options['exclude']
@@ -101,6 +121,7 @@ module ShopifyTheme
101
121
  desc "upload FILE", "upload all theme assets to shop"
102
122
  method_option :quiet, :type => :boolean, :default => false
103
123
  def upload(*keys)
124
+ check(true)
104
125
  assets = keys.empty? ? local_assets_list : keys
105
126
  assets.each do |asset|
106
127
  send_asset(asset, options['quiet'])
@@ -111,6 +132,7 @@ module ShopifyTheme
111
132
  desc "replace FILE", "completely replace shop theme assets with local theme assets"
112
133
  method_option :quiet, :type => :boolean, :default => false
113
134
  def replace(*keys)
135
+ check(true)
114
136
  say("Are you sure you want to completely replace your shop theme assets? This is not undoable.", :yellow)
115
137
  if ask("Continue? (Y/N): ") == "Y"
116
138
  # only delete files on remote that are not present locally
@@ -130,6 +152,7 @@ module ShopifyTheme
130
152
  desc "remove FILE", "remove theme asset"
131
153
  method_option :quiet, :type => :boolean, :default => false
132
154
  def remove(*keys)
155
+ check(true)
133
156
  keys.each do |key|
134
157
  delete_asset(key, options['quiet'])
135
158
  end
@@ -140,14 +163,14 @@ module ShopifyTheme
140
163
  method_option :quiet, :type => :boolean, :default => false
141
164
  method_option :keep_files, :type => :boolean, :default => false
142
165
  def watch
166
+ check(true)
143
167
  puts "Watching current folder: #{Dir.pwd}"
144
168
  watcher do |filename, event|
145
169
  filename = filename.gsub("#{Dir.pwd}/", '')
146
170
 
147
- next unless local_assets_list.include?(filename)
148
- action = if [:changed, :new].include?(event)
171
+ action = if [:changed, :new].include?(event) && local_assets_list.include?(filename)
149
172
  :send_asset
150
- elsif event == :delete
173
+ elsif event == :delete && !options['keep_files']
151
174
  :delete_asset
152
175
  else
153
176
  raise NotImplementedError, "Unknown event -- #{event} -- #{filename}"
@@ -1,3 +1,3 @@
1
1
  module ShopifyTheme
2
- VERSION = "0.0.22"
2
+ VERSION = "0.0.23"
3
3
  end
@@ -0,0 +1,55 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://something.myshopify.com/admin/assets.json
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ X-Shopify-Access-Token:
11
+ - alakazam
12
+ response:
13
+ status:
14
+ code: 503
15
+ message: Unavailable
16
+ headers:
17
+ Server:
18
+ - nginx
19
+ Date:
20
+ - Tue, 01 Sep 2015 18:47:36 GMT
21
+ Content-Type:
22
+ - application/json; charset=utf-8
23
+ Transfer-Encoding:
24
+ - chunked
25
+ Connection:
26
+ - keep-alive
27
+ X-Sorting-Hat-Podid:
28
+ - '0'
29
+ X-Sorting-Hat-Shopid:
30
+ - '2538'
31
+ X-Sorting-Hat-Podid-Cached:
32
+ - '1'
33
+ X-Sorting-Hat-Shopid-Cached:
34
+ - '1'
35
+ Status:
36
+ - 401 Unauthorized
37
+ X-Frame-Options:
38
+ - DENY
39
+ X-Shopid:
40
+ - '2538'
41
+ X-Shardid:
42
+ - '0'
43
+ Www-Authenticate:
44
+ - Basic Realm="Shopify API Authentication"
45
+ X-Xss-Protection:
46
+ - 1; mode=block; report=/xss-report/6cb4f1eb-40ea-4f96-b36c-e7edc4cc6005?source%5Baction%5D=index&source%5Bcontroller%5D=admin%2Fassets&source%5Bsection%5D=admin
47
+ X-Request-Id:
48
+ - 6cb4f1eb-40ea-4f96-b36c-e7edc4cc6005
49
+ body:
50
+ encoding: UTF-8
51
+ string: '{"errors":"[API] Invalid API key or access token (unrecognized login
52
+ or wrong password)"}'
53
+ http_version:
54
+ recorded_at: Tue, 01 Sep 2015 18:47:36 GMT
55
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,55 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://something.myshopify.com/admin/assets.json
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ X-Shopify-Access-Token:
11
+ - alakazam
12
+ response:
13
+ status:
14
+ code: 200
15
+ message: OK
16
+ headers:
17
+ Server:
18
+ - nginx
19
+ Date:
20
+ - Tue, 01 Sep 2015 18:47:35 GMT
21
+ Content-Type:
22
+ - application/json; charset=utf-8
23
+ Transfer-Encoding:
24
+ - chunked
25
+ Connection:
26
+ - keep-alive
27
+ X-Sorting-Hat-Podid:
28
+ - '0'
29
+ X-Sorting-Hat-Shopid:
30
+ - '2538'
31
+ X-Sorting-Hat-Podid-Cached:
32
+ - '0'
33
+ X-Sorting-Hat-Shopid-Cached:
34
+ - '0'
35
+ Status:
36
+ - 401 Unauthorized
37
+ X-Frame-Options:
38
+ - DENY
39
+ X-Shopid:
40
+ - '2538'
41
+ X-Shardid:
42
+ - '0'
43
+ Www-Authenticate:
44
+ - Basic Realm="Shopify API Authentication"
45
+ X-Xss-Protection:
46
+ - 1; mode=block; report=/xss-report/f2203a5b-1bf3-4207-942b-81472f5d3073?source%5Baction%5D=index&source%5Bcontroller%5D=admin%2Fassets&source%5Bsection%5D=admin
47
+ X-Request-Id:
48
+ - f2203a5b-1bf3-4207-942b-81472f5d3073
49
+ body:
50
+ encoding: UTF-8
51
+ string: '{"errors":"[API] Invalid API key or access token (unrecognized login
52
+ or wrong password)"}'
53
+ http_version:
54
+ recorded_at: Tue, 01 Sep 2015 18:47:36 GMT
55
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,55 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://something.myshopify.com/admin/assets.json
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ X-Shopify-Access-Token:
11
+ - alakazam
12
+ response:
13
+ status:
14
+ code: 401
15
+ message: Unauthorized
16
+ headers:
17
+ Server:
18
+ - nginx
19
+ Date:
20
+ - Tue, 01 Sep 2015 18:47:36 GMT
21
+ Content-Type:
22
+ - application/json; charset=utf-8
23
+ Transfer-Encoding:
24
+ - chunked
25
+ Connection:
26
+ - keep-alive
27
+ X-Sorting-Hat-Podid:
28
+ - '0'
29
+ X-Sorting-Hat-Shopid:
30
+ - '2538'
31
+ X-Sorting-Hat-Podid-Cached:
32
+ - '1'
33
+ X-Sorting-Hat-Shopid-Cached:
34
+ - '1'
35
+ Status:
36
+ - 401 Unauthorized
37
+ X-Frame-Options:
38
+ - DENY
39
+ X-Shopid:
40
+ - '2538'
41
+ X-Shardid:
42
+ - '0'
43
+ Www-Authenticate:
44
+ - Basic Realm="Shopify API Authentication"
45
+ X-Xss-Protection:
46
+ - 1; mode=block; report=/xss-report/94fab138-9672-45ff-81b7-38f35ba81ed2?source%5Baction%5D=index&source%5Bcontroller%5D=admin%2Fassets&source%5Bsection%5D=admin
47
+ X-Request-Id:
48
+ - 94fab138-9672-45ff-81b7-38f35ba81ed2
49
+ body:
50
+ encoding: UTF-8
51
+ string: '{"errors":"[API] Invalid API key or access token (unrecognized login
52
+ or wrong password)"}'
53
+ http_version:
54
+ recorded_at: Tue, 01 Sep 2015 18:47:36 GMT
55
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+ require 'shopify_theme'
3
+ require 'shopify_theme/api_checker'
4
+
5
+ module ShopifyTheme
6
+ describe "APIChecker" do
7
+ attr_reader :checker
8
+
9
+ before do
10
+ config = {
11
+ api_key: 'abracadabra',
12
+ password: 'alakazam',
13
+ store: 'something.myshopify.com'
14
+ }
15
+ ShopifyTheme.config = config
16
+ @checker = APIChecker.new(ShopifyTheme)
17
+ end
18
+
19
+ after do
20
+ ShopifyTheme.config = nil
21
+ end
22
+
23
+ it "should return an APIResponse that says if the API is accessible when it gets a 200 response" do
24
+ VCR.use_cassette("api_check_success") do
25
+ response = checker.test_connectivity
26
+ assert response.accessed_api?
27
+ end
28
+ end
29
+
30
+ it "should return an APIResponse that says the API is down if it gets a 500-series response" do
31
+ VCR.use_cassette("api_check_api_down") do
32
+ response = checker.test_connectivity
33
+ assert response.api_down?
34
+ end
35
+ end
36
+
37
+ it "should return an APIResponse that says the client is misconfigured if it gets a 401 response" do
38
+ VCR.use_cassette("api_check_unauthorized") do
39
+ response = checker.test_connectivity
40
+ assert response.invalid_config?
41
+ end
42
+ end
43
+ end
44
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify_theme
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.22
4
+ version: 0.0.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Duff
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-26 00:00:00.000000000 Z
11
+ date: 2015-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -172,13 +172,18 @@ files:
172
172
  - doc/API-key-and-password.jpg
173
173
  - doc/how_to_find_theme_id.png
174
174
  - lib/shopify_theme.rb
175
+ - lib/shopify_theme/api_checker.rb
175
176
  - lib/shopify_theme/cli.rb
176
177
  - lib/shopify_theme/releases.rb
177
178
  - lib/shopify_theme/version.rb
178
179
  - shipit.rubygems.yml
179
180
  - shopify_theme.gemspec
181
+ - spec/cassettes/api_check_api_down.yml
182
+ - spec/cassettes/api_check_success.yml
183
+ - spec/cassettes/api_check_unauthorized.yml
180
184
  - spec/cassettes/timber_releases.yml
181
185
  - spec/spec_helper.rb
186
+ - spec/unit/api_checker_spec.rb
182
187
  - spec/unit/cli_spec.rb
183
188
  - spec/unit/releases_spec.rb
184
189
  homepage: https://github.com/Shopify/shopify_theme
@@ -201,12 +206,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
201
206
  version: '0'
202
207
  requirements: []
203
208
  rubyforge_project: shopify_theme
204
- rubygems_version: 2.2.2
209
+ rubygems_version: 2.2.3
205
210
  signing_key:
206
211
  specification_version: 4
207
212
  summary: Command line tool for developing themes
208
- test_files:
209
- - spec/cassettes/timber_releases.yml
210
- - spec/spec_helper.rb
211
- - spec/unit/cli_spec.rb
212
- - spec/unit/releases_spec.rb
213
+ test_files: []