authpwn_rails 0.3.0 → 0.4.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/.project CHANGED
@@ -1,6 +1,6 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <projectDescription>
3
- <name>pwnauth_rails</name>
3
+ <name>authpwn_rails</name>
4
4
  <comment></comment>
5
5
  <projects>
6
6
  </projects>
data/README.rdoc CHANGED
@@ -4,7 +4,8 @@ User authentication for a Ruby on Rails 3 application. Works with Facebook.
4
4
 
5
5
  == Integration
6
6
 
7
- TBD
7
+ Generate the structure for user accounts:
8
+ rails g authpwn_rails
8
9
 
9
10
  == Note on Patches/Pull Requests
10
11
 
data/Rakefile CHANGED
@@ -11,9 +11,7 @@ begin
11
11
  gem.homepage = "http://github.com/costan/mini_auth_rails"
12
12
  gem.authors = ["Victor Costan"]
13
13
  gem.add_runtime_dependency "fbgraph_rails", ">= 0.1.3"
14
- gem.add_development_dependency "activerecord", ">= 3.0.0.rc"
15
- gem.add_development_dependency "actionpack", ">= 3.0.0.rc"
16
- gem.add_development_dependency "activesupport", ">= 3.0.0.rc"
14
+ gem.add_runtime_dependency "rails", ">= 3.0.0.rc"
17
15
  gem.add_development_dependency "sqlite3-ruby", ">= 1.3.0"
18
16
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
17
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
@@ -2,9 +2,35 @@
2
2
  class SessionController < ApplicationController
3
3
  authenticates_using_session
4
4
 
5
+ # GET /session
6
+ def show
7
+ @user = current_user || User.new
8
+ if @user.new_record?
9
+ render :action => :welcome
10
+ else
11
+ render :action => :home
12
+ end
13
+ end
14
+
15
+ # POST /session
16
+ def create
17
+ @user = User.new params[:user]
18
+ self.current_user =
19
+ User.find_by_email_and_password @user.email, @user.password
20
+
21
+ respond_to do |format|
22
+ if current_user
23
+ format.html { redirect_to session_url }
24
+ else
25
+ flash[:notice] = 'Invalid e-mail or password'
26
+ format.html { redirect_to session_url }
27
+ end
28
+ end
29
+ end
30
+
5
31
  # DELETE /session
6
32
  def destroy
7
33
  self.current_user = nil
8
- redirect_to root_url
34
+ redirect_to session_url
9
35
  end
10
36
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{authpwn_rails}
8
- s.version = "0.3.0"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Victor Costan"]
12
- s.date = %q{2010-08-02}
12
+ s.date = %q{2010-08-03}
13
13
  s.description = %q{Works with Facebook.}
14
14
  s.email = %q{victor@costan.us}
15
15
  s.extra_rdoc_files = [
@@ -26,22 +26,24 @@ Gem::Specification.new do |s|
26
26
  "VERSION",
27
27
  "app/controllers/session_controller.rb",
28
28
  "app/helpers/session_helper.rb",
29
- "app/models/facebook_token.rb",
30
- "app/models/user.rb",
31
29
  "authpwn_rails.gemspec",
32
30
  "config/routes.rb",
33
31
  "lib/authpwn_rails.rb",
34
32
  "lib/authpwn_rails/engine.rb",
35
- "lib/authpwn_rails/facebook_token.rb",
36
- "lib/authpwn_rails/generators/facebook_migration_generator.rb",
33
+ "lib/authpwn_rails/facebook_extensions.rb",
34
+ "lib/authpwn_rails/generators/facebook_generator.rb",
35
+ "lib/authpwn_rails/generators/session_views_generator.rb",
37
36
  "lib/authpwn_rails/generators/templates/001_create_users.rb",
38
37
  "lib/authpwn_rails/generators/templates/002_create_facebook_tokens.rb",
39
38
  "lib/authpwn_rails/generators/templates/facebook_token.rb",
40
39
  "lib/authpwn_rails/generators/templates/facebook_tokens.yml",
40
+ "lib/authpwn_rails/generators/templates/session/home.html.erb",
41
+ "lib/authpwn_rails/generators/templates/session/welcome.html.erb",
41
42
  "lib/authpwn_rails/generators/templates/user.rb",
42
43
  "lib/authpwn_rails/generators/templates/users.yml",
43
- "lib/authpwn_rails/generators/user_migration_generator.rb",
44
+ "lib/authpwn_rails/generators/user_generator.rb",
44
45
  "lib/authpwn_rails/session.rb",
46
+ "lib/authpwn_rails/user_model.rb",
45
47
  "test/cookie_controller_test.rb",
46
48
  "test/facebook_controller_test.rb",
47
49
  "test/facebook_token_test.rb",
@@ -49,6 +51,7 @@ Gem::Specification.new do |s|
49
51
  "test/helpers/db_setup.rb",
50
52
  "test/helpers/fbgraph.rb",
51
53
  "test/helpers/routes.rb",
54
+ "test/helpers/view_helpers.rb",
52
55
  "test/session_controller_test.rb",
53
56
  "test/test_helper.rb",
54
57
  "test/user_test.rb"
@@ -68,7 +71,8 @@ Gem::Specification.new do |s|
68
71
  "test/helpers/application_controller.rb",
69
72
  "test/helpers/routes.rb",
70
73
  "test/helpers/fbgraph.rb",
71
- "test/helpers/db_setup.rb"
74
+ "test/helpers/db_setup.rb",
75
+ "test/helpers/view_helpers.rb"
72
76
  ]
73
77
 
74
78
  if s.respond_to? :specification_version then
@@ -77,22 +81,16 @@ Gem::Specification.new do |s|
77
81
 
78
82
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
79
83
  s.add_runtime_dependency(%q<fbgraph_rails>, [">= 0.1.3"])
80
- s.add_development_dependency(%q<activerecord>, [">= 3.0.0.rc"])
81
- s.add_development_dependency(%q<actionpack>, [">= 3.0.0.rc"])
82
- s.add_development_dependency(%q<activesupport>, [">= 3.0.0.rc"])
84
+ s.add_runtime_dependency(%q<rails>, [">= 3.0.0.rc"])
83
85
  s.add_development_dependency(%q<sqlite3-ruby>, [">= 1.3.0"])
84
86
  else
85
87
  s.add_dependency(%q<fbgraph_rails>, [">= 0.1.3"])
86
- s.add_dependency(%q<activerecord>, [">= 3.0.0.rc"])
87
- s.add_dependency(%q<actionpack>, [">= 3.0.0.rc"])
88
- s.add_dependency(%q<activesupport>, [">= 3.0.0.rc"])
88
+ s.add_dependency(%q<rails>, [">= 3.0.0.rc"])
89
89
  s.add_dependency(%q<sqlite3-ruby>, [">= 1.3.0"])
90
90
  end
91
91
  else
92
92
  s.add_dependency(%q<fbgraph_rails>, [">= 0.1.3"])
93
- s.add_dependency(%q<activerecord>, [">= 3.0.0.rc"])
94
- s.add_dependency(%q<actionpack>, [">= 3.0.0.rc"])
95
- s.add_dependency(%q<activesupport>, [">= 3.0.0.rc"])
93
+ s.add_dependency(%q<rails>, [">= 3.0.0.rc"])
96
94
  s.add_dependency(%q<sqlite3-ruby>, [">= 1.3.0"])
97
95
  end
98
96
  end
data/lib/authpwn_rails.rb CHANGED
@@ -2,8 +2,9 @@
2
2
  module AuthpwnRails
3
3
  end
4
4
 
5
- require 'authpwn_rails/facebook_token.rb'
5
+ require 'authpwn_rails/facebook_extensions.rb'
6
6
  require 'authpwn_rails/session.rb'
7
+ require 'authpwn_rails/user_model.rb'
7
8
 
8
9
  if defined?(Rails)
9
10
  require 'authpwn_rails/engine.rb'
@@ -1,4 +1,4 @@
1
- require 'mini_auth_rails'
1
+ require 'authpwn_rails'
2
2
  require 'rails'
3
3
 
4
4
  # :nodoc: namespace
@@ -17,8 +17,10 @@ class Engine < Rails::Engine
17
17
  # paths.config.locales = "config/locales"
18
18
  paths.config.routes = "config/routes.rb"
19
19
 
20
- def generators
21
- require 'mini_auth_rails/generators/user_model_generator.rb'
20
+ generators do
21
+ require 'authpwn_rails/generators/facebook_generator.rb'
22
+ require 'authpwn_rails/generators/session_views_generator.rb'
23
+ require 'authpwn_rails/generators/user_generator.rb'
22
24
  end
23
25
  end # class AuthpwnRails::Engine
24
26
 
@@ -0,0 +1,121 @@
1
+ require 'action_controller'
2
+ require 'active_record'
3
+
4
+ # :nodoc: namespace
5
+ module AuthpwnRails
6
+
7
+ # :nodoc: namespace
8
+ module FacebookExtensions
9
+
10
+
11
+ # Mixed into ActiveController::Base
12
+ module ControllerMixin
13
+ def self.included(base)
14
+ base.send :extend, ControllerClassMethods
15
+ end
16
+ end
17
+
18
+
19
+ # Methods here become ActiveController::Base class methods.
20
+ module ControllerClassMethods
21
+ # Authenticates users via Facebook OAuth2, using fbgraph_rails.
22
+ #
23
+ # The User model class must implement for_facebook_token. The controller
24
+ # should obtain the Facebook token, using probes_facebook_access_token or
25
+ # requires_facebook_access_token.
26
+ def authenticates_using_facebook(options = {})
27
+ include ControllerInstanceMethods
28
+ before_filter :authenticate_using_facebook_access_token, options
29
+ end
30
+ end # module AuthpwnRails::FacebookExtensions::ControllerClassMethods
31
+
32
+
33
+ # Included in controllers that call authenticates_using_facebook.
34
+ module ControllerInstanceMethods
35
+ def authenticate_using_facebook_access_token
36
+ return true if current_user
37
+ if access_token = current_facebook_access_token
38
+ self.current_user = User.for_facebook_token access_token
39
+ # NOTE: nixing the token from the session so the user won't be logged on
40
+ # immediately after logging off
41
+ self.current_facebook_access_token = nil
42
+ end
43
+ end
44
+ private :authenticate_using_facebook_access_token
45
+ end # module AuthpwnRails::FacebookExtensions::ControllerInstanceMethods
46
+
47
+ ActionController::Base.send :include, ControllerMixin
48
+
49
+
50
+ # Mixed into ActiveRecord::Base
51
+ module ModelMixin
52
+ def self.included(base)
53
+ base.send :extend, ModelClassMethods
54
+ end
55
+ end
56
+
57
+
58
+ # Methods here become ActiveRecord::Base class methods.
59
+ module ModelClassMethods
60
+ # Extends the model with all that it needs to be PwnAuth's user model.
61
+ def pwnauth_facebook_token_model
62
+ # The user whose token this is.
63
+ belongs_to :user
64
+ validates :user, :presence => true
65
+
66
+ # A unique ID on the Facebook site for the user owning this token.
67
+ validates :external_uid, :length => 1..32, :presence => true
68
+
69
+ # The OAuth2 access token.
70
+ validates :access_token, :length => 1..128, :presence => true
71
+
72
+ extend ModelMetaclassMethods
73
+ include ModelInstanceMethods
74
+ end
75
+ end # module AuthpwnRails::UserModel::ModelClassMethods
76
+
77
+
78
+ # Included in the metaclass of models that call pwnauth_facebook_token_model.
79
+ module ModelMetaclassMethods
80
+ # Finds or creates the model containing a token.
81
+ #
82
+ # If a model for the same user exists, the model is updated with the given
83
+ # token. Otherwise, a new model will be created, together with a user.
84
+ def for(access_token)
85
+ uid = uid_from_token access_token
86
+ token = self.where(:external_uid => uid).first
87
+ if token
88
+ token.access_token = access_token
89
+ else
90
+ token = FacebookToken.new :external_uid => uid,
91
+ :access_token => access_token
92
+ token.user = User.create_with_facebook_token token
93
+ end
94
+ token.save!
95
+ token
96
+ end
97
+
98
+ # Extracts the Facebook user ID from a OAuth2 token.
99
+ #
100
+ # This is a hack. It works based on the current format, but might break at any
101
+ # time. Hopefully, we'll eventually have an official way of pulling the UID
102
+ # out of an OAuth2 token.
103
+ def uid_from_token(access_token)
104
+ access_token.split('|')[1].split('-').last
105
+ end
106
+ end # module AuthpwnRails::UserModel::ModelMetaclassMethods
107
+
108
+
109
+ # Included in models that call pwnauth_user_model.
110
+ module ModelInstanceMethods
111
+ # FBGraph client loaded with this access token.
112
+ def facebook_client
113
+ @client ||= FBGraphRails.fbclient(access_token)
114
+ end
115
+ end # module AuthpwnRails::UserModel::ModelInstanceMethods
116
+
117
+ ActiveRecord::Base.send :include, ModelMixin
118
+
119
+ end # namespace AuthpwnRails::FacebookExtensions
120
+
121
+ end # namespace AuthpwnRails
@@ -0,0 +1,18 @@
1
+ # :nodoc: namespace
2
+ module AuthpwnRails
3
+
4
+
5
+ class FacebookGenerator < Rails::Generators::Base
6
+ source_root File.expand_path("../templates", __FILE__)
7
+
8
+ def create_facebook_model
9
+ copy_file 'facebook_token.rb',
10
+ File.join('app', 'models', 'facebook_token.rb')
11
+ copy_file '002_create_facebook_tokens.rb',
12
+ File.join('db', 'migrations', '20100725000002_create_facebook_tokens.rb')
13
+ copy_file 'facebook_tokens.yml',
14
+ File.join('test', 'fixtures', 'facebook_tokens.yml')
15
+ end
16
+ end # class AuthpwnRails::FacebookGenerator
17
+
18
+ end # namespace AuthpwnRails
@@ -0,0 +1,16 @@
1
+ # :nodoc: namespace
2
+ module AuthpwnRails
3
+
4
+
5
+ class SessionViewsGenerator < Rails::Generators::Base
6
+ source_root File.expand_path("../templates", __FILE__)
7
+
8
+ def create_session_views
9
+ copy_file File.join('session', 'home.html.erb'),
10
+ File.join('app', 'views', 'session', 'home.html.erb')
11
+ copy_file File.join('session', 'welcome.html.erb'),
12
+ File.join('app', 'views', 'session', 'welcome.html.erb')
13
+ end
14
+ end # class AuthpwnRails::SessionViewsGenerator
15
+
16
+ end # namespace AuthpwnRails
@@ -1,5 +1,6 @@
1
- # :nodoc: extensions
2
- class FacebookToken
3
- # Add your extensions to the FacebookToken class here.
4
-
1
+ # Wraps an OAuth2 access token for Facebook.
2
+ class FacebookToken < ActiveRecord::Base
3
+ pwnauth_facebook_token_model
4
+
5
+ # Add your extensions to the FacebookToken class here.
5
6
  end
@@ -0,0 +1,4 @@
1
+ <p>
2
+ This view gets displayed when the user is logged in. Right now,
3
+ <%= @current_user.email %> is logged in.
4
+ </p>
@@ -0,0 +1,4 @@
1
+ <p>
2
+ This view gets displayed when the user is not logged in. Entice the user to
3
+ register for your application, and give them a login form.
4
+ </p>
@@ -1,5 +1,6 @@
1
- # :nodoc: extensions
2
- class User
3
- # Add your extensions to the User class here.
4
-
1
+ # An user account.
2
+ class User < ActiveRecord::Base
3
+ pwnauth_user_model
4
+
5
+ # Add your extensions to the User class here.
5
6
  end
@@ -0,0 +1,16 @@
1
+ # :nodoc: namespace
2
+ module AuthpwnRails
3
+
4
+
5
+ class UserGenerator < Rails::Generators::Base
6
+ source_root File.expand_path("../templates", __FILE__)
7
+
8
+ def create_user_model
9
+ copy_file 'user.rb', File.join('app', 'models', 'user.rb')
10
+ copy_file '001_create_users.rb',
11
+ File.join('db', 'migrations', '20100725000001_create_users.rb')
12
+ copy_file 'users.yml', File.join('test', 'fixtures', 'users.yml')
13
+ end
14
+ end # class AuthpwnRails::UserGenerator
15
+
16
+ end # namespace AuthpwnRails
@@ -56,6 +56,12 @@ class ActionController::TestCase
56
56
  def set_session_current_user(user)
57
57
  request.session[:current_user_id] = user ? user.id : nil
58
58
  end
59
+
60
+ # The authenticated user in the test session.
61
+ def session_current_user
62
+ return nil unless user_id = request.session[:current_user_id]
63
+ User.find user_id
64
+ end
59
65
  end
60
66
 
61
67
  end # namespace AuthpwnRails::Session
@@ -0,0 +1,105 @@
1
+ require 'active_record'
2
+
3
+ # :nodoc: namespace
4
+ module AuthpwnRails
5
+
6
+ # :nodoc: namespace
7
+ module UserModel
8
+
9
+
10
+ # Mixed into ActiveRecord::Base
11
+ module ModelMixin
12
+ def self.included(base)
13
+ base.send :extend, ModelClassMethods
14
+ end
15
+ end
16
+
17
+
18
+ # Methods here become ActiveRecord::Base class methods.
19
+ module ModelClassMethods
20
+ # Extends the model with all that it needs to be PwnAuth's user model.
21
+ def pwnauth_user_model
22
+ # E-mail address identifying the user account.
23
+ validates :email, :format => /^[A-Za-z0-9.+_]+@[^@]*\.(\w+)$/,
24
+ :presence => true, :length => 1..64, :uniqueness => true
25
+
26
+ # Random string preventing dictionary attacks on the password database.
27
+ validates :password_salt, :length => 1..16, :allow_nil => true
28
+
29
+ # SHA-256 of (salt + password).
30
+ validates :password_hash, :length => 1..64, :allow_nil => true
31
+
32
+ # Virtual attribute: the user's password.
33
+ attr_reader :password
34
+ validates :password, :confirmation => true
35
+
36
+ # Virtual attribute: confirmation for the user's password.
37
+ attr_accessor :password_confirmation
38
+ validates_confirmation_of :password
39
+
40
+ extend ModelMetaclassMethods
41
+ include ModelInstanceMethods
42
+ end
43
+ end # module AuthpwnRails::UserModel::ModelClassMethods
44
+
45
+
46
+ # Included in the metaclass of models that call pwnauth_user_model.
47
+ module ModelMetaclassMethods
48
+ # The authenticated user or nil.
49
+ def find_by_email_and_password(email, password)
50
+ @user = where(:email => email).first
51
+ (@user && @user.password_matches?(password)) ? @user : nil
52
+ end
53
+
54
+ # Computes a password hash from a raw password and a salt.
55
+ def hash_password(password, salt)
56
+ Digest::SHA2.hexdigest(password + salt)
57
+ end
58
+
59
+ # Generates a random salt value.
60
+ def random_salt
61
+ (0...16).map { |i| 1 + rand(255) }.pack('C*')
62
+ end
63
+
64
+ # Fills out a new user's information based on a Facebook access token.
65
+ def create_with_facebook_token(token)
66
+ self.create :email => "#{token.external_uid}@graph.facebook.com"
67
+ end
68
+
69
+ # The user that owns a given Facebook OAuth2 token.
70
+ #
71
+ # A new user will be created if the token doesn't belong to any user. This is
72
+ # the case for a new visitor.
73
+ def for_facebook_token(access_token)
74
+ FacebookToken.for(access_token).user
75
+ end
76
+ end # module AuthpwnRails::UserModel::ModelMetaclassMethods
77
+
78
+
79
+ # Included in models that call pwnauth_user_model.
80
+ module ModelInstanceMethods
81
+ # Resets the virtual password attributes.
82
+ def reset_password
83
+ @password = @password_confirmation = nil
84
+ end
85
+
86
+ # Compares the given password against the user's stored password.
87
+ #
88
+ # Returns +true+ for a match, +false+ otherwise.
89
+ def password_matches?(passwd)
90
+ password_hash == self.class.hash_password(passwd, password_salt)
91
+ end
92
+
93
+ # Password virtual attribute.
94
+ def password=(new_password)
95
+ @password = new_password
96
+ self.password_salt = self.class.random_salt
97
+ self.password_hash = self.class.hash_password new_password, password_salt
98
+ end
99
+ end # module AuthpwnRails::UserModel::ModelInstanceMethods
100
+
101
+ ActiveRecord::Base.send :include, ModelMixin
102
+
103
+ end # namespace AuthpwnRails::UserModel
104
+
105
+ end # namespace AuthpwnRails
@@ -1,3 +1,5 @@
1
1
  # :nodoc: stubbed, because controllers inherit from it
2
2
  class ApplicationController < ActionController::Base
3
+ prepend_view_path File.expand_path(
4
+ '../../../lib/authpwn_rails/generators/templates', __FILE__)
3
5
  end
@@ -8,8 +8,8 @@ CreateUsers.up
8
8
  require 'authpwn_rails/generators/templates/002_create_facebook_tokens.rb'
9
9
  CreateFacebookTokens.up
10
10
 
11
- require File.expand_path('../../../app/models/facebook_token.rb', __FILE__)
12
- require File.expand_path('../../../app/models/user.rb', __FILE__)
11
+ require 'authpwn_rails/generators/templates/facebook_token.rb'
12
+ require 'authpwn_rails/generators/templates/user.rb'
13
13
 
14
14
  # :nodoc: open TestCase to setup fixtures
15
15
  class ActiveSupport::TestCase
@@ -18,6 +18,7 @@ class ActiveSupport::TestCase
18
18
  self.fixture_path =
19
19
  File.expand_path '../../../lib/authpwn_rails/generators/templates',
20
20
  __FILE__
21
+
21
22
  self.use_transactional_fixtures = false
22
23
  self.use_instantiated_fixtures = false
23
24
  self.pre_loaded_fixtures = false
@@ -0,0 +1,2 @@
1
+ require File.expand_path('../../../app/helpers/session_helper.rb', __FILE__)
2
+ ActionController::Base.helper SessionHelper
@@ -6,12 +6,46 @@ class SessionControllerTest < ActionController::TestCase
6
6
  setup do
7
7
  @user = users(:john)
8
8
  end
9
+
10
+ test "show renders welcome without a user" do
11
+ get :show
12
+ assert_template :welcome
13
+ assert_nil assigns(:current_user)
14
+ end
15
+
16
+ test "show renders home with a user" do
17
+ set_session_current_user @user
18
+ get :show
19
+ assert_template :home
20
+ assert_equal @user, assigns(:current_user)
21
+ end
22
+
23
+ test "create logs in with good account details" do
24
+ post :create, :user => { :email => @user.email, :password => 'password' }
25
+ assert_redirected_to session_url
26
+ assert_equal @user, assigns(:current_user), 'instance variable'
27
+ assert_equal @user, session_current_user, 'session'
28
+ end
29
+
30
+ test "create does not log in with bad password" do
31
+ post :create, :user => { :email => @user.email, :password => 'fail' }
32
+ assert_redirected_to session_url
33
+ assert_nil assigns(:current_user), 'instance variable'
34
+ assert_nil session_current_user, 'session'
35
+ end
36
+
37
+ test "create does not log in with bad e-mail" do
38
+ post :create, :user => { :email => 'nobody@gmail.com', :password => 'no' }
39
+ assert_redirected_to session_url
40
+ assert_nil assigns(:current_user), 'instance variable'
41
+ assert_nil session_current_user, 'session'
42
+ end
9
43
 
10
44
  test "logout" do
11
45
  set_session_current_user @user
12
46
  delete :destroy
13
47
 
14
- assert_redirected_to root_url
48
+ assert_redirected_to session_url
15
49
  assert_nil assigns(:current_user)
16
50
  end
17
51
  end
data/test/test_helper.rb CHANGED
@@ -15,3 +15,4 @@ require 'helpers/application_controller.rb'
15
15
  require 'helpers/db_setup.rb'
16
16
  require 'helpers/fbgraph.rb'
17
17
  require 'helpers/routes.rb'
18
+ require 'helpers/view_helpers.rb'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: authpwn_rails
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
8
+ - 4
9
9
  - 0
10
- version: 0.3.0
10
+ version: 0.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Victor Costan
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-02 00:00:00 -04:00
18
+ date: 2010-08-03 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -35,7 +35,7 @@ dependencies:
35
35
  type: :runtime
36
36
  version_requirements: *id001
37
37
  - !ruby/object:Gem::Dependency
38
- name: activerecord
38
+ name: rails
39
39
  prerelease: false
40
40
  requirement: &id002 !ruby/object:Gem::Requirement
41
41
  none: false
@@ -49,46 +49,12 @@ dependencies:
49
49
  - 0
50
50
  - rc
51
51
  version: 3.0.0.rc
52
- type: :development
52
+ type: :runtime
53
53
  version_requirements: *id002
54
- - !ruby/object:Gem::Dependency
55
- name: actionpack
56
- prerelease: false
57
- requirement: &id003 !ruby/object:Gem::Requirement
58
- none: false
59
- requirements:
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- hash: 7712042
63
- segments:
64
- - 3
65
- - 0
66
- - 0
67
- - rc
68
- version: 3.0.0.rc
69
- type: :development
70
- version_requirements: *id003
71
- - !ruby/object:Gem::Dependency
72
- name: activesupport
73
- prerelease: false
74
- requirement: &id004 !ruby/object:Gem::Requirement
75
- none: false
76
- requirements:
77
- - - ">="
78
- - !ruby/object:Gem::Version
79
- hash: 7712042
80
- segments:
81
- - 3
82
- - 0
83
- - 0
84
- - rc
85
- version: 3.0.0.rc
86
- type: :development
87
- version_requirements: *id004
88
54
  - !ruby/object:Gem::Dependency
89
55
  name: sqlite3-ruby
90
56
  prerelease: false
91
- requirement: &id005 !ruby/object:Gem::Requirement
57
+ requirement: &id003 !ruby/object:Gem::Requirement
92
58
  none: false
93
59
  requirements:
94
60
  - - ">="
@@ -100,7 +66,7 @@ dependencies:
100
66
  - 0
101
67
  version: 1.3.0
102
68
  type: :development
103
- version_requirements: *id005
69
+ version_requirements: *id003
104
70
  description: Works with Facebook.
105
71
  email: victor@costan.us
106
72
  executables: []
@@ -120,22 +86,24 @@ files:
120
86
  - VERSION
121
87
  - app/controllers/session_controller.rb
122
88
  - app/helpers/session_helper.rb
123
- - app/models/facebook_token.rb
124
- - app/models/user.rb
125
89
  - authpwn_rails.gemspec
126
90
  - config/routes.rb
127
91
  - lib/authpwn_rails.rb
128
92
  - lib/authpwn_rails/engine.rb
129
- - lib/authpwn_rails/facebook_token.rb
130
- - lib/authpwn_rails/generators/facebook_migration_generator.rb
93
+ - lib/authpwn_rails/facebook_extensions.rb
94
+ - lib/authpwn_rails/generators/facebook_generator.rb
95
+ - lib/authpwn_rails/generators/session_views_generator.rb
131
96
  - lib/authpwn_rails/generators/templates/001_create_users.rb
132
97
  - lib/authpwn_rails/generators/templates/002_create_facebook_tokens.rb
133
98
  - lib/authpwn_rails/generators/templates/facebook_token.rb
134
99
  - lib/authpwn_rails/generators/templates/facebook_tokens.yml
100
+ - lib/authpwn_rails/generators/templates/session/home.html.erb
101
+ - lib/authpwn_rails/generators/templates/session/welcome.html.erb
135
102
  - lib/authpwn_rails/generators/templates/user.rb
136
103
  - lib/authpwn_rails/generators/templates/users.yml
137
- - lib/authpwn_rails/generators/user_migration_generator.rb
104
+ - lib/authpwn_rails/generators/user_generator.rb
138
105
  - lib/authpwn_rails/session.rb
106
+ - lib/authpwn_rails/user_model.rb
139
107
  - test/cookie_controller_test.rb
140
108
  - test/facebook_controller_test.rb
141
109
  - test/facebook_token_test.rb
@@ -143,6 +111,7 @@ files:
143
111
  - test/helpers/db_setup.rb
144
112
  - test/helpers/fbgraph.rb
145
113
  - test/helpers/routes.rb
114
+ - test/helpers/view_helpers.rb
146
115
  - test/session_controller_test.rb
147
116
  - test/test_helper.rb
148
117
  - test/user_test.rb
@@ -191,3 +160,4 @@ test_files:
191
160
  - test/helpers/routes.rb
192
161
  - test/helpers/fbgraph.rb
193
162
  - test/helpers/db_setup.rb
163
+ - test/helpers/view_helpers.rb
@@ -1,47 +0,0 @@
1
- require 'active_record'
2
-
3
-
4
- # Wraps an OAuth2 access token for Facebook.
5
- class FacebookToken < ActiveRecord::Base
6
- # The user whose token this is.
7
- belongs_to :user
8
- validates :user, :presence => true
9
-
10
- # A unique ID on the Facebook site for the user owning this token.
11
- validates :external_uid, :length => 1..32, :presence => true
12
-
13
- # The OAuth2 access token.
14
- validates :access_token, :length => 1..128, :presence => true
15
-
16
- # FBGraph client loaded with this access token.
17
- def facebook_client
18
- @client ||= FBGraphRails.fbclient(access_token)
19
- end
20
-
21
- # Finds or creates the model containing a token.
22
- #
23
- # If a model for the same user exists, the model is updated with the given
24
- # token. Otherwise, a new model will be created, together with a user.
25
- def self.for(access_token)
26
- uid = uid_from_token access_token
27
- token = self.where(:external_uid => uid).first
28
- if token
29
- token.access_token = access_token
30
- else
31
- token = FacebookToken.new :external_uid => uid,
32
- :access_token => access_token
33
- token.user = User.create_with_facebook_token token
34
- end
35
- token.save!
36
- token
37
- end
38
-
39
- # Extracts the Facebook user ID from a OAuth2 token.
40
- #
41
- # This is a hack. It works based on the current format, but might break at any
42
- # time. Hopefully, we'll eventually have an official way of pulling the UID
43
- # out of an OAuth2 token.
44
- def self.uid_from_token(access_token)
45
- access_token.split('|')[1].split('-').last
46
- end
47
- end
data/app/models/user.rb DELETED
@@ -1,70 +0,0 @@
1
- require 'active_record'
2
-
3
-
4
- # An user account.
5
- class User < ActiveRecord::Base
6
- # E-mail address identifying the user account.
7
- validates :email, :format => /^[A-Za-z0-9.+_]+@[^@]*\.(\w+)$/,
8
- :presence => true, :length => 1..64, :uniqueness => true
9
-
10
- # Random string preventing dictionary attacks on the password database.
11
- validates :password_salt, :length => 1..16, :allow_nil => true
12
-
13
- # SHA-256 of (salt + password).
14
- validates :password_hash, :length => 1..64, :allow_nil => true
15
-
16
- # Virtual attribute: the user's password.
17
- attr_reader :password
18
- validates :password, :confirmation => true
19
- def password=(new_password)
20
- @password = new_password
21
- self.password_salt = self.class.random_salt
22
- self.password_hash = self.class.hash_password new_password, password_salt
23
- end
24
-
25
- # Virtual attribute: confirmation for the user's password.
26
- attr_accessor :password_confirmation
27
- validates_confirmation_of :password
28
-
29
- # The authenticated user or nil.
30
- def self.find_by_email_and_password(email, password)
31
- @user = User.where(:email => email).first
32
- (@user && @user.password_matches?(password)) ? @user : nil
33
- end
34
-
35
- # Compares the given password against the user's stored password.
36
- #
37
- # Returns +true+ for a match, +false+ otherwise.
38
- def password_matches?(passwd)
39
- password_hash == User.hash_password(passwd, password_salt)
40
- end
41
-
42
- # Computes a password hash from a raw password and a salt.
43
- def self.hash_password(password, salt)
44
- Digest::SHA2.hexdigest(password + salt)
45
- end
46
-
47
- # Generates a random salt value.
48
- def self.random_salt
49
- (0...16).map { |i| 1 + rand(255) }.pack('C*')
50
- end
51
-
52
- # Resets the virtual password attributes.
53
- def reset_password
54
- @password = @password_confirmation = nil
55
- end
56
-
57
-
58
- # Fills out a new user's information based on a Facebook access token.
59
- def self.create_with_facebook_token(token)
60
- self.create :email => "#{token.external_uid}@graph.facebook.com"
61
- end
62
-
63
- # The user that owns a given Facebook OAuth2 token.
64
- #
65
- # A new user will be created if the token doesn't belong to any user. This is
66
- # the case for a new visitor.
67
- def self.for_facebook_token(access_token)
68
- FacebookToken.for(access_token).user
69
- end
70
- end
@@ -1,44 +0,0 @@
1
- require 'action_controller'
2
-
3
- # :nodoc: namespace
4
- module AuthpwnRails
5
-
6
- # :nodoc: namespace
7
- module FacebookToken
8
-
9
- # Mixed into ActiveController::Base
10
- module ControllerMixin
11
- def self.included(base)
12
- base.send :extend, ControllerClassMethods
13
- end
14
- end
15
-
16
- # Methods here become ActiveController::Base class methods.
17
- module ControllerClassMethods
18
- # Authenticates users via Facebook OAuth2, using fbgraph_rails.
19
- #
20
- # The User model class must implement for_facebook_token. The controller
21
- # should obtain the Facebook token, using probes_facebook_access_token or
22
- # requires_facebook_access_token.
23
- def authenticates_using_facebook(options = {})
24
- include ControllerInstanceMethods
25
- before_filter :authenticate_using_facebook_access_token, options
26
- end
27
- end
28
-
29
- # Included in controllers that call authenticates_using_facebook.
30
- module ControllerInstanceMethods
31
- def authenticate_using_facebook_access_token
32
- return true if current_user
33
- if access_token = current_facebook_access_token
34
- self.current_user = User.for_facebook_token access_token
35
- end
36
- end
37
- private :authenticate_using_facebook_access_token
38
- end
39
-
40
- ActionController::Base.send :include, ControllerMixin
41
-
42
- end # namespace AuthpwnRails::FacebookToken
43
-
44
- end # namespace AuthpwnRails
@@ -1,17 +0,0 @@
1
- # :nodoc: namespace
2
- module AuthpwnRails
3
-
4
-
5
- class FacebookMigrationGenerator < Rails::Generators::Base
6
- source_root File.expand_path("../templates", __FILE__)
7
-
8
- def create_session_model
9
- template 'facebook_token.rb',
10
- File.join('app/models', class_path, 'facebook_token.rb')
11
- template '002_create_facebook_tokens.rb',
12
- File.join('db/migrations', '20100725000002_create_facebook_tokens.rb')
13
- template 'facebook_tokens.yml', File.join('test/fixtures', 'facebook_tokens.yml')
14
- end
15
- end # class AuthpwnRails::UserMigrationGenerator
16
-
17
- end # namespace AuthpwnRails
@@ -1,17 +0,0 @@
1
- # :nodoc: namespace
2
- module AuthpwnRails
3
-
4
-
5
- class UserMigrationGenerator < Rails::Generators::Base
6
- source_root File.expand_path("../templates", __FILE__)
7
-
8
- def create_session_model
9
- template 'user_token.rb',
10
- File.join('app/models', class_path, 'user.rb')
11
- template '001_create_users.rb',
12
- File.join('db/migrations', '20100725000001_create_users.rb')
13
- template 'users.yml', File.join('test/fixtures', 'users.yml')
14
- end
15
- end # class AuthpwnRails::UserMigrationGenerator
16
-
17
- end # namespace AuthpwnRails