authpwn_rails 0.8.3 → 0.9.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/VERSION +1 -1
- data/authpwn_rails.gemspec +6 -4
- data/lib/authpwn_rails/facebook_session.rb +33 -0
- data/lib/authpwn_rails/facebook_token_model.rb +66 -0
- data/lib/authpwn_rails/generators/templates/facebook_token.rb +1 -1
- data/lib/authpwn_rails/generators/templates/session_controller.rb +1 -1
- data/lib/authpwn_rails/generators/templates/user.rb +1 -1
- data/lib/authpwn_rails/session.rb +10 -117
- data/lib/authpwn_rails/session_controller.rb +102 -0
- data/lib/authpwn_rails/user_model.rb +83 -99
- data/lib/authpwn_rails.rb +3 -1
- data/test/cookie_controller_test.rb +2 -1
- metadata +27 -25
- data/lib/authpwn_rails/facebook_extensions.rb +0 -121
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.9.0
|
data/authpwn_rails.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{authpwn_rails}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.9.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = [%q{Victor Costan}]
|
12
|
-
s.date = %q{2011-07-
|
12
|
+
s.date = %q{2011-07-05}
|
13
13
|
s.description = %q{Works with Facebook.}
|
14
14
|
s.email = %q{victor@costan.us}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -29,7 +29,8 @@ Gem::Specification.new do |s|
|
|
29
29
|
"authpwn_rails.gemspec",
|
30
30
|
"lib/authpwn_rails.rb",
|
31
31
|
"lib/authpwn_rails/engine.rb",
|
32
|
-
"lib/authpwn_rails/
|
32
|
+
"lib/authpwn_rails/facebook_session.rb",
|
33
|
+
"lib/authpwn_rails/facebook_token_model.rb",
|
33
34
|
"lib/authpwn_rails/generators/facebook_generator.rb",
|
34
35
|
"lib/authpwn_rails/generators/session_generator.rb",
|
35
36
|
"lib/authpwn_rails/generators/templates/001_create_users.rb",
|
@@ -46,6 +47,7 @@ Gem::Specification.new do |s|
|
|
46
47
|
"lib/authpwn_rails/generators/templates/users.yml",
|
47
48
|
"lib/authpwn_rails/generators/users_generator.rb",
|
48
49
|
"lib/authpwn_rails/session.rb",
|
50
|
+
"lib/authpwn_rails/session_controller.rb",
|
49
51
|
"lib/authpwn_rails/user_model.rb",
|
50
52
|
"test/cookie_controller_test.rb",
|
51
53
|
"test/facebook_controller_test.rb",
|
@@ -62,7 +64,7 @@ Gem::Specification.new do |s|
|
|
62
64
|
s.homepage = %q{http://github.com/pwnall/authpwn_rails}
|
63
65
|
s.licenses = [%q{MIT}]
|
64
66
|
s.require_paths = [%q{lib}]
|
65
|
-
s.rubygems_version = %q{1.8.
|
67
|
+
s.rubygems_version = %q{1.8.5}
|
66
68
|
s.summary = %q{User authentication for Rails 3 applications.}
|
67
69
|
|
68
70
|
if s.respond_to? :specification_version then
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'action_controller'
|
2
|
+
|
3
|
+
# :nodoc: add authenticates_using_facebook
|
4
|
+
class ActionController::Base
|
5
|
+
# Authenticates users via Facebook OAuth2, using fbgraph_rails.
|
6
|
+
#
|
7
|
+
# The User model class must implement for_facebook_token. The controller
|
8
|
+
# should obtain the Facebook token, using probes_facebook_access_token or
|
9
|
+
# requires_facebook_access_token.
|
10
|
+
def self.authenticates_using_facebook(options = {})
|
11
|
+
include AuthpwnRails::FacebookControllerInstanceMethods
|
12
|
+
before_filter :authenticate_using_facebook_access_token, options
|
13
|
+
end
|
14
|
+
end # module AuthpwnRails::FacebookExtensions::ControllerClassMethods
|
15
|
+
|
16
|
+
# :nodoc: namespace
|
17
|
+
module AuthpwnRails
|
18
|
+
|
19
|
+
# Included in controllers that call authenticates_using_facebook.
|
20
|
+
module FacebookControllerInstanceMethods
|
21
|
+
def authenticate_using_facebook_access_token
|
22
|
+
return true if current_user
|
23
|
+
if access_token = current_facebook_access_token
|
24
|
+
self.current_user = User.for_facebook_token access_token
|
25
|
+
# NOTE: nixing the token from the session so the user won't be logged on
|
26
|
+
# immediately after logging off
|
27
|
+
self.current_facebook_access_token = nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
private :authenticate_using_facebook_access_token
|
31
|
+
end # module AuthpwnRails::FacebookControllerInstanceMethods
|
32
|
+
|
33
|
+
end # namespace AuthpwnRails
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
# :nodoc: namespace
|
4
|
+
module AuthpwnRails
|
5
|
+
|
6
|
+
# Included by the model class that represents facebook tokens.
|
7
|
+
#
|
8
|
+
# Right now, some parts of the codebase assume the model will be named
|
9
|
+
# FacebookToken.
|
10
|
+
module FacebookTokenModel
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
included do
|
14
|
+
# The user whose token this is.
|
15
|
+
belongs_to :user, :inverse_of => :facebook_token
|
16
|
+
validates :user, :presence => true
|
17
|
+
|
18
|
+
# A unique ID on the Facebook site for the user owning this token.
|
19
|
+
validates :external_uid, :length => 1..32, :presence => true
|
20
|
+
|
21
|
+
# The OAuth2 access token.
|
22
|
+
validates :access_token, :length => 1..128, :presence => true
|
23
|
+
end
|
24
|
+
|
25
|
+
# Included in the metaclass of models that call pwnauth_facebook_token_model.
|
26
|
+
module ClassMethods
|
27
|
+
# Finds or creates the model containing a token.
|
28
|
+
#
|
29
|
+
# If a model for the same user exists, the model is updated with the given
|
30
|
+
# token. Otherwise, a new model will be created, together with a user.
|
31
|
+
def for(access_token)
|
32
|
+
uid = uid_from_token access_token
|
33
|
+
token = self.where(:external_uid => uid.to_str).first
|
34
|
+
if token
|
35
|
+
token.access_token = access_token
|
36
|
+
else
|
37
|
+
token = FacebookToken.new :external_uid => uid,
|
38
|
+
:access_token => access_token
|
39
|
+
token.user = User.create_with_facebook_token token
|
40
|
+
end
|
41
|
+
token.save!
|
42
|
+
token
|
43
|
+
end
|
44
|
+
|
45
|
+
# Extracts the Facebook user ID from a OAuth2 token.
|
46
|
+
#
|
47
|
+
# This is a hack. It works based on the current format, but might break at
|
48
|
+
# any time. Hopefully, we'll eventually have an official way of pulling the
|
49
|
+
# UID out of an OAuth2 token.
|
50
|
+
def uid_from_token(access_token)
|
51
|
+
access_token.split('|')[1].split('-').last
|
52
|
+
end
|
53
|
+
end # module AuthpwnRails::FacebookTokenModel::ClassMethods
|
54
|
+
|
55
|
+
|
56
|
+
# Included in models that include AuthpwnRails::FacebookTokenModel.
|
57
|
+
module InstanceMethods
|
58
|
+
# FBGraph client loaded with this access token.
|
59
|
+
def facebook_client
|
60
|
+
@client ||= FBGraphRails.fbclient(access_token)
|
61
|
+
end
|
62
|
+
end # module AuthpwnRails::FacebookTokenModel::InstanceMethods
|
63
|
+
|
64
|
+
end # namespace AuthpwnRails::FacebookTokenModel
|
65
|
+
|
66
|
+
end # namespace AuthpwnRails
|
@@ -1,40 +1,21 @@
|
|
1
1
|
require 'action_controller'
|
2
2
|
|
3
|
-
# :nodoc:
|
4
|
-
|
5
|
-
|
6
|
-
# :nodoc: namespace
|
7
|
-
module Session
|
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
|
3
|
+
# :nodoc: adds authenticates_using_session
|
4
|
+
class ActionController::Base
|
18
5
|
# Keeps track of the currently authenticated user via the session.
|
19
6
|
#
|
20
7
|
# Assumes the existence of a User model. A bare ActiveModel model will do the
|
21
8
|
# trick. Model instances must implement id, and the model class must implement
|
22
9
|
# find_by_id.
|
23
|
-
def authenticates_using_session(options = {})
|
24
|
-
include ControllerInstanceMethods
|
10
|
+
def self.authenticates_using_session(options = {})
|
11
|
+
include AuthpwnRails::ControllerInstanceMethods
|
25
12
|
before_filter :authenticate_using_session, options
|
26
|
-
end
|
27
|
-
|
28
|
-
# Turns the current controller into the session processing controller.
|
29
|
-
#
|
30
|
-
# Right now, this should be called from SessionController. The controller name
|
31
|
-
# is hardwired in other parts of the implementation.
|
32
|
-
def authpwn_session_controller
|
33
|
-
include SessionControllerInstanceMethods
|
34
|
-
authenticates_using_session
|
35
|
-
end
|
13
|
+
end
|
36
14
|
end
|
37
15
|
|
16
|
+
# :nodoc: namespace
|
17
|
+
module AuthpwnRails
|
18
|
+
|
38
19
|
# Included in controllers that call authenticates_using_session.
|
39
20
|
module ControllerInstanceMethods
|
40
21
|
attr_reader :current_user
|
@@ -82,93 +63,9 @@ module ControllerInstanceMethods
|
|
82
63
|
end
|
83
64
|
end
|
84
65
|
end
|
85
|
-
end
|
86
|
-
|
87
|
-
# Included in controllers that call authpwn_session_controller.
|
88
|
-
module SessionControllerInstanceMethods
|
89
|
-
# GET /session/new
|
90
|
-
def new
|
91
|
-
@user = User.new
|
92
|
-
@redirect_url = flash[:auth_redirect_url]
|
93
|
-
redirect_to session_url if current_user
|
94
|
-
end
|
95
|
-
|
96
|
-
# GET /session
|
97
|
-
def show
|
98
|
-
@user = current_user || User.new
|
99
|
-
if @user.new_record?
|
100
|
-
welcome
|
101
|
-
unless performed?
|
102
|
-
respond_to do |format|
|
103
|
-
format.html { render :action => :welcome }
|
104
|
-
format.json { render :json => {} }
|
105
|
-
end
|
106
|
-
end
|
107
|
-
else
|
108
|
-
home
|
109
|
-
unless performed?
|
110
|
-
respond_to do |format|
|
111
|
-
format.html { render :action => :home }
|
112
|
-
format.json do
|
113
|
-
user_data = @user.as_json
|
114
|
-
user_data = user_data['user'] if @user.class.include_root_in_json
|
115
|
-
render :json => { :user => user_data,
|
116
|
-
:csrf => form_authenticity_token }
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
# POST /session
|
124
|
-
def create
|
125
|
-
@user = User.new params[:user]
|
126
|
-
@redirect_url = params[:redirect_url] || session_url
|
127
|
-
self.current_user =
|
128
|
-
User.find_by_email_and_password @user.email, @user.password
|
129
|
-
|
130
|
-
respond_to do |format|
|
131
|
-
if current_user
|
132
|
-
format.html { redirect_to @redirect_url }
|
133
|
-
format.json do
|
134
|
-
user_data = @user.as_json
|
135
|
-
user_data = user_data['user'] if @user.class.include_root_in_json
|
136
|
-
render :json => { :user => user_data,
|
137
|
-
:csrf => form_authenticity_token }
|
138
|
-
end
|
139
|
-
else
|
140
|
-
notice = 'Invalid e-mail or password'
|
141
|
-
format.html do
|
142
|
-
redirect_to new_session_url, :flash => {
|
143
|
-
:notice => notice, :auth_redirect_url => @redirect_url }
|
144
|
-
end
|
145
|
-
format.json { render :json => { :error => notice} }
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
# DELETE /session
|
151
|
-
def destroy
|
152
|
-
self.current_user = nil
|
153
|
-
respond_to do |format|
|
154
|
-
format.html { redirect_to session_url }
|
155
|
-
format.json { head :ok }
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
# Hook for setting up the home view.
|
160
|
-
def home
|
161
|
-
end
|
162
|
-
private :home
|
163
|
-
|
164
|
-
# Hook for setting up the welcome view.
|
165
|
-
def welcome
|
166
|
-
end
|
167
|
-
private :welcome
|
168
|
-
end # module Authpwn::Session::SessionControllerInstanceMethods
|
169
|
-
|
170
|
-
ActionController::Base.send :include, ControllerMixin
|
66
|
+
end # module AuthpwnRails::ControllerInstanceMethods
|
171
67
|
|
68
|
+
end # namespace AuthpwnRails
|
172
69
|
|
173
70
|
# :nodoc: add session modification
|
174
71
|
class ActionController::TestCase
|
@@ -183,7 +80,3 @@ class ActionController::TestCase
|
|
183
80
|
User.find_by_param user_param
|
184
81
|
end
|
185
82
|
end
|
186
|
-
|
187
|
-
end # namespace AuthpwnRails::Session
|
188
|
-
|
189
|
-
end # namespace AuthpwnRails
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
# :nodoc: namespace
|
4
|
+
module AuthpwnRails
|
5
|
+
|
6
|
+
# Included by the controller that handles user authentication.
|
7
|
+
#
|
8
|
+
# Right now, some parts of the codebase assume the controller will be named
|
9
|
+
# Session.
|
10
|
+
module SessionController
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
included do
|
14
|
+
authenticates_using_session
|
15
|
+
end
|
16
|
+
|
17
|
+
# Included in controllers that include AuthpwnRails::SessionController.
|
18
|
+
module InstanceMethods
|
19
|
+
# GET /session/new
|
20
|
+
def new
|
21
|
+
@user = User.new
|
22
|
+
@redirect_url = flash[:auth_redirect_url]
|
23
|
+
redirect_to session_url if current_user
|
24
|
+
end
|
25
|
+
|
26
|
+
# GET /session
|
27
|
+
def show
|
28
|
+
@user = current_user || User.new
|
29
|
+
if @user.new_record?
|
30
|
+
welcome
|
31
|
+
unless performed?
|
32
|
+
respond_to do |format|
|
33
|
+
format.html { render :action => :welcome }
|
34
|
+
format.json { render :json => {} }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
else
|
38
|
+
home
|
39
|
+
unless performed?
|
40
|
+
respond_to do |format|
|
41
|
+
format.html { render :action => :home }
|
42
|
+
format.json do
|
43
|
+
user_data = @user.as_json
|
44
|
+
user_data = user_data['user'] if @user.class.include_root_in_json
|
45
|
+
render :json => { :user => user_data,
|
46
|
+
:csrf => form_authenticity_token }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# POST /session
|
54
|
+
def create
|
55
|
+
@user = User.new params[:user]
|
56
|
+
@redirect_url = params[:redirect_url] || session_url
|
57
|
+
self.current_user =
|
58
|
+
User.find_by_email_and_password @user.email, @user.password
|
59
|
+
|
60
|
+
respond_to do |format|
|
61
|
+
if current_user
|
62
|
+
format.html { redirect_to @redirect_url }
|
63
|
+
format.json do
|
64
|
+
user_data = @user.as_json
|
65
|
+
user_data = user_data['user'] if @user.class.include_root_in_json
|
66
|
+
render :json => { :user => user_data,
|
67
|
+
:csrf => form_authenticity_token }
|
68
|
+
end
|
69
|
+
else
|
70
|
+
notice = 'Invalid e-mail or password'
|
71
|
+
format.html do
|
72
|
+
redirect_to new_session_url, :flash => {
|
73
|
+
:notice => notice, :auth_redirect_url => @redirect_url }
|
74
|
+
end
|
75
|
+
format.json { render :json => { :error => notice} }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# DELETE /session
|
81
|
+
def destroy
|
82
|
+
self.current_user = nil
|
83
|
+
respond_to do |format|
|
84
|
+
format.html { redirect_to session_url }
|
85
|
+
format.json { head :ok }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Hook for setting up the home view.
|
90
|
+
def home
|
91
|
+
end
|
92
|
+
private :home
|
93
|
+
|
94
|
+
# Hook for setting up the welcome view.
|
95
|
+
def welcome
|
96
|
+
end
|
97
|
+
private :welcome
|
98
|
+
end # module AuthpwnRails::SessionController::InstanceMethods
|
99
|
+
|
100
|
+
end # module AuthpwnRails::SessionController
|
101
|
+
|
102
|
+
end # namespace AuthpwnRails
|
@@ -1,24 +1,16 @@
|
|
1
|
-
require '
|
1
|
+
require 'active_model'
|
2
|
+
require 'active_support'
|
2
3
|
|
3
4
|
# :nodoc: namespace
|
4
5
|
module AuthpwnRails
|
5
6
|
|
6
|
-
#
|
7
|
+
# Included by the model class that represents users.
|
8
|
+
#
|
9
|
+
# Right now, some parts of the codebase assume the model will be named User.
|
7
10
|
module UserModel
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
included do
|
22
14
|
# E-mail address identifying the user account.
|
23
15
|
validates :email, :format => /^[A-Za-z0-9.+_]+@[^@]*\.(\w+)$/,
|
24
16
|
:presence => true, :length => 1..128, :uniqueness => true
|
@@ -42,94 +34,86 @@ module ModelClassMethods
|
|
42
34
|
|
43
35
|
# Facebook token.
|
44
36
|
has_one :facebook_token, :dependent => :destroy, :inverse_of => :user
|
45
|
-
|
46
|
-
extend ModelMetaclassMethods
|
47
|
-
include ModelInstanceMethods
|
48
37
|
end
|
49
|
-
end # module AuthpwnRails::UserModel::ModelClassMethods
|
50
38
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
60
|
-
|
61
|
-
# The authenticated user or nil.
|
62
|
-
def find_by_email_and_password(email, password)
|
63
|
-
user = where(:email => email).first
|
64
|
-
(user && user.password_matches?(password)) ? user : nil
|
65
|
-
end
|
66
|
-
|
67
|
-
# Computes a password hash from a raw password and a salt.
|
68
|
-
def hash_password(password, salt)
|
69
|
-
Digest::SHA2.hexdigest(password + salt)
|
70
|
-
end
|
71
|
-
|
72
|
-
# Generates a random salt value.
|
73
|
-
def random_salt
|
74
|
-
[(0...12).map { |i| 1 + rand(255) }.pack('C*')].pack('m').strip
|
75
|
-
end
|
76
|
-
|
77
|
-
# Fills out a new user's information based on a Facebook access token.
|
78
|
-
def create_with_facebook_token(token)
|
79
|
-
self.create! :email => "#{token.external_uid}@graph.facebook.com"
|
80
|
-
end
|
81
|
-
|
82
|
-
# The user that owns a given Facebook OAuth2 token.
|
83
|
-
#
|
84
|
-
# A new user will be created if the token doesn't belong to any user. This is
|
85
|
-
# the case for a new visitor.
|
86
|
-
def for_facebook_token(access_token)
|
87
|
-
FacebookToken.for(access_token).user
|
88
|
-
end
|
89
|
-
end # module AuthpwnRails::UserModel::ModelMetaclassMethods
|
90
|
-
|
91
|
-
|
92
|
-
# Included in models that call pwnauth_user_model.
|
93
|
-
module ModelInstanceMethods
|
94
|
-
# Resets the virtual password attributes.
|
95
|
-
def reset_password
|
96
|
-
@password = @password_confirmation = nil
|
97
|
-
end
|
39
|
+
# Class methods on models that include AuthpwnRails::UserModel.
|
40
|
+
module ClassMethods
|
41
|
+
# Queries the database using the value returned by User#to_param.
|
42
|
+
#
|
43
|
+
# Returns nil if no matching User exists.
|
44
|
+
def find_by_param(param)
|
45
|
+
where(:email_hash => param).first
|
46
|
+
end
|
98
47
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
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...12).map { |i| 1 + rand(255) }.pack('C*')].pack('m').strip
|
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
|
72
|
+
# is 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::ClassMethods
|
118
77
|
|
119
|
-
#
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
78
|
+
# Included in models that include AuthpwnRails::UserModel.
|
79
|
+
module InstanceMethods
|
80
|
+
# Resets the virtual password attributes.
|
81
|
+
def reset_password
|
82
|
+
@password = @password_confirmation = nil
|
83
|
+
end
|
84
|
+
|
85
|
+
# Compares the given password against the user's stored password.
|
86
|
+
#
|
87
|
+
# Returns +true+ for a match, +false+ otherwise.
|
88
|
+
def password_matches?(passwd)
|
89
|
+
password_hash == self.class.hash_password(passwd, password_salt)
|
90
|
+
end
|
124
91
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
92
|
+
# Password virtual attribute.
|
93
|
+
def password=(new_password)
|
94
|
+
@password = new_password
|
95
|
+
self.password_salt = self.class.random_salt
|
96
|
+
self.password_hash = new_password &&
|
97
|
+
self.class.hash_password(new_password, password_salt)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Use e-mails instead of exposing ActiveRecord IDs.
|
101
|
+
def to_param
|
102
|
+
email_hash
|
103
|
+
end
|
104
|
+
|
105
|
+
# :nodoc: overwrites
|
106
|
+
def email=(new_email)
|
107
|
+
super
|
108
|
+
self.email_hash = new_email && Digest::SHA2.hexdigest(new_email)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Do not expose password and ActiveRecord IDs in JSON representation.
|
112
|
+
def as_json(options = {})
|
113
|
+
options ||= {}
|
114
|
+
super(options.merge(:except => [:password_salt, :password_hash, :id]))
|
115
|
+
end
|
116
|
+
end # module AuthpwnRails::UserModel::InstanceMethods
|
133
117
|
|
134
118
|
end # namespace AuthpwnRails::UserModel
|
135
119
|
|
data/lib/authpwn_rails.rb
CHANGED
@@ -2,8 +2,10 @@
|
|
2
2
|
module AuthpwnRails
|
3
3
|
end
|
4
4
|
|
5
|
-
require 'authpwn_rails/
|
5
|
+
require 'authpwn_rails/facebook_session.rb'
|
6
|
+
require 'authpwn_rails/facebook_token_model.rb'
|
6
7
|
require 'authpwn_rails/session.rb'
|
8
|
+
require 'authpwn_rails/session_controller.rb'
|
7
9
|
require 'authpwn_rails/user_model.rb'
|
8
10
|
|
9
11
|
if defined?(Rails)
|
@@ -34,7 +34,8 @@ class CookieControllerTest < ActionController::TestCase
|
|
34
34
|
get :show
|
35
35
|
assert_response :success
|
36
36
|
assert_equal @user, assigns(:current_user)
|
37
|
-
assert_equal "User: #{Fixtures.identify(:john)}",
|
37
|
+
assert_equal "User: #{ActiveRecord::Fixtures.identify(:john)}",
|
38
|
+
response.body
|
38
39
|
end
|
39
40
|
|
40
41
|
test "invalid user_pid in session" do
|
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:
|
4
|
+
hash: 59
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 9
|
9
|
+
- 0
|
10
|
+
version: 0.9.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Victor Costan
|
@@ -15,11 +15,10 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-07-
|
18
|
+
date: 2011-07-05 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
|
22
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
21
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
23
22
|
none: false
|
24
23
|
requirements:
|
25
24
|
- - ">="
|
@@ -30,12 +29,12 @@ dependencies:
|
|
30
29
|
- 1
|
31
30
|
- 7
|
32
31
|
version: 0.1.7
|
32
|
+
type: :runtime
|
33
|
+
requirement: *id001
|
33
34
|
prerelease: false
|
34
|
-
version_requirements: *id001
|
35
35
|
name: fbgraph_rails
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
|
-
|
38
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
39
38
|
none: false
|
40
39
|
requirements:
|
41
40
|
- - ">="
|
@@ -48,12 +47,12 @@ dependencies:
|
|
48
47
|
- rc
|
49
48
|
- 4
|
50
49
|
version: 3.1.0.rc4
|
50
|
+
type: :runtime
|
51
|
+
requirement: *id002
|
51
52
|
prerelease: false
|
52
|
-
version_requirements: *id002
|
53
53
|
name: rails
|
54
54
|
- !ruby/object:Gem::Dependency
|
55
|
-
|
56
|
-
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
57
56
|
none: false
|
58
57
|
requirements:
|
59
58
|
- - ~>
|
@@ -64,12 +63,12 @@ dependencies:
|
|
64
63
|
- 0
|
65
64
|
- 0
|
66
65
|
version: 1.0.0
|
66
|
+
type: :development
|
67
|
+
requirement: *id003
|
67
68
|
prerelease: false
|
68
|
-
version_requirements: *id003
|
69
69
|
name: bundler
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
|
-
|
72
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
73
72
|
none: false
|
74
73
|
requirements:
|
75
74
|
- - ~>
|
@@ -80,12 +79,12 @@ dependencies:
|
|
80
79
|
- 6
|
81
80
|
- 0
|
82
81
|
version: 1.6.0
|
82
|
+
type: :development
|
83
|
+
requirement: *id004
|
83
84
|
prerelease: false
|
84
|
-
version_requirements: *id004
|
85
85
|
name: jeweler
|
86
86
|
- !ruby/object:Gem::Dependency
|
87
|
-
|
88
|
-
requirement: &id005 !ruby/object:Gem::Requirement
|
87
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
89
88
|
none: false
|
90
89
|
requirements:
|
91
90
|
- - ">="
|
@@ -94,12 +93,12 @@ dependencies:
|
|
94
93
|
segments:
|
95
94
|
- 0
|
96
95
|
version: "0"
|
96
|
+
type: :development
|
97
|
+
requirement: *id005
|
97
98
|
prerelease: false
|
98
|
-
version_requirements: *id005
|
99
99
|
name: rcov
|
100
100
|
- !ruby/object:Gem::Dependency
|
101
|
-
|
102
|
-
requirement: &id006 !ruby/object:Gem::Requirement
|
101
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
103
102
|
none: false
|
104
103
|
requirements:
|
105
104
|
- - ">="
|
@@ -110,8 +109,9 @@ dependencies:
|
|
110
109
|
- 3
|
111
110
|
- 3
|
112
111
|
version: 1.3.3
|
112
|
+
type: :development
|
113
|
+
requirement: *id006
|
113
114
|
prerelease: false
|
114
|
-
version_requirements: *id006
|
115
115
|
name: sqlite3
|
116
116
|
description: Works with Facebook.
|
117
117
|
email: victor@costan.us
|
@@ -135,7 +135,8 @@ files:
|
|
135
135
|
- authpwn_rails.gemspec
|
136
136
|
- lib/authpwn_rails.rb
|
137
137
|
- lib/authpwn_rails/engine.rb
|
138
|
-
- lib/authpwn_rails/
|
138
|
+
- lib/authpwn_rails/facebook_session.rb
|
139
|
+
- lib/authpwn_rails/facebook_token_model.rb
|
139
140
|
- lib/authpwn_rails/generators/facebook_generator.rb
|
140
141
|
- lib/authpwn_rails/generators/session_generator.rb
|
141
142
|
- lib/authpwn_rails/generators/templates/001_create_users.rb
|
@@ -152,6 +153,7 @@ files:
|
|
152
153
|
- lib/authpwn_rails/generators/templates/users.yml
|
153
154
|
- lib/authpwn_rails/generators/users_generator.rb
|
154
155
|
- lib/authpwn_rails/session.rb
|
156
|
+
- lib/authpwn_rails/session_controller.rb
|
155
157
|
- lib/authpwn_rails/user_model.rb
|
156
158
|
- test/cookie_controller_test.rb
|
157
159
|
- test/facebook_controller_test.rb
|
@@ -193,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
193
195
|
requirements: []
|
194
196
|
|
195
197
|
rubyforge_project:
|
196
|
-
rubygems_version: 1.8.
|
198
|
+
rubygems_version: 1.8.5
|
197
199
|
signing_key:
|
198
200
|
specification_version: 3
|
199
201
|
summary: User authentication for Rails 3 applications.
|
@@ -1,121 +0,0 @@
|
|
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, :inverse_of => :facebook_token
|
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.to_str).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
|