Class: SchoolFriend::Session

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

Defined Under Namespace

Classes: OauthCodeAuthenticationFailedError, RequireSessionScopeError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Session

Returns a new instance of Session.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/school_friend/session.rb', line 35

def initialize(options = {})
  @options       = keys_to_symbols!(options)
  @session_scope = (options[:session_key] && options[:session_secret_key]) || \
                       options[:oauth_code] || \
                       (options[:access_token] && options[:refresh_token])

# only has oauth_code, get access_token
if options[:oauth_code]
  response, data = \
    _post_request(api_server + "/oauth/token.do",
                  {"code" => options[:oauth_code], "redirect_uri" => "http://127.0.0.1:2000",
                   "client_id" => SchoolFriend.application_id, "client_secret" => SchoolFriend.secret_key,
                   "grant_type" => 'authorization_code'})

    if response.is_a?(Net::HTTPSuccess)
      response = JSON(response.body)

      if response.has_key?("error")
          raise OauthCodeAuthenticationFailedError, "failed to use oauth_code for authentication: #{response["error"]}: #{response["error_description"]}"
      end

      options[:access_token] = response["access_token"]
      options[:refresh_token] = response["refresh_token"]

      SchoolFriend.logger.debug "Tokens received: #{options[:access_token]} #{options[:refresh_token]}"
    else
      raise OauthCodeAuthenticationFailedError, "failed to use oauth_code for authentication - Request Failed"
    end

    options.delete(:oauth_code)
  end
end

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options.



21
22
23
# File 'lib/school_friend/session.rb', line 21

def options
  @options
end

#session_scopeObject (readonly) Also known as: session_scope?

Returns the value of attribute session_scope.



21
22
23
# File 'lib/school_friend/session.rb', line 21

def session_scope
  @session_scope
end

Instance Method Details

#_post_request(url, params) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
# File 'lib/school_friend/session.rb', line 23

def _post_request(url, params)
  uri = URI.parse(url)
  http = Net::HTTP.new(uri.host, 80)
  data = URI.encode_www_form(params)

  headers = {
    'Content-Type' => 'application/x-www-form-urlencoded'
  }

  http.post(uri.path, data, headers)
end

#additional_paramsHash

Returns additional params which are required for all requests. Depends on request scope.

Returns:

  • (Hash)


164
165
166
167
168
169
170
171
172
173
174
# File 'lib/school_friend/session.rb', line 164

def additional_params
  @additional_params ||= if session_scope?
    if oauth2_session?
      {application_key: application_key}
    else
      {application_key: application_key, session_key: options[:session_key]}
    end
  else
    {application_key: application_key}
  end
end

#api_call(method, params = {}, force_session_call = false) ⇒ Net::HTTPResponse

Performs API call to Odnoklassniki

Examples:

Performs API call in current scope

school_friend = SchoolFriend::Session.new
school_friend.api_call('widget.getWidgets', wids: 'mobile-header,mobile-footer') # Net::HTTPResponse

Force performs API call in session scope

school_friend = SchoolFriend::Session.new
school_friend.api_call('widget.getWidgets', {wids: 'mobile-header,mobile-footer'}, true) # SchoolFriend::Session::RequireSessionScopeError

Parameters:

  • method (String)

    API method

  • params (Hash) (defaults to: {})

    params which should be sent to portal

  • force_session_call (FalseClass, TrueClass) (defaults to: false)

    says if this call should be performed in session scope

Returns:

  • (Net::HTTPResponse)

Raises:



191
192
193
194
195
196
# File 'lib/school_friend/session.rb', line 191

def api_call(method, params = {}, force_session_call = false)
  raise RequireSessionScopeError.new('This API call requires session scope') if force_session_call and application_scope?

  uri = build_uri(method, params)
  Net::HTTP.get_response(uri)
end

#api_serverObject

Returns API server

@@return [String]



138
139
140
# File 'lib/school_friend/session.rb', line 138

def api_server
  SchoolFriend.api_server
end

#application_keyString

Returns application key

Returns:

  • (String)


120
121
122
# File 'lib/school_friend/session.rb', line 120

def application_key
  SchoolFriend.application_key
end

#application_scope?TrueClass, FalseClass

Returns true if API call is performed in application scope

Returns:

  • (TrueClass, FalseClass)


109
110
111
# File 'lib/school_friend/session.rb', line 109

def application_scope?
  not session_scope?
end

#build_uri(method, params = {}) ⇒ URI::HTTP

Builds URI object

Parameters:

  • method (String)

    request method

  • params (Hash) (defaults to: {})

    request params

Returns:

  • (URI::HTTP)


203
204
205
206
207
208
209
210
211
# File 'lib/school_friend/session.rb', line 203

def build_uri(method, params = {})
  uri = URI(api_server)
  uri.path  = '/api/' + method.sub('.', '/')
  uri.query = URI.encode_www_form(sign(params))

  SchoolFriend.logger.debug "API Request: #{uri}"

  uri
end

#oauth2_session?Boolean

Returns:

  • (Boolean)


113
114
115
# File 'lib/school_friend/session.rb', line 113

def oauth2_session?
  options[:access_token] && options[:refresh_token]
end

#refresh_access_tokenObject



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/school_friend/session.rb', line 68

def refresh_access_token
  # true on success false otherwise
  if oauth2_session?
    response, data = \
      _post_request(api_server + "/oauth/token.do",
                    {"refresh_token" => options[:refresh_token],\
                     "client_id" => SchoolFriend.application_id, "client_secret" => SchoolFriend.secret_key,
                     "grant_type" => 'refresh_token'})

    if response.is_a?(Net::HTTPSuccess)
      response = JSON(response.body)

      if response.has_key?("error")
        SchoolFriend.logger.warn "#{__method__}: failed to refresh access token - #{response["error"]}"

        return false
      end

      options[:access_token] = response["access_token"]

      SchoolFriend.logger.debug "#{__method__}: Token received: #{options[:access_token]}"
      
      return true
    el
      SchoolFriend.logger.warn "#{__method__}: Failed to refresh access token - request Failed"

      return false
    end
  else
    return false
  end
end

#sign(params = {}) ⇒ Hash

Signs params

Parameters:

  • params (Hash) (defaults to: {})

Returns:

  • (Hash)

    returns modified params



146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/school_friend/session.rb', line 146

def sign(params = {})
  params = additional_params.merge(params)
  digest = params.sort_by(&:first).map{ |key, value| "#{key}=#{value}" }.join

  if oauth2_session?
    params[:sig] = Digest::MD5.hexdigest("#{digest}" + Digest::MD5.hexdigest(options[:access_token] + SchoolFriend.secret_key))
    params[:access_token] = options[:access_token]
  else
    params[:sig] = Digest::MD5.hexdigest("#{digest}#{signature}")
  end

  params
end

#signatureString

Returns signature for signing request params

Returns:

  • (String)


127
128
129
130
131
132
133
# File 'lib/school_friend/session.rb', line 127

def signature
  unless session_scope?
    return SchoolFriend.secret_key
  end

  options[:access_token] || options[:session_secret_key]
end