fbauth 1.2.0.2 → 1.2.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/fbauth/auth.rb +88 -0
- data/lib/fbauth/config.rb +20 -0
- data/lib/fbauth/decoder.rb +25 -0
- data/lib/fbauth/graph.rb +26 -0
- data/lib/fbauth/http.rb +97 -0
- data/lib/fbauth/query.rb +16 -0
- metadata +9 -3
data/lib/fbauth/auth.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
class FacebookAuth
|
2
|
+
|
3
|
+
attr_accessor :access_token, :expires, :uid
|
4
|
+
attr_accessor :user_data, :validation_error
|
5
|
+
|
6
|
+
def self.create parms
|
7
|
+
auth = self.new
|
8
|
+
# Sense old-style FB auth structure, or new-style
|
9
|
+
if parms.has_key?('access_token')
|
10
|
+
auth.access_token = parms['access_token']
|
11
|
+
auth.uid = parms['uid']
|
12
|
+
auth.expires_epoch = parms['expires'].to_i unless parms['expires'].nil?
|
13
|
+
elsif parms.has_key?('oauth_token')
|
14
|
+
auth.access_token = parms['oauth_token']
|
15
|
+
auth.uid = parms['user_id']
|
16
|
+
auth.expires_epoch = parms['expires'].to_i if parms.has_key?('expires')
|
17
|
+
end
|
18
|
+
auth
|
19
|
+
end
|
20
|
+
|
21
|
+
def expires_epoch= epoch
|
22
|
+
# Need to convolve for SanFran TZ?
|
23
|
+
self.expires = Time.at(epoch)
|
24
|
+
end
|
25
|
+
|
26
|
+
def is_expired?
|
27
|
+
if self.expires.nil?
|
28
|
+
true
|
29
|
+
else
|
30
|
+
self.expires < Time.now
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def validate
|
35
|
+
valid = false
|
36
|
+
msgs = []
|
37
|
+
unless self.uid.nil? || self.access_token.nil?
|
38
|
+
begin
|
39
|
+
self.user_data = FacebookGraph.new(self.access_token).call(self.uid)
|
40
|
+
rescue => e
|
41
|
+
msgs << "Error calling FacebookGraph - #{e}"
|
42
|
+
end
|
43
|
+
if self.user_data && self.user_data.has_key?('error')
|
44
|
+
msgs << self.user_data['error'].inspect
|
45
|
+
self.user_data = nil
|
46
|
+
elsif self.user_data
|
47
|
+
valid = true
|
48
|
+
end
|
49
|
+
else
|
50
|
+
msgs << "UID provided is nil" if self.uid.nil?
|
51
|
+
msgs << "access_token provided is nil" if self.access_token.nil?
|
52
|
+
end
|
53
|
+
self.validation_error = msgs.join(", ") unless valid
|
54
|
+
return valid
|
55
|
+
end
|
56
|
+
|
57
|
+
def session_data
|
58
|
+
return {
|
59
|
+
'access_token' => self.access_token,
|
60
|
+
'uid' => self.uid,
|
61
|
+
'expires' => self.expires.to_i
|
62
|
+
}.to_json
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
# User data typically looks like this:
|
68
|
+
#
|
69
|
+
# {
|
70
|
+
# "id"=>"849395216",
|
71
|
+
# "name"=>"Steven Vetzal",
|
72
|
+
# "first_name"=>"Steven"
|
73
|
+
# "last_name"=>"Vetzal",
|
74
|
+
# "gender"=>"male",
|
75
|
+
# "verified"=>true,
|
76
|
+
# "link"=>"http://www.facebook.com/svetzal",
|
77
|
+
# "timezone"=>-5,
|
78
|
+
# "locale"=>"en_US",
|
79
|
+
# "location"=>{
|
80
|
+
# "name"=>"Oshawa, Ontario",
|
81
|
+
# "id"=>"114418101908145"
|
82
|
+
# },
|
83
|
+
# "hometown"=>{
|
84
|
+
# "name"=>"Oshawa, Ontario",
|
85
|
+
# "id"=>"114418101908145"
|
86
|
+
# },
|
87
|
+
# "updated_time"=>"2010-04-28T12:57:20+0000",
|
88
|
+
# }
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class FacebookConfig
|
2
|
+
def self.[](key)
|
3
|
+
get_environment[key].value
|
4
|
+
end
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def self.get_environment
|
9
|
+
read_yaml[ENV["RAILS_ENV"]]
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.read_yaml
|
13
|
+
file = File.join(::RAILS_ROOT, 'config', 'facebook.yml')
|
14
|
+
YAML.parse(ERB.new(IO.read(file)).result)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.app_url
|
18
|
+
"http://apps.facebook.com/#{self['app_context']}/"
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'digest/sha2'
|
3
|
+
|
4
|
+
class FacebookDecoder
|
5
|
+
|
6
|
+
def self.decode data
|
7
|
+
unless data.nil?
|
8
|
+
sig, b64udata = data.split('.')
|
9
|
+
unless b64udata.nil?
|
10
|
+
json = b64udata.tr('-_', '+/').unpack('m')[0]
|
11
|
+
begin
|
12
|
+
parms = JSON.parse(balance(json))
|
13
|
+
rescue => e
|
14
|
+
raise "Unable to parse json structure - '#{json}'"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
parms
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.balance input
|
22
|
+
input += '"' * (input.count('"') % 2)
|
23
|
+
input += "}" * (input.count('{') - input.count('}'))
|
24
|
+
end
|
25
|
+
end
|
data/lib/fbauth/graph.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
class FacebookGraph
|
5
|
+
include FacebookHttp
|
6
|
+
|
7
|
+
FB_GRAPH_URL = "https://graph.facebook.com"
|
8
|
+
|
9
|
+
def initialize(access_token = nil, options = {})
|
10
|
+
@options = options.merge({ :access_token => access_token })
|
11
|
+
end
|
12
|
+
|
13
|
+
# Generic Graph call to lookup data for any path
|
14
|
+
def call(path, options = {})
|
15
|
+
get "#{FB_GRAPH_URL}/#{path}", merged_options(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Post item to member's wall
|
19
|
+
# Available options: message, picture, link, name, caption, description
|
20
|
+
def publish_to_member_feed(uid, options)
|
21
|
+
raise "access_token required" unless has_access_token?(options)
|
22
|
+
if %w{staging production}.include? Rails.env
|
23
|
+
post "#{FB_GRAPH_URL}/#{uid}/feed", merged_options(options)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/fbauth/http.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'net/http'
|
3
|
+
require 'net/https' # Required for Ruby 1.8.7
|
4
|
+
require 'uri'
|
5
|
+
require 'cgi'
|
6
|
+
|
7
|
+
module FacebookHttp
|
8
|
+
|
9
|
+
def build_get_url(url, params = {})
|
10
|
+
q = build_query_string(params)
|
11
|
+
if q
|
12
|
+
url + q
|
13
|
+
else
|
14
|
+
url
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def caching_enabled?
|
19
|
+
ActionController::Base.cache_store.class.name == "ActiveSupport::Cache::MemCacheStore"
|
20
|
+
end
|
21
|
+
|
22
|
+
def get(url, params = {})
|
23
|
+
json = nil
|
24
|
+
uri = URI.parse(build_get_url(url, params))
|
25
|
+
|
26
|
+
json = Rails.cache.read(uri.to_s) if caching_enabled?
|
27
|
+
if json.nil?
|
28
|
+
bench = Benchmark.measure do
|
29
|
+
http = Net::HTTP.new uri.host, uri.port
|
30
|
+
begin
|
31
|
+
http.use_ssl = (uri.scheme == "https")
|
32
|
+
req = Net::HTTP::Get.new(uri.request_uri)
|
33
|
+
response = http.request(req)
|
34
|
+
raise "Facebook error response #{response.code} - #{response.body}" unless response.code == '200'
|
35
|
+
begin
|
36
|
+
json = JSON.parse(response.body)
|
37
|
+
rescue => e
|
38
|
+
raise "Error parsing facebook response: #{response.body}"
|
39
|
+
end
|
40
|
+
ensure
|
41
|
+
http.finish if http.started?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
logger.warn("Facebook GET call to #{uri.to_s} completed in #{bench.real} seconds")
|
45
|
+
Rails.cache.write(uri.to_s, json, :expires_in => 60) if json && caching_enabled?
|
46
|
+
end
|
47
|
+
json
|
48
|
+
end
|
49
|
+
|
50
|
+
def post(url, params = {})
|
51
|
+
json = nil
|
52
|
+
uri = URI.parse(url)
|
53
|
+
bench = Benchmark.measure do
|
54
|
+
http = Net::HTTP.new uri.host, uri.port
|
55
|
+
begin
|
56
|
+
http.use_ssl = (uri.scheme == "https")
|
57
|
+
req = Net::HTTP::Post.new(uri.path)
|
58
|
+
req.set_form_data(params)
|
59
|
+
response = http.request(req)
|
60
|
+
raise "Facebook error response #{response.code} - #{response.body}" unless response.code == '200'
|
61
|
+
begin
|
62
|
+
json = JSON.parse(response.body)
|
63
|
+
rescue => e
|
64
|
+
raise "Error parsing Facebook response: #{response.body}"
|
65
|
+
end
|
66
|
+
ensure
|
67
|
+
http.finish if http.started?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
logger.warn("Facebook POST call to #{uri.to_s} completed in #{bench.real} seconds")
|
71
|
+
json
|
72
|
+
end
|
73
|
+
|
74
|
+
def build_query_string options={}
|
75
|
+
params = []
|
76
|
+
str_keys = options.keys.collect{ |k| k.to_s }
|
77
|
+
str_keys.sort.each do |str_key|
|
78
|
+
key = str_key.to_sym
|
79
|
+
value = options[key]
|
80
|
+
params << "#{key.to_s}=#{URI.escape(value.to_s)}" unless value.nil?
|
81
|
+
end
|
82
|
+
"?#{params.join('&')}" unless params.empty?
|
83
|
+
end
|
84
|
+
|
85
|
+
def merged_options(options = {})
|
86
|
+
options.merge!(@options) if @options
|
87
|
+
options
|
88
|
+
end
|
89
|
+
|
90
|
+
def has_access_token?(options = {})
|
91
|
+
merged_options.has_key? :access_token
|
92
|
+
end
|
93
|
+
|
94
|
+
def logger
|
95
|
+
Rails.logger
|
96
|
+
end
|
97
|
+
end
|
data/lib/fbauth/query.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
class FacebookQuery
|
4
|
+
include FacebookHttp
|
5
|
+
|
6
|
+
FB_API_URL = "https://api.facebook.com/method/fql.query"
|
7
|
+
|
8
|
+
def initialize(access_token = nil, options = {})
|
9
|
+
@options = options.merge({ :access_token => access_token })
|
10
|
+
@options.merge!({ :format => "JSON" }) unless @options.has_key?(:format)
|
11
|
+
end
|
12
|
+
|
13
|
+
def fql(query, options = {})
|
14
|
+
get FB_API_URL, merged_options(options.merge({ :query => query }))
|
15
|
+
end
|
16
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fbauth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 73
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 2
|
9
9
|
- 0
|
10
|
-
-
|
11
|
-
version: 1.2.0.
|
10
|
+
- 3
|
11
|
+
version: 1.2.0.3
|
12
12
|
platform: ruby
|
13
13
|
authors:
|
14
14
|
- Three Wise Men Inc.
|
@@ -30,6 +30,12 @@ extra_rdoc_files:
|
|
30
30
|
- README.mdown
|
31
31
|
files:
|
32
32
|
- lib/fbauth.rb
|
33
|
+
- lib/fbauth/auth.rb
|
34
|
+
- lib/fbauth/config.rb
|
35
|
+
- lib/fbauth/decoder.rb
|
36
|
+
- lib/fbauth/graph.rb
|
37
|
+
- lib/fbauth/http.rb
|
38
|
+
- lib/fbauth/query.rb
|
33
39
|
- app/controllers/facebook_auth_functions.rb
|
34
40
|
- app/helpers/fbauth_helper.rb
|
35
41
|
- app/views/fbauth/_init.html.haml
|