authpwn_rails 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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