benhutton-facebooker2 0.0.5.x4

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.
@@ -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
+