challah-facebook 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.
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: []