Pārlūkot izejas kodu

Add a myshopify_domain class variable to use for building the site url.

This is an extra precaution, in addition to signature validation, to make
sure requests always go to a .myshopify.com domain.
Dylan Thacker-Smith 10 gadi atpakaļ
vecāks
revīzija
b16ab2a41b
2 mainītis faili ar 43 papildinājumiem un 35 dzēšanām
  1. 21 26
      lib/shopify_api/session.rb
  2. 22 9
      test/session_test.rb

+ 21 - 26
lib/shopify_api/session.rb

@@ -6,10 +6,9 @@ module ShopifyAPI
   end
 
   class Session
-    cattr_accessor :api_key
-    cattr_accessor :secret
-    cattr_accessor :protocol
+    cattr_accessor :api_key, :secret, :protocol, :myshopify_domain, :port
     self.protocol = 'https'
+    self.myshopify_domain = 'myshopify.com'
 
     attr_accessor :url, :token, :name
 
@@ -21,12 +20,9 @@ module ShopifyAPI
 
       def temp(domain, token, &block)
         session = new(domain, token)
-        begin
-          original_domain = host_with_port(ShopifyAPI::Base.site.to_s)
-        rescue URI::InvalidURIError
-        end
-        original_token   = ShopifyAPI::Base.headers['X-Shopify-Access-Token']
-        original_session = new(original_domain, original_token)
+        original_site = ShopifyAPI::Base.site.to_s
+        original_token = ShopifyAPI::Base.headers['X-Shopify-Access-Token']
+        original_session = new(original_site, original_token)
 
         begin
           ShopifyAPI::Base.activate_session(session)
@@ -38,8 +34,19 @@ module ShopifyAPI
 
       def prepare_url(url)
         return nil if url.blank?
-        url.gsub!(/https?:\/\//, '')                            # remove http:// or https://
-        url.concat(".myshopify.com") unless url.include?('.')   # extend url to myshopify.com if no host is given
+        # remove http:// or https://
+        url = url.strip.gsub(/\Ahttps?:\/\//, '')
+        # extract host, removing any username, password or path
+        shop = URI.parse("https://#{url}").host
+        # extract subdomain of .myshopify.com
+        if idx = shop.index(".")
+          shop = shop.slice(0, idx)
+        end
+        return nil if shop.empty?
+        shop = "#{shop}.#{myshopify_domain}"
+        port ? "#{shop}:#{port}" : shop
+      rescue URI::InvalidURIError
+        nil
       end
 
       def validate_signature(params)
@@ -49,29 +56,17 @@ module ShopifyAPI
         sorted_params = params.except(:signature, :hmac, :action, :controller).collect{|k,v|"#{k}=#{v}"}.sort.join('&')
         OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new(), secret, sorted_params) == signature
       end
-
-      def host_with_port(site)
-        parsed_site = URI.parse(site)
-        host = parsed_site.host or return
-        port = parsed_site.port
-        if (protocol == 'http' && port == 80) || (protocol == 'https' && port == 443)
-          host
-        else
-          "#{host}:#{port}"
-        end
-      end
-
     end
 
     def initialize(url, token = nil)
-      self.url, self.token = url, token
-      self.class.prepare_url(self.url)
+      self.url = self.class.prepare_url(url)
+      self.token = token
     end
 
     def create_permission_url(scope, redirect_uri = nil)
       params = {:client_id => api_key, :scope => scope.join(',')}
       params[:redirect_uri] = redirect_uri if redirect_uri
-      "#{protocol}://#{url}/admin/oauth/authorize?#{parameterize(params)}"
+      "#{site}/oauth/authorize?#{parameterize(params)}"
     end
 
     def request_token(params)

+ 22 - 9
test/session_test.rb

@@ -18,6 +18,14 @@ class SessionTest < Test::Unit::TestCase
       assert session.valid?
     end
 
+    should "ignore everything but the subdomain in the shop" do
+      assert_equal "https://testshop.myshopify.com/admin", ShopifyAPI::Session.new("http://user:pass@testshop.notshopify.net/path", "any-token").site
+    end
+
+    should "append the myshopify domain if not given" do
+      assert_equal "https://testshop.myshopify.com/admin", ShopifyAPI::Session.new("testshop", "any-token").site
+    end
+
     should "not raise error without params" do
       assert_nothing_raised do
         session = ShopifyAPI::Session.new("testshop.myshopify.com", "any-token")
@@ -96,16 +104,21 @@ class SessionTest < Test::Unit::TestCase
       assert_equal false, session.valid?
     end
 
-    should "#temp reset ShopifyAPI::Base.site to original value when using a non-standard port" do
-      ShopifyAPI::Session.setup(:api_key => "key", :secret => "secret")
-      session1 = ShopifyAPI::Session.new('fakeshop.myshopify.com:3000', 'token1')
-      ShopifyAPI::Base.activate_session(session1)
+    should "myshopify_domain supports non-standard ports" do
+      begin
+        ShopifyAPI::Session.setup(:api_key => "key", :secret => "secret", :myshopify_domain => 'localhost', port: '3000')
 
-      ShopifyAPI::Session.temp("testshop.myshopify.com", "any-token") {
-        @assigned_site = ShopifyAPI::Base.site
-      }
-      assert_equal 'https://testshop.myshopify.com/admin', @assigned_site.to_s
-      assert_equal 'https://fakeshop.myshopify.com:3000/admin', ShopifyAPI::Base.site.to_s
+        session = ShopifyAPI::Session.new('fakeshop.localhost:3000', 'token1')
+        ShopifyAPI::Base.activate_session(session)
+        assert_equal 'https://fakeshop.localhost:3000/admin', ShopifyAPI::Base.site.to_s
+
+        session = ShopifyAPI::Session.new('fakeshop', 'token1')
+        ShopifyAPI::Base.activate_session(session)
+        assert_equal 'https://fakeshop.localhost:3000/admin', ShopifyAPI::Base.site.to_s
+      ensure
+        ShopifyAPI::Session.myshopify_domain = "myshopify.com"
+        ShopifyAPI::Session.port = nil
+      end
     end
 
     should "return site for session" do