challah-facebook 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## challah-facebook 0.1.0
2
+
3
+ * Basic Facebook authentication compatibility with Challah
data/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # challah-facebook
2
+
3
+ `challah-facebook` is an extension to the [Challah](http://github.com/jdtornow/challah) gem that allows users to register and authenticate with the Facebook graph API (Facebook Connect.)
4
+
5
+ ## Requirements
6
+
7
+ * Ruby 1.9.2+
8
+ * Bundler
9
+ * Rails 3.1+
10
+ * Challah Gem 0.9+
11
+
12
+ ## Installation
13
+
14
+ gem install challah
15
+ gem install challah-facebook
16
+
17
+ Or, in your `Gemfile`
18
+
19
+ gem 'challah', '>= 0.9'
20
+ gem 'challah-facebook'
21
+
22
+ ## License
23
+
24
+ `challah-facebook` is released under the [MIT license](http://www.opensource.org/licenses/MIT)
25
+
26
+ Contributions and pull-requests are more than welcome.
@@ -0,0 +1,36 @@
1
+ require 'challah/facebook/interfaces/base'
2
+
3
+ # Set up the proper interface depending on installed gems
4
+ if defined?(FbGraph)
5
+ require 'challah/facebook/interfaces/fb_graph'
6
+
7
+ module Challah
8
+ module Facebook
9
+ class Interface < Challah::Facebook::Interfaces::FbGraph
10
+ end
11
+ end
12
+ end
13
+ elsif defined?(Koala)
14
+ require 'challah/facebook/interfaces/koala'
15
+
16
+ module Challah
17
+ module Facebook
18
+ class Interface < Challah::Facebook::Interfaces::Koala
19
+ end
20
+ end
21
+ end
22
+ else
23
+ module Challah
24
+ module Facebook
25
+ class Interface
26
+ def self.mode
27
+ "none"
28
+ end
29
+
30
+ def method_missing
31
+ raise "No Facebook adapter found. Please install fb_graph or koala gem to use Facebook"
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,46 @@
1
+ module Challah
2
+ module Facebook
3
+ module Interfaces
4
+ class Base
5
+ attr_reader :app_id, :app_secret
6
+
7
+ def self.app_id
8
+ ENV['FACEBOOK_APP_ID']
9
+ end
10
+
11
+ def self.app_secret
12
+ ENV['FACEBOOK_SECRET']
13
+ end
14
+
15
+ def self.permissions
16
+ ENV['FACEBOOK_PERMISSIONS'].to_s.split(',')
17
+ end
18
+
19
+ def self.user_fields
20
+ %w( first_name last_name email )
21
+ end
22
+
23
+ def initialize(app_id, app_secret)
24
+ @app_id = app_id
25
+ @app_secret = app_secret
26
+ end
27
+
28
+ def self.get_access_token_for_oauth_code(code, callback_uri)
29
+ raise 'Not implemented: get_access_token_for_oauth_code'
30
+ end
31
+
32
+ def self.get_access_token_from_cookies(cookies_hash)
33
+ raise 'Not implemented: get_access_token_from_cookies'
34
+ end
35
+
36
+ def self.get_facebook_uid_from_access_token(access_token)
37
+ raise 'Not implemented: get_facebook_uid_from_access_token'
38
+ end
39
+
40
+ def self.get_authorization_url(callback_uri, permissions = nil)
41
+ raise 'Not implemented: get_authorization_url'
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,65 @@
1
+ module Challah
2
+ module Facebook
3
+ module Interfaces
4
+ class FbGraph < Base
5
+ def self.mode
6
+ "fb_graph"
7
+ end
8
+
9
+ def self.get_access_token_for_oauth_code(code, callback_uri)
10
+ client = new(app_id, app_secret).auth(callback_uri).client
11
+ client.authorization_code = code
12
+ client.access_token!(:client_auth_body).to_s
13
+ end
14
+
15
+ def self.get_access_token_from_cookies(cookies_hash)
16
+ fb_auth = new(app_id, app_secret).auth
17
+ fb_auth.from_cookie(cookies_hash)
18
+ fb_auth.access_token.to_s
19
+ rescue
20
+ nil
21
+ end
22
+
23
+ def self.get_extended_token(access_token)
24
+ fb_auth = new(app_id, app_secret).auth
25
+ fb_auth.exchange_token!(access_token)
26
+ fb_auth.access_token.to_s
27
+ end
28
+
29
+ def self.get_facebook_uid_from_access_token(access_token)
30
+ fb_user = ::FbGraph::User.me(access_token).fetch
31
+
32
+ if fb_user
33
+ return fb_user.identifier.to_s
34
+ end
35
+
36
+ nil
37
+ rescue
38
+ nil
39
+ end
40
+
41
+ def self.get_user_info_from_access_token(access_token)
42
+ result = {}
43
+
44
+ fb_user = ::FbGraph::User.me(access_token).fetch
45
+
46
+ self.user_fields.each do |field|
47
+ result[field] = fb_user.send(field)
48
+ end
49
+
50
+ result
51
+ end
52
+
53
+ def self.get_authorization_url(callback_uri, permissions = nil)
54
+ scope = self.permissions if scope.nil?
55
+ client = new(app_id, app_secret).auth(callback_uri).client
56
+ client.authorization_uri(scope: scope)
57
+ end
58
+
59
+ def auth(callback_uri = nil)
60
+ ::FbGraph::Auth.new(app_id, app_secret, redirect_uri: callback_uri)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,11 @@
1
+ module Challah
2
+ module Facebook
3
+ module Interfaces
4
+ class Koala < Base
5
+ def self.mode
6
+ "koala"
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,59 @@
1
+ module Challah
2
+ module Facebook
3
+ class Provider
4
+ def self.save(record)
5
+ set({
6
+ user_id: record.id,
7
+ token: record.facebook_provider.fetch(:token),
8
+ uid: record.facebook_provider.fetch(:uid)
9
+ })
10
+ end
11
+
12
+ def self.set(options = {})
13
+ user_id = options.fetch(:user_id)
14
+ uid = options.fetch(:uid, '')
15
+ token = options.fetch(:token, '')
16
+
17
+ ::Authorization.set({
18
+ provider: :facebook,
19
+ user_id: user_id,
20
+ uid: uid,
21
+ token: token
22
+ })
23
+ end
24
+
25
+ def self.valid?(user)
26
+ return false unless user.facebook_provider?
27
+
28
+ uid = user.facebook_provider.fetch(:uid).to_s.strip
29
+ token = user.facebook_provider.fetch(:token)
30
+
31
+ # Both a fb_uid and access token are required
32
+ if uid.present? and token.present?
33
+ if ::Authorization.where(provider: 'facebook', uid: uid).count > 0
34
+ user.errors.add :facebook, 'account has already been used'
35
+ return false
36
+ end
37
+
38
+ begin
39
+ # Get extended token
40
+ extended_token = Interface.get_extended_token(token)
41
+ user.facebook_provider[:token] = extended_token
42
+
43
+ # Verify UID
44
+ test_uid = Interface.get_facebook_uid_from_access_token(extended_token)
45
+
46
+ # If the uid's match up, this is a valid token
47
+ return test_uid == uid
48
+ rescue
49
+ return false
50
+ end
51
+
52
+ true
53
+ else
54
+ false
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,29 @@
1
+ module Challah
2
+ module Facebook
3
+ class Technique
4
+ def initialize(session)
5
+ @provider = session.provider? ? session.provider : nil
6
+ @token = session.token? ? session.token : nil
7
+ @uid = session.uid? ? session.uid : nil
8
+ end
9
+
10
+ def authenticate
11
+ return nil unless @provider == 'facebook'
12
+ return nil unless @token
13
+
14
+ token = Interface.get_extended_token(@token)
15
+ auth = ::Authorization.where(provider: 'facebook', token: token, uid: @uid).first
16
+
17
+ if auth
18
+ return auth.user
19
+ end
20
+
21
+ nil
22
+ end
23
+
24
+ def persist?
25
+ true
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,5 @@
1
+ module Challah
2
+ module Facebook
3
+ VERSION = "0.1.0" unless defined?(::Challah::Facebook::VERSION)
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ require 'challah/facebook/version'
2
+
3
+ module Challah
4
+ module Facebook
5
+ autoload :Interface, 'challah/facebook/interface'
6
+ autoload :Provider, 'challah/facebook/provider'
7
+ autoload :Technique, 'challah/facebook/technique'
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ require 'challah'
2
+ require 'challah/facebook'
3
+
4
+ if Challah.respond_to?(:register_technique)
5
+ Challah.register_technique :facebook, Challah::Facebook::Technique
6
+ Challah.register_provider :facebook, Challah::Facebook::Provider
7
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,121 @@
1
+ # Coverage reporting, needs to be loaded first to capture all code coverage stats
2
+ require 'simplecov'
3
+
4
+ # Setup a sample rails app for testing rails modules
5
+ sample_root = File.expand_path(File.join(File.dirname(__FILE__), '..', 'tmp', 'sampleapp'))
6
+ FileUtils.rm_rf(sample_root) if File.exists?(sample_root)
7
+ `rails new #{sample_root} --skip-bundle --skip-sprockets`
8
+
9
+ # Setup environment variables for the Rails instance
10
+ ENV['RAILS_ENV'] = 'test'
11
+ ENV['BUNDLE_GEMFILE'] ||= File.join(sample_root, 'Gemfile')
12
+
13
+ # Load the newly created rails instance environment
14
+ require "#{sample_root}/config/environment"
15
+
16
+ # Some other dependencies for testing w/ shoulda and factory girl
17
+ require 'shoulda'
18
+ require 'mocha/setup'
19
+ require 'factory_girl'
20
+ require 'factories'
21
+ require 'rails/test_help'
22
+
23
+ # Load the challah libraries
24
+ require 'challah'
25
+ require 'challah/facebook'
26
+ require 'challah/test'
27
+
28
+ # Setup the challah app, including running migrations within the rails app
29
+ # TODO - this causes some annoying output in 1.9.3, still works, but would like to suppress
30
+ `rake --rakefile #{File.join(sample_root, 'Rakefile')} challah:setup:migrations`
31
+
32
+ # Run migrations for the sample app, hiding output
33
+ ActiveRecord::Migration.verbose = false
34
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate")
35
+
36
+ # Use ActiveSupport::TestCase for any tests using factories and database saving,
37
+ # so we can have a transactional rollback after each test.
38
+ class ActiveSupport::TestCase
39
+ include FactoryGirl::Syntax::Methods
40
+
41
+ self.use_transactional_fixtures = true
42
+ end
43
+
44
+ class MockController
45
+ include Challah::Controller
46
+ include Challah::Rolls::Controller
47
+
48
+ attr_accessor :request, :session, :params
49
+
50
+ def initialize()
51
+ @request = MockRequest.new
52
+ @session ||= {}
53
+ @params ||= {}
54
+ end
55
+
56
+ def redirect_to(*args)
57
+ # do nothing
58
+ end
59
+
60
+ def login_path
61
+ "/login"
62
+ end
63
+
64
+ def logout_path
65
+ "/logout"
66
+ end
67
+
68
+ def signin_path
69
+ "/sign-in"
70
+ end
71
+
72
+ def signout_path
73
+ "/sign-out"
74
+ end
75
+ end
76
+
77
+ class MockRequest
78
+ attr_accessor :cookie_jar, :session_options, :url
79
+
80
+ class MockCookieJar < Hash
81
+ def delete(key, options = {})
82
+ super(key)
83
+ end
84
+ end
85
+
86
+ def initialize
87
+ @cookie_jar = MockCookieJar.new
88
+ @session_options = { :domain => 'test.dev' }
89
+ @url = "http://example.com/"
90
+ end
91
+
92
+ def cookies
93
+ @cookie_jar
94
+ end
95
+
96
+ def cookies=(value)
97
+ @cookie_jar = value
98
+ end
99
+
100
+ def remote_ip
101
+ "8.8.8.8"
102
+ end
103
+
104
+ def user_agent
105
+ "Some Cool Browser"
106
+ end
107
+ end
108
+
109
+ # Monkey patch fix for shoulda and Rails 3.1+.
110
+ module Shoulda
111
+ module ActiveRecord
112
+ module Matchers
113
+ class AssociationMatcher
114
+ protected
115
+ def foreign_key
116
+ reflection.foreign_key
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: challah-facebook
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - John Tornow
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-04 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: challah
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.9.0.pre
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: 0.9.0.pre
30
+ - !ruby/object:Gem::Dependency
31
+ name: rails
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '3.1'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '3.1'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.9.2
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.2
62
+ description: A Challah plugin to allow authentication and registration with Facebook
63
+ API.
64
+ email:
65
+ - john@johntornow.com
66
+ executables: []
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - test/helper.rb
71
+ - lib/challah/facebook/interface.rb
72
+ - lib/challah/facebook/interfaces/base.rb
73
+ - lib/challah/facebook/interfaces/fb_graph.rb
74
+ - lib/challah/facebook/interfaces/koala.rb
75
+ - lib/challah/facebook/provider.rb
76
+ - lib/challah/facebook/technique.rb
77
+ - lib/challah/facebook/version.rb
78
+ - lib/challah/facebook.rb
79
+ - lib/challah-facebook.rb
80
+ - README.md
81
+ - CHANGELOG.md
82
+ homepage: http://github.com/jdtornow/challah-facebook
83
+ licenses: []
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: 1.9.2
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubyforge_project:
102
+ rubygems_version: 1.8.23
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: Facebook authentication interface for Challah.
106
+ test_files: []