Permalink
Browse files

Some code documentation and in-code samples

  • Loading branch information...
1 parent d8a21f8 commit 727173122d6489aa909f546951dd4fcb7bf59ba5 @dekart committed Dec 26, 2011
@@ -1,41 +1,54 @@
module Facepalm
module Rails
+
+ # Rails application controller extension
module Controller
def self.included(base)
base.class_eval do
include Facepalm::Rails::Controller::OauthAccess
include Facepalm::Rails::Controller::UrlRewriting
include Facepalm::Rails::Controller::Redirects
+ # Fix cookie permission issue in IE
before_filter :normal_cookies_for_ie_in_iframes!
helper_method(:facepalm, :fb_signed_request, :current_facebook_user, :params_without_facebook_data)
end
end
+ # Accessor to current application config. Override it in your controller
+ # if you need multi-application support or per-request configuration selection.
def facepalm
Facepalm::Config.default
end
+ # Accessor to current facebook user. Returns instance of Facepalm::User
def current_facebook_user
@current_facebook_user ||= fetch_current_facebook_user
end
- def fetch_current_facebook_user
- Facepalm::User.from_signed_request(facepalm, fb_signed_request || fb_cookie)
- end
-
+ # Accessor to secure cookie set by Facebook
def fb_cookie
cookies["fbsr_#{ facepalm.app_id }"]
end
+ # Accessor to signed request passed either in params or in flash
def fb_signed_request
request.env['HTTP_SIGNED_REQUEST'] || flash[:signed_request]
end
+ # A hash of params passed to this action, excluding secure information
+ # passed by Facebook
def params_without_facebook_data
params.except(:signed_request)
end
+
+ private
+
+ def fetch_current_facebook_user
+ Facepalm::User.from_signed_request(facepalm, fb_signed_request || fb_cookie)
+ end
end
+
end
end
@@ -3,11 +3,14 @@ class OAuthException < StandardError; end
module Rails
module Controller
+
+ # OAuth 2.0 authentication module
module OauthAccess
def self.included(base)
base.extend(ClassMethods)
end
+ # A filter class for Rails
class AccessFilter
def initialize(*permissions)
@permissions = permissions
@@ -19,6 +22,17 @@ def filter(controller)
end
module ClassMethods
+ # Requires Facebook authentication for the whole set of controller actions.
+ # Use it to setup a given set of permissions for the whole controller
+ #
+ # @param permissions An array of permissions to require
+ # @param options A hash of options to control filter application, similar to
+ # options hash for before_filter
+ #
+ # @example
+ # class MyController < ApplicationController
+ # facepalm_authentication :email, :publish_actions, :only => :index
+ # end
def facepalm_authentication(*permissions)
options = permissions.extract_options!
@@ -30,10 +44,32 @@ def facepalm_authentication(*permissions)
end
end
+ # Requires a given set of permissions in context of the current action.
+ # Use it to require permissions in a single action or custom filter.
+ #
+ # @param permissions An array of permissions to require
+ #
+ # @return true if user authorized the application, false otehrwise
+ #
+ # @example
+ # class MyController < ApplicationController
+ # before_filter :my_custom_filter, :only => :show
+ #
+ # def my_custom_filter
+ # my_custom_condition? and facepalm_require_authentication(:publish_actions)
+ # end
+ #
+ # def index
+ # if facepalm_require_authentication(:email)
+ # ... do what you need ...
+ # end
+ # end
+ # end
def facepalm_require_authentication(*permissions)
if current_facebook_user.try(:authenticated?)
true
else
+ # Encrypting return URL to pass it to Facebook
return_code = facepalm_url_encryptor.encrypt(
url_for(params_without_facebook_data.merge(:canvas => false, :only_path => true))
)
@@ -51,6 +87,7 @@ def facepalm_require_authentication(*permissions)
end
end
+ # OAuth 2.0 endpoint action added to ApplicationController and mounted to /facebook_oauth
def facepalm_oauth_endpoint
if params[:error]
raise Facepalm::OAuthException.new(params[:error][:message])
@@ -60,6 +97,7 @@ def facepalm_oauth_endpoint
# under the Authentication docs at http://developers.facebook.com/docs/authentication/)
if params[:code]
begin
+ # Decrypting return URL and redirecting to it
redirect_to(facebook_canvas_page_url + facepalm_url_encryptor.decrypt(params[:fb_return_to].to_s))
rescue ActiveSupport::MessageEncryptor::InvalidMessage
::Rails.logger.fatal "Failed to decrypt return URL: #{ params[:fb_return_to] }"
@@ -74,6 +112,11 @@ def facepalm_oauth_endpoint
end
end
+ # Internally used to encrypt return URL for authentication endpoint
+ #
+ # @return ActiveSupport::MessageEncryptor
+ #
+ # @private
def facepalm_url_encryptor
@facebook_url_encryptor ||= ActiveSupport::MessageEncryptor.new(facepalm.secret)
end
@@ -2,12 +2,15 @@ module Facepalm
module Rails
module Controller
module Redirects
+ # Overrides ActionController::Base#redirect_to to pass signed_request in flash[]
def redirect_to(*args)
flash[:signed_request] = fb_signed_request
super(*args)
end
+ # Redirects user to a definite URL with JavaScript code that overwrites
+ # top frame location. Use it to redirect user from within an iframe.
def redirect_from_iframe(url_options)
redirect_url = url_options.is_a?(String) ? url_options : url_for(url_options)
@@ -19,6 +22,12 @@ def redirect_from_iframe(url_options)
)
end
+ # Generates HTML and JavaScript code to redirect user with top frame location
+ # overwrite
+ #
+ # @param target_url An URL to redirect the user to
+ # @param custom_code A custom HTML code to insert into the result document.
+ # Can be used to add OpenGraph tags to redirect page code.
def iframe_redirect_code(target_url, custom_code = nil)
%{
<html><head>
@@ -10,14 +10,24 @@ def self.included(base)
end
end
+ # A helper to generate an URL of the application canvas page URL
+ #
+ # @param protocol A request protocol, should be either 'http://' or 'https://'.
+ # Defaults to current protocol.
def facebook_canvas_page_url(protocol = nil)
facepalm.canvas_page_url(protocol || request.protocol)
end
+ # A helper to generate an application callback URL
+ #
+ # @param protocol A request protocol, should be either 'http://' or 'https://'.
+ # Defaults to current protocol.
def facebook_callback_url(protocol = nil)
facepalm.callback_url(protocol || request.protocol)
end
+ # Overrides ActionController::Base#urs_for to filter out secure Facebook params
+ # and add Facebook Canvas URL if necessary
def url_for_with_facepalm(options = {})
if options.is_a?(Hash)
if options.delete(:canvas) && !options[:host]
@@ -2,33 +2,48 @@ module Facepalm
module Rails
module Helpers
module JavascriptHelper
+
+ # A helper to integrate Facebook Connect to the current page. Generates a
+ # JavaScript code that initializes Facebook Javascript client for the
+ # current application.
+ #
+ # @param app_id Facebook App ID of the application. Defaults to value provided by the current config.
+ # @param options A hash of options for JavaScript generation. Available options are:
+ # :cookie - Enable cookie generation for the application. Default to true.
+ # :status - Enable login status check. Defaults to true.
+ # :xfbml - Enable XFBML tag parsing. Default to true.
+ # :frictionless - Enable frictionless app request delivery. Defaults to true
+ # :locale - Locale to use for JavaScript client. Defaults to 'en_US'.
+ # :weak_cache - Enable FB JS client cache expiration every minute. Defaults to false.
+ # :async - Enable asynchronous FB JS client code load and initialization. Defaults to false.
+ # :cache_url - An URL to load custom or cached version of the FB JS client code. Not used by default.
+ # @param &block A block of JS code to be inserted in addition to FB client initialization code.
def fb_connect_js(*args, &block)
options = args.extract_options!
app_id = args.shift || facepalm.app_id
options.reverse_merge!(
- :cookie => true,
- :status => true,
- :xfbml => true,
- :oauth => true,
- :frictionless_requests => :true,
- :locale => "en_US"
+ :cookie => true,
+ :status => true,
+ :xfbml => true,
+ :frictionless => true,
+ :locale => "en_US"
)
extra_js = capture(&block) if block_given?
init_js = <<-JAVASCRIPT
FB.init({
- appId : '#{app_id}',
- status : #{ options[:status] }, // check login status
- cookie : #{ options[:cookie] }, // enable cookies to allow the server to access the session
- xfbml : #{ options[:xfbml] }, // parse XFBML
- oauth : #{ options[:oauth] },
- frictionlessRequests : #{ options[:frictionless_requests] },
+ appId : '#{ app_id }',
+ status : #{ options[:status] },
+ cookie : #{ options[:cookie] },
+ xfbml : #{ options[:xfbml] },
+ frictionlessRequests : #{ options[:frictionless] },
channelUrl : '#{ options[:channel_url] || 'null' }'
});
JAVASCRIPT
+
init_js = "FB._https = true; #{ init_js }" if request.ssl?
js_url = "connect.facebook.net/#{options[:locale]}/all.js"

0 comments on commit 7271731

Please sign in to comment.