facebookdp 0.1.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/README.markdown +76 -0
- data/lib/facebookdp.rb +8 -0
- data/lib/facebookdp/base.rb +56 -0
- data/lib/facebookdp/oauth.rb +35 -0
- data/test/facebookdp_test.rb +94 -0
- metadata +71 -0
data/README.markdown
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Overview
|
2
|
+
|
3
|
+
This gem allows you to authenticate against facebook and then make Graph API calls from ruby
|
4
|
+
|
5
|
+
# Authenticating a user against Facebook to obtain an access\_token
|
6
|
+
|
7
|
+
The goal here is to delegate authentication to Facebook and retrieve a
|
8
|
+
secret OAuth2 `access_token`. In other words, you want your web
|
9
|
+
application to be able to send a user to facebook, and have facebook
|
10
|
+
figure out whether or not they are who they say they are.
|
11
|
+
|
12
|
+
Facebook uses OAuth2 to authenticate users on thirdparty application's
|
13
|
+
behalf. This gem handles the Oauth2 "handshake" with
|
14
|
+
facebook. Basically, here are the steps:
|
15
|
+
|
16
|
+
1) Register you application with Facebook and get your API Key and API Secret
|
17
|
+
|
18
|
+
2) Create Facebook::OAuth object like so:
|
19
|
+
|
20
|
+
@oauth2 ||= Facebookdp::OAuth.new(your-api-key, you-api-secret, 'https://graph.facebook.com', facebook-callback-url)
|
21
|
+
|
22
|
+
The `facebook-callback-url` argument should be something like
|
23
|
+
`http://yourwebapp/facebook-controller/handle-facebook-response`. If
|
24
|
+
you don't specifiy a facebook-callback-url, it will default to
|
25
|
+
`http://localhost:3000/facebook`. So you might want to just stick a
|
26
|
+
controller there when doing development for easy testing.
|
27
|
+
|
28
|
+
3) Next, call `@oauth2.authorize_url`. This should give you a url like
|
29
|
+
this:
|
30
|
+
`https://graph.facebook.com/oauth/authorize?client_id=YOUR_APP_ID&type=web_server&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Ffacebook%2Fcallback`
|
31
|
+
|
32
|
+
4) Now it's time to trade the `client_id` for a Access Token (note the
|
33
|
+
http param named `client_id` in the `authorize_url`). Your web app
|
34
|
+
should redirect the user's browser to the `authorize_url`. Facebook
|
35
|
+
then prompts for a username and password. The user enters a username
|
36
|
+
and password.
|
37
|
+
|
38
|
+
Tip: During development, sometimes it helps to simply copy and paste the `authorize_url` into your
|
39
|
+
browser.
|
40
|
+
|
41
|
+
5a) If the user enters invalid credentials, they'll be redirected back
|
42
|
+
to the `facebook-callback-url` specified above. The request will
|
43
|
+
include a http param named `error_reason` so your application can
|
44
|
+
handle the invalid username and password error appropriately.
|
45
|
+
|
46
|
+
5b) If this is the first time the user has ever logged into your
|
47
|
+
application, they'll be prompted by Facebook whether to allow or deny
|
48
|
+
your web application. After they choose to allow or deny, they'll be
|
49
|
+
redirected to the facebook-callback-url specified above.
|
50
|
+
|
51
|
+
6) Assuming the user entered correct credentials and approved your web
|
52
|
+
application, then they'll be redirected back to the
|
53
|
+
`facebook-callback-url` you specified above. For example, something like this
|
54
|
+
|
55
|
+
http://yourwebapp/facebook-controller/handle-facebook-response?code=dd8490a3a1c82de377f45bc3-1388092492|\_6MST-8QGIQhiKP3ZkdEMou44Uo
|
56
|
+
|
57
|
+
Your web appilcation should parse that access code and hang onto it!
|
58
|
+
|
59
|
+
7) Next, you trade the access code for an `access_token` like so:
|
60
|
+
|
61
|
+
@oauth2_token = @oath2.get_access_token
|
62
|
+
@oauth2_token ||= @oauth2.get_access_token(the-access-code-you-parsed-and-saved)
|
63
|
+
|
64
|
+
# Using this Facebook Gem to make Graph API calls
|
65
|
+
|
66
|
+
First, you have to do the whole OAuth2 song and dance as described above. Once you do that, you should have a OAuth2 `access_token` for the user. You can then use the token to create an instance of the Facebookdp::Base class.
|
67
|
+
|
68
|
+
@client = Facebookdp::Base.new(@oauth2_token)
|
69
|
+
|
70
|
+
Then, simply use the `@client` instance to make Facebook Graph API
|
71
|
+
calls on the user's behalf. For example, you can get all the users
|
72
|
+
friends:
|
73
|
+
|
74
|
+
friends = @client.friends
|
75
|
+
|
76
|
+
|
data/lib/facebookdp.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module Facebookdp
|
2
|
+
class Base
|
3
|
+
def initialize(oauth2_access_token)
|
4
|
+
@access_token = oauth2_access_token
|
5
|
+
end
|
6
|
+
|
7
|
+
#
|
8
|
+
# Return current user's account information
|
9
|
+
def my_account
|
10
|
+
@my_account ||= Crack::JSON.parse(get_request("/me"))
|
11
|
+
end
|
12
|
+
|
13
|
+
def my_picture_url
|
14
|
+
@my_picture_url ||= "http://graph.facebook.com/#{my_account['id']}/picture"
|
15
|
+
end
|
16
|
+
|
17
|
+
# Get list of hash's id and name keys for each of current_user's friends
|
18
|
+
def friend_ids_and_names
|
19
|
+
@friend_ids ||= Crack::JSON.parse(get_request("/me/friends?fields=id,name"))['data']
|
20
|
+
end
|
21
|
+
|
22
|
+
# Get all information about all your friends. Pass limit
|
23
|
+
def friends(limit=0, offset=0)
|
24
|
+
if(limit<=0)
|
25
|
+
@friends ||= Crack::JSON.parse(get_request("/me/friends"))['data']
|
26
|
+
else
|
27
|
+
#TODO: this isn't working, not sure why
|
28
|
+
@friends ||= Crack::JSON.parse(get_request("/me/friends?limit=#{limit}&offset=#{offset}"))['data']
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Retrieve full information about a friend given their facebook id
|
33
|
+
def friend_info(fbid)
|
34
|
+
Crack::JSON.parse(get_request("/#{fbid}"))
|
35
|
+
end
|
36
|
+
|
37
|
+
# Retrieve last 10 statuses of a friend. Pass in limit to control
|
38
|
+
# number of status returned
|
39
|
+
def friend_statuses(fbid, limit=10)
|
40
|
+
Crack::JSON.parse(get_request("/#{fbid}/statuses?limit=#{limit}"))['data']
|
41
|
+
end
|
42
|
+
|
43
|
+
# Retrieve all statuses published by a friend since the date specified.
|
44
|
+
# TODO: not tested yet
|
45
|
+
def friend_latest_statuses(unix_timestamp)
|
46
|
+
Crack::JSON.parse(get_request("/#{fbid}/statuses?since=#{unix_timestamp}"))
|
47
|
+
end
|
48
|
+
|
49
|
+
protected
|
50
|
+
|
51
|
+
def get_request(path)
|
52
|
+
@access_token.get(path)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Facebookdp
|
2
|
+
class OAuth
|
3
|
+
attr_accessor :apikey, :apisecret, :graph_api_url, :callback_url, :code
|
4
|
+
|
5
|
+
def initialize(apikey, apisecret, graph_api_url = "https://graph.facebook.com", callback_url = "http://localhost:3000/facebook/callback")
|
6
|
+
@apikey = apikey
|
7
|
+
@apisecret = apisecret
|
8
|
+
@graph_api_url = graph_api_url
|
9
|
+
@callback_url = callback_url
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
# client is an instance of an oauth object, but needs to be
|
14
|
+
# authenticated by having a user visit facebook and retrieve a
|
15
|
+
# access code
|
16
|
+
def client
|
17
|
+
@client ||= OAuth2::Client.new(@apikey, @apisecret, :site => @graph_api_url)
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# Get the url needed to recieve auth token
|
22
|
+
# behind the scenes, oauth2 is passing id and secret
|
23
|
+
def authorize_url
|
24
|
+
client.web_server.authorize_url( :redirect_uri => callback_url )
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# Create access_token, and then we're connected
|
29
|
+
def get_access_token(code)
|
30
|
+
@code = code
|
31
|
+
@access_token ||= client.web_server.get_access_token( @code, :redirect_uri => callback_url)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'facebookdp'
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
class FacebookdpTest < Test::Unit::TestCase
|
6
|
+
# copy valid code here:
|
7
|
+
ACCESS_CODE = ''
|
8
|
+
FACEBOOK_APP_ID = ''
|
9
|
+
FACEBOOK_APP_SECRET = ''
|
10
|
+
class << self
|
11
|
+
def startup
|
12
|
+
unless @oauth2_token
|
13
|
+
@oauth2 ||= Facebookdp::OAuth.new(FACEBOOK_APP_ID, FACEBOOK_APP_SECRET , 'https://graph.facebook.com', 'http://localhost:3000/oauth2_consumers/facebook/callback')
|
14
|
+
expected = "https://graph.facebook.com/oauth/authorize?client_id=#{FACEBOOK_APP_ID}&type=web_server&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Ffacebook%2Fcallback"
|
15
|
+
begin
|
16
|
+
@oauth2_token ||= @oauth2.get_access_token(ACCESS_CODE)
|
17
|
+
@client = Facebookdp::Base.new(@oauth2_token)
|
18
|
+
rescue
|
19
|
+
#TODO: how to know if session is invalid and recover?
|
20
|
+
puts "Copy the following url into your browser to get a valid access token: #{@oauth2.authorize_url}"
|
21
|
+
raise
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def shutdown
|
27
|
+
# puts 'this runs once at end'
|
28
|
+
end
|
29
|
+
|
30
|
+
def oauth2_token
|
31
|
+
@oauth2_token
|
32
|
+
end
|
33
|
+
|
34
|
+
def client
|
35
|
+
@client
|
36
|
+
end
|
37
|
+
|
38
|
+
def suite
|
39
|
+
mysuite = super
|
40
|
+
def mysuite.run(*args)
|
41
|
+
FacebookdpTest.startup()
|
42
|
+
super
|
43
|
+
FacebookdpTest.shutdown()
|
44
|
+
end
|
45
|
+
mysuite
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def setup
|
50
|
+
# puts 'runs once before each test'
|
51
|
+
end
|
52
|
+
|
53
|
+
def teardown
|
54
|
+
# puts 'runs once after each test'
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_simple
|
58
|
+
assert(true)
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_get_my_account
|
62
|
+
result = self.class.client.my_account
|
63
|
+
assert_equal("Dave Paroulek", result['name'])
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_get_friend_ids
|
67
|
+
result = self.class.client.friend_ids_and_names
|
68
|
+
assert_equal(159, result.size)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_get_friends
|
72
|
+
result = self.class.client.friends
|
73
|
+
assert_equal(159, result.size)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_get_friend_info
|
77
|
+
result = self.class.client.friend_info(1500782)
|
78
|
+
assert_equal(result['name'], "Michael Shafrir")
|
79
|
+
assert_equal(result['first_name'], "Michael")
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_get_friend_statuses
|
83
|
+
result = self.class.client.friend_statuses(1500782, 1)
|
84
|
+
assert_equal(1, result.size)
|
85
|
+
assert_not_nil(result[0]['message'])
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_get_my_picture
|
89
|
+
expected = "http://graph.facebook.com/1388092492/picture"
|
90
|
+
result = self.class.client.my_picture_url
|
91
|
+
assert_equal(expected,result)
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: facebookdp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Dave Paroulek
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-11-02 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Consumes the Facebook OAuth2 Graph Rest API
|
23
|
+
email: dave @nospam@ daveparoulek.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- README.markdown
|
32
|
+
- lib/facebookdp/base.rb
|
33
|
+
- lib/facebookdp/oauth.rb
|
34
|
+
- lib/facebookdp.rb
|
35
|
+
- test/facebookdp_test.rb
|
36
|
+
has_rdoc: true
|
37
|
+
homepage: http://upgradingdave.com
|
38
|
+
licenses: []
|
39
|
+
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
hash: 3
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 3
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.3.7
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: Exposes Facebook OAuth2 Graph Rest API and provides ability to authenticate users against Facebook
|
70
|
+
test_files: []
|
71
|
+
|