session.rb 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. module ShopifyAPI
  2. class Session
  3. cattr_accessor :api_key
  4. cattr_accessor :secret
  5. cattr_accessor :protocol
  6. self.protocol = 'https'
  7. attr_accessor :url, :token, :name
  8. class << self
  9. def setup(params)
  10. params.each { |k,value| send("#{k}=", value) }
  11. end
  12. def temp(domain, token, &block)
  13. session = new(domain, token)
  14. begin
  15. original_domain = host_with_port(ShopifyAPI::Base.site.to_s)
  16. rescue URI::InvalidURIError
  17. end
  18. original_token = ShopifyAPI::Base.headers['X-Shopify-Access-Token']
  19. original_session = new(original_domain, original_token)
  20. begin
  21. ShopifyAPI::Base.activate_session(session)
  22. yield
  23. ensure
  24. ShopifyAPI::Base.activate_session(original_session)
  25. end
  26. end
  27. def prepare_url(url)
  28. return nil if url.blank?
  29. url.gsub!(/https?:\/\//, '') # remove http:// or https://
  30. url.concat(".myshopify.com") unless url.include?('.') # extend url to myshopify.com if no host is given
  31. end
  32. def validate_signature(params)
  33. return false unless signature = params[:signature]
  34. sorted_params = params.except(:signature, :action, :controller).collect{|k,v|"#{k}=#{v}"}.sort.join
  35. Digest::MD5.hexdigest(secret + sorted_params) == signature
  36. end
  37. def host_with_port(site)
  38. parsed_site = URI.parse(site)
  39. host = parsed_site.host or return
  40. port = parsed_site.port
  41. if (protocol == 'http' && port == 80) || (protocol == 'https' && port == 443)
  42. host
  43. else
  44. "#{host}:#{port}"
  45. end
  46. end
  47. end
  48. def initialize(url, token = nil)
  49. self.url, self.token = url, token
  50. self.class.prepare_url(self.url)
  51. end
  52. def create_permission_url(scope, redirect_uri = nil)
  53. params = {:client_id => api_key, :scope => scope.join(',')}
  54. params[:redirect_uri] = redirect_uri if redirect_uri
  55. "#{protocol}://#{url}/admin/oauth/authorize?#{parameterize(params)}"
  56. end
  57. def request_token(params)
  58. return token if token
  59. unless self.class.validate_signature(params) && params[:timestamp].to_i > 24.hours.ago.utc.to_i
  60. raise "Invalid Signature: Possible malicious login"
  61. end
  62. code = params['code']
  63. response = access_token_request(code)
  64. if response.code == "200"
  65. token = JSON.parse(response.body)['access_token']
  66. else
  67. raise RuntimeError, response.msg
  68. end
  69. end
  70. def shop
  71. Shop.current
  72. end
  73. def site
  74. "#{protocol}://#{url}/admin"
  75. end
  76. def valid?
  77. url.present? && token.present?
  78. end
  79. private
  80. def parameterize(params)
  81. URI.escape(params.collect{|k,v| "#{k}=#{v}"}.join('&'))
  82. end
  83. def access_token_request(code)
  84. uri = URI.parse("#{protocol}://#{url}/admin/oauth/access_token")
  85. https = Net::HTTP.new(uri.host, uri.port)
  86. https.use_ssl = true
  87. request = Net::HTTP::Post.new(uri.request_uri)
  88. request.set_form_data({"client_id" => api_key, "client_secret" => secret, "code" => code})
  89. https.request(request)
  90. end
  91. end
  92. end