thorsson_facebooker2 0.0.17
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/rack/post_canvas.rb +23 -0
- data/lib/facebooker2/rails/controller.rb +245 -0
- data/lib/facebooker2/rails/helpers/facebook_connect.rb +60 -0
- data/lib/facebooker2/rails/helpers/javascript.rb +57 -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 +55 -0
- metadata +165 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Rack middleware that converts POST requests from Facebook to GET request.
|
|
2
|
+
# When there is a signed_parameter in the request params, this is a request iniated by the top Facebook frame
|
|
3
|
+
# It will be sent as a POST request that we want to convert to a GET request to keep the app restful
|
|
4
|
+
# See for details : http://blog.coderubik.com/?p=178
|
|
5
|
+
module Rack
|
|
6
|
+
class PostCanvas
|
|
7
|
+
|
|
8
|
+
def initialize(app)
|
|
9
|
+
@app = app
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def call(env)
|
|
13
|
+
request = Request.new(env)
|
|
14
|
+
|
|
15
|
+
if request.POST['signed_request']
|
|
16
|
+
env["REQUEST_METHOD"] = 'GET'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
return @app.call(env)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
require "digest/md5"
|
|
2
|
+
require "hmac-sha2"
|
|
3
|
+
module Facebooker2
|
|
4
|
+
module Rails
|
|
5
|
+
module Controller
|
|
6
|
+
|
|
7
|
+
def self.included(controller)
|
|
8
|
+
controller.helper Facebooker2::Rails::Helpers
|
|
9
|
+
controller.helper_method :current_facebook_user
|
|
10
|
+
controller.helper_method :current_facebook_client
|
|
11
|
+
controller.helper_method :facebook_params
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def current_facebook_user
|
|
15
|
+
if (Facebooker2.oauth2)
|
|
16
|
+
oauth2_fetch_client_and_user
|
|
17
|
+
else
|
|
18
|
+
fetch_client_and_user
|
|
19
|
+
end
|
|
20
|
+
@_current_facebook_user
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def current_facebook_client
|
|
24
|
+
if (Facebooker2.oauth2)
|
|
25
|
+
oauth2_fetch_client_and_user
|
|
26
|
+
else
|
|
27
|
+
fetch_client_and_user
|
|
28
|
+
end
|
|
29
|
+
@_current_facebook_client
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# This mimics the getSession logic from the php facebook SDK
|
|
33
|
+
# https://github.com/facebook/php-sdk/blob/master/src/facebook.php#L333
|
|
34
|
+
#
|
|
35
|
+
def fetch_client_and_user
|
|
36
|
+
return if @_fb_user_fetched
|
|
37
|
+
# Try to authenticate from the signed request first
|
|
38
|
+
sig = fetch_client_and_user_from_signed_request
|
|
39
|
+
sig = fetch_client_and_user_from_cookie if @_current_facebook_client.nil? and !signed_request_from_logged_out_user?
|
|
40
|
+
|
|
41
|
+
#write the authentication params to a new cookie
|
|
42
|
+
if !@_current_facebook_client.nil?
|
|
43
|
+
#we may have generated the signature based on the params in @facebook_params, and the expiration here is different
|
|
44
|
+
|
|
45
|
+
set_fb_cookie(@_current_facebook_client.access_token, @_current_facebook_client.expiration, @_current_facebook_user.id, sig)
|
|
46
|
+
else
|
|
47
|
+
# if we do not have a client, delete the cookie
|
|
48
|
+
set_fb_cookie(nil,nil,nil,nil)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
@_fb_user_fetched = true
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def fetch_client_and_user_from_cookie
|
|
55
|
+
if (hash_data = fb_cookie_hash) and
|
|
56
|
+
fb_cookie_signature_correct?(fb_cookie_hash,Facebooker2.secret)
|
|
57
|
+
fb_create_user_and_client(hash_data["access_token"],hash_data["expires"],hash_data["uid"])
|
|
58
|
+
return fb_cookie_hash["sig"]
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def fb_create_user_and_client(token,expires,userid)
|
|
63
|
+
client = Mogli::Client.new(token,expires.to_i)
|
|
64
|
+
user = Mogli::User.new(:id=>userid)
|
|
65
|
+
fb_sign_in_user_and_client(user,client)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def fb_sign_in_user_and_client(user,client)
|
|
69
|
+
user.client = client
|
|
70
|
+
@_current_facebook_user = user
|
|
71
|
+
@_current_facebook_client = client
|
|
72
|
+
@_fb_user_fetched = true
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def fb_cookie_hash
|
|
76
|
+
return nil unless fb_cookie?
|
|
77
|
+
hash={}
|
|
78
|
+
data = fb_cookie.gsub(/"/,"")
|
|
79
|
+
data.split("&").each do |str|
|
|
80
|
+
parts = str.split("=")
|
|
81
|
+
hash[parts.first] = parts.last
|
|
82
|
+
end
|
|
83
|
+
hash
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def fb_cookie?
|
|
87
|
+
!fb_cookie.blank?
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def fb_cookie
|
|
91
|
+
cookies[fb_cookie_name]
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def fb_cookie_name
|
|
95
|
+
return "#{Facebooker2.cookie_prefix + Facebooker2.app_id.to_s}"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# check if the expected signature matches the one from facebook
|
|
99
|
+
def fb_cookie_signature_correct?(hash,secret)
|
|
100
|
+
generate_signature(hash,secret) == hash["sig"]
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# If the signed request is valid but contains no oauth token,
|
|
104
|
+
# the user is either logged out from Facebook or has not authorized the app
|
|
105
|
+
def signed_request_from_logged_out_user?
|
|
106
|
+
!facebook_params.empty? && facebook_params[:oauth_token].nil?
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# compute the md5 sig based on access_token,expires,uid, and the app secret
|
|
110
|
+
def generate_signature(hash,secret)
|
|
111
|
+
sorted_keys = hash.keys.reject {|k| k=="sig"}.sort
|
|
112
|
+
test_string = ""
|
|
113
|
+
sorted_keys.each do |key|
|
|
114
|
+
test_string += "#{key}=#{hash[key]}"
|
|
115
|
+
end
|
|
116
|
+
test_string += secret
|
|
117
|
+
sig = Digest::MD5.hexdigest(test_string)
|
|
118
|
+
return sig
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def fb_signed_request_json(encoded)
|
|
122
|
+
chars_to_add = 4-(encoded.size % 4)
|
|
123
|
+
encoded += ("=" * chars_to_add)
|
|
124
|
+
Base64.decode64(encoded)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def facebook_params
|
|
128
|
+
@facebook_param ||= fb_load_facebook_params
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def fb_load_facebook_params
|
|
132
|
+
return {} if params[:signed_request].blank?
|
|
133
|
+
sig,encoded_json = params[:signed_request].split(".")
|
|
134
|
+
return {} unless fb_signed_request_sig_valid?(sig,encoded_json)
|
|
135
|
+
ActiveSupport::JSON.decode(fb_signed_request_json(encoded_json)).with_indifferent_access
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def fb_signed_request_sig_valid?(sig,encoded)
|
|
139
|
+
base64 = Base64.encode64(HMAC::SHA256.digest(Facebooker2.secret,encoded))
|
|
140
|
+
#now make the url changes that facebook makes
|
|
141
|
+
url_escaped_base64 = base64.gsub(/=*\n?$/,"").tr("+/","-_")
|
|
142
|
+
sig == url_escaped_base64
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def fetch_client_and_user_from_signed_request
|
|
146
|
+
if facebook_params[:oauth_token]
|
|
147
|
+
fb_create_user_and_client(facebook_params[:oauth_token],facebook_params[:expires],facebook_params[:user_id])
|
|
148
|
+
|
|
149
|
+
if @_current_facebook_client
|
|
150
|
+
#compute a signature so we can store it in the cookie
|
|
151
|
+
sig_hash = Hash["uid"=>facebook_params[:user_id],"access_token"=>facebook_params[:oauth_token],"expires"=>facebook_params[:expires]]
|
|
152
|
+
return generate_signature(sig_hash, Facebooker2.secret)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
# /**
|
|
159
|
+
# This method was shamelessly stolen from the php facebook SDK:
|
|
160
|
+
# https://github.com/facebook/php-sdk/blob/master/src/facebook.php
|
|
161
|
+
#
|
|
162
|
+
# Set a JS Cookie based on the _passed in_ session. It does not use the
|
|
163
|
+
# currently stored session -- you need to explicitly pass it in.
|
|
164
|
+
#
|
|
165
|
+
# If a nil access_token is passed in this method will actually delete the fbs_ cookie
|
|
166
|
+
#
|
|
167
|
+
# */
|
|
168
|
+
def set_fb_cookie(access_token,expires,uid,sig)
|
|
169
|
+
|
|
170
|
+
#default values for the cookie
|
|
171
|
+
value = 'deleted'
|
|
172
|
+
expires = Time.now.utc - 3600 unless expires != nil
|
|
173
|
+
|
|
174
|
+
# If the expires value is set to some large value in the future, then the 'offline access' permission has been
|
|
175
|
+
# granted. In the Facebook JS SDK, this causes a value of 0 to be set for the expires parameter. This value
|
|
176
|
+
# needs to be correct otherwise the request signing fails, so if the expires parameter retrieved from the graph
|
|
177
|
+
# api is more than a year in the future, then we set expires to 0 to match the JS SDK.
|
|
178
|
+
expires = 0 if expires > Time.now + 1.year
|
|
179
|
+
|
|
180
|
+
if access_token
|
|
181
|
+
# Retrieve the existing cookie data
|
|
182
|
+
data = fb_cookie_hash || {}
|
|
183
|
+
# Remove the deleted value if this has previously been set, as we don't want to include it as part of the
|
|
184
|
+
# request signing parameters
|
|
185
|
+
data.delete('deleted') if data.key?('deleted')
|
|
186
|
+
# Keep existing cookie data that could have been set by FB JS SDK
|
|
187
|
+
data.merge!('access_token' => access_token, 'uid' => uid, 'sig' => sig, 'expires' => expires.to_i.to_s)
|
|
188
|
+
# Create string to store in cookie
|
|
189
|
+
value = '"'
|
|
190
|
+
data.each do |k,v|
|
|
191
|
+
value += "#{k.to_s}=#{v.to_s}&"
|
|
192
|
+
end
|
|
193
|
+
value.chop!
|
|
194
|
+
value+='"'
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# if an existing cookie is not set, we dont need to delete it
|
|
198
|
+
if (value == 'deleted' && (!fb_cookie? || fb_cookie == "" ))
|
|
199
|
+
return;
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
#My browser doesn't seem to save the cookie if I set expires
|
|
203
|
+
cookies[fb_cookie_name] = { :value=>value }#, :expires=>expires}
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
# For canvas apps, You need to set the p3p header in order to get IE 6/7 to accept the third-party cookie
|
|
208
|
+
# For details http://www.softwareprojects.com/resources/programming/t-how-to-get-internet-explorer-to-use-cookies-inside-1612.html
|
|
209
|
+
def set_p3p_header_for_third_party_cookies
|
|
210
|
+
response.headers['P3P'] = 'CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"'
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
### Oauth2
|
|
214
|
+
def oauth2_current_facebook_user
|
|
215
|
+
oauth2_fetch_client_and_user
|
|
216
|
+
@_current_facebook_user
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def oauth2_fetch_client_and_user
|
|
220
|
+
return if @_fb_user_fetched
|
|
221
|
+
sig = oauth2_fetch_client_and_user_from_cookie if @_current_facebook_client.nil?
|
|
222
|
+
@_fb_user_fetched = true
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def oauth2_fetch_client_and_user_from_cookie
|
|
226
|
+
return unless fb_cookie?
|
|
227
|
+
sig,payload = fb_cookie.split('.')
|
|
228
|
+
return unless fb_signed_request_sig_valid?(sig, payload)
|
|
229
|
+
data = JSON.parse(base64_url_decode(payload))
|
|
230
|
+
authenticator = Mogli::Authenticator.new(Facebooker2.app_id, Facebooker2.secret, nil)
|
|
231
|
+
client = Mogli::Client.create_from_code_and_authenticator(data["code"], authenticator)
|
|
232
|
+
user = Mogli::User.new(:id=>data["user_id"])
|
|
233
|
+
fb_sign_in_user_and_client(user, client)
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def base64_url_decode(encoded)
|
|
238
|
+
chars_to_add = 4-(encoded.size % 4)
|
|
239
|
+
encoded += ("=" * chars_to_add)
|
|
240
|
+
Base64.decode64(encoded.tr("-_", "+/"))
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
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
|
+
# Check if we got the update_page method (pre-Rails 3.1)
|
|
21
|
+
if respond_to? 'update_page'
|
|
22
|
+
js = update_page do |page|
|
|
23
|
+
page.redirect_to url
|
|
24
|
+
end
|
|
25
|
+
# Else use plain js
|
|
26
|
+
else
|
|
27
|
+
js = "window.location.href = '#{url}'"
|
|
28
|
+
end
|
|
29
|
+
text = options.delete(:text)
|
|
30
|
+
|
|
31
|
+
#rails 3 only escapes non-html_safe strings, so get the raw string instead of the SafeBuffer
|
|
32
|
+
content_tag("fb:login-button",text,options.merge(:onlogin=>js.to_str))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def fb_login(options = {},&proc)
|
|
36
|
+
js = capture(&proc)
|
|
37
|
+
text = options.delete(:text)
|
|
38
|
+
concat(content_tag("fb:login-button",text,options.merge(:onlogin=>js.to_str)))
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
#
|
|
42
|
+
# Logs the user out of facebook and redirects to the given URL
|
|
43
|
+
# args are passed to the call to link_to_function
|
|
44
|
+
def fb_logout_link(text,url,*args)
|
|
45
|
+
function= "FB.logout(function() {window.location.href = '#{url}';})"
|
|
46
|
+
link_to_function text, function.to_str, *args
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def fb_server_fbml(style=nil, width=nil, &proc)
|
|
50
|
+
style_string=" style=\"#{style}\"" if style
|
|
51
|
+
width_string=" width=\"#{width}\"" if width
|
|
52
|
+
content = capture(&proc)
|
|
53
|
+
output = "<fb:serverFbml#{style_string}#{width_string}><script type='text/fbml'><fb:fbml>#{content}</fb:fbml></script></fb:serverFbml>"
|
|
54
|
+
output = output.respond_to?(:html_safe) ? output.html_safe : output
|
|
55
|
+
concat(output)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Facebooker2
|
|
2
|
+
module Rails
|
|
3
|
+
module Helpers
|
|
4
|
+
module Javascript
|
|
5
|
+
|
|
6
|
+
def fb_html_safe(str)
|
|
7
|
+
if str.respond_to?(:html_safe)
|
|
8
|
+
str.html_safe
|
|
9
|
+
else
|
|
10
|
+
str
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def fb_connect_async_js(app_id=Facebooker2.app_id,options={},&proc)
|
|
15
|
+
opts = Hash.new.merge!(options)
|
|
16
|
+
cookie = opts[:cookie].nil? ? true : opts[:cookie]
|
|
17
|
+
status = opts[:status].nil? ? true : opts[:status]
|
|
18
|
+
xfbml = opts[:xfbml].nil? ? true : opts[:xfbml]
|
|
19
|
+
channel_url = opts[:channel_url]
|
|
20
|
+
lang = opts[:locale] || 'en_US'
|
|
21
|
+
extra_js = capture(&proc) if block_given?
|
|
22
|
+
js = <<-JAVASCRIPT
|
|
23
|
+
<div id="fb-root"></div>
|
|
24
|
+
<script>
|
|
25
|
+
window.fbAsyncInit = function() {
|
|
26
|
+
FB.init({
|
|
27
|
+
appId : '#{app_id}',
|
|
28
|
+
status : #{status}, // check login status
|
|
29
|
+
cookie : #{cookie}, // enable cookies to allow the server to access the session
|
|
30
|
+
#{"channelUrl : '#{channel_url}', // add channelURL to avoid IE redirect problems" unless channel_url.blank?}
|
|
31
|
+
oauth : true,
|
|
32
|
+
xfbml : #{xfbml} // parse XFBML
|
|
33
|
+
});
|
|
34
|
+
#{extra_js}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
(function() {
|
|
38
|
+
var e = document.createElement('script'); e.async = true;
|
|
39
|
+
e.src = document.location.protocol + '//connect.facebook.net/#{lang}/all.js';
|
|
40
|
+
document.getElementById('fb-root').appendChild(e);
|
|
41
|
+
}());
|
|
42
|
+
</script>
|
|
43
|
+
JAVASCRIPT
|
|
44
|
+
escaped_js = fb_html_safe(js)
|
|
45
|
+
if block_given?
|
|
46
|
+
concat(escaped_js)
|
|
47
|
+
#return the empty string, since concat returns the buffer and we don't want double output
|
|
48
|
+
# from klochner
|
|
49
|
+
""
|
|
50
|
+
else
|
|
51
|
+
escaped_js
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
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,55 @@
|
|
|
1
|
+
# Facebooker2
|
|
2
|
+
require "mogli"
|
|
3
|
+
module Facebooker2
|
|
4
|
+
|
|
5
|
+
@oauth2 = true
|
|
6
|
+
@cookie_prefix = 'fbsr_'
|
|
7
|
+
|
|
8
|
+
class NotConfigured < Exception; end
|
|
9
|
+
class << self
|
|
10
|
+
attr_accessor :api_key, :secret, :app_id, :cookie_prefix, :oauth2
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.secret
|
|
14
|
+
@secret || raise_unconfigured_exception
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.app_id
|
|
18
|
+
@app_id || raise_unconfigured_exception
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.raise_unconfigured_exception
|
|
22
|
+
raise NotConfigured.new("No configuration provided for Facebooker2. Either set the app_id and secret or call Facebooker2.load_facebooker_yaml in an initializer")
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.configuration=(hash)
|
|
26
|
+
self.api_key = hash[:api_key]
|
|
27
|
+
self.secret = hash[:secret]
|
|
28
|
+
self.app_id = hash[:app_id]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.load_facebooker_yaml
|
|
32
|
+
config = (YAML.load(ERB.new(File.read(File.join(::Rails.root,"config","facebooker.yml"))).result)[::Rails.env])
|
|
33
|
+
raise NotConfigured.new("Unable to load configuration for #{::Rails.env} from facebooker.yml. Is it set up?") if config.nil?
|
|
34
|
+
self.configuration = config.with_indifferent_access
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.cast_to_facebook_id(object)
|
|
38
|
+
if object.kind_of?(Mogli::Profile)
|
|
39
|
+
object.id
|
|
40
|
+
elsif object.respond_to?(:facebook_id)
|
|
41
|
+
object.facebook_id
|
|
42
|
+
else
|
|
43
|
+
object
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
require "facebooker2/rails/controller"
|
|
50
|
+
require "facebooker2/rails/helpers/facebook_connect"
|
|
51
|
+
require "facebooker2/rails/helpers/javascript"
|
|
52
|
+
require "facebooker2/rails/helpers/request_forms"
|
|
53
|
+
require "facebooker2/rails/helpers/user"
|
|
54
|
+
require "facebooker2/rails/helpers"
|
|
55
|
+
require "facebooker2/rack/post_canvas"
|
metadata
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: thorsson_facebooker2
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.17
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Mike Mangino Ivan Turkovic
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2013-01-28 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: mogli
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
18
|
+
requirements:
|
|
19
|
+
- - ! '>='
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: 0.0.33
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ! '>='
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: 0.0.33
|
|
30
|
+
- !ruby/object:Gem::Dependency
|
|
31
|
+
name: ruby-hmac
|
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
|
33
|
+
none: false
|
|
34
|
+
requirements:
|
|
35
|
+
- - ! '>='
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: '0'
|
|
38
|
+
type: :runtime
|
|
39
|
+
prerelease: false
|
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
41
|
+
none: false
|
|
42
|
+
requirements:
|
|
43
|
+
- - ! '>='
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '0'
|
|
46
|
+
- !ruby/object:Gem::Dependency
|
|
47
|
+
name: rake
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
49
|
+
none: false
|
|
50
|
+
requirements:
|
|
51
|
+
- - ~>
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 0.8.7
|
|
54
|
+
type: :development
|
|
55
|
+
prerelease: false
|
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
57
|
+
none: false
|
|
58
|
+
requirements:
|
|
59
|
+
- - ~>
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 0.8.7
|
|
62
|
+
- !ruby/object:Gem::Dependency
|
|
63
|
+
name: rspec
|
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
|
65
|
+
none: false
|
|
66
|
+
requirements:
|
|
67
|
+
- - ~>
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: 1.3.1
|
|
70
|
+
type: :development
|
|
71
|
+
prerelease: false
|
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
73
|
+
none: false
|
|
74
|
+
requirements:
|
|
75
|
+
- - ~>
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: 1.3.1
|
|
78
|
+
- !ruby/object:Gem::Dependency
|
|
79
|
+
name: rspec-rails
|
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
|
81
|
+
none: false
|
|
82
|
+
requirements:
|
|
83
|
+
- - ~>
|
|
84
|
+
- !ruby/object:Gem::Version
|
|
85
|
+
version: 1.3.1
|
|
86
|
+
type: :development
|
|
87
|
+
prerelease: false
|
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
89
|
+
none: false
|
|
90
|
+
requirements:
|
|
91
|
+
- - ~>
|
|
92
|
+
- !ruby/object:Gem::Version
|
|
93
|
+
version: 1.3.1
|
|
94
|
+
- !ruby/object:Gem::Dependency
|
|
95
|
+
name: rails
|
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
|
97
|
+
none: false
|
|
98
|
+
requirements:
|
|
99
|
+
- - ~>
|
|
100
|
+
- !ruby/object:Gem::Version
|
|
101
|
+
version: 2.3.10
|
|
102
|
+
type: :development
|
|
103
|
+
prerelease: false
|
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
105
|
+
none: false
|
|
106
|
+
requirements:
|
|
107
|
+
- - ~>
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: 2.3.10
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: json
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
none: false
|
|
114
|
+
requirements:
|
|
115
|
+
- - ~>
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: 1.4.0
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
none: false
|
|
122
|
+
requirements:
|
|
123
|
+
- - ~>
|
|
124
|
+
- !ruby/object:Gem::Version
|
|
125
|
+
version: 1.4.0
|
|
126
|
+
description: Facebook Connect integration library for ruby and rails
|
|
127
|
+
email: mmangino@elevatedrails.com
|
|
128
|
+
executables: []
|
|
129
|
+
extensions: []
|
|
130
|
+
extra_rdoc_files: []
|
|
131
|
+
files:
|
|
132
|
+
- lib/facebooker2/rack/post_canvas.rb
|
|
133
|
+
- lib/facebooker2/rails/controller.rb
|
|
134
|
+
- lib/facebooker2/rails/helpers/facebook_connect.rb
|
|
135
|
+
- lib/facebooker2/rails/helpers/javascript.rb
|
|
136
|
+
- lib/facebooker2/rails/helpers/request_forms.rb
|
|
137
|
+
- lib/facebooker2/rails/helpers/user.rb
|
|
138
|
+
- lib/facebooker2/rails/helpers.rb
|
|
139
|
+
- lib/facebooker2/rails.rb
|
|
140
|
+
- lib/facebooker2.rb
|
|
141
|
+
homepage: http://developers.facebook.com/docs/api
|
|
142
|
+
licenses: []
|
|
143
|
+
post_install_message:
|
|
144
|
+
rdoc_options: []
|
|
145
|
+
require_paths:
|
|
146
|
+
- lib
|
|
147
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
148
|
+
none: false
|
|
149
|
+
requirements:
|
|
150
|
+
- - ! '>='
|
|
151
|
+
- !ruby/object:Gem::Version
|
|
152
|
+
version: '0'
|
|
153
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
|
+
none: false
|
|
155
|
+
requirements:
|
|
156
|
+
- - ! '>='
|
|
157
|
+
- !ruby/object:Gem::Version
|
|
158
|
+
version: '0'
|
|
159
|
+
requirements: []
|
|
160
|
+
rubyforge_project:
|
|
161
|
+
rubygems_version: 1.8.25
|
|
162
|
+
signing_key:
|
|
163
|
+
specification_version: 3
|
|
164
|
+
summary: Facebook Connect integration library for ruby and rails
|
|
165
|
+
test_files: []
|