faceb 0.1.0

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.
Files changed (81) hide show
  1. data/.document +5 -0
  2. data/.gitignore +24 -0
  3. data/Gemfile +13 -0
  4. data/LICENSE +20 -0
  5. data/README.md +70 -0
  6. data/Rakefile +76 -0
  7. data/VERSION +1 -0
  8. data/bin/console +3 -0
  9. data/faceb.gemspec +164 -0
  10. data/features/faceb-session.feature +7 -0
  11. data/features/step_definitions/facebook-session_steps.rb +14 -0
  12. data/features/support/env.rb +4 -0
  13. data/lib/faceb.rb +7 -0
  14. data/lib/faceb/api.rb +69 -0
  15. data/lib/faceb/base.rb +51 -0
  16. data/lib/faceb/rails.rb +12 -0
  17. data/lib/faceb/rails/api.rb +21 -0
  18. data/lib/faceb/rails/base.rb +30 -0
  19. data/lib/faceb/rails/configuration.rb +31 -0
  20. data/lib/faceb/rails/controller.rb +49 -0
  21. data/lib/faceb/rails/generators.rb +3 -0
  22. data/lib/faceb/rails/generators/config/USAGE +8 -0
  23. data/lib/faceb/rails/generators/config/config_generator.rb +16 -0
  24. data/lib/faceb/rails/generators/config/templates/faceb.yml +6 -0
  25. data/lib/faceb/rails/generators/fb_connect/USAGE +7 -0
  26. data/lib/faceb/rails/generators/fb_connect/fb_connect_generator.rb +16 -0
  27. data/lib/faceb/rails/generators/fb_connect/templates/xd_receiver.html +10 -0
  28. data/lib/faceb/rails/generators/fb_connect/templates/xd_receiver_ssl.html +10 -0
  29. data/lib/faceb/rails/rails_23_init.rb +21 -0
  30. data/lib/faceb/rails/railtie.rb +39 -0
  31. data/lib/faceb/rails/tasks.rb +2 -0
  32. data/lib/faceb/rails/tasks/faceb.tasks +6 -0
  33. data/lib/faceb/rails/tasks/tunnel.tasks +46 -0
  34. data/lib/faceb/session.rb +38 -0
  35. data/spec/faceb_api_spec.rb +107 -0
  36. data/spec/faceb_base_spec.rb +48 -0
  37. data/spec/faceb_session_spec.rb +64 -0
  38. data/spec/rails/config_generator_spec.rb +39 -0
  39. data/spec/rails/configuration_sepc.rb +11 -0
  40. data/spec/rails/controller_spec.rb +39 -0
  41. data/spec/rails/fb_connect_generator_spec.rb +28 -0
  42. data/spec/rails/railtie_spec.rb +23 -0
  43. data/spec/rails_app/app/controllers/application_controller.rb +3 -0
  44. data/spec/rails_app/app/controllers/posts_controller.rb +7 -0
  45. data/spec/rails_app/app/helpers/application_helper.rb +2 -0
  46. data/spec/rails_app/config.ru +4 -0
  47. data/spec/rails_app/config/application.rb +46 -0
  48. data/spec/rails_app/config/boot.rb +9 -0
  49. data/spec/rails_app/config/database.yml +22 -0
  50. data/spec/rails_app/config/environment.rb +5 -0
  51. data/spec/rails_app/config/environments/development.rb +19 -0
  52. data/spec/rails_app/config/environments/production.rb +33 -0
  53. data/spec/rails_app/config/environments/test.rb +32 -0
  54. data/spec/rails_app/config/faceb.yml +3 -0
  55. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  56. data/spec/rails_app/config/initializers/cookie_verification_secret.rb +7 -0
  57. data/spec/rails_app/config/initializers/inflections.rb +10 -0
  58. data/spec/rails_app/config/initializers/mime_types.rb +5 -0
  59. data/spec/rails_app/config/initializers/session_store.rb +10 -0
  60. data/spec/rails_app/config/locales/en.yml +5 -0
  61. data/spec/rails_app/config/routes.rb +58 -0
  62. data/spec/rails_app/log/development.log +0 -0
  63. data/spec/rails_app/log/production.log +0 -0
  64. data/spec/rails_app/log/server.log +0 -0
  65. data/spec/rails_app/log/test.log +0 -0
  66. data/spec/rails_app/public/404.html +26 -0
  67. data/spec/rails_app/public/422.html +26 -0
  68. data/spec/rails_app/public/500.html +26 -0
  69. data/spec/rails_app/public/favicon.ico +0 -0
  70. data/spec/rails_app/public/javascripts/application.js +2 -0
  71. data/spec/rails_app/public/javascripts/controls.js +965 -0
  72. data/spec/rails_app/public/javascripts/dragdrop.js +974 -0
  73. data/spec/rails_app/public/javascripts/effects.js +1123 -0
  74. data/spec/rails_app/public/javascripts/prototype.js +4874 -0
  75. data/spec/rails_app/public/javascripts/rails.js +110 -0
  76. data/spec/rails_app/public/stylesheets/.gitkeep +0 -0
  77. data/spec/rails_app/script/rails +9 -0
  78. data/spec/rails_spec_helper.rb +6 -0
  79. data/spec/spec.opts +1 -0
  80. data/spec/spec_helper.rb +27 -0
  81. metadata +247 -0
data/lib/faceb/base.rb ADDED
@@ -0,0 +1,51 @@
1
+ module FaceB
2
+ class << self
3
+ ##
4
+ # Return the current Facebook session
5
+ #
6
+ # @return [FaceB::Session] The current facebook session
7
+ def current_session
8
+ Session.current
9
+ end
10
+
11
+ ##
12
+ # Create a new Facebook session
13
+ #
14
+ # @param [String] api_key The Facebook application api key
15
+ # @param [String] secret_key The Facebook application secret key
16
+ # @param [String] session_key The session key of a Facebook user
17
+ #
18
+ # @return [FaceB::Session] The new current facebook session
19
+ #
20
+ # @example Create a new session
21
+ # FaceB.new('api-key', 'secret-key')
22
+ # @example Create a new session with a specific session key
23
+ # FaceB.new('api-key', 'secret-key', 'session-key')
24
+ #
25
+ # @see FaceB::Session.create
26
+ def new(api_key = nil, secret_key = nil, session_key = nil)
27
+ Session.create(api_key, secret_key, session_key)
28
+ end
29
+
30
+ ##
31
+ # Call a Facebook API method
32
+ #
33
+ # @param [String] api_key The Facebook application api key
34
+ # @param [String] secret_key The Facebook application secret key
35
+ # @param [String] method The API method to call
36
+ # @param [Hash] params Params to pass to API method call (see FaceB::Api#call)
37
+ #
38
+ # @return [FaceB::Api::Response] The API method response
39
+ #
40
+ # @example Call a method
41
+ # FaceB.call('api-key', 'secret-key', 'method.name', :key1 => 'value1')
42
+ # @example Call a method with a specific
43
+ # FaceB.call('api-key', 'secret-key', 'method.name', :key1 => 'value1', :secret_key => 'session-key')
44
+ #
45
+ # @see FaceB::Api#call
46
+ # @see FaceB::Session#call
47
+ def call(api_key, secret_key, method, params = {})
48
+ Session.new(api_key, secret_key).call(method, params)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,12 @@
1
+ if Rails.version >= "3.0"
2
+ require 'faceb/rails/railtie'
3
+ require 'faceb/rails/generators'
4
+ elsif Rails.version >= "2.3"
5
+ require 'faceb/rails/rails_23_init'
6
+ else
7
+ raise "Sorry, but FaceB needs Rails 2.3 or later"
8
+ end
9
+
10
+ require 'faceb/rails/base'
11
+ require 'faceb/rails/api'
12
+ require 'faceb/rails/controller'
@@ -0,0 +1,21 @@
1
+ module FaceB
2
+ Api.class_eval do
3
+ def call_with_rails(method, params = {})
4
+ ActiveSupport::Notifications.instrument("faceb.api", :method => method, :params => params) do
5
+ call_without_rails(method, params)
6
+ end
7
+ end
8
+
9
+ alias_method :call_without_rails, :call
10
+ alias_method :call, :call_with_rails
11
+ end
12
+
13
+ class LogSubscriber < Rails::LogSubscriber
14
+ def api(event)
15
+ debug color("FaceB call method '#{event.payload[:method]}' with #{event.payload[:params].inspect} in (#{event.duration})", :blue, true)
16
+ end
17
+ end
18
+ end
19
+
20
+ # Add log for API method call
21
+ Rails::LogSubscriber.add :faceb, FaceB::LogSubscriber.new
@@ -0,0 +1,30 @@
1
+ require 'faceb/rails/configuration'
2
+
3
+ module FaceB
4
+ class << self
5
+
6
+ ##
7
+ # Return FaceB config file path
8
+ #
9
+ # @return [String] config file path
10
+ def config_file_path
11
+ File.join(::Rails.root, 'config', 'faceb.yml')
12
+ end
13
+
14
+ ##
15
+ # Return the current Facebook Rails configuration
16
+ #
17
+ # @return [FaceB::Configuration] the current Facebook Rails configuration
18
+ def config
19
+ FaceB::Configuration.config
20
+ end
21
+
22
+ # Change method signature with default api_key and secret_key
23
+ def new_with_rails(api_key = FaceB.config.api_key, secret_key = FaceB.config.secret_key, session_key = nil)
24
+ new_without_rails(api_key, secret_key, session_key)
25
+ end
26
+
27
+ alias_method :new_without_rails, :new
28
+ alias_method :new, :new_with_rails
29
+ end
30
+ end
@@ -0,0 +1,31 @@
1
+ require 'yaml'
2
+
3
+ module FaceB
4
+ class Configuration
5
+ def initialize(config)
6
+ @config = config
7
+ end
8
+
9
+ def method_missing(name, *args)
10
+ @config[name.to_s]
11
+ end
12
+
13
+
14
+ ##
15
+ # Load a config file to create a new instance of Configuration
16
+ #
17
+ # @param [String] file File path
18
+ # @param [String] environment The Rails environment
19
+ def self.load_config_file(file, environment)
20
+ @config = self.new(YAML.load_file(file)[environment])
21
+ end
22
+
23
+ ##
24
+ # Return the current configuration instance
25
+ #
26
+ # @return [FaceB::Configuration] The current configuration instance
27
+ def self.config
28
+ @config
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,49 @@
1
+ module FaceB
2
+ module Rails
3
+ module Controller
4
+
5
+ def self.included(controller)
6
+ controller.extend(ClassMethods)
7
+ controller.before_filter :set_facebook_request_format
8
+ controller.helper_method :facebook_session
9
+ end
10
+
11
+ def facebook_session
12
+ FaceB::Session.current
13
+ end
14
+
15
+ def create_facebook_session
16
+ FaceB::Session.create(FaceB.config.api_key, FaceB.config.secret_key, env['facebook.session_key'])
17
+ end
18
+
19
+ def ensure_authenticated_to_facebook
20
+ create_facebook_session
21
+ end
22
+
23
+ # Return true if request comes from a Facebook canvas
24
+ def in_canvas?
25
+ !!env['facebook.in_canvas']
26
+ end
27
+
28
+ # Return true if request comes from a Facebook iframe
29
+ def in_iframe?
30
+ !!env["facebook.in_iframe"]
31
+ end
32
+
33
+ # Set the request format
34
+ def set_facebook_request_format
35
+ if in_canvas? && !in_iframe?
36
+ request.format = :fbml
37
+ end
38
+ end
39
+
40
+ # Class methods
41
+ module ClassMethods
42
+ def ensure_authenticated_to_facebook(options = {})
43
+ before_filter :ensure_authenticated_to_facebook, options
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+
@@ -0,0 +1,3 @@
1
+ Dir[File.dirname(__FILE__) + '/generators/**/*_generator.rb'].each { |generator|
2
+ require generator
3
+ }
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Create The FaceB config file.
3
+
4
+ Example:
5
+ `rails generate face_b:config`
6
+ `rails generate face_b:config --api-key="my-api-key" --secret-key="my-secret-key"`
7
+ `rails generate face_b:config -a my-api-key -s my-secret-key`
8
+
@@ -0,0 +1,16 @@
1
+ require 'rails/generators'
2
+
3
+ module FaceB
4
+ class ConfigGenerator < Rails::Generators::Base
5
+ class_option :api_key, :type => :string, :aliases => '-a', :desc => "Facebook API key"
6
+ class_option :secret_key, :type => :string, :aliases => '-s', :desc => "Facebook secret key"
7
+
8
+ def create_config_file
9
+ template "faceb.yml", "config/faceb.yml"
10
+ end
11
+
12
+ def self.source_root
13
+ File.join(File.dirname(__FILE__), 'templates')
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+ development: &DEVELOPMENT
2
+ api_key: <%= options.api_key %>
3
+ secret_key: <%= options.secret_key %>
4
+
5
+ test:
6
+ <<: *DEVELOPMENT
@@ -0,0 +1,7 @@
1
+ Description:
2
+ Create xd_receiver file for Facebook connect.
3
+
4
+ Example:
5
+ `rails generate face_b:fb_connect`
6
+ `rails generate face_b:fb_connect --ssl`
7
+
@@ -0,0 +1,16 @@
1
+ require 'rails/generators'
2
+
3
+ module FaceB
4
+ class FbConnectGenerator < Rails::Generators::Base
5
+ class_option :ssl, :type => :boolean, :desc => "SSL support"
6
+
7
+ def create_xd_receiver_file
8
+ file = options.ssl ? 'xd_receiver_ssl.html' : 'xd_receiver.html'
9
+ template file, "public/#{file}"
10
+ end
11
+
12
+ def self.source_root
13
+ File.join(File.dirname(__FILE__), 'templates')
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" >
4
+ <head>
5
+ <title>Cross-Domain Receiver Page</title>
6
+ </head>
7
+ <body>
8
+ <script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver.js" type="text/javascript"></script>
9
+ </body>
10
+ </html>
@@ -0,0 +1,10 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" >
4
+ <head>
5
+ <title>Cross-Domain Receiver Page</title>
6
+ </head>
7
+ <body>
8
+ <script src="https://ssl.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver.js" type="text/javascript"></script>
9
+ </body>
10
+ </html>
@@ -0,0 +1,21 @@
1
+ Rails.configuration.after_initialize do
2
+ require 'rack/facebook'
3
+
4
+ # Load the FaceB config file
5
+ begin
6
+ @facebook_config = FaceB::Configuration.load_config_file(FaceB.config_file_path, ::Rails.env)
7
+ rescue Errno::ENOENT
8
+ puts "Warning : config/faceb.yml is not present. Maybe you should called rake faceb:init"
9
+ rescue
10
+ puts "Error during load FaceB config file."
11
+ end
12
+
13
+ # Load Rack-Facebook as a middleware
14
+ Rails.configuration.middleware.use Rack::Facebook, {
15
+ :application_secret => @facebook_config.secret_key,
16
+ :api_key => @facebook_config.api_key
17
+ }
18
+
19
+ # Registered FBML request type
20
+ Mime::Type.register "text/html", :fbml
21
+ end
@@ -0,0 +1,39 @@
1
+ require 'rails'
2
+ require 'faceb'
3
+ require 'rack/facebook'
4
+
5
+ module FaceB
6
+ class Railtie < ::Rails::Railtie
7
+ railtie_name :facebook
8
+
9
+ # Load the FaceB config file
10
+ initializer "faceb.load_config_file" do |app|
11
+ begin
12
+ @facebook_config = FaceB::Configuration.load_config_file(FaceB.config_file_path, ::Rails.env)
13
+ rescue Errno::ENOENT
14
+ puts "Warning : config/faceb.yml is not present. Maybe you should called ./script/rails generate face_b"
15
+ rescue
16
+ puts "Error during load FaceB config file."
17
+ end
18
+ end
19
+
20
+ # Load Rack-Facebook as a middleware
21
+ initializer "faceb.add_middleware" do |app|
22
+ app.config.middleware.use Rack::Facebook, {
23
+ :application_secret => @facebook_config.secret_key,
24
+ :api_key => @facebook_config.api_key
25
+ } if @facebook_config
26
+ end
27
+
28
+ # Registered FBML request type
29
+ initializer "faceb.add_fbml_request_type" do |app|
30
+ Mime::Type.register "text/html", :fbml
31
+ end
32
+
33
+ # load Facebook Specific tasks
34
+ rake_tasks do
35
+ load "faceb/rails/tasks/faceb.tasks"
36
+ load "faceb/rails/tasks/tunnel.tasks"
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,2 @@
1
+ load 'faceb/rails/tasks/faceb.tasks'
2
+ load 'faceb/rails/tasks/tunnel.tasks'
@@ -0,0 +1,6 @@
1
+ namespace :faceb do
2
+ desc "Configure environment to use FaceB"
3
+ task :config => :environment do
4
+ # Todo config task for Rails 2.3.x
5
+ end
6
+ end
@@ -0,0 +1,46 @@
1
+ namespace :faceb do
2
+
3
+ tunnel_ns = namespace :tunnel do
4
+ # Courtesy of Christopher Haupt
5
+ # http://www.BuildingWebApps.com
6
+ # http://www.LearningRails.com
7
+ desc "Create a reverse ssh tunnel from a public server to a private development server."
8
+ task :start => [ :environment, :config ] do
9
+ puts @notification
10
+ system @ssh_command
11
+ end
12
+
13
+ desc "Create a reverse ssh tunnel in the background. Requires ssh keys to be setup."
14
+ task :background_start => [ :environment, :config ] do
15
+ puts @notification
16
+ system "#{@ssh_command} > /dev/null 2>&1 &"
17
+ end
18
+
19
+ # Adapted from Evan Weaver: http://blog.evanweaver.com/articles/2007/07/13/developing-a-facebook-app-locally/
20
+ desc "Check if reverse tunnel is running"
21
+ task :status => [ :environment, :config ] do
22
+ if `ssh #{@public_host} -l #{@public_host_username} netstat -an | egrep "tcp.*:#{@public_port}.*LISTEN" | wc`.to_i > 0
23
+ puts "Seems ok"
24
+ else
25
+ puts "Down"
26
+ end
27
+ end
28
+
29
+ task :config => :environment do
30
+ facebook_config = File.join(Rails.root, 'config', 'faceb.yml')
31
+ FACEBOOKER = YAML.load(ERB.new(File.read(facebook_config)).result)[Rails.env]
32
+ @public_host_username = FACEBOOKER['tunnel']['public_host_username']
33
+ @public_host = FACEBOOKER['tunnel']['public_host']
34
+ @public_port = FACEBOOKER['tunnel']['public_port']
35
+ @local_port = FACEBOOKER['tunnel']['local_port']
36
+ @ssh_port = FACEBOOKER['tunnel']['ssh_port'] || 22
37
+ @server_alive_interval = FACEBOOKER['tunnel']['server_alive_interval'] || 0
38
+ @notification = "Starting tunnel #{@public_host}:#{@public_port} to 0.0.0.0:#{@local_port}"
39
+ @notification << " using SSH port #{@ssh_port}" unless @ssh_port == 22
40
+ # "GatewayPorts yes" needs to be enabled in the remote's sshd config
41
+ @ssh_command = %Q[ssh -v -p #{@ssh_port} -nNT4 -o "ServerAliveInterval #{@server_alive_interval}" -R *:#{@public_port}:localhost:#{@local_port} #{@public_host_username}@#{@public_host}]
42
+ end
43
+ end
44
+ desc "Create a reverse ssh tunnel from a public server to a private development server."
45
+ task :tunnel => tunnel_ns[:start]
46
+ end
@@ -0,0 +1,38 @@
1
+ module FaceB
2
+ class Session
3
+ attr_reader :api_key, :secret_key, :session_key, :user_facebook_uid
4
+
5
+ def self.create(api_key, secret_key, session_key = nil)
6
+ @current_session = self.new(api_key, secret_key, session_key) unless defined?(@current_session) && !!@current_session
7
+ @current_session
8
+ end
9
+
10
+ def self.current
11
+ @current_session
12
+ end
13
+
14
+ def self.reset!
15
+ @current_session = nil
16
+ end
17
+
18
+ def initialize(api_key, secret_key, session_key = nil)
19
+ @api_key = api_key
20
+ @secret_key = secret_key
21
+ @session_key = session_key
22
+ secure_with_session_key!(session_key) unless !session_key
23
+ end
24
+
25
+ def call(method, params ={})
26
+ Api.new(self).call(method, params)
27
+ end
28
+
29
+ def secure_with_session_key!(session_key)
30
+ @session_key = session_key
31
+ @user_facebook_uid = self.call('users.getLoggedInUser', :session_key => session_key).data
32
+ end
33
+
34
+ def secured?
35
+ !!@user_facebook_uid
36
+ end
37
+ end
38
+ end