doesfacebook 0.6.0 → 1.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,46 @@
1
+ # AWEXOME LABS
2
+ # DoesFacebook
3
+ #
4
+ # Application -- representation of a single Facebook Application, defined on the
5
+ # developers portal at developers.facebook.com.
6
+ #
7
+ # Fields used in configuration match Facebook's API keys for the corresponding
8
+ # setting whenever possible. For reference, review the Graph API doc for Application:
9
+ # https://developers.facebook.com/docs/reference/api/application/
10
+ #
11
+
12
+ module DoesFacebook
13
+
14
+ class Application
15
+
16
+ # Define settable configuration keys for each application:
17
+ attr_accessor :id, :secret, :namespace, :canvas_url, :secure_canvas_url
18
+
19
+ # Prepare with a predefined configuration:
20
+ def initialize(opts={})
21
+ update_options(opts)
22
+ end
23
+
24
+ # Bulk set configuration options for this application
25
+ def update_options(opts={})
26
+ opts.each do |key, val|
27
+ self.send("#{key}=", val)
28
+ end
29
+ end
30
+
31
+ # Error in the case of an unknown key being configured:
32
+ def method_missing(meth, *args, &block)
33
+ if meth.to_s =~ /\=$/
34
+ key_name = meth.to_s.gsub(/\=$/,"")
35
+ raise DoesFacebook::ConfigurationError.new("Unknown configuration key `#{key_name}` cannot be set for Facebook applications.")
36
+ end
37
+ super
38
+ end
39
+
40
+ # Return true if this application supports SSL/HTTPS:
41
+ def supports_ssl?
42
+ !secure_canvas_url.nil?
43
+ end
44
+
45
+ end # Application
46
+ end # DoesFacebook
@@ -0,0 +1,58 @@
1
+ # AWEXOME LABS
2
+ # DoesFacebook : Configuration
3
+
4
+ module DoesFacebook
5
+
6
+ class Configuration
7
+
8
+ # Configurable options:
9
+ attr_accessor :applications, :app_selector
10
+
11
+ # Declare defaults on load:
12
+ def initialize
13
+ @applications = Array.new
14
+ @app_selector = Proc.new() do |request, apps|
15
+ apps.find do |a|
16
+ callback_path = request.ssl? && a.supports_ssl? ? a.secure_canvas_url : a.canvas_url
17
+ request.url.match(/^#{callback_path}.*/)
18
+ end
19
+ end
20
+ end
21
+
22
+ # If an unknown settings is configured, notify the user:
23
+ def method_missing(meth, *args, &block)
24
+ if meth.to_s =~ /\=$/
25
+ key_name = meth.to_s.gsub(/\=$/,"")
26
+ raise DoesFacebook::ConfigurationError.new("Unknown configuration `#{key_name}` cannot be set for DoesFacebook.")
27
+ end
28
+ super
29
+ end
30
+
31
+ # Add an application definition:
32
+ def add_application(app)
33
+ app = DoesFacebook::Application.new(app) if app.is_a?(Hash)
34
+ @applications << app
35
+ end
36
+
37
+ # Determine the current app given an incoming request:
38
+ def current_application(request)
39
+ app_selector.call(request, applications)
40
+ end
41
+
42
+ end # Configuration
43
+
44
+
45
+ # Provide an accessor to the gem configuration:
46
+ class << self
47
+ attr_accessor :configuration
48
+ end
49
+
50
+ # Yield the configuration to host:
51
+ def self.configure
52
+ self.configuration ||= Configuration.new
53
+ yield(configuration)
54
+ end
55
+
56
+ DoesFacebook.configuration = Configuration.new
57
+
58
+ end # DoesFacebook
@@ -0,0 +1,98 @@
1
+ # AWEXOME LABS
2
+ # DoesFacebook
3
+ #
4
+ # ControllerExtensions - convenience methods and filters injected into controllers
5
+ # which enact DoesFacebook
6
+ #
7
+
8
+ module DoesFacebook
9
+ module ControllerExtensions
10
+
11
+ protected
12
+
13
+ def fb_app
14
+ @fb_app ||= DoesFacebook.configuration.current_application(request)
15
+ end
16
+
17
+ def url_for_canvas(opts={})
18
+ canvas_root = if request.ssl? && fb_app.supports_ssl?
19
+ "https://apps.facebook.com/#{fb_app.namespace}/"
20
+ else
21
+ "http://apps.facebook.com/#{fb_app.namespace}/"
22
+ end
23
+ case opts
24
+ when String
25
+ opts =~ /:\/\// ? opts : File.join(canvas_root, opts)
26
+ when Hash
27
+ opts.merge(:only_path=>true)
28
+ File.join(canvas_root, url_for(opts))
29
+ end
30
+ end
31
+
32
+ def redirect_to_canvas(opts={})
33
+ @facebook_redirect_url = url_for_canvas(opts)
34
+ Rails.logger.info "Canvas Redirect to #{@facebook_redirect_url}"
35
+ begin
36
+ render :partial=>"facebook/redirect"
37
+ rescue ActionView::MissingTemplate => e
38
+ logger.info "Pretty Redirect Partial facebook/redirect Not Found. Using Unformatted Text."
39
+ render :text=>%{
40
+ Redirecting you to <a href="#{@facebook_redirect_url}">#{@facebook_redirect_url}</a>...
41
+ <script type="text/javascript"> top.location.href = "#{@facebook_redirect_url}"; </script>
42
+ }.html_safe
43
+ end
44
+ end
45
+
46
+
47
+
48
+ private
49
+
50
+ # Captures a signed_request parameter and manipulates the session to allow for
51
+ # a signed_request to be passed from iframe request to iframe request
52
+ # def sessionify_signed_request
53
+ # if request_parameter = request.params["signed_request"]
54
+ # session[:signed_request] = request_parameter
55
+ # logger.info " Facebook Signed Request received. Stored/updated in session."
56
+ # else
57
+ # params["signed_request"] = session[:signed_request]
58
+ # logger.info " No Facebook Signed Request received. Loaded, if present, from session."
59
+ # end
60
+ # end
61
+
62
+ # Ensures, using configuration options, that the request was signed by Facebook
63
+ def validate_signed_request
64
+ if request_parameter = request.params["signed_request"]
65
+ encoded_signature, encoded_data = request_parameter.split(".")
66
+ decoded_signature = base64_url_decode(encoded_signature)
67
+ digested = OpenSSL::HMAC.digest("sha256", fb_app.secret, encoded_data)
68
+ if valid = (digested == decoded_signature)
69
+ Rails.logger.info " Facebook Signed Request Valid."
70
+ else
71
+ Rails.logger.info " Facebook Signed Request is not Valid. Ensure request is from Facebook and correct Facebook app has been selected."
72
+ raise DoesFacebook::RequestSignatureInvalidError.new()
73
+ end
74
+ end
75
+ end
76
+
77
+ # If present, parses data from the signed request and inserts it into the fbparams
78
+ # object for use during requests
79
+ def parse_signed_request
80
+ Rails.logger.info " Facebook application \"#{fb_app.namespace}\" configuration in use for this request."
81
+ if request_parameter = request.params["signed_request"]
82
+ encoded_signature, encoded_data = request_parameter.split(".")
83
+ decoded_signature = base64_url_decode(encoded_signature)
84
+ decoded_data = base64_url_decode(encoded_data)
85
+ @fbparams = HashWithIndifferentAccess.new(JSON.parse(decoded_data))
86
+ Rails.logger.info " Facebook Parameters: #{fbparams.inspect}"
87
+ end
88
+ end
89
+
90
+
91
+ # Base64 URL Decode method
92
+ # see http://developers.facebook.com/docs/authentication/canvas
93
+ def base64_url_decode(str)
94
+ "#{str}==".tr("-_", "+/").unpack("m")[0]
95
+ end
96
+
97
+ end # ControllerExtensions
98
+ end # DoesFacebook
@@ -0,0 +1,37 @@
1
+ # AWEXOME LABS
2
+ # DoesFacebook
3
+ #
4
+ # Error -- represent individual configuration and runtime errors specific to
5
+ # the Facebook application or DoesFacebook
6
+ #
7
+
8
+ module DoesFacebook
9
+
10
+ class Error < StandardError
11
+ def initialize(message="DoesFacebook Runtime Error")
12
+ super
13
+ end
14
+ end # Error
15
+
16
+
17
+ class ConfigurationError < Error
18
+ def initialize(message="DoesFacebook Configuration Error")
19
+ super
20
+ end
21
+ end # ConfigurationError
22
+
23
+
24
+ class MiddlewareError < Error
25
+ def initialize(message="DoesFacebook Runtime Error")
26
+ super
27
+ end
28
+ end # MiddlewareError
29
+
30
+ class RequestSignatureInvalidError < Error
31
+ def initialize(message="Signed Request from Facebook is not valid.")
32
+ super
33
+ end
34
+ end # MiddlewareError
35
+
36
+
37
+ end # DoesFacebook
data/lib/doesfacebook.rb CHANGED
@@ -1,79 +1,60 @@
1
1
  # AWEXOME LABS
2
2
  # DoesFacebook
3
3
 
4
- require 'doesfacebook'
5
- require 'rails'
6
- require 'action_controller'
7
-
8
- require 'doesfacebook/config'
9
- require 'doesfacebook/filters'
10
- require 'doesfacebook/controls'
11
- require 'doesfacebook/session'
12
- require 'doesfacebook/middleware'
13
-
14
- require 'generators/doesfacebook/config/config_generator'
4
+ require "doesfacebook"
5
+ require "rails"
6
+ require "action_controller"
7
+
8
+ require "doesfacebook/configuration"
9
+ require "doesfacebook/error"
10
+ require "doesfacebook/application"
11
+ require "doesfacebook/controller_extensions"
12
+ require "helpers/does_facebook_helper"
13
+ # require "doesfacebook/session"
14
+ require "doesfacebook/middleware"
15
+ require "generators/doesfacebook/config/config_generator"
15
16
 
16
17
  module DoesFacebook
17
18
 
18
- # Create a Rails Engine
19
+ # Add configuration and features to Rails as an Engine:
19
20
  class Engine < Rails::Engine
20
- # engine_name :doesfacebook
21
- end
22
-
23
- # Create a Railtie for Rack, config injection
24
- class Railtie < Rails::Railtie
25
21
  initializer "doesfacebook.init" do |app|
26
22
  app.middleware.use DoesFacebook::Middleware
27
23
  end
24
+
25
+ initializer "doesfacebook.static_assets" do |app|
26
+ app.middleware.use ::ActionDispatch::Static, "#{root}/public"
27
+ end
28
+
29
+ paths["app/helpers"] << "lib/helpers"
28
30
  end
29
-
30
- # Return the current working version of DoesFacebook from VERSION file:
31
+
32
+ # Return the current version of the gem:
31
33
  def self.version
32
34
  @@version ||= File.open(File.join(File.dirname(__FILE__), "..", "VERSION"), "r").read
33
35
  end
34
-
36
+
35
37
  end # DoesFacebook
36
38
 
37
39
 
38
40
  module ActionController
39
41
  class Base
40
-
41
- # Call this method within your controller to parse configuration and enabled
42
- # session validation and parsing
42
+
43
+ # Call this method within your controller to enable Facebook actions:
43
44
  def self.does_facebook(opts={})
44
- self.instance_eval do
45
- include DoesFacebook::Config
46
- include DoesFacebook::Controls
47
- include DoesFacebook::Filters
48
- prepend_before_filter :parse_signed_request, :validate_signed_request
49
- prepend_before_filter :sessionify_signed_request unless opts[:session]==false
45
+ self.instance_eval do
46
+ include DoesFacebook::ControllerExtensions
50
47
  helper :does_facebook
51
-
52
- protected
53
- attr_reader :fbparams
54
- end
55
- end
56
-
57
- end
58
- end # ActionController
48
+ prepend_before_filter :validate_signed_request, opts
49
+ prepend_before_filter :parse_signed_request, opts
50
+ #prepend_before_filter :sessionify_signed_request unless opts[:session]==false
59
51
 
60
-
61
- module ActionMailer
62
- class Base
63
-
64
- # Call this method within your controller to parse configuration and enabled
65
- # session validation and parsing
66
- def self.does_facebook
67
- self.instance_eval do
68
- include DoesFacebook::Config
69
- helper :does_facebook
70
-
71
52
  protected
72
53
  attr_reader :fbparams
73
54
  end
74
55
  end
75
-
56
+
76
57
  end
77
- end # ActionMailer
58
+ end # ActionController
78
59
 
79
60
 
@@ -8,14 +8,14 @@ module DoesFacebook
8
8
  module Generators
9
9
  class ConfigGenerator < ::Rails::Generators::Base
10
10
 
11
- desc "Creates a boilerplate DoesFacebook configuration file at config/doesfacebook.yml"
11
+ desc "Creates a boilerplate DoesFacebook config/initializer at config/initializers/doesfacebook.rb"
12
12
 
13
13
  source_root File.expand_path("../templates", __FILE__)
14
14
 
15
15
  def create_config_file
16
- template "doesfacebook.yml", File.join("config","doesfacebook.yml")
16
+ template "doesfacebook.rb", File.join("config/initializers","doesfacebook.rb")
17
17
  end
18
18
 
19
19
  end
20
20
  end #Generators
21
- end #DoesFacebook
21
+ end #DoesFacebook
@@ -0,0 +1,33 @@
1
+ # AWEXOME LABS
2
+ # DoesFacebook Configuration File
3
+ #
4
+ # Use this initializer to declare logical Facebook applications your
5
+ # Rails app will harness.
6
+ #
7
+ # You can specify any number of applications statically, from a dynamic
8
+ # source such as your database, or from elsewhere.
9
+ #
10
+
11
+ DoesFacebook.configure do |config|
12
+
13
+ # Add each Facebook Application (defined in your Developer Dashboard
14
+ # at developers.facebook.com) here, like so:
15
+ config.add_application(
16
+ id: 123456789012345,
17
+ secret: "abcdefghijklmnopqrstuvwxyzABCDEF"
18
+ namespace: "your_app_namespace",
19
+ canvas_url: "http://your.dev.server.com/and/path",
20
+ secure_canvas_url: "https://secure.dev.server"
21
+ )
22
+
23
+ # You may specify the method by which DoesFacebook selects the app
24
+ # configuration for each request with a lambda or Proc. This example
25
+ # uses canvas_url, but you can make this distinction however you wish:
26
+ # config.app_selector = Proc.new() do |request, apps|
27
+ # apps.find do |a|
28
+ # callback_path = request.ssl? && a.supports_ssl? ? a.secure_canvas_url : a.canvas_url
29
+ # request.url.match(/^#{callback_path}.*/)
30
+ # end
31
+ # end
32
+
33
+ end
@@ -0,0 +1,70 @@
1
+ # AWEXOME LABS
2
+ # DoesFacebook
3
+ #
4
+ # DoesFacebookHelper - add helpers to
5
+
6
+ module DoesFacebookHelper
7
+
8
+ # Return a reference to the current Facebook Application config:
9
+ def fb_app
10
+ @fb_app
11
+ end
12
+
13
+ # Return the current application id to the view
14
+ def app_id
15
+ fb_app.id
16
+ end
17
+
18
+ # Return the current app namespace:
19
+ def app_namespace
20
+ fb_app.namespace
21
+ end
22
+
23
+ # Return the full canvas URL:
24
+ def app_canvas_url
25
+ "#{request.ssl? ? "https://" : "http://"}apps.facebook.com/#{app_namespace}"
26
+ end
27
+
28
+ # Generate a URL that points within the Facebook canvas
29
+ def url_for_canvas(url_opts={})
30
+ controller.send(:url_for_canvas, url_opts)
31
+ end
32
+
33
+ # Generate a link that points within the Facebook canvas
34
+ def link_to_canvas(text, url_opts={}, html_opts={})
35
+ content_tag("a", text, html_opts.merge(:rev=>"canvas", :href=>url_for_canvas(url_opts), :target=>"_top"), false)
36
+ end
37
+
38
+ # Display a user's Facebook profile photo
39
+ def profile_pic(facebook_id, opts={})
40
+ type = opts.delete(:type) || "square" # <= Valid types: square, small, normal, large
41
+ opts = {:class=>"profile-pic", :border=>0}.merge(opts)
42
+ image_tag("//graph.facebook.com/#{facebook_id}/picture?type=#{type}", opts)
43
+ end
44
+
45
+
46
+ # Insert properly-formed FB.init() call with fb-root doc element. Yields a block which
47
+ # can be used to inject further FB initialization JavaScript within fbAsyncInit
48
+ def fb_init(init_opts={}, &block)
49
+ init_opts = {appId: app_id, channelUrl: "/channel.html", status: true, cookie: true, xfbml: false}.merge(init_opts)
50
+ injection = """<!-- Facebook JS SDK -->
51
+ <div id=\"fb-root\"></div>
52
+ <script>
53
+ window.fbAsyncInit = function() {
54
+ FB.init(#{init_opts.to_json});"""
55
+ injection += capture(&block) if block_given?
56
+ injection += """
57
+ };
58
+ (function(d){
59
+ var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
60
+ if (d.getElementById(id)) {return;}
61
+ js = d.createElement('script'); js.id = id; js.async = true;
62
+ js.src = \"//connect.facebook.net/en_US/all.js\";
63
+ ref.parentNode.insertBefore(js, ref);
64
+ }(document));
65
+ </script>"""
66
+ return injection.html_safe
67
+ end
68
+
69
+
70
+ end
@@ -0,0 +1,2 @@
1
+ <script src="//connect.facebook.net/en_US/all.js"></script>
2
+ <!-- DoesFacebook: Facebook Channel File: https://developers.facebook.com/docs/reference/javascript/ -->
metadata CHANGED
@@ -1,59 +1,128 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: doesfacebook
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
5
- prerelease:
4
+ version: 1.0.0.pre1
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
- - mccolin
8
+ - Awexome Labs
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-11 00:00:00.000000000Z
12
+ date: 2013-05-21 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 3.2.0
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: 3.2.0
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: bundler
16
- requirement: &2154459220 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
17
33
  none: false
18
34
  requirements:
19
- - - ~>
35
+ - - ! '>='
20
36
  - !ruby/object:Gem::Version
21
- version: 1.0.0
37
+ version: '1.1'
22
38
  type: :development
23
39
  prerelease: false
24
- version_requirements: *2154459220
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '1.1'
25
46
  - !ruby/object:Gem::Dependency
26
47
  name: jeweler
27
- requirement: &2154458600 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 1.8.4
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: 1.8.4
62
+ - !ruby/object:Gem::Dependency
63
+ name: rdoc
64
+ requirement: !ruby/object:Gem::Requirement
28
65
  none: false
29
66
  requirements:
30
67
  - - ~>
31
68
  - !ruby/object:Gem::Version
32
- version: 1.5.1
69
+ version: '3.12'
33
70
  type: :development
34
71
  prerelease: false
35
- version_requirements: *2154458600
36
- description: Paper-thin Facebook validation and signed request parsing Rails plugin
37
- email: info@awexomelabs.com
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '3.12'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: 2.11.0
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: 2.11.0
94
+ description: Lightweight gem enables your Rails application to quickly and simply
95
+ integrate with Facebook
96
+ email: engineering@awexomelabs.com
38
97
  executables: []
39
98
  extensions: []
40
99
  extra_rdoc_files:
41
100
  - LICENSE
42
101
  - README.rdoc
43
102
  files:
44
- - app/helpers/does_facebook_helper.rb
103
+ - CHANGELOG.rdoc
104
+ - Gemfile
105
+ - Gemfile.lock
106
+ - LICENSE
107
+ - README.rdoc
108
+ - ROADMAP.rdoc
109
+ - Rakefile
110
+ - VERSION
111
+ - doesfacebook.gemspec
45
112
  - lib/doesfacebook.rb
46
- - lib/doesfacebook/config.rb
47
- - lib/doesfacebook/controls.rb
48
- - lib/doesfacebook/filters.rb
113
+ - lib/doesfacebook/application.rb
114
+ - lib/doesfacebook/configuration.rb
115
+ - lib/doesfacebook/controller_extensions.rb
116
+ - lib/doesfacebook/error.rb
49
117
  - lib/doesfacebook/middleware.rb
50
118
  - lib/doesfacebook/session.rb
51
119
  - lib/generators/doesfacebook/config/config_generator.rb
52
- - lib/generators/doesfacebook/config/templates/doesfacebook.yml
53
- - LICENSE
54
- - README.rdoc
55
- homepage: http://awexomelabs.com/
56
- licenses: []
120
+ - lib/generators/doesfacebook/config/templates/doesfacebook.rb
121
+ - lib/helpers/does_facebook_helper.rb
122
+ - public/channel.html
123
+ homepage: http://github.com/awexome/doesfacebook
124
+ licenses:
125
+ - MIT
57
126
  post_install_message:
58
127
  rdoc_options: []
59
128
  require_paths:
@@ -64,16 +133,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
64
133
  - - ! '>='
65
134
  - !ruby/object:Gem::Version
66
135
  version: '0'
136
+ segments:
137
+ - 0
138
+ hash: 2444230836581017084
67
139
  required_rubygems_version: !ruby/object:Gem::Requirement
68
140
  none: false
69
141
  requirements:
70
- - - ! '>='
142
+ - - ! '>'
71
143
  - !ruby/object:Gem::Version
72
- version: '0'
144
+ version: 1.3.1
73
145
  requirements: []
74
146
  rubyforge_project:
75
- rubygems_version: 1.8.17
147
+ rubygems_version: 1.8.24
76
148
  signing_key:
77
149
  specification_version: 3
78
- summary: Paper-thin Facebook validation and signed request parsing Rails plugin
150
+ summary: Lightweight gem enables your Rails application to quickly and simply integrate
151
+ with Facebook
79
152
  test_files: []