benhutton-facebooker2 0.0.5.x4

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