taweili-facebooker 1.0.37
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/.autotest +15 -0
- data/CHANGELOG.rdoc +24 -0
- data/COPYING.rdoc +19 -0
- data/Manifest.txt +133 -0
- data/README.rdoc +104 -0
- data/Rakefile +85 -0
- data/TODO.rdoc +4 -0
- data/examples/desktop_login.rb +14 -0
- data/facebooker.gemspec +38 -0
- data/generators/facebook/facebook_generator.rb +14 -0
- data/generators/facebook/templates/config/facebooker.yml +49 -0
- data/generators/facebook/templates/public/javascripts/facebooker.js +83 -0
- data/generators/facebook_controller/USAGE +33 -0
- data/generators/facebook_controller/facebook_controller_generator.rb +40 -0
- data/generators/facebook_controller/templates/controller.rb +7 -0
- data/generators/facebook_controller/templates/functional_test.rb +11 -0
- data/generators/facebook_controller/templates/helper.rb +2 -0
- data/generators/facebook_controller/templates/view.fbml.erb +2 -0
- data/generators/facebook_controller/templates/view.html.erb +2 -0
- data/generators/facebook_publisher/facebook_publisher_generator.rb +14 -0
- data/generators/facebook_publisher/templates/create_facebook_templates.rb +15 -0
- data/generators/facebook_publisher/templates/publisher.rb +3 -0
- data/generators/facebook_scaffold/USAGE +27 -0
- data/generators/facebook_scaffold/facebook_scaffold_generator.rb +118 -0
- data/generators/facebook_scaffold/templates/controller.rb +93 -0
- data/generators/facebook_scaffold/templates/facebook_style.css +2579 -0
- data/generators/facebook_scaffold/templates/functional_test.rb +89 -0
- data/generators/facebook_scaffold/templates/helper.rb +2 -0
- data/generators/facebook_scaffold/templates/layout.fbml.erb +6 -0
- data/generators/facebook_scaffold/templates/layout.html.erb +17 -0
- data/generators/facebook_scaffold/templates/style.css +74 -0
- data/generators/facebook_scaffold/templates/view_edit.fbml.erb +13 -0
- data/generators/facebook_scaffold/templates/view_edit.html.erb +18 -0
- data/generators/facebook_scaffold/templates/view_index.fbml.erb +24 -0
- data/generators/facebook_scaffold/templates/view_index.html.erb +24 -0
- data/generators/facebook_scaffold/templates/view_new.fbml.erb +12 -0
- data/generators/facebook_scaffold/templates/view_new.html.erb +17 -0
- data/generators/facebook_scaffold/templates/view_show.fbml.erb +10 -0
- data/generators/facebook_scaffold/templates/view_show.html.erb +10 -0
- data/generators/publisher/publisher_generator.rb +14 -0
- data/generators/xd_receiver/templates/xd_receiver.html +10 -0
- data/generators/xd_receiver/xd_receiver_generator.rb +10 -0
- data/init.rb +25 -0
- data/install.rb +12 -0
- data/lib/facebooker/adapters/adapter_base.rb +91 -0
- data/lib/facebooker/adapters/bebo_adapter.rb +77 -0
- data/lib/facebooker/adapters/facebook_adapter.rb +52 -0
- data/lib/facebooker/admin.rb +42 -0
- data/lib/facebooker/batch_request.rb +45 -0
- data/lib/facebooker/data.rb +57 -0
- data/lib/facebooker/feed.rb +78 -0
- data/lib/facebooker/logging.rb +44 -0
- data/lib/facebooker/mobile.rb +20 -0
- data/lib/facebooker/mock/service.rb +50 -0
- data/lib/facebooker/mock/session.rb +18 -0
- data/lib/facebooker/model.rb +139 -0
- data/lib/facebooker/models/affiliation.rb +10 -0
- data/lib/facebooker/models/album.rb +11 -0
- data/lib/facebooker/models/applicationproperties.rb +39 -0
- data/lib/facebooker/models/applicationrestrictions.rb +10 -0
- data/lib/facebooker/models/cookie.rb +10 -0
- data/lib/facebooker/models/education_info.rb +11 -0
- data/lib/facebooker/models/event.rb +28 -0
- data/lib/facebooker/models/friend_list.rb +16 -0
- data/lib/facebooker/models/group.rb +36 -0
- data/lib/facebooker/models/info_item.rb +10 -0
- data/lib/facebooker/models/info_section.rb +10 -0
- data/lib/facebooker/models/location.rb +8 -0
- data/lib/facebooker/models/notifications.rb +17 -0
- data/lib/facebooker/models/page.rb +28 -0
- data/lib/facebooker/models/photo.rb +19 -0
- data/lib/facebooker/models/tag.rb +12 -0
- data/lib/facebooker/models/user.rb +497 -0
- data/lib/facebooker/models/video.rb +9 -0
- data/lib/facebooker/models/work_info.rb +10 -0
- data/lib/facebooker/parser.rb +650 -0
- data/lib/facebooker/rails/backwards_compatible_param_checks.rb +31 -0
- data/lib/facebooker/rails/controller.rb +337 -0
- data/lib/facebooker/rails/cucumber/world.rb +46 -0
- data/lib/facebooker/rails/cucumber.rb +28 -0
- data/lib/facebooker/rails/extensions/action_controller.rb +48 -0
- data/lib/facebooker/rails/extensions/rack_setup.rb +6 -0
- data/lib/facebooker/rails/extensions/routing.rb +15 -0
- data/lib/facebooker/rails/facebook_form_builder.rb +112 -0
- data/lib/facebooker/rails/facebook_pretty_errors.rb +22 -0
- data/lib/facebooker/rails/facebook_request_fix.rb +30 -0
- data/lib/facebooker/rails/facebook_request_fix_2-3.rb +31 -0
- data/lib/facebooker/rails/facebook_session_handling.rb +68 -0
- data/lib/facebooker/rails/facebook_url_helper.rb +192 -0
- data/lib/facebooker/rails/facebook_url_rewriting.rb +60 -0
- data/lib/facebooker/rails/helpers/fb_connect.rb +118 -0
- data/lib/facebooker/rails/helpers.rb +780 -0
- data/lib/facebooker/rails/integration_session.rb +38 -0
- data/lib/facebooker/rails/profile_publisher_extensions.rb +42 -0
- data/lib/facebooker/rails/publisher.rb +554 -0
- data/lib/facebooker/rails/routing.rb +49 -0
- data/lib/facebooker/rails/test_helpers.rb +68 -0
- data/lib/facebooker/rails/utilities.rb +22 -0
- data/lib/facebooker/server_cache.rb +24 -0
- data/lib/facebooker/service.rb +102 -0
- data/lib/facebooker/session.rb +606 -0
- data/lib/facebooker/version.rb +9 -0
- data/lib/facebooker.rb +180 -0
- data/lib/net/http_multipart_post.rb +123 -0
- data/lib/rack/facebook.rb +77 -0
- data/lib/tasks/facebooker.rake +18 -0
- data/lib/tasks/tunnel.rake +46 -0
- data/rails/init.rb +1 -0
- data/setup.rb +1585 -0
- data/templates/layout.erb +24 -0
- data/test/facebooker/adapters_test.rb +96 -0
- data/test/facebooker/admin_test.rb +102 -0
- data/test/facebooker/batch_request_test.rb +83 -0
- data/test/facebooker/data_test.rb +86 -0
- data/test/facebooker/logging_test.rb +43 -0
- data/test/facebooker/mobile_test.rb +45 -0
- data/test/facebooker/model_test.rb +133 -0
- data/test/facebooker/models/event_test.rb +15 -0
- data/test/facebooker/models/photo_test.rb +16 -0
- data/test/facebooker/models/user_test.rb +343 -0
- data/test/facebooker/rails/facebook_request_fix_2-3_test.rb +24 -0
- data/test/facebooker/rails/facebook_url_rewriting_test.rb +39 -0
- data/test/facebooker/rails/publisher_test.rb +481 -0
- data/test/facebooker/rails_integration_test.rb +1398 -0
- data/test/facebooker/server_cache_test.rb +44 -0
- data/test/facebooker/session_test.rb +614 -0
- data/test/facebooker_test.rb +951 -0
- data/test/fixtures/multipart_post_body_with_only_parameters.txt +33 -0
- data/test/fixtures/multipart_post_body_with_single_file.txt +38 -0
- data/test/fixtures/multipart_post_body_with_single_file_that_has_nil_key.txt +38 -0
- data/test/net/http_multipart_post_test.rb +52 -0
- data/test/rack/facebook_test.rb +61 -0
- data/test/rails_test_helper.rb +27 -0
- data/test/test_helper.rb +74 -0
- metadata +232 -0
@@ -0,0 +1,337 @@
|
|
1
|
+
require 'facebooker'
|
2
|
+
require 'facebooker/rails/profile_publisher_extensions'
|
3
|
+
module Facebooker
|
4
|
+
module Rails
|
5
|
+
module Controller
|
6
|
+
include Facebooker::Rails::BackwardsCompatibleParamChecks
|
7
|
+
include Facebooker::Rails::ProfilePublisherExtensions
|
8
|
+
def self.included(controller)
|
9
|
+
controller.extend(ClassMethods)
|
10
|
+
controller.before_filter :set_adapter
|
11
|
+
controller.before_filter :set_facebook_request_format
|
12
|
+
controller.helper_attr :facebook_session_parameters
|
13
|
+
controller.helper_method :request_comes_from_facebook?
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize *args
|
17
|
+
@facebook_session = nil
|
18
|
+
@installation_required = nil
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def facebook_session
|
23
|
+
@facebook_session
|
24
|
+
end
|
25
|
+
|
26
|
+
def facebook_session_parameters
|
27
|
+
{:fb_sig_session_key=>params[:fb_sig_session_key]}
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_facebook_session
|
31
|
+
secure_with_facebook_params! || secure_with_cookies! || secure_with_token!
|
32
|
+
end
|
33
|
+
|
34
|
+
def set_facebook_session
|
35
|
+
# first, see if we already have a session
|
36
|
+
session_set = session_already_secured?
|
37
|
+
# if not, see if we can load it from the environment
|
38
|
+
unless session_set
|
39
|
+
session_set = create_facebook_session
|
40
|
+
session[:facebook_session] = @facebook_session if session_set
|
41
|
+
end
|
42
|
+
if session_set
|
43
|
+
capture_facebook_friends_if_available!
|
44
|
+
Session.current = facebook_session
|
45
|
+
end
|
46
|
+
return session_set
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def facebook_params
|
51
|
+
@facebook_params ||= verified_facebook_params
|
52
|
+
end
|
53
|
+
|
54
|
+
# Redirects the top window to the given url if the content is in an iframe, otherwise performs
|
55
|
+
# a normal redirect_to call.
|
56
|
+
def top_redirect_to(*args)
|
57
|
+
if request_is_facebook_iframe?
|
58
|
+
@redirect_url = url_for(*args)
|
59
|
+
render :layout => false, :inline => <<-HTML
|
60
|
+
<html><head>
|
61
|
+
<script type="text/javascript">
|
62
|
+
window.top.location.href = <%= @redirect_url.to_json -%>;
|
63
|
+
</script>
|
64
|
+
<noscript>
|
65
|
+
<meta http-equiv="refresh" content="0;url=<%=h @redirect_url %>" />
|
66
|
+
<meta http-equiv="window-target" content="_top" />
|
67
|
+
</noscript>
|
68
|
+
</head></html>
|
69
|
+
HTML
|
70
|
+
else
|
71
|
+
redirect_to(*args)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def redirect_to(*args)
|
76
|
+
if request_is_for_a_facebook_canvas? and !request_is_facebook_tab?
|
77
|
+
render :text => fbml_redirect_tag(*args)
|
78
|
+
else
|
79
|
+
super
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def session_already_secured?
|
86
|
+
(@facebook_session = session[:facebook_session]) && session[:facebook_session].secured? if valid_session_key_in_session?
|
87
|
+
end
|
88
|
+
|
89
|
+
def user_has_deauthorized_application?
|
90
|
+
# if we're inside the facebook session and there is no session key,
|
91
|
+
# that means the user revoked our access
|
92
|
+
# we don't want to keep using the old expired key from the cookie.
|
93
|
+
request_comes_from_facebook? and params[:fb_sig_session_key].blank?
|
94
|
+
end
|
95
|
+
|
96
|
+
def clear_facebook_session_information
|
97
|
+
session[:facebook_session] = nil
|
98
|
+
@facebook_session=nil
|
99
|
+
end
|
100
|
+
|
101
|
+
def valid_session_key_in_session?
|
102
|
+
#before we access the facebook_params, make sure we have the parameters
|
103
|
+
#otherwise we will blow up trying to access the secure parameters
|
104
|
+
if user_has_deauthorized_application?
|
105
|
+
clear_facebook_session_information
|
106
|
+
false
|
107
|
+
else
|
108
|
+
!session[:facebook_session].blank? && (params[:fb_sig_session_key].blank? || session[:facebook_session].session_key == facebook_params[:session_key])
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def clear_fb_cookies!
|
113
|
+
domain_cookie_tag = "base_domain_#{Facebooker.api_key}"
|
114
|
+
cookie_domain = ".#{cookies[domain_cookie_tag]}" if cookies[domain_cookie_tag]
|
115
|
+
fb_cookie_names.each {|name| cookies.delete(name, :domain=>cookie_domain)}
|
116
|
+
cookies.delete Facebooker.api_key
|
117
|
+
end
|
118
|
+
|
119
|
+
def fb_cookie_prefix
|
120
|
+
Facebooker.api_key+"_"
|
121
|
+
end
|
122
|
+
|
123
|
+
def fb_cookie_names
|
124
|
+
fb_cookie_names = cookies.keys.select{|k| k.starts_with?(fb_cookie_prefix)}
|
125
|
+
end
|
126
|
+
|
127
|
+
def secure_with_cookies!
|
128
|
+
parsed = {}
|
129
|
+
|
130
|
+
fb_cookie_names.each { |key| parsed[key[fb_cookie_prefix.size,key.size]] = cookies[key] }
|
131
|
+
|
132
|
+
#returning gracefully if the cookies aren't set or have expired
|
133
|
+
return unless parsed['session_key'] && parsed['user'] && parsed['expires'] && parsed['ss']
|
134
|
+
return unless Time.at(parsed['expires'].to_s.to_f) > Time.now || (parsed['expires'] == "0")
|
135
|
+
#if we have the unexpired cookies, we'll throw an exception if the sig doesn't verify
|
136
|
+
verify_signature(parsed,cookies[Facebooker.api_key])
|
137
|
+
|
138
|
+
@facebook_session = new_facebook_session
|
139
|
+
@facebook_session.secure_with!(parsed['session_key'],parsed['user'],parsed['expires'],parsed['ss'])
|
140
|
+
@facebook_session
|
141
|
+
end
|
142
|
+
|
143
|
+
def secure_with_token!
|
144
|
+
if params['auth_token']
|
145
|
+
@facebook_session = new_facebook_session
|
146
|
+
@facebook_session.auth_token = params['auth_token']
|
147
|
+
@facebook_session.secure!
|
148
|
+
@facebook_session
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def secure_with_facebook_params!
|
153
|
+
return unless request_comes_from_facebook?
|
154
|
+
|
155
|
+
if ['user', 'session_key'].all? {|element| facebook_params[element]}
|
156
|
+
@facebook_session = new_facebook_session
|
157
|
+
@facebook_session.secure_with!(facebook_params['session_key'], facebook_params['user'], facebook_params['expires'])
|
158
|
+
@facebook_session
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
#override to specify where the user should be sent after logging in
|
163
|
+
def after_facebook_login_url
|
164
|
+
nil
|
165
|
+
end
|
166
|
+
|
167
|
+
def create_new_facebook_session_and_redirect!
|
168
|
+
session[:facebook_session] = new_facebook_session
|
169
|
+
url_params = after_facebook_login_url.nil? ? {} : {:next=>after_facebook_login_url}
|
170
|
+
top_redirect_to session[:facebook_session].login_url(url_params) unless @installation_required
|
171
|
+
false
|
172
|
+
end
|
173
|
+
|
174
|
+
def new_facebook_session
|
175
|
+
Facebooker::Session.create(Facebooker.api_key, Facebooker.secret_key)
|
176
|
+
end
|
177
|
+
|
178
|
+
def capture_facebook_friends_if_available!
|
179
|
+
return unless request_comes_from_facebook?
|
180
|
+
if friends = facebook_params['friends']
|
181
|
+
facebook_session.user.friends = friends.map do |friend_uid|
|
182
|
+
User.new(friend_uid, facebook_session)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def blank?(value)
|
188
|
+
(value == '0' || value.nil? || value == '')
|
189
|
+
end
|
190
|
+
|
191
|
+
def verified_facebook_params
|
192
|
+
facebook_sig_params = params.inject({}) do |collection, pair|
|
193
|
+
collection[pair.first.sub(/^fb_sig_/, '')] = pair.last if pair.first[0,7] == 'fb_sig_'
|
194
|
+
collection
|
195
|
+
end
|
196
|
+
verify_signature(facebook_sig_params,params['fb_sig'])
|
197
|
+
|
198
|
+
facebook_sig_params.inject(HashWithIndifferentAccess.new) do |collection, pair|
|
199
|
+
collection[pair.first] = facebook_parameter_conversions[pair.first].call(pair.last)
|
200
|
+
collection
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def earliest_valid_session
|
205
|
+
48.hours.ago
|
206
|
+
end
|
207
|
+
|
208
|
+
def verify_signature(facebook_sig_params,expected_signature)
|
209
|
+
# Don't verify the signature if rack has already done so.
|
210
|
+
if ::Rails.version >= "2.3"
|
211
|
+
return if ActionController::Dispatcher.middleware.include? Rack::Facebook
|
212
|
+
end
|
213
|
+
raw_string = facebook_sig_params.map{ |*args| args.join('=') }.sort.join
|
214
|
+
actual_sig = Digest::MD5.hexdigest([raw_string, Facebooker::Session.secret_key].join)
|
215
|
+
raise Facebooker::Session::IncorrectSignature if actual_sig != expected_signature
|
216
|
+
raise Facebooker::Session::SignatureTooOld if facebook_sig_params['time'] && Time.at(facebook_sig_params['time'].to_f) < earliest_valid_session
|
217
|
+
true
|
218
|
+
end
|
219
|
+
|
220
|
+
def facebook_parameter_conversions
|
221
|
+
@facebook_parameter_conversions ||= Hash.new do |hash, key|
|
222
|
+
lambda{|value| value}
|
223
|
+
end.merge(
|
224
|
+
'time' => lambda{|value| Time.at(value.to_f)},
|
225
|
+
'in_canvas' => lambda{|value| !blank?(value)},
|
226
|
+
'added' => lambda{|value| !blank?(value)},
|
227
|
+
'expires' => lambda{|value| blank?(value) ? nil : Time.at(value.to_f)},
|
228
|
+
'friends' => lambda{|value| value.split(/,/)}
|
229
|
+
)
|
230
|
+
end
|
231
|
+
|
232
|
+
def fbml_redirect_tag(url)
|
233
|
+
"<fb:redirect url=\"#{url_for(url)}\" />"
|
234
|
+
end
|
235
|
+
|
236
|
+
def request_comes_from_facebook?
|
237
|
+
request_is_for_a_facebook_canvas? || request_is_facebook_ajax? || request_is_fb_ping?
|
238
|
+
end
|
239
|
+
|
240
|
+
def request_is_fb_ping?
|
241
|
+
!params['fb_sig'].blank?
|
242
|
+
end
|
243
|
+
|
244
|
+
def request_is_for_a_facebook_canvas?
|
245
|
+
!params['fb_sig_in_canvas'].blank?
|
246
|
+
end
|
247
|
+
|
248
|
+
def request_is_facebook_tab?
|
249
|
+
!params["fb_sig_in_profile_tab"].blank?
|
250
|
+
end
|
251
|
+
|
252
|
+
def request_is_facebook_iframe?
|
253
|
+
!params["fb_sig_in_iframe"].blank?
|
254
|
+
end
|
255
|
+
|
256
|
+
def request_is_facebook_ajax?
|
257
|
+
one_or_true(params["fb_sig_is_mockajax"]) || one_or_true(params["fb_sig_is_ajax"])
|
258
|
+
end
|
259
|
+
|
260
|
+
def xml_http_request?
|
261
|
+
request_is_facebook_ajax? || super
|
262
|
+
end
|
263
|
+
|
264
|
+
def application_is_installed?
|
265
|
+
facebook_params['added']
|
266
|
+
end
|
267
|
+
|
268
|
+
def ensure_has_status_update
|
269
|
+
has_extended_permission?("status_update") || application_needs_permission("status_update")
|
270
|
+
end
|
271
|
+
def ensure_has_photo_upload
|
272
|
+
has_extended_permission?("photo_upload") || application_needs_permission("photo_upload")
|
273
|
+
end
|
274
|
+
def ensure_has_video_upload
|
275
|
+
has_extended_permission?("video_upload") || application_needs_permission("video_upload")
|
276
|
+
end
|
277
|
+
def ensure_has_create_listing
|
278
|
+
has_extended_permission?("create_listing") || application_needs_permission("create_listing")
|
279
|
+
end
|
280
|
+
|
281
|
+
def application_needs_permission(perm)
|
282
|
+
top_redirect_to(facebook_session.permission_url(perm))
|
283
|
+
end
|
284
|
+
|
285
|
+
def has_extended_permission?(perm)
|
286
|
+
params["fb_sig_ext_perms"] and params["fb_sig_ext_perms"].include?(perm)
|
287
|
+
end
|
288
|
+
|
289
|
+
def ensure_authenticated_to_facebook
|
290
|
+
set_facebook_session || create_new_facebook_session_and_redirect!
|
291
|
+
end
|
292
|
+
|
293
|
+
def ensure_application_is_installed_by_facebook_user
|
294
|
+
@installation_required = true
|
295
|
+
returning ensure_authenticated_to_facebook && application_is_installed? do |authenticated_and_installed|
|
296
|
+
application_is_not_installed_by_facebook_user unless authenticated_and_installed
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
def application_is_not_installed_by_facebook_user
|
301
|
+
url_params = after_facebook_login_url.nil? ? {} : { :next => after_facebook_login_url }
|
302
|
+
top_redirect_to session[:facebook_session].install_url(url_params)
|
303
|
+
end
|
304
|
+
|
305
|
+
def set_facebook_request_format
|
306
|
+
if request_is_facebook_ajax?
|
307
|
+
request.format = :fbjs
|
308
|
+
elsif request_comes_from_facebook? && !request_is_facebook_iframe?
|
309
|
+
request.format = :fbml
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
def set_adapter
|
314
|
+
Facebooker.load_adapter(params) if(params[:fb_sig_api_key])
|
315
|
+
end
|
316
|
+
|
317
|
+
|
318
|
+
module ClassMethods
|
319
|
+
#
|
320
|
+
# Creates a filter which reqires a user to have already authenticated to
|
321
|
+
# Facebook before executing actions. Accepts the same optional options hash which
|
322
|
+
# before_filter and after_filter accept.
|
323
|
+
def ensure_authenticated_to_facebook(options = {})
|
324
|
+
before_filter :ensure_authenticated_to_facebook, options
|
325
|
+
end
|
326
|
+
|
327
|
+
def ensure_application_is_installed_by_facebook_user(options = {})
|
328
|
+
before_filter :ensure_application_is_installed_by_facebook_user, options
|
329
|
+
end
|
330
|
+
|
331
|
+
def request_comes_from_facebook?
|
332
|
+
request_is_for_a_facebook_canvas? || request_is_facebook_ajax?
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'cucumber/rails/world'
|
2
|
+
require 'facebooker/rails/integration_session'
|
3
|
+
|
4
|
+
module Facebooker
|
5
|
+
module Rails
|
6
|
+
module Cucumber
|
7
|
+
class World < ::Cucumber::Rails::World
|
8
|
+
def open_session
|
9
|
+
session = Facebooker::Rails::IntegrationSession.new
|
10
|
+
|
11
|
+
# delegate the fixture accessors back to the test instance
|
12
|
+
extras = Module.new { attr_accessor :delegate, :test_result }
|
13
|
+
if self.class.respond_to?(:fixture_table_names)
|
14
|
+
self.class.fixture_table_names.each do |table_name|
|
15
|
+
name = table_name.tr(".", "_")
|
16
|
+
next unless respond_to?(name)
|
17
|
+
extras.__send__(:define_method, name) { |*args| delegate.send(name, *args) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# delegate add_assertion to the test case
|
22
|
+
extras.__send__(:define_method, :add_assertion) { test_result.add_assertion }
|
23
|
+
session.extend(extras)
|
24
|
+
session.delegate = self
|
25
|
+
session.test_result = @_result
|
26
|
+
|
27
|
+
yield session if block_given?
|
28
|
+
session
|
29
|
+
end
|
30
|
+
|
31
|
+
def without_canvas
|
32
|
+
in_canvas = @integration_session.canvas
|
33
|
+
@integration_session.canvas = false
|
34
|
+
yield
|
35
|
+
@integration_session.canvas = in_canvas
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
World do
|
43
|
+
w = Facebooker::Rails::Cucumber::World.new
|
44
|
+
w.reset!
|
45
|
+
w
|
46
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'facebooker/rails/cucumber/world'
|
2
|
+
require 'facebooker/mock/session'
|
3
|
+
require 'facebooker/mock/service'
|
4
|
+
|
5
|
+
Facebooker::MockService.fixture_path = File.join(RAILS_ROOT, 'features', 'support', 'facebook')
|
6
|
+
|
7
|
+
module Facebooker
|
8
|
+
class << self
|
9
|
+
# prevent Facebooker from adding canvas name as prefix to URLs
|
10
|
+
def request_for_canvas(arg)
|
11
|
+
yield
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module Rails
|
16
|
+
module Controller
|
17
|
+
# prevent Facebooker from rendering fb:redirect
|
18
|
+
def redirect_to(*args)
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
# Return the mock session
|
23
|
+
def new_facebook_session
|
24
|
+
Facebooker::MockSession.create
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module ::ActionController
|
2
|
+
class Base
|
3
|
+
def self.inherited_with_facebooker(subclass)
|
4
|
+
inherited_without_facebooker(subclass)
|
5
|
+
if subclass.to_s == "ApplicationController"
|
6
|
+
subclass.send(:include,Facebooker::Rails::Controller)
|
7
|
+
subclass.helper Facebooker::Rails::Helpers
|
8
|
+
end
|
9
|
+
end
|
10
|
+
class << self
|
11
|
+
alias_method_chain :inherited, :facebooker
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
# When making get requests, Facebook sends fb_sig parameters both in the query string
|
18
|
+
# and also in the post body. We want to ignore the query string ones because they are one
|
19
|
+
# request out of date
|
20
|
+
# We only do thise when there are POST parameters so that IFrame linkage still works
|
21
|
+
if Rails.version < '2.3'
|
22
|
+
class ActionController::AbstractRequest
|
23
|
+
def query_parameters_with_facebooker
|
24
|
+
if request_parameters.blank?
|
25
|
+
query_parameters_without_facebooker
|
26
|
+
else
|
27
|
+
(query_parameters_without_facebooker||{}).reject {|key,value| key.to_s =~ /^fb_sig/}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
alias_method_chain :query_parameters, :facebooker
|
32
|
+
end
|
33
|
+
else
|
34
|
+
class ActionController::Request
|
35
|
+
def query_parameters_with_facebooker
|
36
|
+
if request_parameters.blank?
|
37
|
+
query_parameters_without_facebooker
|
38
|
+
else
|
39
|
+
(query_parameters_without_facebooker||{}).reject {|key,value| key.to_s =~ /^fb_sig/}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
alias_method_chain :query_parameters, :facebooker
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Mime::Type.register_alias "text/html", :fbml
|
48
|
+
Mime::Type.register_alias "text/javascript", :fbjs
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class ActionController::Routing::Route
|
2
|
+
def recognition_conditions_with_facebooker
|
3
|
+
defaults = recognition_conditions_without_facebooker
|
4
|
+
defaults << " env[:canvas] == conditions[:canvas] " if conditions[:canvas]
|
5
|
+
defaults
|
6
|
+
end
|
7
|
+
alias_method_chain :recognition_conditions, :facebooker
|
8
|
+
end
|
9
|
+
|
10
|
+
# We turn off route optimization to make named routes use our code for figuring out if they should go to the session
|
11
|
+
ActionController::Base::optimise_named_routes = false
|
12
|
+
|
13
|
+
# pull :canvas=> into env in routing to allow for conditions
|
14
|
+
ActionController::Routing::RouteSet.send :include, Facebooker::Rails::Routing::RouteSetExtensions
|
15
|
+
ActionController::Routing::RouteSet::Mapper.send :include, Facebooker::Rails::Routing::MapperExtensions
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module Facebooker
|
2
|
+
module Rails
|
3
|
+
class FacebookFormBuilder < ActionView::Helpers::FormBuilder
|
4
|
+
|
5
|
+
|
6
|
+
second_param = %w(password_field file_field check_box date_select datetime_select time_select)
|
7
|
+
third_param = %w(radio_button country_select select time_zone_select)
|
8
|
+
fifth_param = %w(collection_select)
|
9
|
+
|
10
|
+
def self.create_with_offset(name,offset)
|
11
|
+
define_method name do |field,*args|
|
12
|
+
options = args[offset] || {}
|
13
|
+
build_shell(field,options) do
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
second_param.each do |name|
|
20
|
+
create_with_offset(name,0)
|
21
|
+
end
|
22
|
+
third_param.each do |name|
|
23
|
+
create_with_offset(name,1)
|
24
|
+
end
|
25
|
+
fifth_param.each do |name|
|
26
|
+
create_with_offset(name,3)
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_shell(field,options)
|
30
|
+
@template.content_tag "fb:editor-custom", :label=>label_for(field,options) do
|
31
|
+
yield
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def label_for(field,options)
|
36
|
+
options[:label] || field.to_s.humanize
|
37
|
+
end
|
38
|
+
|
39
|
+
def text(string,options={})
|
40
|
+
@template.content_tag "fb:editor-custom",string, :label=>label_for("",options)
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def text_field(method, options = {})
|
45
|
+
options[:label] ||= label_for(method,options)
|
46
|
+
add_default_name_and_id(options,method)
|
47
|
+
options["value"] ||= value_before_type_cast(object,method)
|
48
|
+
@template.content_tag("fb:editor-text","",options)
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def text_area(method, options = {})
|
53
|
+
options[:label] ||= label_for(method,options)
|
54
|
+
add_default_name_and_id(options,method)
|
55
|
+
@template.content_tag("fb:editor-textarea",value_before_type_cast(object,method),options)
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Build a text input area that uses typeahed
|
60
|
+
# options are like collection_select
|
61
|
+
def collection_typeahead(method,collection,value_method,text_method,options={})
|
62
|
+
build_shell(method,options) do
|
63
|
+
collection_typeahead_internal(method,collection,value_method,text_method,options)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def collection_typeahead_internal(method,collection,value_method,text_method,options={})
|
68
|
+
option_values = collection.map do |item|
|
69
|
+
value=item.send(value_method)
|
70
|
+
text=item.send(text_method)
|
71
|
+
@template.content_tag "fb:typeahead-option",text,:value=>value
|
72
|
+
end.join
|
73
|
+
add_default_name_and_id(options,method)
|
74
|
+
options["value"] ||= value_before_type_cast(object,method)
|
75
|
+
@template.content_tag("fb:typeahead-input",option_values,options)
|
76
|
+
end
|
77
|
+
|
78
|
+
def value_before_type_cast(object,method)
|
79
|
+
unless object.nil?
|
80
|
+
method_name = method.to_s
|
81
|
+
object.respond_to?(method_name + "_before_type_cast") ?
|
82
|
+
object.send(method_name + "_before_type_cast") :
|
83
|
+
object.send(method_name)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def multi_friend_input(options={})
|
88
|
+
build_shell(:friends,options) do
|
89
|
+
@template.content_tag("fb:multi-friend-input","",options)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def buttons(*names)
|
94
|
+
buttons=names.map do |name|
|
95
|
+
create_button(name)
|
96
|
+
end.join
|
97
|
+
|
98
|
+
@template.content_tag "fb:editor-buttonset",buttons
|
99
|
+
end
|
100
|
+
|
101
|
+
def create_button(name)
|
102
|
+
@template.content_tag("fb:editor-button","",:value=>name,:name=>"commit")
|
103
|
+
end
|
104
|
+
|
105
|
+
def add_default_name_and_id(options,method)
|
106
|
+
options[:name] ||= "#{object.class.name.underscore}[#{method}]"
|
107
|
+
options[:id] ||= "#{object.class.name.underscore}_#{method}"
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class ActionController::Base
|
2
|
+
def rescues_path_with_facebooker(template_name)
|
3
|
+
t = "#{RAILS_ROOT}/vendor/plugins/facebooker/templates/#{template_name}.erb"
|
4
|
+
if pretty_facebook_errors? && File.exist?(t)
|
5
|
+
t
|
6
|
+
else
|
7
|
+
rescues_path_without_facebooker(template_name)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
alias_method_chain :rescues_path, :facebooker
|
11
|
+
|
12
|
+
def response_code_for_rescue_with_facebooker(exception)
|
13
|
+
pretty_facebook_errors? ? 200 : response_code_for_rescue_without_facebooker(exception)
|
14
|
+
end
|
15
|
+
alias_method_chain :response_code_for_rescue, :facebooker
|
16
|
+
|
17
|
+
|
18
|
+
def pretty_facebook_errors?
|
19
|
+
Facebooker.facebooker_config['pretty_errors'] ||
|
20
|
+
(Facebooker.facebooker_config['pretty_errors'].nil? && RAILS_ENV=="development")
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module ::ActionController
|
2
|
+
class AbstractRequest
|
3
|
+
include Facebooker::Rails::BackwardsCompatibleParamChecks
|
4
|
+
|
5
|
+
def request_method_with_facebooker
|
6
|
+
if parameters[:_method].blank?
|
7
|
+
if %w{GET HEAD}.include?(parameters[:fb_sig_request_method])
|
8
|
+
parameters[:_method] = parameters[:fb_sig_request_method]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
request_method_without_facebooker
|
12
|
+
end
|
13
|
+
|
14
|
+
if new.methods.include?("request_method")
|
15
|
+
alias_method_chain :request_method, :facebooker
|
16
|
+
end
|
17
|
+
|
18
|
+
def xml_http_request_with_facebooker?
|
19
|
+
one_or_true(parameters["fb_sig_is_mockajax"]) ||
|
20
|
+
one_or_true(parameters["fb_sig_is_ajax"]) ||
|
21
|
+
xml_http_request_without_facebooker?
|
22
|
+
end
|
23
|
+
alias_method_chain :xml_http_request?, :facebooker
|
24
|
+
# we have to re-alias xhr? since it was pointing to the old method
|
25
|
+
unless defined? :xhr?
|
26
|
+
alias xhr? :xml_http_request?
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ::ActionController
|
2
|
+
|
3
|
+
class Request
|
4
|
+
|
5
|
+
include Facebooker::Rails::BackwardsCompatibleParamChecks
|
6
|
+
|
7
|
+
def request_method_with_facebooker
|
8
|
+
if parameters[:_method].blank?
|
9
|
+
if %w{GET HEAD}.include?(parameters[:fb_sig_request_method])
|
10
|
+
parameters[:_method] = parameters[:fb_sig_request_method]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
request_method_without_facebooker
|
14
|
+
end
|
15
|
+
|
16
|
+
if new({}).methods.include?("request_method")
|
17
|
+
alias_method_chain :request_method, :facebooker
|
18
|
+
end
|
19
|
+
|
20
|
+
def xml_http_request_with_facebooker?
|
21
|
+
one_or_true(parameters["fb_sig_is_mockajax"]) ||
|
22
|
+
one_or_true(parameters["fb_sig_is_ajax"]) ||
|
23
|
+
xml_http_request_without_facebooker?
|
24
|
+
end
|
25
|
+
alias_method_chain :xml_http_request?, :facebooker
|
26
|
+
|
27
|
+
# we have to re-alias xhr? since it was pointing to the old method
|
28
|
+
alias xhr? :xml_http_request?
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|