ryw-facebooker2 0.0.5.x2

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_facebooker_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_facebooker_yaml
44
+ config = YAML.load(ERB.new(File.read(File.join(::Rails.root,"config","facebooker.yml"))).result)[::Rails.env]
45
+ raise NotConfigured.new("Unable to load configuration for #{::Rails.env} from facebooker.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,131 @@
1
+ require "digest/md5"
2
+ require "hmac-sha2"
3
+ require "ruby-debug"
4
+
5
+ module Facebooker2
6
+ module Rails
7
+ module Controller
8
+
9
+ # load required helpers
10
+ def self.included(controller)
11
+ controller.helper Facebooker2::Rails::Helpers
12
+ controller.helper_method :current_facebook_user
13
+ controller.helper_method :current_facebook_client
14
+ controller.helper_method :facebook_params
15
+ end
16
+
17
+ #
18
+ def current_facebook_user
19
+ fetch_client_and_user
20
+ @_current_facebook_user
21
+ end
22
+
23
+ #
24
+ def current_facebook_client
25
+ fetch_client_and_user
26
+ @_current_facebook_client
27
+ end
28
+
29
+ #
30
+ def fetch_client_and_user
31
+ return if @_fb_user_fetched
32
+ fetch_client_and_user_from_cookie
33
+ fetch_client_and_user_from_signed_request unless @_current_facebook_client
34
+ @_fb_user_fetched = true
35
+ end
36
+
37
+ #
38
+ def fetch_client_and_user_from_cookie
39
+ app_id = Facebooker2.app_id
40
+ if (hash_data = fb_cookie_hash_for_app_id(app_id)) and
41
+ fb_cookie_signature_correct?(fb_cookie_hash_for_app_id(app_id),Facebooker2.secret)
42
+ fb_create_user_and_client(hash_data["access_token"],hash_data["expires"],hash_data["uid"])
43
+ end
44
+ end
45
+
46
+ #
47
+ def fb_create_user_and_client(token,expires,userid)
48
+ client = Mogli::Client.new(token,expires.to_i)
49
+ user = Mogli::User.new(:id=>userid)
50
+ fb_sign_in_user_and_client(user,client)
51
+ end
52
+
53
+ # cache current facebook user and current facebook client
54
+ def fb_sign_in_user_and_client(user,client)
55
+ user.client = client
56
+ @_current_facebook_user = user
57
+ @_current_facebook_client = client
58
+ @_fb_user_fetched = true
59
+ end
60
+
61
+ #
62
+ def fb_cookie_hash_for_app_id(app_id)
63
+ return nil unless fb_cookie_for_app_id?(app_id)
64
+ hash={}
65
+ data = fb_cookie_for_app_id(app_id).gsub(/"/,"")
66
+ data.split("&").each do |str|
67
+ parts = str.split("=")
68
+ hash[parts.first] = parts.last
69
+ end
70
+ hash
71
+ end
72
+
73
+ #
74
+ def fb_cookie_for_app_id?(app_id)
75
+ !fb_cookie_for_app_id(app_id).nil?
76
+ end
77
+
78
+ #
79
+ def fb_cookie_for_app_id(app_id)
80
+ cookies["fbs_#{app_id}"]
81
+ end
82
+
83
+ #
84
+ def fb_cookie_signature_correct?(hash,secret)
85
+ sorted_keys = hash.keys.reject {|k| k=="sig"}.sort
86
+ test_string = ""
87
+ sorted_keys.each do |key|
88
+ test_string += "#{key}=#{hash[key]}"
89
+ end
90
+ test_string += secret
91
+ Digest::MD5.hexdigest(test_string) == hash["sig"]
92
+ end
93
+
94
+ #
95
+ def fb_signed_request_json(encoded)
96
+ chars_to_add = 4-(encoded.size % 4)
97
+ encoded += ("=" * chars_to_add)
98
+ Base64.decode64(encoded)
99
+ end
100
+
101
+ # cached access to facebook params
102
+ def facebook_params
103
+ @facebook_params ||= fb_load_facebook_params
104
+ end
105
+
106
+ #
107
+ def fb_load_facebook_params
108
+ return {} if params[:signed_request].blank?
109
+ sig,encoded_json = params[:signed_request].split(".")
110
+ return {} unless fb_signed_request_sig_valid?(sig,encoded_json)
111
+ ActiveSupport::JSON.decode(fb_signed_request_json(encoded_json)).with_indifferent_access
112
+ end
113
+
114
+ #
115
+ def fb_signed_request_sig_valid?(sig,encoded)
116
+ base64 = Base64.encode64(HMAC::SHA256.digest(Facebooker2.secret,encoded))
117
+ #now make the url changes that facebook makes
118
+ url_escaped_base64 = base64.gsub(/=*\n?$/,"").tr("+/","-_")
119
+ sig == url_escaped_base64
120
+ end
121
+
122
+ #
123
+ def fetch_client_and_user_from_signed_request
124
+ if facebook_params[:oauth_token]
125
+ fb_create_user_and_client(facebook_params[:oauth_token],facebook_params[:expires],facebook_params[:user_id])
126
+ end
127
+ end
128
+
129
+ end
130
+ end
131
+ 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,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ryw-facebooker2
3
+ version: !ruby/object:Gem::Version
4
+ hash: 8118013
5
+ prerelease: true
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 5
10
+ - x2
11
+ version: 0.0.5.x2
12
+ platform: ruby
13
+ authors:
14
+ - Ryan Walker
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-08-22 00:00:00 -04:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: mogli
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 7
31
+ segments:
32
+ - 0
33
+ - 0
34
+ - 12
35
+ version: 0.0.12
36
+ type: :runtime
37
+ version_requirements: *id001
38
+ - !ruby/object:Gem::Dependency
39
+ name: ruby-hmac
40
+ prerelease: false
41
+ requirement: &id002 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ hash: 3
47
+ segments:
48
+ - 0
49
+ version: "0"
50
+ type: :runtime
51
+ version_requirements: *id002
52
+ description: Facebook Connect integration library for ruby and rails (for Rspec2 + Rails3)
53
+ email: ry@anotherventure.com.com
54
+ executables: []
55
+
56
+ extensions: []
57
+
58
+ extra_rdoc_files: []
59
+
60
+ files:
61
+ - lib/facebooker2/not_configured.rb
62
+ - lib/facebooker2/rails/controller.rb
63
+ - lib/facebooker2/rails/helpers/facebook_connect.rb
64
+ - lib/facebooker2/rails/helpers/javascript.rb
65
+ - lib/facebooker2/rails/helpers/request_forms.rb
66
+ - lib/facebooker2/rails/helpers/user.rb
67
+ - lib/facebooker2/rails/helpers.rb
68
+ - lib/facebooker2/rails.rb
69
+ - lib/facebooker2.rb
70
+ has_rdoc: true
71
+ homepage: http://github.com/ryw/facebooker2
72
+ licenses: []
73
+
74
+ post_install_message:
75
+ rdoc_options: []
76
+
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ hash: 3
85
+ segments:
86
+ - 0
87
+ version: "0"
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">"
92
+ - !ruby/object:Gem::Version
93
+ hash: 25
94
+ segments:
95
+ - 1
96
+ - 3
97
+ - 1
98
+ version: 1.3.1
99
+ requirements: []
100
+
101
+ rubyforge_project:
102
+ rubygems_version: 1.3.7
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: Facebook Connect integration library for ruby and rails (for Rspec2 + Rails3)
106
+ test_files: []
107
+