koala 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +3 -1
- data/.rspec +1 -0
- data/.travis.yml +4 -0
- data/.yardopts +3 -0
- data/CHANGELOG +28 -0
- data/Gemfile +14 -0
- data/Guardfile +6 -0
- data/koala.gemspec +3 -3
- data/lib/koala/api/batch_operation.rb +83 -0
- data/lib/koala/api/graph_api.rb +476 -0
- data/lib/koala/{graph_batch_api.rb → api/graph_batch_api.rb} +22 -17
- data/lib/koala/api/graph_collection.rb +107 -0
- data/lib/koala/api/legacy.rb +26 -0
- data/lib/koala/{rest_api.rb → api/rest_api.rb} +34 -13
- data/lib/koala/api.rb +93 -0
- data/lib/koala/http_service/multipart_request.rb +41 -0
- data/lib/koala/http_service/response.rb +18 -0
- data/lib/koala/http_service/uploadable_io.rb +187 -0
- data/lib/koala/http_service.rb +69 -20
- data/lib/koala/oauth.rb +170 -36
- data/lib/koala/realtime_updates.rb +89 -51
- data/lib/koala/test_users.rb +122 -32
- data/lib/koala/utils.rb +11 -4
- data/lib/koala/version.rb +1 -1
- data/lib/koala.rb +16 -96
- data/readme.md +9 -9
- data/spec/cases/api_spec.rb +19 -12
- data/spec/cases/error_spec.rb +10 -0
- data/spec/cases/graph_api_batch_spec.rb +100 -58
- data/spec/cases/graph_collection_spec.rb +23 -7
- data/spec/cases/http_service_spec.rb +5 -26
- data/spec/cases/koala_spec.rb +22 -4
- data/spec/cases/legacy_spec.rb +115 -0
- data/spec/cases/multipart_request_spec.rb +7 -7
- data/spec/cases/oauth_spec.rb +134 -48
- data/spec/cases/realtime_updates_spec.rb +154 -47
- data/spec/cases/test_users_spec.rb +276 -219
- data/spec/cases/uploadable_io_spec.rb +1 -1
- data/spec/cases/utils_spec.rb +29 -5
- data/spec/fixtures/mock_facebook_responses.yml +41 -30
- data/spec/spec_helper.rb +3 -0
- data/spec/support/custom_matchers.rb +28 -0
- data/spec/support/graph_api_shared_examples.rb +192 -14
- data/spec/support/koala_test.rb +10 -1
- data/spec/support/mock_http_service.rb +2 -2
- data/spec/support/rest_api_shared_examples.rb +5 -165
- metadata +75 -99
- data/lib/koala/batch_operation.rb +0 -74
- data/lib/koala/graph_api.rb +0 -270
- data/lib/koala/graph_collection.rb +0 -59
- data/lib/koala/multipart_request.rb +0 -35
- data/lib/koala/uploadable_io.rb +0 -181
- data/spec/cases/graph_and_rest_api_spec.rb +0 -22
- data/spec/cases/graph_api_spec.rb +0 -22
- data/spec/cases/rest_api_spec.rb +0 -22
data/lib/koala/http_service.rb
CHANGED
|
@@ -1,30 +1,37 @@
|
|
|
1
1
|
require 'faraday'
|
|
2
|
+
require 'koala/http_service/multipart_request'
|
|
3
|
+
require 'koala/http_service/uploadable_io'
|
|
4
|
+
require 'koala/http_service/response'
|
|
2
5
|
|
|
3
6
|
module Koala
|
|
4
|
-
|
|
5
|
-
attr_reader :status, :body, :headers
|
|
6
|
-
def initialize(status, body, headers)
|
|
7
|
-
@status = status
|
|
8
|
-
@body = body
|
|
9
|
-
@headers = headers
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
module HTTPService
|
|
14
|
-
# common functionality for all HTTP services
|
|
15
|
-
|
|
7
|
+
module HTTPService
|
|
16
8
|
class << self
|
|
17
|
-
|
|
9
|
+
# A customized stack of Faraday middleware that will be used to make each request.
|
|
10
|
+
attr_accessor :faraday_middleware
|
|
11
|
+
# A default set of HTTP options (see https://github.com/arsduo/koala/wiki/HTTP-Services)
|
|
12
|
+
attr_accessor :http_options
|
|
18
13
|
end
|
|
19
14
|
|
|
20
15
|
@http_options ||= {}
|
|
21
16
|
|
|
17
|
+
# Koala's default middleware stack.
|
|
18
|
+
# We encode requests in a Facebook-compatible multipart request,
|
|
19
|
+
# and use whichever adapter has been configured for this application.
|
|
22
20
|
DEFAULT_MIDDLEWARE = Proc.new do |builder|
|
|
23
|
-
builder.use Koala::MultipartRequest
|
|
21
|
+
builder.use Koala::HTTPService::MultipartRequest
|
|
24
22
|
builder.request :url_encoded
|
|
25
23
|
builder.adapter Faraday.default_adapter
|
|
26
24
|
end
|
|
27
25
|
|
|
26
|
+
# The address of the appropriate Facebook server.
|
|
27
|
+
#
|
|
28
|
+
# @param options various flags to indicate which server to use.
|
|
29
|
+
# @option options :rest_api use the old REST API instead of the Graph API
|
|
30
|
+
# @option options :video use the server designated for video uploads
|
|
31
|
+
# @option options :beta use the beta tier
|
|
32
|
+
# @option options :use_ssl force https, even if not needed
|
|
33
|
+
#
|
|
34
|
+
# @return a complete server address with protocol
|
|
28
35
|
def self.server(options = {})
|
|
29
36
|
server = "#{options[:rest_api] ? Facebook::REST_SERVER : Facebook::GRAPH_SERVER}"
|
|
30
37
|
server.gsub!(/\.facebook/, "-video.facebook") if options[:video]
|
|
@@ -32,6 +39,23 @@ module Koala
|
|
|
32
39
|
"#{options[:use_ssl] ? "https" : "http"}://#{server}"
|
|
33
40
|
end
|
|
34
41
|
|
|
42
|
+
# Makes a request directly to Facebook.
|
|
43
|
+
# @note You'll rarely need to call this method directly.
|
|
44
|
+
#
|
|
45
|
+
# @see Koala::Facebook::API#api
|
|
46
|
+
# @see Koala::Facebook::GraphAPIMethods#graph_call
|
|
47
|
+
# @see Koala::Facebook::RestAPIMethods#rest_call
|
|
48
|
+
#
|
|
49
|
+
# @param path the server path for this request
|
|
50
|
+
# @param args (see Koala::Facebook::API#api)
|
|
51
|
+
# @param verb the HTTP method to use.
|
|
52
|
+
# If not get or post, this will be turned into a POST request with the appropriate :method
|
|
53
|
+
# specified in the arguments.
|
|
54
|
+
# @param options (see Koala::Facebook::API#api)
|
|
55
|
+
#
|
|
56
|
+
# @raise an appropriate connection error if unable to make the request to Facebook
|
|
57
|
+
#
|
|
58
|
+
# @return [Koala::HTTPService::Response] a response object representing the results from Facebook
|
|
35
59
|
def self.make_request(path, args, verb, options = {})
|
|
36
60
|
# if the verb isn't get or post, send it as a post argument
|
|
37
61
|
args.merge!({:method => verb}) && verb = "post" if verb != "get" && verb != "post"
|
|
@@ -48,13 +72,20 @@ module Koala
|
|
|
48
72
|
conn = Faraday.new(server(request_options), request_options, &(faraday_middleware || DEFAULT_MIDDLEWARE))
|
|
49
73
|
|
|
50
74
|
response = conn.send(verb, path, (verb == "post" ? params : {}))
|
|
51
|
-
Koala::Response.new(response.status.to_i, response.body, response.headers)
|
|
52
|
-
end
|
|
53
|
-
|
|
75
|
+
Koala::HTTPService::Response.new(response.status.to_i, response.body, response.headers)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Encodes a given hash into a query string.
|
|
79
|
+
# This is used mainly by the Batch API nowadays, since Faraday handles this for regular cases.
|
|
80
|
+
#
|
|
81
|
+
# @param params_hash a hash of values to CGI-encode and appropriately join
|
|
82
|
+
#
|
|
83
|
+
# @example
|
|
84
|
+
# Koala.http_service.encode_params({:a => 2, :b => "My String"})
|
|
85
|
+
# => "a=2&b=My+String"
|
|
86
|
+
#
|
|
87
|
+
# @return the appropriately-encoded string
|
|
54
88
|
def self.encode_params(param_hash)
|
|
55
|
-
# unfortunately, we can't use to_query because that's Rails, not Ruby
|
|
56
|
-
# if no hash (e.g. no auth token) return empty string
|
|
57
|
-
# this is used mainly by the Batch API nowadays
|
|
58
89
|
((param_hash || {}).collect do |key_and_value|
|
|
59
90
|
key_and_value[1] = MultiJson.encode(key_and_value[1]) unless key_and_value[1].is_a? String
|
|
60
91
|
"#{key_and_value[0].to_s}=#{CGI.escape key_and_value[1]}"
|
|
@@ -64,76 +95,92 @@ module Koala
|
|
|
64
95
|
# deprecations
|
|
65
96
|
# not elegant or compact code, but temporary
|
|
66
97
|
|
|
98
|
+
# @private
|
|
67
99
|
def self.always_use_ssl
|
|
68
100
|
Koala::Utils.deprecate("HTTPService.always_use_ssl is now HTTPService.http_options[:use_ssl]; always_use_ssl will be removed in a future version.")
|
|
69
101
|
http_options[:use_ssl]
|
|
70
102
|
end
|
|
71
103
|
|
|
104
|
+
# @private
|
|
72
105
|
def self.always_use_ssl=(value)
|
|
73
106
|
Koala::Utils.deprecate("HTTPService.always_use_ssl is now HTTPService.http_options[:use_ssl]; always_use_ssl will be removed in a future version.")
|
|
74
107
|
http_options[:use_ssl] = value
|
|
75
108
|
end
|
|
76
109
|
|
|
110
|
+
# @private
|
|
77
111
|
def self.timeout
|
|
78
112
|
Koala::Utils.deprecate("HTTPService.timeout is now HTTPService.http_options[:timeout]; .timeout will be removed in a future version.")
|
|
79
113
|
http_options[:timeout]
|
|
80
114
|
end
|
|
81
115
|
|
|
116
|
+
# @private
|
|
82
117
|
def self.timeout=(value)
|
|
83
118
|
Koala::Utils.deprecate("HTTPService.timeout is now HTTPService.http_options[:timeout]; .timeout will be removed in a future version.")
|
|
84
119
|
http_options[:timeout] = value
|
|
85
120
|
end
|
|
86
121
|
|
|
122
|
+
# @private
|
|
87
123
|
def self.timeout
|
|
88
124
|
Koala::Utils.deprecate("HTTPService.timeout is now HTTPService.http_options[:timeout]; .timeout will be removed in a future version.")
|
|
89
125
|
http_options[:timeout]
|
|
90
126
|
end
|
|
91
127
|
|
|
128
|
+
# @private
|
|
92
129
|
def self.timeout=(value)
|
|
93
130
|
Koala::Utils.deprecate("HTTPService.timeout is now HTTPService.http_options[:timeout]; .timeout will be removed in a future version.")
|
|
94
131
|
http_options[:timeout] = value
|
|
95
132
|
end
|
|
96
133
|
|
|
134
|
+
# @private
|
|
97
135
|
def self.proxy
|
|
98
136
|
Koala::Utils.deprecate("HTTPService.proxy is now HTTPService.http_options[:proxy]; .proxy will be removed in a future version.")
|
|
99
137
|
http_options[:proxy]
|
|
100
138
|
end
|
|
101
139
|
|
|
140
|
+
# @private
|
|
102
141
|
def self.proxy=(value)
|
|
103
142
|
Koala::Utils.deprecate("HTTPService.proxy is now HTTPService.http_options[:proxy]; .proxy will be removed in a future version.")
|
|
104
143
|
http_options[:proxy] = value
|
|
105
144
|
end
|
|
106
145
|
|
|
146
|
+
# @private
|
|
107
147
|
def self.ca_path
|
|
108
148
|
Koala::Utils.deprecate("HTTPService.ca_path is now (HTTPService.http_options[:ssl] ||= {})[:ca_path]; .ca_path will be removed in a future version.")
|
|
109
149
|
(http_options[:ssl] || {})[:ca_path]
|
|
110
150
|
end
|
|
111
151
|
|
|
152
|
+
# @private
|
|
112
153
|
def self.ca_path=(value)
|
|
113
154
|
Koala::Utils.deprecate("HTTPService.ca_path is now (HTTPService.http_options[:ssl] ||= {})[:ca_path]; .ca_path will be removed in a future version.")
|
|
114
155
|
(http_options[:ssl] ||= {})[:ca_path] = value
|
|
115
156
|
end
|
|
116
157
|
|
|
158
|
+
# @private
|
|
117
159
|
def self.ca_file
|
|
118
160
|
Koala::Utils.deprecate("HTTPService.ca_file is now (HTTPService.http_options[:ssl] ||= {})[:ca_file]; .ca_file will be removed in a future version.")
|
|
119
161
|
(http_options[:ssl] || {})[:ca_file]
|
|
120
162
|
end
|
|
121
163
|
|
|
164
|
+
# @private
|
|
122
165
|
def self.ca_file=(value)
|
|
123
166
|
Koala::Utils.deprecate("HTTPService.ca_file is now (HTTPService.http_options[:ssl] ||= {})[:ca_file]; .ca_file will be removed in a future version.")
|
|
124
167
|
(http_options[:ssl] ||= {})[:ca_file] = value
|
|
125
168
|
end
|
|
126
169
|
|
|
170
|
+
# @private
|
|
127
171
|
def self.verify_mode
|
|
128
172
|
Koala::Utils.deprecate("HTTPService.verify_mode is now (HTTPService.http_options[:ssl] ||= {})[:verify_mode]; .verify_mode will be removed in a future version.")
|
|
129
173
|
(http_options[:ssl] || {})[:verify_mode]
|
|
130
174
|
end
|
|
131
175
|
|
|
176
|
+
# @private
|
|
132
177
|
def self.verify_mode=(value)
|
|
133
178
|
Koala::Utils.deprecate("HTTPService.verify_mode is now (HTTPService.http_options[:ssl] ||= {})[:verify_mode]; .verify_mode will be removed in a future version.")
|
|
134
179
|
(http_options[:ssl] ||= {})[:verify_mode] = value
|
|
135
180
|
end
|
|
136
181
|
|
|
182
|
+
private
|
|
183
|
+
|
|
137
184
|
def self.process_options(options)
|
|
138
185
|
if typhoeus_options = options.delete(:typhoeus_options)
|
|
139
186
|
Koala::Utils.deprecate("typhoeus_options should now be included directly in the http_options hash. Support for this key will be removed in a future version.")
|
|
@@ -159,6 +206,7 @@ module Koala
|
|
|
159
206
|
end
|
|
160
207
|
end
|
|
161
208
|
|
|
209
|
+
# @private
|
|
162
210
|
module TyphoeusService
|
|
163
211
|
def self.deprecated_interface
|
|
164
212
|
# support old-style interface with a warning
|
|
@@ -167,6 +215,7 @@ module Koala
|
|
|
167
215
|
end
|
|
168
216
|
end
|
|
169
217
|
|
|
218
|
+
# @private
|
|
170
219
|
module NetHTTPService
|
|
171
220
|
def self.deprecated_interface
|
|
172
221
|
# support old-style interface with a warning
|
data/lib/koala/oauth.rb
CHANGED
|
@@ -1,66 +1,165 @@
|
|
|
1
|
+
# OpenSSL and Base64 are required to support signed_request
|
|
2
|
+
require 'openssl'
|
|
3
|
+
require 'base64'
|
|
4
|
+
|
|
1
5
|
module Koala
|
|
2
6
|
module Facebook
|
|
7
|
+
|
|
8
|
+
DIALOG_HOST = "www.facebook.com"
|
|
9
|
+
|
|
3
10
|
class OAuth
|
|
4
11
|
attr_reader :app_id, :app_secret, :oauth_callback_url
|
|
12
|
+
|
|
13
|
+
# Creates a new OAuth client.
|
|
14
|
+
#
|
|
15
|
+
# @param app_id [String, Integer] a Facebook application ID
|
|
16
|
+
# @param app_secret a Facebook application secret
|
|
17
|
+
# @param oauth_callback_url the URL in your app to which users authenticating with OAuth will be sent
|
|
5
18
|
def initialize(app_id, app_secret, oauth_callback_url = nil)
|
|
6
19
|
@app_id = app_id
|
|
7
20
|
@app_secret = app_secret
|
|
8
21
|
@oauth_callback_url = oauth_callback_url
|
|
9
22
|
end
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
|
|
24
|
+
# Parses the cookie set Facebook's JavaScript SDK.
|
|
25
|
+
#
|
|
26
|
+
# @note in parsing Facebook's new signed cookie format this method has to make a request to Facebook.
|
|
27
|
+
# We recommend storing authenticated user info in your Rails session (or equivalent) and only
|
|
28
|
+
# calling this when needed.
|
|
29
|
+
#
|
|
30
|
+
# @param cookie_hash a set of cookies that includes the Facebook cookie.
|
|
31
|
+
# You can pass Rack/Rails/Sinatra's cookie hash directly to this method.
|
|
32
|
+
#
|
|
33
|
+
# @return the authenticated user's information as a hash, or nil.
|
|
34
|
+
def get_user_info_from_cookies(cookie_hash)
|
|
20
35
|
if signed_cookie = cookie_hash["fbsr_#{@app_id}"]
|
|
21
36
|
parse_signed_cookie(signed_cookie)
|
|
22
37
|
elsif unsigned_cookie = cookie_hash["fbs_#{@app_id}"]
|
|
23
38
|
parse_unsigned_cookie(unsigned_cookie)
|
|
24
39
|
end
|
|
25
40
|
end
|
|
26
|
-
alias_method :
|
|
41
|
+
alias_method :get_user_info_from_cookie, :get_user_info_from_cookies
|
|
27
42
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
43
|
+
# Parses the cookie set Facebook's JavaScript SDK and returns only the user ID.
|
|
44
|
+
#
|
|
45
|
+
# @note (see #get_user_info_from_cookie)
|
|
46
|
+
#
|
|
47
|
+
# @param (see #get_user_info_from_cookie)
|
|
48
|
+
#
|
|
49
|
+
# @return the authenticated user's Facebook ID, or nil.
|
|
50
|
+
def get_user_from_cookies(cookies)
|
|
51
|
+
if signed_cookie = cookies["fbsr_#{@app_id}"]
|
|
52
|
+
if components = parse_signed_request(signed_cookie)
|
|
53
|
+
components["user_id"]
|
|
54
|
+
end
|
|
55
|
+
elsif info = get_user_info_from_cookies(cookies)
|
|
56
|
+
# Parsing unsigned cookie
|
|
57
|
+
info["uid"]
|
|
32
58
|
end
|
|
33
59
|
end
|
|
34
|
-
alias_method :
|
|
60
|
+
alias_method :get_user_from_cookie, :get_user_from_cookies
|
|
35
61
|
|
|
36
62
|
# URLs
|
|
37
|
-
|
|
63
|
+
|
|
64
|
+
# Builds an OAuth URL, where users will be prompted to log in and for any desired permissions.
|
|
65
|
+
# When the users log in, you receive a callback with their
|
|
66
|
+
# See http://developers.facebook.com/docs/authentication/.
|
|
67
|
+
#
|
|
68
|
+
# @see #url_for_access_token
|
|
69
|
+
#
|
|
70
|
+
# @note The server-side authentication and dialog methods should only be used
|
|
71
|
+
# if your application can't use the Facebook Javascript SDK,
|
|
72
|
+
# which provides a much better user experience.
|
|
73
|
+
# See http://developers.facebook.com/docs/reference/javascript/.
|
|
74
|
+
#
|
|
75
|
+
# @param options any query values to add to the URL, as well as any special/required values listed below.
|
|
76
|
+
# @option options permissions an array or comma-separated string of desired permissions
|
|
77
|
+
#
|
|
78
|
+
# @raise ArgumentError if no OAuth callback was specified in OAuth#new or in options as :redirect_uri
|
|
79
|
+
#
|
|
80
|
+
# @return an OAuth URL you can send your users to
|
|
38
81
|
def url_for_oauth_code(options = {})
|
|
39
82
|
# for permissions, see http://developers.facebook.com/docs/authentication/permissions
|
|
40
|
-
permissions = options
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
raise ArgumentError, "url_for_oauth_code must get a callback either from the OAuth object or in the options!" unless callback
|
|
46
|
-
|
|
83
|
+
if permissions = options.delete(:permissions)
|
|
84
|
+
options[:scope] = permissions.is_a?(Array) ? permissions.join(",") : permissions
|
|
85
|
+
end
|
|
86
|
+
url_options = {:client_id => @app_id}.merge(options)
|
|
87
|
+
|
|
47
88
|
# Creates the URL for oauth authorization for a given callback and optional set of permissions
|
|
48
|
-
"https://#{GRAPH_SERVER}/oauth/authorize
|
|
89
|
+
build_url("https://#{GRAPH_SERVER}/oauth/authorize", true, url_options)
|
|
49
90
|
end
|
|
50
91
|
|
|
92
|
+
# Once you receive an OAuth code, you need to redeem it from Facebook using an appropriate URL.
|
|
93
|
+
# (This is done by your server behind the scenes.)
|
|
94
|
+
# See http://developers.facebook.com/docs/authentication/.
|
|
95
|
+
#
|
|
96
|
+
# @see #url_for_oauth_code
|
|
97
|
+
#
|
|
98
|
+
# @note (see #url_for_oauth_code)
|
|
99
|
+
#
|
|
100
|
+
# @param code an OAuth code received from Facebook
|
|
101
|
+
# @param options any additional query parameters to add to the URL
|
|
102
|
+
#
|
|
103
|
+
# @raise (see #url_for_oauth_code)
|
|
104
|
+
#
|
|
105
|
+
# @return an URL your server can query for the user's access token
|
|
51
106
|
def url_for_access_token(code, options = {})
|
|
52
107
|
# Creates the URL for the token corresponding to a given code generated by Facebook
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
108
|
+
url_options = {
|
|
109
|
+
:client_id => @app_id,
|
|
110
|
+
:code => code,
|
|
111
|
+
:client_secret => @app_secret
|
|
112
|
+
}.merge(options)
|
|
113
|
+
build_url("https://#{GRAPH_SERVER}/oauth/access_token", true, url_options)
|
|
56
114
|
end
|
|
57
115
|
|
|
116
|
+
# Builds a URL for a given dialog (feed, friends, OAuth, pay, send, etc.)
|
|
117
|
+
# See http://developers.facebook.com/docs/reference/dialogs/.
|
|
118
|
+
#
|
|
119
|
+
# @note (see #url_for_oauth_code)
|
|
120
|
+
#
|
|
121
|
+
# @param dialog_type the kind of Facebook dialog you want to show
|
|
122
|
+
# @param options any additional query parameters to add to the URL
|
|
123
|
+
#
|
|
124
|
+
# @return an URL your server can query for the user's access token
|
|
125
|
+
def url_for_dialog(dialog_type, options = {})
|
|
126
|
+
# some endpoints require app_id, some client_id, supply both doesn't seem to hurt
|
|
127
|
+
url_options = {:app_id => @app_id, :client_id => @app_id}.merge(options)
|
|
128
|
+
build_url("http://#{DIALOG_HOST}/dialog/#{dialog_type}", true, url_options)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# access tokens
|
|
132
|
+
|
|
133
|
+
# Fetches an access token, token expiration, and other info from Facebook.
|
|
134
|
+
# Useful when you've received an OAuth code using the server-side authentication process.
|
|
135
|
+
# @see url_for_oauth_code
|
|
136
|
+
#
|
|
137
|
+
# @note (see #url_for_oauth_code)
|
|
138
|
+
#
|
|
139
|
+
# @param code (see #url_for_access_token)
|
|
140
|
+
# @param options any additional parameters to send to Facebook when redeeming the token
|
|
141
|
+
#
|
|
142
|
+
# @raise Koala::Facebook::APIError if Facebook returns an error response
|
|
143
|
+
#
|
|
144
|
+
# @return a hash of the access token info returned by Facebook (token, expiration, etc.)
|
|
58
145
|
def get_access_token_info(code, options = {})
|
|
59
146
|
# convenience method to get a parsed token from Facebook for a given code
|
|
60
147
|
# should this require an OAuth callback URL?
|
|
61
148
|
get_token_from_server({:code => code, :redirect_uri => options[:redirect_uri] || @oauth_callback_url}, false, options)
|
|
62
149
|
end
|
|
63
150
|
|
|
151
|
+
|
|
152
|
+
# Fetches the access token (ignoring expiration and other info) from Facebook.
|
|
153
|
+
# Useful when you've received an OAuth code using the server-side authentication process.
|
|
154
|
+
# @see get_access_token_info
|
|
155
|
+
#
|
|
156
|
+
# @note (see #url_for_oauth_code)
|
|
157
|
+
#
|
|
158
|
+
# @param (see #get_access_token_info)
|
|
159
|
+
#
|
|
160
|
+
# @raise (see #get_access_token_info)
|
|
161
|
+
#
|
|
162
|
+
# @return the access token
|
|
64
163
|
def get_access_token(code, options = {})
|
|
65
164
|
# upstream methods will throw errors if needed
|
|
66
165
|
if info = get_access_token_info(code, options)
|
|
@@ -68,22 +167,36 @@ module Koala
|
|
|
68
167
|
end
|
|
69
168
|
end
|
|
70
169
|
|
|
170
|
+
# Fetches the application's access token, along with any other information provided by Facebook.
|
|
171
|
+
# See http://developers.facebook.com/docs/authentication/ (search for App Login).
|
|
172
|
+
#
|
|
173
|
+
# @param options any additional parameters to send to Facebook when redeeming the token
|
|
174
|
+
#
|
|
175
|
+
# @return the application access token and other information (expiration, etc.)
|
|
71
176
|
def get_app_access_token_info(options = {})
|
|
72
177
|
# convenience method to get a the application's sessionless access token
|
|
73
178
|
get_token_from_server({:type => 'client_cred'}, true, options)
|
|
74
179
|
end
|
|
75
180
|
|
|
181
|
+
# Fetches the application's access token (ignoring expiration and other info).
|
|
182
|
+
# @see get_app_access_token_info
|
|
183
|
+
#
|
|
184
|
+
# @param (see #get_app_access_token_info)
|
|
185
|
+
#
|
|
186
|
+
# @return the application access token
|
|
76
187
|
def get_app_access_token(options = {})
|
|
77
188
|
if info = get_app_access_token_info(options)
|
|
78
189
|
string = info["access_token"]
|
|
79
190
|
end
|
|
80
191
|
end
|
|
81
192
|
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
#
|
|
86
|
-
#
|
|
193
|
+
# Parses a signed request string provided by Facebook to canvas apps or in a secure cookie.
|
|
194
|
+
#
|
|
195
|
+
# @param input the signed request from Facebook
|
|
196
|
+
#
|
|
197
|
+
# @raise RuntimeError if the signature is incomplete, invalid, or using an unsupported algorithm
|
|
198
|
+
#
|
|
199
|
+
# @return a hash of the validated request information
|
|
87
200
|
def parse_signed_request(input)
|
|
88
201
|
encoded_sig, encoded_envelope = input.split('.', 2)
|
|
89
202
|
raise 'SignedRequest: Invalid (incomplete) signature data' unless encoded_sig && encoded_envelope
|
|
@@ -100,8 +213,12 @@ module Koala
|
|
|
100
213
|
envelope
|
|
101
214
|
end
|
|
102
215
|
|
|
103
|
-
#
|
|
216
|
+
# Old session key code
|
|
217
|
+
|
|
218
|
+
# @deprecated Facebook no longer provides session keys.
|
|
104
219
|
def get_token_info_from_session_keys(sessions, options = {})
|
|
220
|
+
Koala::Utils.deprecate("Facebook no longer provides session keys. The relevant OAuth methods will be removed in the next release.")
|
|
221
|
+
|
|
105
222
|
# fetch the OAuth tokens from Facebook
|
|
106
223
|
response = fetch_token_string({
|
|
107
224
|
:type => 'client_cred',
|
|
@@ -119,6 +236,7 @@ module Koala
|
|
|
119
236
|
MultiJson.decode(response)
|
|
120
237
|
end
|
|
121
238
|
|
|
239
|
+
# @deprecated (see #get_token_info_from_session_keys)
|
|
122
240
|
def get_tokens_from_session_keys(sessions, options = {})
|
|
123
241
|
# get the original hash results
|
|
124
242
|
results = get_token_info_from_session_keys(sessions, options)
|
|
@@ -126,6 +244,7 @@ module Koala
|
|
|
126
244
|
results.collect { |r| r ? r["access_token"] : nil }
|
|
127
245
|
end
|
|
128
246
|
|
|
247
|
+
# @deprecated (see #get_token_info_from_session_keys)
|
|
129
248
|
def get_token_from_session_key(session, options = {})
|
|
130
249
|
# convenience method for a single key
|
|
131
250
|
# gets the overlaoded strings automatically
|
|
@@ -169,8 +288,15 @@ module Koala
|
|
|
169
288
|
|
|
170
289
|
def parse_signed_cookie(fb_cookie)
|
|
171
290
|
components = parse_signed_request(fb_cookie)
|
|
172
|
-
if
|
|
173
|
-
|
|
291
|
+
if code = components["code"]
|
|
292
|
+
begin
|
|
293
|
+
token_info = get_access_token_info(code, :redirect_uri => '')
|
|
294
|
+
rescue Koala::Facebook::APIError => err
|
|
295
|
+
return nil if err.message =~ /Code was invalid or expired/
|
|
296
|
+
raise
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
components.merge(token_info) if token_info
|
|
174
300
|
else
|
|
175
301
|
nil
|
|
176
302
|
end
|
|
@@ -189,6 +315,14 @@ module Koala
|
|
|
189
315
|
str += '=' * (4 - str.length.modulo(4))
|
|
190
316
|
Base64.decode64(str.tr('-_', '+/'))
|
|
191
317
|
end
|
|
318
|
+
|
|
319
|
+
def build_url(base, require_redirect_uri = false, url_options = {})
|
|
320
|
+
if require_redirect_uri && !(url_options[:redirect_uri] ||= url_options.delete(:callback) || @oauth_callback_url)
|
|
321
|
+
raise ArgumentError, "url_for_dialog must get a callback either from the OAuth object or in the parameters!"
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
"#{base}?#{Koala::HTTPService.encode_params(url_options)}"
|
|
325
|
+
end
|
|
192
326
|
end
|
|
193
327
|
end
|
|
194
328
|
end
|