gtg-facebooker2 0.0.6
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/lib/facebooker2/rails/controller.rb +113 -0
- data/lib/facebooker2/rails/helpers/facebook_connect.rb +51 -0
- data/lib/facebooker2/rails/helpers/javascript.rb +39 -0
- data/lib/facebooker2/rails/helpers/request_forms.rb +33 -0
- data/lib/facebooker2/rails/helpers/user.rb +49 -0
- data/lib/facebooker2/rails/helpers.rb +33 -0
- data/lib/facebooker2/rails.rb +4 -0
- data/lib/facebooker2.rb +50 -0
- metadata +103 -0
@@ -0,0 +1,113 @@
|
|
1
|
+
require "digest/md5"
|
2
|
+
require "hmac-sha2"
|
3
|
+
require "ruby-debug"
|
4
|
+
module Facebooker2
|
5
|
+
module Rails
|
6
|
+
module Controller
|
7
|
+
|
8
|
+
def self.included(controller)
|
9
|
+
controller.helper Facebooker2::Rails::Helpers
|
10
|
+
controller.helper_method :current_facebook_user
|
11
|
+
controller.helper_method :current_facebook_client
|
12
|
+
controller.helper_method :facebook_params
|
13
|
+
end
|
14
|
+
|
15
|
+
def current_facebook_user
|
16
|
+
fetch_client_and_user
|
17
|
+
@_current_facebook_user
|
18
|
+
end
|
19
|
+
|
20
|
+
def current_facebook_client
|
21
|
+
fetch_client_and_user
|
22
|
+
@_current_facebook_client
|
23
|
+
end
|
24
|
+
|
25
|
+
def fetch_client_and_user
|
26
|
+
return if @_fb_user_fetched
|
27
|
+
fetch_client_and_user_from_cookie
|
28
|
+
fetch_client_and_user_from_signed_request unless @_current_facebook_client
|
29
|
+
@_fb_user_fetched = true
|
30
|
+
end
|
31
|
+
|
32
|
+
def fetch_client_and_user_from_cookie
|
33
|
+
app_id = Facebooker2.app_id
|
34
|
+
if (hash_data = fb_cookie_hash_for_app_id(app_id)) and
|
35
|
+
fb_cookie_signature_correct?(fb_cookie_hash_for_app_id(app_id),Facebooker2.secret)
|
36
|
+
fb_create_user_and_client(hash_data["access_token"],hash_data["expires"],hash_data["uid"])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def fb_create_user_and_client(token,expires,userid)
|
41
|
+
client = Mogli::Client.new(token,expires.to_i)
|
42
|
+
user = Mogli::User.new(:id=>userid)
|
43
|
+
fb_sign_in_user_and_client(user,client)
|
44
|
+
end
|
45
|
+
|
46
|
+
def fb_sign_in_user_and_client(user,client)
|
47
|
+
user.client = client
|
48
|
+
@_current_facebook_user = user
|
49
|
+
@_current_facebook_client = client
|
50
|
+
@_fb_user_fetched = true
|
51
|
+
end
|
52
|
+
|
53
|
+
def fb_cookie_hash_for_app_id(app_id)
|
54
|
+
return nil unless fb_cookie_for_app_id?(app_id)
|
55
|
+
hash={}
|
56
|
+
data = fb_cookie_for_app_id(app_id).gsub(/"/,"")
|
57
|
+
data.split("&").each do |str|
|
58
|
+
parts = str.split("=")
|
59
|
+
hash[parts.first] = parts.last
|
60
|
+
end
|
61
|
+
hash
|
62
|
+
end
|
63
|
+
|
64
|
+
def fb_cookie_for_app_id?(app_id)
|
65
|
+
!fb_cookie_for_app_id(app_id).nil?
|
66
|
+
end
|
67
|
+
|
68
|
+
def fb_cookie_for_app_id(app_id)
|
69
|
+
cookies["fbs_#{app_id}"]
|
70
|
+
end
|
71
|
+
|
72
|
+
def fb_cookie_signature_correct?(hash,secret)
|
73
|
+
sorted_keys = hash.keys.reject {|k| k=="sig"}.sort
|
74
|
+
test_string = ""
|
75
|
+
sorted_keys.each do |key|
|
76
|
+
test_string += "#{key}=#{hash[key]}"
|
77
|
+
end
|
78
|
+
test_string += secret
|
79
|
+
Digest::MD5.hexdigest(test_string) == hash["sig"]
|
80
|
+
end
|
81
|
+
|
82
|
+
def fb_signed_request_json(encoded)
|
83
|
+
chars_to_add = 4-(encoded.size % 4)
|
84
|
+
encoded += ("=" * chars_to_add)
|
85
|
+
Base64.decode64(encoded)
|
86
|
+
end
|
87
|
+
|
88
|
+
def facebook_params
|
89
|
+
@facebook_param ||= fb_load_facebook_params
|
90
|
+
end
|
91
|
+
|
92
|
+
def fb_load_facebook_params
|
93
|
+
return {} if params[:signed_request].blank?
|
94
|
+
sig,encoded_json = params[:signed_request].split(".")
|
95
|
+
return {} unless fb_signed_request_sig_valid?(sig,encoded_json)
|
96
|
+
ActiveSupport::JSON.decode(fb_signed_request_json(encoded_json)).with_indifferent_access
|
97
|
+
end
|
98
|
+
|
99
|
+
def fb_signed_request_sig_valid?(sig,encoded)
|
100
|
+
base64 = Base64.encode64(HMAC::SHA256.digest(Facebooker2.secret,encoded))
|
101
|
+
#now make the url changes that facebook makes
|
102
|
+
url_escaped_base64 = base64.gsub(/=*\n?$/,"").tr("+/","-_")
|
103
|
+
sig == url_escaped_base64
|
104
|
+
end
|
105
|
+
|
106
|
+
def fetch_client_and_user_from_signed_request
|
107
|
+
if facebook_params[:oauth_token]
|
108
|
+
fb_create_user_and_client(facebook_params[:oauth_token],facebook_params[:expires],facebook_params[:user_id])
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Facebooker2
|
2
|
+
module Rails
|
3
|
+
module Helpers
|
4
|
+
module FacebookConnect
|
5
|
+
#
|
6
|
+
# Render an <fb:login-button> element, similar to
|
7
|
+
# fb_login_button. Adds a js redirect to the onlogin event via rjs.
|
8
|
+
#
|
9
|
+
# ==== Examples
|
10
|
+
#
|
11
|
+
# fb_login_and_redirect '/other_page'
|
12
|
+
# => <fb:login-button onlogin="window.location.href = "/other_page";"></fb:login-button>
|
13
|
+
#
|
14
|
+
# Like #fb_login_button, this also supports the :text option
|
15
|
+
#
|
16
|
+
# fb_login_and_redirect '/other_page', :text => "Login with Facebook", :v => '2'
|
17
|
+
# => <fb:login-button onlogin="window.location.href = "/other_page";" v="2">Login with Facebook</fb:login-button>
|
18
|
+
#
|
19
|
+
def fb_login_and_redirect(url, options = {})
|
20
|
+
js = update_page do |page|
|
21
|
+
page.redirect_to url
|
22
|
+
end
|
23
|
+
|
24
|
+
text = options.delete(:text)
|
25
|
+
|
26
|
+
content_tag("fb:login-button",text,options.merge(:onlogin=>js))
|
27
|
+
end
|
28
|
+
|
29
|
+
def fb_login(options = {},&proc)
|
30
|
+
js = capture(&proc)
|
31
|
+
text = options.delete(:text)
|
32
|
+
concat(content_tag("fb:login-button",text,options.merge(:onlogin=>js)))
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# Logs the user out of facebook and redirects to the given URL
|
37
|
+
# args are passed to the call to link_to_function
|
38
|
+
def fb_logout_link(text,url,*args)
|
39
|
+
function= "FB.logout(function() {window.location.href = '#{url}';})"
|
40
|
+
link_to_function text, function, *args
|
41
|
+
end
|
42
|
+
|
43
|
+
def fb_server_fbml(style=nil,&proc)
|
44
|
+
style_string=" style=\"#{style}\"" if style
|
45
|
+
content = capture(&proc)
|
46
|
+
concat("<fb:serverFbml#{style_string}><script type='text/fbml'>#{content}</script></fb:serverFbml>")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Facebooker2
|
2
|
+
module Rails
|
3
|
+
module Helpers
|
4
|
+
module Javascript
|
5
|
+
def fb_connect_async_js(app_id=Facebooker2.app_id,options={},&proc)
|
6
|
+
opts = Hash.new(true).merge!(options)
|
7
|
+
cookie = opts[:cookie]
|
8
|
+
status = opts[:status]
|
9
|
+
xfbml = opts[:xfbml]
|
10
|
+
extra_js = capture(&proc) if block_given?
|
11
|
+
js = <<-JAVASCRIPT
|
12
|
+
<script>
|
13
|
+
window.fbAsyncInit = function() {
|
14
|
+
FB.init({
|
15
|
+
appId : '#{app_id}',
|
16
|
+
status : #{status}, // check login status
|
17
|
+
cookie : #{cookie}, // enable cookies to allow the server to access the session
|
18
|
+
xfbml : #{xfbml} // parse XFBML
|
19
|
+
});
|
20
|
+
#{extra_js}
|
21
|
+
};
|
22
|
+
|
23
|
+
(function() {
|
24
|
+
var s = document.createElement('div');
|
25
|
+
s.setAttribute('id','fb-root');
|
26
|
+
document.documentElement.getElementsByTagName("HEAD")[0].appendChild(s);
|
27
|
+
var e = document.createElement('script');
|
28
|
+
e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
|
29
|
+
e.async = true;
|
30
|
+
s.appendChild(e);
|
31
|
+
}());
|
32
|
+
</script>
|
33
|
+
JAVASCRIPT
|
34
|
+
block_given? ? concat(js) : js
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Facebooker2
|
2
|
+
module Rails
|
3
|
+
module Helpers
|
4
|
+
module RequestForms
|
5
|
+
def fb_req_choice(label,url)
|
6
|
+
tag "fb:req-choice",:label=>label,:url=>url
|
7
|
+
end
|
8
|
+
|
9
|
+
def fb_multi_friend_selector(message,options={},&block)
|
10
|
+
options = fb_stringify_vals({:showborder=>false,:actiontext=>message,:max=>20}.merge(options.dup))
|
11
|
+
tag("fb:multi-friend-selector",options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def fb_request_form(type,url,message,options={},&block)
|
15
|
+
content = capture(&block)
|
16
|
+
concat(content_tag("fb:request-form", content.to_s + fb_forgery_protection_token_tag,
|
17
|
+
{:action=>url,:method=>"post",:invite=>true,:type=>type,:content=>message}.merge(options)))
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def fb_forgery_protection_token_tag
|
22
|
+
unless protect_against_forgery?
|
23
|
+
''
|
24
|
+
else
|
25
|
+
tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Facebooker2
|
2
|
+
module Rails
|
3
|
+
module Helpers
|
4
|
+
module User
|
5
|
+
# Render an fb:name tag for the given user
|
6
|
+
# This renders the name of the user specified. You can use this tag as both subject and object of
|
7
|
+
# a sentence. <em> See </em> http://wiki.developers.facebook.com/index.php/Fb:name for full description.
|
8
|
+
# Use this tag on FBML pages instead of retrieving the user's info and rendering the name explicitly.
|
9
|
+
#
|
10
|
+
def fb_name(user, options={})
|
11
|
+
options = fb_transform_keys(options,FB_NAME_OPTION_KEYS_TO_TRANSFORM)
|
12
|
+
fb_assert_valid_keys(options, FB_NAME_VALID_OPTION_KEYS)
|
13
|
+
options.merge!(:uid => Facebooker2.cast_to_facebook_id(user))
|
14
|
+
content_tag("fb:name",nil, fb_stringify_vals(options))
|
15
|
+
end
|
16
|
+
|
17
|
+
FB_NAME_OPTION_KEYS_TO_TRANSFORM = {:first_name_only => :firstnameonly,
|
18
|
+
:last_name_only => :lastnameonly,
|
19
|
+
:show_network => :shownetwork,
|
20
|
+
:use_you => :useyou,
|
21
|
+
:if_cant_see => :ifcantsee,
|
22
|
+
:subject_id => :subjectid}
|
23
|
+
FB_NAME_VALID_OPTION_KEYS = [:firstnameonly, :linked, :lastnameonly, :possessive, :reflexive,
|
24
|
+
:shownetwork, :useyou, :ifcantsee, :capitalize, :subjectid]
|
25
|
+
|
26
|
+
|
27
|
+
def fb_profile_pic(user, options={})
|
28
|
+
options = options.dup
|
29
|
+
validate_fb_profile_pic_size(options)
|
30
|
+
options = fb_transform_keys(options,FB_PROFILE_PIC_OPTION_KEYS_TO_TRANSFORM)
|
31
|
+
fb_assert_valid_keys(options,FB_PROFILE_PIC_VALID_OPTION_KEYS)
|
32
|
+
options.merge!(:uid => Facebooker2.cast_to_facebook_id(user))
|
33
|
+
content_tag("fb:profile-pic", nil,fb_stringify_vals(options))
|
34
|
+
end
|
35
|
+
|
36
|
+
FB_PROFILE_PIC_OPTION_KEYS_TO_TRANSFORM = {:facebook_logo => 'facebook-logo'}
|
37
|
+
FB_PROFILE_PIC_VALID_OPTION_KEYS = [:size, :linked, 'facebook-logo', :width, :height]
|
38
|
+
VALID_FB_PROFILE_PIC_SIZES = [:thumb, :small, :normal, :square]
|
39
|
+
def validate_fb_profile_pic_size(options)
|
40
|
+
if options.has_key?(:size) && !VALID_FB_PROFILE_PIC_SIZES.include?(options[:size].to_sym)
|
41
|
+
raise(ArgumentError, "Unknown value for size: #{options[:size]}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Facebooker2
|
2
|
+
module Rails
|
3
|
+
module Helpers
|
4
|
+
include FacebookConnect
|
5
|
+
include Javascript
|
6
|
+
include RequestForms
|
7
|
+
include User
|
8
|
+
|
9
|
+
def fb_stringify_vals(hash)
|
10
|
+
result={}
|
11
|
+
hash.each do |key,value|
|
12
|
+
result[key]=value.to_s
|
13
|
+
end
|
14
|
+
result
|
15
|
+
end
|
16
|
+
def fb_transform_keys(options,transformation_hash)
|
17
|
+
new_hash = {}
|
18
|
+
options.each do |key,value|
|
19
|
+
new_key = transformation_hash[key]||key
|
20
|
+
new_hash[new_key]=value
|
21
|
+
end
|
22
|
+
new_hash
|
23
|
+
end
|
24
|
+
FB_ALWAYS_VALID_OPTION_KEYS = [:class, :style]
|
25
|
+
|
26
|
+
def fb_assert_valid_keys(options,*valid_keys)
|
27
|
+
unknown_keys = options.keys - [valid_keys + FB_ALWAYS_VALID_OPTION_KEYS].flatten
|
28
|
+
raise(ArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty?
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/facebooker2.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# Facebooker2
|
2
|
+
require "mogli"
|
3
|
+
module Facebooker2
|
4
|
+
class NotConfigured < Exception; end
|
5
|
+
class << self
|
6
|
+
attr_accessor :api_key, :secret, :app_id
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.secret
|
10
|
+
@secret || raise_unconfigured_exception
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.app_id
|
14
|
+
@app_id || raise_unconfigured_exception
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.raise_unconfigured_exception
|
18
|
+
raise NotConfigured.new("No configuration provided for Facebooker2. Either set the app_id and secret or call Facebooker2.load_facebooker_yaml in an initializer")
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.configuration=(hash)
|
22
|
+
self.api_key = hash[:api_key]
|
23
|
+
self.secret = hash[:secret]
|
24
|
+
self.app_id = hash[:app_id]
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.load_facebooker_yaml
|
28
|
+
config = YAML.load(File.read(File.join(::Rails.root,"config","facebooker.yml")))[::Rails.env]
|
29
|
+
raise NotConfigured.new("Unable to load configuration for #{::Rails.env} from facebooker.yml. Is it set up?") if config.nil?
|
30
|
+
self.configuration = config.with_indifferent_access
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.cast_to_facebook_id(object)
|
34
|
+
if object.kind_of?(Mogli::Profile)
|
35
|
+
object.id
|
36
|
+
elsif object.respond_to?(:facebook_id)
|
37
|
+
object.facebook_id
|
38
|
+
else
|
39
|
+
object
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
require "facebooker2/rails/controller"
|
46
|
+
require "facebooker2/rails/helpers/facebook_connect"
|
47
|
+
require "facebooker2/rails/helpers/javascript"
|
48
|
+
require "facebooker2/rails/helpers/request_forms"
|
49
|
+
require "facebooker2/rails/helpers/user"
|
50
|
+
require "facebooker2/rails/helpers"
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gtg-facebooker2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 19
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 6
|
10
|
+
version: 0.0.6
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Mike Mangino
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-07-23 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: mogli
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 7
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 0
|
33
|
+
- 12
|
34
|
+
version: 0.0.12
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: ruby-hmac
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 3
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
version: "0"
|
49
|
+
type: :runtime
|
50
|
+
version_requirements: *id002
|
51
|
+
description: Facebook Connect integration library for ruby and rails
|
52
|
+
email: mmangino@elevatedrails.com,goss@gamesthatgive.net
|
53
|
+
executables: []
|
54
|
+
|
55
|
+
extensions: []
|
56
|
+
|
57
|
+
extra_rdoc_files: []
|
58
|
+
|
59
|
+
files:
|
60
|
+
- lib/facebooker2/rails/controller.rb
|
61
|
+
- lib/facebooker2/rails/helpers/facebook_connect.rb
|
62
|
+
- lib/facebooker2/rails/helpers/javascript.rb
|
63
|
+
- lib/facebooker2/rails/helpers/request_forms.rb
|
64
|
+
- lib/facebooker2/rails/helpers/user.rb
|
65
|
+
- lib/facebooker2/rails/helpers.rb
|
66
|
+
- lib/facebooker2/rails.rb
|
67
|
+
- lib/facebooker2.rb
|
68
|
+
has_rdoc: false
|
69
|
+
homepage: http://developers.facebook.com/docs/api
|
70
|
+
licenses: []
|
71
|
+
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
hash: 3
|
83
|
+
segments:
|
84
|
+
- 0
|
85
|
+
version: "0"
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
hash: 3
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
version: "0"
|
95
|
+
requirements: []
|
96
|
+
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 1.3.7
|
99
|
+
signing_key:
|
100
|
+
specification_version: 3
|
101
|
+
summary: Facebook Connect integration library for ruby and rails
|
102
|
+
test_files: []
|
103
|
+
|