Class: ShopifyAPI::Session

Inherits:
Object
  • Object
show all
Defined in:
lib/shopify_api/session.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(domain:, token:, api_version: ShopifyAPI::Base.api_version, extra: {}) ⇒ Session

Returns a new instance of Session.


94
95
96
97
98
99
# File 'lib/shopify_api/session.rb', line 94

def initialize(domain:, token:, api_version: ShopifyAPI::Base.api_version, extra: {})
  self.domain = self.class.prepare_domain(domain)
  self.api_version = api_version
  self.token = token
  self.extra = extra
end

Instance Attribute Details

#api_versionObject

Returns the value of attribute api_version


14
15
16
# File 'lib/shopify_api/session.rb', line 14

def api_version
  @api_version
end

#domainObject Also known as: url

Returns the value of attribute domain


13
14
15
# File 'lib/shopify_api/session.rb', line 13

def domain
  @domain
end

#extraObject

Returns the value of attribute extra


13
14
15
# File 'lib/shopify_api/session.rb', line 13

def extra
  @extra
end

#nameObject

Returns the value of attribute name


13
14
15
# File 'lib/shopify_api/session.rb', line 13

def name
  @name
end

#tokenObject

Returns the value of attribute token


13
14
15
# File 'lib/shopify_api/session.rb', line 13

def token
  @token
end

Class Method Details

.prepare_domain(domain) ⇒ Object


52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/shopify_api/session.rb', line 52

def prepare_domain(domain)
  return nil if domain.blank?
  # remove http:// or https://
  domain = domain.strip.gsub(%r{\Ahttps?://}, '')
  # extract host, removing any username, password or path
  shop = URI.parse("https://#{domain}").host
  # extract subdomain of .myshopify.com
  if (idx = shop.index("."))
    shop = shop.slice(0, idx)
  end
  return nil if shop.empty?
  "#{shop}.#{myshopify_domain}"
rescue URI::InvalidURIError
  nil
end

.setup(params) ⇒ Object


19
20
21
# File 'lib/shopify_api/session.rb', line 19

def setup(params)
  params.each { |k,value| public_send("#{k}=", value) }
end

.temp(domain:, token:, api_version: ShopifyAPI::Base.api_version, &block) ⇒ Object


23
24
25
26
27
# File 'lib/shopify_api/session.rb', line 23

def temp(domain:, token:, api_version: ShopifyAPI::Base.api_version, &block)
  session = new(domain: domain, token: token, api_version: api_version)

  with_session(session, &block)
end

.validate_signature(params) ⇒ Object


68
69
70
71
72
73
74
75
76
77
# File 'lib/shopify_api/session.rb', line 68

def validate_signature(params)
  params = (params.respond_to?(:to_unsafe_hash) ? params.to_unsafe_hash : params).with_indifferent_access
  return false unless (signature = params[:hmac])

  calculated_signature = OpenSSL::HMAC.hexdigest(
    OpenSSL::Digest.new('SHA256'), secret, encoded_params_for_signature(params)
  )

  Rack::Utils.secure_compare(calculated_signature, signature)
end

.with_session(session, &_block) ⇒ Object


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/shopify_api/session.rb', line 29

def with_session(session, &_block)
  original_session = extract_current_session
  original_user = ShopifyAPI::Base.user
  original_password = ShopifyAPI::Base.password

  begin
    ShopifyAPI::Base.clear_session
    ShopifyAPI::Base.activate_session(session)
    yield
  ensure
    ShopifyAPI::Base.activate_session(original_session)
    ShopifyAPI::Base.user = original_user
    ShopifyAPI::Base.password = original_password
  end
end

.with_version(api_version, &block) ⇒ Object


45
46
47
48
49
50
# File 'lib/shopify_api/session.rb', line 45

def with_version(api_version, &block)
  original_session = extract_current_session
  session = new(domain: original_session.site, token: original_session.token, api_version: api_version)

  with_session(session, &block)
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?


167
168
169
# File 'lib/shopify_api/session.rb', line 167

def ==(other)
  self.class == other.class && state == other.state
end

#create_permission_url(scope, redirect_uri, options = {}) ⇒ Object


101
102
103
104
105
# File 'lib/shopify_api/session.rb', line 101

def create_permission_url(scope, redirect_uri, options = {})
  params = { client_id: api_key, scope: scope.join(','), redirect_uri: redirect_uri }
  params[:state] = options[:state] if options[:state]
  construct_oauth_url("authorize", params)
end

#expired?Boolean

Returns:

  • (Boolean)

158
159
160
161
# File 'lib/shopify_api/session.rb', line 158

def expired?
  return false if expires_in.nil?
  expires_in <= 0
end

#expires_atObject


153
154
155
156
# File 'lib/shopify_api/session.rb', line 153

def expires_at
  return unless extra.present?
  @expires_at ||= Time.at(extra['expires_at']).utc
end

#expires_inObject


148
149
150
151
# File 'lib/shopify_api/session.rb', line 148

def expires_in
  return unless expires_at.present?
  [0, expires_at.to_i - Time.now.utc.to_i].max
end

#hashObject


163
164
165
# File 'lib/shopify_api/session.rb', line 163

def hash
  state.hash
end

#request_token(params) ⇒ Object


107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/shopify_api/session.rb', line 107

def request_token(params)
  return token if token

  unless self.class.validate_signature(params) && params[:timestamp].to_i > 24.hours.ago.utc.to_i
    raise ShopifyAPI::ValidationException, "Invalid Signature: Possible malicious login"
  end

  response = access_token_request(params[:code])
  if response.code == "200"
    self.extra = JSON.parse(response.body)
    self.token = extra.delete('access_token')

    if (expires_in = extra.delete('expires_in'))
      extra['expires_at'] = Time.now.utc.to_i + expires_in
    end
    token
  else
    raise RuntimeError, response.msg
  end
end

#shopObject


128
129
130
# File 'lib/shopify_api/session.rb', line 128

def shop
  Shop.current
end

#siteObject


132
133
134
# File 'lib/shopify_api/session.rb', line 132

def site
  "https://#{domain}"
end

#valid?Boolean

Returns:

  • (Boolean)

144
145
146
# File 'lib/shopify_api/session.rb', line 144

def valid?
  domain.present? && token.present? && api_version.is_a?(ApiVersion)
end