koala 1.3.0 → 1.4.0.rc1
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/.travis.yml +6 -9
- data/CHANGELOG +15 -1
- data/Gemfile +3 -4
- data/lib/koala/api/graph_api.rb +57 -53
- data/lib/koala/http_service.rb +1 -1
- data/lib/koala/oauth.rb +63 -36
- data/lib/koala/version.rb +1 -1
- data/readme.md +1 -1
- data/spec/cases/graph_api_batch_spec.rb +19 -19
- data/spec/cases/http_service_spec.rb +7 -0
- data/spec/cases/koala_test_spec.rb +5 -0
- data/spec/cases/oauth_spec.rb +72 -32
- data/spec/fixtures/facebook_data.yml +1 -1
- data/spec/fixtures/mock_facebook_responses.yml +12 -3
- data/spec/support/graph_api_shared_examples.rb +19 -21
- data/spec/support/mock_http_service.rb +1 -1
- metadata +13 -11
data/.travis.yml
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
rvm:
|
|
2
|
-
- 1.8.7
|
|
2
|
+
- 1.8.7
|
|
3
3
|
- 1.9.2
|
|
4
4
|
- 1.9.3
|
|
5
5
|
- ruby-head
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
branches:
|
|
12
|
-
except:
|
|
13
|
-
- rdoc
|
|
6
|
+
- jruby-18mode # JRuby in 1.8 mode
|
|
7
|
+
- jruby-19mode # JRuby in 1.9 mode
|
|
8
|
+
- rbx-18mode
|
|
9
|
+
- rbx-19mode
|
|
10
|
+
- ree
|
data/CHANGELOG
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
v1.4
|
|
2
|
+
New methods:
|
|
3
|
+
-- OAuth#exchange_access_token(_info) allows you to extend access tokens you receive (thanks, etiennebarrie!)
|
|
4
|
+
Updated methods:
|
|
5
|
+
-- HTTPServices#encode_params sorts parameters to aid in URL comparison (thanks, sholden!)
|
|
6
|
+
-- get_connections is now aliased as get_connection (use whichever makes sense to you)
|
|
7
|
+
Internal improvements:
|
|
8
|
+
-- Fixed a readme typo (thanks, brycethornton!)
|
|
9
|
+
Testing improvements:
|
|
10
|
+
-- Added parallel_tests to development gem file
|
|
11
|
+
-- Fixed failing live tests
|
|
12
|
+
-- Koala now tests against JRuby and Rubinius in 1.9 mode on Travis-CI
|
|
13
|
+
|
|
14
|
+
|
|
1
15
|
v1.3
|
|
2
16
|
New methods:
|
|
3
17
|
-- OAuth#url_for_dialog creates URLs for Facebook dialog pages
|
|
@@ -24,7 +38,7 @@ Testing improvements:
|
|
|
24
38
|
-- Expanded/improved test coverage
|
|
25
39
|
-- The test suite no longer users any hard-coded user IDs
|
|
26
40
|
-- KoalaTest.test_user_api allows access to the TestUsers instance
|
|
27
|
-
-- Configured tests to run in random order using RSpec 2.8.0rc1
|
|
41
|
+
-- Configured tests to run in random order using RSpec 2.8.0rc1
|
|
28
42
|
|
|
29
43
|
v1.2.1
|
|
30
44
|
New methods:
|
data/Gemfile
CHANGED
|
@@ -5,11 +5,12 @@ group :development do
|
|
|
5
5
|
end
|
|
6
6
|
|
|
7
7
|
group :development, :test do
|
|
8
|
-
gem "typhoeus"
|
|
8
|
+
gem "typhoeus" unless defined? JRUBY_VERSION
|
|
9
9
|
|
|
10
10
|
# Testing infrastructure
|
|
11
11
|
gem 'guard'
|
|
12
12
|
gem 'guard-rspec'
|
|
13
|
+
gem "parallel_tests"
|
|
13
14
|
|
|
14
15
|
if RUBY_PLATFORM =~ /darwin/
|
|
15
16
|
# OS X integration
|
|
@@ -18,8 +19,6 @@ group :development, :test do
|
|
|
18
19
|
end
|
|
19
20
|
end
|
|
20
21
|
|
|
21
|
-
if defined? JRUBY_VERSION
|
|
22
|
-
gem "jruby-openssl"
|
|
23
|
-
end
|
|
22
|
+
gem "jruby-openssl" if defined? JRUBY_VERSION
|
|
24
23
|
|
|
25
24
|
gemspec
|
data/lib/koala/api/graph_api.rb
CHANGED
|
@@ -17,7 +17,7 @@ module Koala
|
|
|
17
17
|
# token, this will fetch the profile of the active user and the list
|
|
18
18
|
# of the user's friends:
|
|
19
19
|
#
|
|
20
|
-
# @example
|
|
20
|
+
# @example
|
|
21
21
|
# graph = Koala::Facebook::API.new(access_token)
|
|
22
22
|
# user = graph.get_object("me")
|
|
23
23
|
# friends = graph.get_connections(user["id"], "friends")
|
|
@@ -25,7 +25,7 @@ module Koala
|
|
|
25
25
|
# You can see a list of all of the objects and connections supported
|
|
26
26
|
# by the API at http://developers.facebook.com/docs/reference/api/.
|
|
27
27
|
#
|
|
28
|
-
# You can obtain an access token via OAuth or by using the Facebook JavaScript SDK.
|
|
28
|
+
# You can obtain an access token via OAuth or by using the Facebook JavaScript SDK.
|
|
29
29
|
# If you're using the JavaScript SDK, you can use the
|
|
30
30
|
# {Koala::Facebook::OAuth#get_user_from_cookie} method to get the OAuth access token
|
|
31
31
|
# for the active user from the cookie provided by Facebook.
|
|
@@ -35,12 +35,12 @@ module Koala
|
|
|
35
35
|
# Objects
|
|
36
36
|
|
|
37
37
|
# Get information about a Facebook object.
|
|
38
|
-
#
|
|
38
|
+
#
|
|
39
39
|
# @param id the object ID (string or number)
|
|
40
|
-
# @param args any additional arguments
|
|
40
|
+
# @param args any additional arguments
|
|
41
41
|
# (fields, metadata, etc. -- see {http://developers.facebook.com/docs/reference/api/ Facebook's documentation})
|
|
42
42
|
# @param options (see Koala::Facebook::API#api)
|
|
43
|
-
#
|
|
43
|
+
#
|
|
44
44
|
# @raise [Koala::Facebook::APIError] if the ID is invalid or you don't have access to that object
|
|
45
45
|
#
|
|
46
46
|
# @return a hash of object data
|
|
@@ -50,11 +50,11 @@ module Koala
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
# Get information about multiple Facebook objects in one call.
|
|
53
|
-
#
|
|
53
|
+
#
|
|
54
54
|
# @param ids an array or comma-separated string of object IDs
|
|
55
55
|
# @param args (see #get_object)
|
|
56
56
|
# @param options (see Koala::Facebook::API#api)
|
|
57
|
-
#
|
|
57
|
+
#
|
|
58
58
|
# @raise [Koala::Facebook::APIError] if any ID is invalid or you don't have access to that object
|
|
59
59
|
#
|
|
60
60
|
# @return an array of object data hashes
|
|
@@ -70,14 +70,14 @@ module Koala
|
|
|
70
70
|
#
|
|
71
71
|
# @note put_object is (for historical reasons) the same as put_connections.
|
|
72
72
|
# Please use put_connections; in a future version of Koala (2.0?),
|
|
73
|
-
# put_object will issue a POST directly to an individual object, not to a connection.
|
|
73
|
+
# put_object will issue a POST directly to an individual object, not to a connection.
|
|
74
74
|
def put_object(parent_object, connection_name, args = {}, options = {})
|
|
75
75
|
raise APIError.new({"type" => "KoalaMissingAccessToken", "message" => "Write operations require an access token"}) unless @access_token
|
|
76
76
|
graph_call("#{parent_object}/#{connection_name}", args, "post", options)
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
# Delete an object from the Graph if you have appropriate permissions.
|
|
80
|
-
#
|
|
80
|
+
#
|
|
81
81
|
# @param id (see #get_object)
|
|
82
82
|
# @param options (see #get_object)
|
|
83
83
|
#
|
|
@@ -91,27 +91,28 @@ module Koala
|
|
|
91
91
|
# Fetch information about a given connection (e.g. type of activity -- feed, events, photos, etc.)
|
|
92
92
|
# for a specific user.
|
|
93
93
|
# See {http://developers.facebook.com/docs/api Facebook's documentation} for a complete list of connections.
|
|
94
|
-
#
|
|
95
|
-
# @note to access connections like /user_id/CONNECTION/other_user_id,
|
|
94
|
+
#
|
|
95
|
+
# @note to access connections like /user_id/CONNECTION/other_user_id,
|
|
96
96
|
# simply pass "CONNECTION/other_user_id" as the connection_name
|
|
97
97
|
#
|
|
98
98
|
# @param id (see #get_object)
|
|
99
|
-
# @param connection_name what
|
|
99
|
+
# @param connection_name what
|
|
100
100
|
# @param args any additional arguments
|
|
101
101
|
# @param options (see #get_object)
|
|
102
|
-
#
|
|
102
|
+
#
|
|
103
103
|
# @return [Koala::Facebook::API::GraphCollection] an array of object hashes (in most cases)
|
|
104
|
-
def
|
|
104
|
+
def get_connection(id, connection_name, args = {}, options = {})
|
|
105
105
|
# Fetchs the connections for given object.
|
|
106
106
|
graph_call("#{id}/#{connection_name}", args, "get", options)
|
|
107
107
|
end
|
|
108
|
+
alias_method :get_connections, :get_connection
|
|
108
109
|
|
|
109
110
|
|
|
110
111
|
# Write an object to the Graph for a specific user.
|
|
111
|
-
# See {http://developers.facebook.com/docs/api#publishing Facebook's documentation}
|
|
112
|
+
# See {http://developers.facebook.com/docs/api#publishing Facebook's documentation}
|
|
112
113
|
# for all the supported writeable objects.
|
|
113
114
|
#
|
|
114
|
-
# @note (see #
|
|
115
|
+
# @note (see #get_connection)
|
|
115
116
|
#
|
|
116
117
|
# @example
|
|
117
118
|
# graph.put_object("me", "feed", :message => "Hello, world")
|
|
@@ -123,8 +124,8 @@ module Koala
|
|
|
123
124
|
# extended permissions.
|
|
124
125
|
#
|
|
125
126
|
# @param id (see #get_object)
|
|
126
|
-
# @param connection_name (see #
|
|
127
|
-
# @param args (see #
|
|
127
|
+
# @param connection_name (see #get_connection)
|
|
128
|
+
# @param args (see #get_connection)
|
|
128
129
|
# @param options (see #get_object)
|
|
129
130
|
#
|
|
130
131
|
# @return a hash containing the new object's id
|
|
@@ -136,11 +137,11 @@ module Koala
|
|
|
136
137
|
|
|
137
138
|
# Delete an object's connection (for instance, unliking the object).
|
|
138
139
|
#
|
|
139
|
-
# @note (see #
|
|
140
|
-
#
|
|
140
|
+
# @note (see #get_connection)
|
|
141
|
+
#
|
|
141
142
|
# @param id (see #get_object)
|
|
142
|
-
# @param connection_name (see #
|
|
143
|
-
# @args (see #
|
|
143
|
+
# @param connection_name (see #get_connection)
|
|
144
|
+
# @args (see #get_connection)
|
|
144
145
|
# @param options (see #get_object)
|
|
145
146
|
#
|
|
146
147
|
# @return (see #delete_object)
|
|
@@ -150,10 +151,13 @@ module Koala
|
|
|
150
151
|
graph_call("#{id}/#{connection_name}", args, "delete", options)
|
|
151
152
|
end
|
|
152
153
|
|
|
153
|
-
# Fetches a photo.
|
|
154
|
-
# (Facebook returns the src of the photo as a response header; this method parses that properly,
|
|
154
|
+
# Fetches a photo.
|
|
155
|
+
# (Facebook returns the src of the photo as a response header; this method parses that properly,
|
|
155
156
|
# unlike using get_connections("photo").)
|
|
156
157
|
#
|
|
158
|
+
# @param options options for Facebook (see #get_object).
|
|
159
|
+
# To get a different size photo, pass :type => size (small, normal, large, square).
|
|
160
|
+
#
|
|
157
161
|
# @note to delete photos or videos, use delete_object(id)
|
|
158
162
|
#
|
|
159
163
|
# @return the URL to the image
|
|
@@ -199,7 +203,7 @@ module Koala
|
|
|
199
203
|
put_object(*args)
|
|
200
204
|
end
|
|
201
205
|
|
|
202
|
-
# Write directly to the user's wall.
|
|
206
|
+
# Write directly to the user's wall.
|
|
203
207
|
# Convenience method equivalent to put_object(id, "feed").
|
|
204
208
|
#
|
|
205
209
|
# To get wall posts, use get_connections(user, "feed")
|
|
@@ -220,13 +224,13 @@ module Koala
|
|
|
220
224
|
# "picture" => "http://www.example.com/thumbnail.jpg"
|
|
221
225
|
# })
|
|
222
226
|
#
|
|
223
|
-
# @see #put_connections
|
|
227
|
+
# @see #put_connections
|
|
224
228
|
# @return (see #put_connections)
|
|
225
229
|
def put_wall_post(message, attachment = {}, target_id = "me", options = {})
|
|
226
230
|
self.put_object(target_id, "feed", attachment.merge({:message => message}), options)
|
|
227
231
|
end
|
|
228
232
|
|
|
229
|
-
# Comment on a given object.
|
|
233
|
+
# Comment on a given object.
|
|
230
234
|
# Convenience method equivalent to put_connection(id, "comments").
|
|
231
235
|
#
|
|
232
236
|
# To delete comments, use delete_object(comment_id).
|
|
@@ -242,7 +246,7 @@ module Koala
|
|
|
242
246
|
self.put_object(id, "comments", {:message => message}, options)
|
|
243
247
|
end
|
|
244
248
|
|
|
245
|
-
# Like a given object.
|
|
249
|
+
# Like a given object.
|
|
246
250
|
# Convenience method equivalent to put_connections(id, "likes").
|
|
247
251
|
#
|
|
248
252
|
# To get a list of a user's or object's likes, use get_connections(id, "likes").
|
|
@@ -256,7 +260,7 @@ module Koala
|
|
|
256
260
|
self.put_object(id, "likes", {}, options)
|
|
257
261
|
end
|
|
258
262
|
|
|
259
|
-
# Unlike a given object.
|
|
263
|
+
# Unlike a given object.
|
|
260
264
|
# Convenience method equivalent to delete_connection(id, "likes").
|
|
261
265
|
#
|
|
262
266
|
# @param id (see #get_object)
|
|
@@ -275,7 +279,7 @@ module Koala
|
|
|
275
279
|
# @param search_terms the query to search for
|
|
276
280
|
# @param args additional arguments, such as type, fields, etc.
|
|
277
281
|
# @param options (see #get_object)
|
|
278
|
-
#
|
|
282
|
+
#
|
|
279
283
|
# @return [Koala::Facebook::API::GraphCollection] an array of search results
|
|
280
284
|
def search(search_terms, args = {}, options = {})
|
|
281
285
|
args.merge!({:q => search_terms}) unless search_terms.nil?
|
|
@@ -286,10 +290,10 @@ module Koala
|
|
|
286
290
|
# In general, we're trying to avoid adding convenience methods to Koala
|
|
287
291
|
# except to support cases where the Facebook API requires non-standard input
|
|
288
292
|
# such as JSON-encoding arguments, posts directly to objects, etc.
|
|
289
|
-
|
|
290
|
-
# Make an FQL query.
|
|
293
|
+
|
|
294
|
+
# Make an FQL query.
|
|
291
295
|
# Convenience method equivalent to get_object("fql", :q => query).
|
|
292
|
-
#
|
|
296
|
+
#
|
|
293
297
|
# @param query the FQL query to perform
|
|
294
298
|
# @param args (see #get_object)
|
|
295
299
|
# @param options (see #get_object)
|
|
@@ -298,15 +302,15 @@ module Koala
|
|
|
298
302
|
end
|
|
299
303
|
|
|
300
304
|
# Make an FQL multiquery.
|
|
301
|
-
# This method simplifies the result returned from multiquery into a more logical format.
|
|
302
|
-
#
|
|
305
|
+
# This method simplifies the result returned from multiquery into a more logical format.
|
|
306
|
+
#
|
|
303
307
|
# @param queries a hash of query names => FQL queries
|
|
304
308
|
# @param args (see #get_object)
|
|
305
309
|
# @param options (see #get_object)
|
|
306
310
|
#
|
|
307
311
|
# @example
|
|
308
312
|
# @api.fql_multiquery({
|
|
309
|
-
# "query1" => "select post_id from stream where source_id = me()",
|
|
313
|
+
# "query1" => "select post_id from stream where source_id = me()",
|
|
310
314
|
# "query2" => "select fromid from comment where post_id in (select post_id from #query1)"
|
|
311
315
|
# })
|
|
312
316
|
# # returns {"query1" => [obj1, obj2, ...], "query2" => [obj3, ...]}
|
|
@@ -319,15 +323,15 @@ module Koala
|
|
|
319
323
|
results.inject({}) {|outcome, data| outcome[data["name"]] = data["fql_result_set"]; outcome}
|
|
320
324
|
end
|
|
321
325
|
end
|
|
322
|
-
|
|
326
|
+
|
|
323
327
|
# Get a page's access token, allowing you to act as the page.
|
|
324
328
|
# Convenience method for @api.get_object(page_id, :fields => "access_token").
|
|
325
329
|
#
|
|
326
330
|
# @param id the page ID
|
|
327
331
|
# @param args (see #get_object)
|
|
328
|
-
# @param options (see #get_object)
|
|
332
|
+
# @param options (see #get_object)
|
|
329
333
|
#
|
|
330
|
-
# @return the page's access token (discarding expiration and any other information)
|
|
334
|
+
# @return the page's access token (discarding expiration and any other information)
|
|
331
335
|
def get_page_access_token(id, args = {}, options = {})
|
|
332
336
|
result = get_object(id, args.merge(:fields => "access_token"), options) do
|
|
333
337
|
result ? result["access_token"] : nil
|
|
@@ -340,14 +344,14 @@ module Koala
|
|
|
340
344
|
# @param urls the URLs for which you want comments
|
|
341
345
|
# @param args (see #get_object)
|
|
342
346
|
# @param options (see #get_object)
|
|
343
|
-
#
|
|
347
|
+
#
|
|
344
348
|
# @returns a hash of urls => comment arrays
|
|
345
349
|
def get_comments_for_urls(urls = [], args = {}, options = {})
|
|
346
350
|
return [] if urls.empty?
|
|
347
351
|
args.merge!(:ids => urls.respond_to?(:join) ? urls.join(",") : urls)
|
|
348
352
|
get_object("comments", args, options)
|
|
349
353
|
end
|
|
350
|
-
|
|
354
|
+
|
|
351
355
|
def set_app_restrictions(app_id, restrictions_hash, args = {}, options = {})
|
|
352
356
|
graph_call(app_id, args.merge(:restrictions => MultiJson.encode(restrictions_hash)), "post", options)
|
|
353
357
|
end
|
|
@@ -355,9 +359,9 @@ module Koala
|
|
|
355
359
|
# Certain calls such as {#get_connections} return an array of results which you can page through
|
|
356
360
|
# forwards and backwards (to see more feed stories, search results, etc.).
|
|
357
361
|
# Those methods use get_page to request another set of results from Facebook.
|
|
358
|
-
#
|
|
362
|
+
#
|
|
359
363
|
# @note You'll rarely need to use this method unless you're using Sinatra or another non-Rails framework
|
|
360
|
-
# (see {Koala::Facebook::GraphCollection GraphCollection} for more information).
|
|
364
|
+
# (see {Koala::Facebook::GraphCollection GraphCollection} for more information).
|
|
361
365
|
#
|
|
362
366
|
# @param params an array of arguments to graph_call
|
|
363
367
|
# as returned by {Koala::Facebook::GraphCollection.parse_page_url}.
|
|
@@ -367,10 +371,10 @@ module Koala
|
|
|
367
371
|
graph_call(*params)
|
|
368
372
|
end
|
|
369
373
|
|
|
370
|
-
# Execute a set of Graph API calls as a batch.
|
|
371
|
-
# See {https://github.com/arsduo/koala/wiki/Batch-requests batch request documentation}
|
|
374
|
+
# Execute a set of Graph API calls as a batch.
|
|
375
|
+
# See {https://github.com/arsduo/koala/wiki/Batch-requests batch request documentation}
|
|
372
376
|
# for more information and examples.
|
|
373
|
-
#
|
|
377
|
+
#
|
|
374
378
|
# @param http_options HTTP options for the entire request.
|
|
375
379
|
#
|
|
376
380
|
# @yield batch_api [Koala::Facebook::GraphBatchAPI] an API subclass
|
|
@@ -388,7 +392,7 @@ module Koala
|
|
|
388
392
|
# end
|
|
389
393
|
# # => [{"id" => my_id, ...}, {"id"" => koppel_id, ...}]
|
|
390
394
|
#
|
|
391
|
-
# @return an array of results from your batch calls (as if you'd made them individually),
|
|
395
|
+
# @return an array of results from your batch calls (as if you'd made them individually),
|
|
392
396
|
# arranged in the same order they're made.
|
|
393
397
|
def batch(http_options = {}, &block)
|
|
394
398
|
batch_client = GraphBatchAPI.new(access_token, self)
|
|
@@ -399,7 +403,7 @@ module Koala
|
|
|
399
403
|
batch_client
|
|
400
404
|
end
|
|
401
405
|
end
|
|
402
|
-
|
|
406
|
+
|
|
403
407
|
# Make a call directly to the Graph API.
|
|
404
408
|
# (See any of the other methods for example invocations.)
|
|
405
409
|
#
|
|
@@ -408,12 +412,12 @@ module Koala
|
|
|
408
412
|
# @param verb the type of HTTP request to make (get, post, delete, etc.)
|
|
409
413
|
# @options (see #get_object)
|
|
410
414
|
#
|
|
411
|
-
# @yield response when making a batch API call, you can pass in a block
|
|
412
|
-
# that parses the results, allowing for cleaner code.
|
|
415
|
+
# @yield response when making a batch API call, you can pass in a block
|
|
416
|
+
# that parses the results, allowing for cleaner code.
|
|
413
417
|
# The block's return value is returned in the batch results.
|
|
414
418
|
# See the code for {#get_picture} or {#fql_multiquery} for examples.
|
|
415
419
|
# (Not needed in regular calls; you'll probably rarely use this.)
|
|
416
|
-
#
|
|
420
|
+
#
|
|
417
421
|
# @raise [Koala::Facebook::APIError] if Facebook returns an error
|
|
418
422
|
#
|
|
419
423
|
# @return the result from Facebook
|
|
@@ -425,13 +429,13 @@ module Koala
|
|
|
425
429
|
|
|
426
430
|
# turn this into a GraphCollection if it's pageable
|
|
427
431
|
result = GraphCollection.evaluate(result, self)
|
|
428
|
-
|
|
432
|
+
|
|
429
433
|
# now process as appropriate for the given call (get picture header, etc.)
|
|
430
434
|
post_processing ? post_processing.call(result) : result
|
|
431
435
|
end
|
|
432
436
|
|
|
433
437
|
private
|
|
434
|
-
|
|
438
|
+
|
|
435
439
|
def check_response(response)
|
|
436
440
|
# check for Graph API-specific errors
|
|
437
441
|
# this returns an error, which is immediately raised (non-batch)
|
data/lib/koala/http_service.rb
CHANGED
|
@@ -86,7 +86,7 @@ module Koala
|
|
|
86
86
|
#
|
|
87
87
|
# @return the appropriately-encoded string
|
|
88
88
|
def self.encode_params(param_hash)
|
|
89
|
-
((param_hash || {}).collect do |key_and_value|
|
|
89
|
+
((param_hash || {}).sort_by{|k, v| k.to_s}.collect do |key_and_value|
|
|
90
90
|
key_and_value[1] = MultiJson.encode(key_and_value[1]) unless key_and_value[1].is_a? String
|
|
91
91
|
"#{key_and_value[0].to_s}=#{CGI.escape key_and_value[1]}"
|
|
92
92
|
end).join("&")
|
data/lib/koala/oauth.rb
CHANGED
|
@@ -4,12 +4,12 @@ require 'base64'
|
|
|
4
4
|
|
|
5
5
|
module Koala
|
|
6
6
|
module Facebook
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
DIALOG_HOST = "www.facebook.com"
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
class OAuth
|
|
11
11
|
attr_reader :app_id, :app_secret, :oauth_callback_url
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
# Creates a new OAuth client.
|
|
14
14
|
#
|
|
15
15
|
# @param app_id [String, Integer] a Facebook application ID
|
|
@@ -20,14 +20,14 @@ module Koala
|
|
|
20
20
|
@app_secret = app_secret
|
|
21
21
|
@oauth_callback_url = oauth_callback_url
|
|
22
22
|
end
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
# Parses the cookie set Facebook's JavaScript SDK.
|
|
25
25
|
#
|
|
26
26
|
# @note in parsing Facebook's new signed cookie format this method has to make a request to Facebook.
|
|
27
27
|
# We recommend storing authenticated user info in your Rails session (or equivalent) and only
|
|
28
28
|
# calling this when needed.
|
|
29
29
|
#
|
|
30
|
-
# @param cookie_hash a set of cookies that includes the Facebook cookie.
|
|
30
|
+
# @param cookie_hash a set of cookies that includes the Facebook cookie.
|
|
31
31
|
# You can pass Rack/Rails/Sinatra's cookie hash directly to this method.
|
|
32
32
|
#
|
|
33
33
|
# @return the authenticated user's information as a hash, or nil.
|
|
@@ -60,21 +60,21 @@ module Koala
|
|
|
60
60
|
alias_method :get_user_from_cookie, :get_user_from_cookies
|
|
61
61
|
|
|
62
62
|
# URLs
|
|
63
|
-
|
|
63
|
+
|
|
64
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
|
|
65
|
+
# When the users log in, you receive a callback with their
|
|
66
66
|
# See http://developers.facebook.com/docs/authentication/.
|
|
67
67
|
#
|
|
68
68
|
# @see #url_for_access_token
|
|
69
69
|
#
|
|
70
|
-
# @note The server-side authentication and dialog methods should only be used
|
|
70
|
+
# @note The server-side authentication and dialog methods should only be used
|
|
71
71
|
# if your application can't use the Facebook Javascript SDK,
|
|
72
72
|
# which provides a much better user experience.
|
|
73
73
|
# See http://developers.facebook.com/docs/reference/javascript/.
|
|
74
74
|
#
|
|
75
75
|
# @param options any query values to add to the URL, as well as any special/required values listed below.
|
|
76
76
|
# @option options permissions an array or comma-separated string of desired permissions
|
|
77
|
-
#
|
|
77
|
+
#
|
|
78
78
|
# @raise ArgumentError if no OAuth callback was specified in OAuth#new or in options as :redirect_uri
|
|
79
79
|
#
|
|
80
80
|
# @return an OAuth URL you can send your users to
|
|
@@ -84,7 +84,7 @@ module Koala
|
|
|
84
84
|
options[:scope] = permissions.is_a?(Array) ? permissions.join(",") : permissions
|
|
85
85
|
end
|
|
86
86
|
url_options = {:client_id => @app_id}.merge(options)
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
# Creates the URL for oauth authorization for a given callback and optional set of permissions
|
|
89
89
|
build_url("https://#{GRAPH_SERVER}/oauth/authorize", true, url_options)
|
|
90
90
|
end
|
|
@@ -92,9 +92,9 @@ module Koala
|
|
|
92
92
|
# Once you receive an OAuth code, you need to redeem it from Facebook using an appropriate URL.
|
|
93
93
|
# (This is done by your server behind the scenes.)
|
|
94
94
|
# See http://developers.facebook.com/docs/authentication/.
|
|
95
|
-
#
|
|
95
|
+
#
|
|
96
96
|
# @see #url_for_oauth_code
|
|
97
|
-
#
|
|
97
|
+
#
|
|
98
98
|
# @note (see #url_for_oauth_code)
|
|
99
99
|
#
|
|
100
100
|
# @param code an OAuth code received from Facebook
|
|
@@ -106,7 +106,7 @@ module Koala
|
|
|
106
106
|
def url_for_access_token(code, options = {})
|
|
107
107
|
# Creates the URL for the token corresponding to a given code generated by Facebook
|
|
108
108
|
url_options = {
|
|
109
|
-
:client_id => @app_id,
|
|
109
|
+
:client_id => @app_id,
|
|
110
110
|
:code => code,
|
|
111
111
|
:client_secret => @app_secret
|
|
112
112
|
}.merge(options)
|
|
@@ -115,7 +115,7 @@ module Koala
|
|
|
115
115
|
|
|
116
116
|
# Builds a URL for a given dialog (feed, friends, OAuth, pay, send, etc.)
|
|
117
117
|
# See http://developers.facebook.com/docs/reference/dialogs/.
|
|
118
|
-
#
|
|
118
|
+
#
|
|
119
119
|
# @note (see #url_for_oauth_code)
|
|
120
120
|
#
|
|
121
121
|
# @param dialog_type the kind of Facebook dialog you want to show
|
|
@@ -124,37 +124,37 @@ module Koala
|
|
|
124
124
|
# @return an URL your server can query for the user's access token
|
|
125
125
|
def url_for_dialog(dialog_type, options = {})
|
|
126
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)
|
|
127
|
+
url_options = {:app_id => @app_id, :client_id => @app_id}.merge(options)
|
|
128
128
|
build_url("http://#{DIALOG_HOST}/dialog/#{dialog_type}", true, url_options)
|
|
129
129
|
end
|
|
130
|
-
|
|
130
|
+
|
|
131
131
|
# access tokens
|
|
132
|
-
|
|
132
|
+
|
|
133
133
|
# Fetches an access token, token expiration, and other info from Facebook.
|
|
134
134
|
# Useful when you've received an OAuth code using the server-side authentication process.
|
|
135
135
|
# @see url_for_oauth_code
|
|
136
136
|
#
|
|
137
137
|
# @note (see #url_for_oauth_code)
|
|
138
|
-
#
|
|
138
|
+
#
|
|
139
139
|
# @param code (see #url_for_access_token)
|
|
140
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.)
|
|
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.)
|
|
145
145
|
def get_access_token_info(code, options = {})
|
|
146
146
|
# convenience method to get a parsed token from Facebook for a given code
|
|
147
147
|
# should this require an OAuth callback URL?
|
|
148
148
|
get_token_from_server({:code => code, :redirect_uri => options[:redirect_uri] || @oauth_callback_url}, false, options)
|
|
149
149
|
end
|
|
150
150
|
|
|
151
|
-
|
|
151
|
+
|
|
152
152
|
# Fetches the access token (ignoring expiration and other info) from Facebook.
|
|
153
153
|
# Useful when you've received an OAuth code using the server-side authentication process.
|
|
154
154
|
# @see get_access_token_info
|
|
155
|
-
#
|
|
155
|
+
#
|
|
156
156
|
# @note (see #url_for_oauth_code)
|
|
157
|
-
#
|
|
157
|
+
#
|
|
158
158
|
# @param (see #get_access_token_info)
|
|
159
159
|
#
|
|
160
160
|
# @raise (see #get_access_token_info)
|
|
@@ -169,7 +169,7 @@ module Koala
|
|
|
169
169
|
|
|
170
170
|
# Fetches the application's access token, along with any other information provided by Facebook.
|
|
171
171
|
# See http://developers.facebook.com/docs/authentication/ (search for App Login).
|
|
172
|
-
#
|
|
172
|
+
#
|
|
173
173
|
# @param options any additional parameters to send to Facebook when redeeming the token
|
|
174
174
|
#
|
|
175
175
|
# @return the application access token and other information (expiration, etc.)
|
|
@@ -180,7 +180,7 @@ module Koala
|
|
|
180
180
|
|
|
181
181
|
# Fetches the application's access token (ignoring expiration and other info).
|
|
182
182
|
# @see get_app_access_token_info
|
|
183
|
-
#
|
|
183
|
+
#
|
|
184
184
|
# @param (see #get_app_access_token_info)
|
|
185
185
|
#
|
|
186
186
|
# @return the application access token
|
|
@@ -190,13 +190,40 @@ module Koala
|
|
|
190
190
|
end
|
|
191
191
|
end
|
|
192
192
|
|
|
193
|
+
# Fetches an access_token with extended expiration time, along with any other information provided by Facebook.
|
|
194
|
+
# See https://developers.facebook.com/docs/offline-access-deprecation/#extend_token (search for fb_exchange_token).
|
|
195
|
+
#
|
|
196
|
+
# @param access_token the access token to exchange
|
|
197
|
+
# @param options any additional parameters to send to Facebook when exchanging tokens.
|
|
198
|
+
#
|
|
199
|
+
# @return the access token with extended expiration time and other information (expiration, etc.)
|
|
200
|
+
def exchange_access_token_info(access_token, options = {})
|
|
201
|
+
get_token_from_server({
|
|
202
|
+
:grant_type => 'fb_exchange_token',
|
|
203
|
+
:fb_exchange_token => access_token
|
|
204
|
+
}, true, options)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Fetches an access token with extended expiration time (ignoring expiration and other info).
|
|
208
|
+
|
|
209
|
+
# @see exchange_access_token_info
|
|
210
|
+
#
|
|
211
|
+
# @param (see #exchange_access_token_info)
|
|
212
|
+
#
|
|
213
|
+
# @return A new access token or the existing one, set to expire in 60 days.
|
|
214
|
+
def exchange_access_token(access_token, options = {})
|
|
215
|
+
if info = exchange_access_token_info(access_token, options)
|
|
216
|
+
info["access_token"]
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
193
220
|
# Parses a signed request string provided by Facebook to canvas apps or in a secure cookie.
|
|
194
221
|
#
|
|
195
222
|
# @param input the signed request from Facebook
|
|
196
|
-
#
|
|
223
|
+
#
|
|
197
224
|
# @raise RuntimeError if the signature is incomplete, invalid, or using an unsupported algorithm
|
|
198
|
-
#
|
|
199
|
-
# @return a hash of the validated request information
|
|
225
|
+
#
|
|
226
|
+
# @return a hash of the validated request information
|
|
200
227
|
def parse_signed_request(input)
|
|
201
228
|
encoded_sig, encoded_envelope = input.split('.', 2)
|
|
202
229
|
raise 'SignedRequest: Invalid (incomplete) signature data' unless encoded_sig && encoded_envelope
|
|
@@ -214,7 +241,7 @@ module Koala
|
|
|
214
241
|
end
|
|
215
242
|
|
|
216
243
|
# Old session key code
|
|
217
|
-
|
|
244
|
+
|
|
218
245
|
# @deprecated Facebook no longer provides session keys.
|
|
219
246
|
def get_token_info_from_session_keys(sessions, options = {})
|
|
220
247
|
Koala::Utils.deprecate("Facebook no longer provides session keys. The relevant OAuth methods will be removed in the next release.")
|
|
@@ -271,7 +298,7 @@ module Koala
|
|
|
271
298
|
end
|
|
272
299
|
components
|
|
273
300
|
end
|
|
274
|
-
|
|
301
|
+
|
|
275
302
|
def parse_unsigned_cookie(fb_cookie)
|
|
276
303
|
# remove the opening/closing quote
|
|
277
304
|
fb_cookie = fb_cookie.gsub(/\"/, "")
|
|
@@ -285,7 +312,7 @@ module Koala
|
|
|
285
312
|
sig = Digest::MD5.hexdigest(auth_string + @app_secret)
|
|
286
313
|
sig == components["sig"] && (components["expires"] == "0" || Time.now.to_i < components["expires"].to_i) ? components : nil
|
|
287
314
|
end
|
|
288
|
-
|
|
315
|
+
|
|
289
316
|
def parse_signed_cookie(fb_cookie)
|
|
290
317
|
components = parse_signed_request(fb_cookie)
|
|
291
318
|
if code = components["code"]
|
|
@@ -315,12 +342,12 @@ module Koala
|
|
|
315
342
|
str += '=' * (4 - str.length.modulo(4))
|
|
316
343
|
Base64.decode64(str.tr('-_', '+/'))
|
|
317
344
|
end
|
|
318
|
-
|
|
345
|
+
|
|
319
346
|
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)
|
|
347
|
+
if require_redirect_uri && !(url_options[:redirect_uri] ||= url_options.delete(:callback) || @oauth_callback_url)
|
|
321
348
|
raise ArgumentError, "url_for_dialog must get a callback either from the OAuth object or in the parameters!"
|
|
322
349
|
end
|
|
323
|
-
|
|
350
|
+
|
|
324
351
|
"#{base}?#{Koala::HTTPService.encode_params(url_options)}"
|
|
325
352
|
end
|
|
326
353
|
end
|