authpwn_rails 0.13.4 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +4 -2
- data/Gemfile +5 -5
- data/Gemfile.lock +47 -45
- data/Gemfile.rails3 +15 -0
- data/Gemfile.rails4 +15 -0
- data/VERSION +1 -1
- data/app/models/credentials/email.rb +35 -19
- data/app/models/credentials/facebook.rb +11 -9
- data/app/models/credentials/password.rb +7 -5
- data/app/models/tokens/base.rb +27 -14
- data/app/models/tokens/email_verification.rb +1 -1
- data/app/models/tokens/session_uid.rb +5 -5
- data/authpwn_rails.gemspec +15 -15
- data/lib/authpwn_rails/credential_model.rb +8 -6
- data/lib/authpwn_rails/expires.rb +1 -1
- data/lib/authpwn_rails/generators/templates/001_create_users.rb +4 -4
- data/lib/authpwn_rails/generators/templates/003_create_credentials.rb +8 -10
- data/lib/authpwn_rails/generators/templates/session/password_change.html.erb +1 -1
- data/lib/authpwn_rails/generators/templates/session_controller.rb +1 -1
- data/lib/authpwn_rails/generators/templates/session_controller_test.rb +9 -9
- data/lib/authpwn_rails/http_basic.rb +2 -2
- data/lib/authpwn_rails/routes.rb +18 -18
- data/lib/authpwn_rails/session.rb +3 -3
- data/lib/authpwn_rails/session_controller.rb +39 -25
- data/lib/authpwn_rails/session_mailer.rb +5 -5
- data/lib/authpwn_rails/test_extensions.rb +6 -6
- data/lib/authpwn_rails/user_extensions/email_field.rb +33 -16
- data/lib/authpwn_rails/user_extensions/facebook_fields.rb +1 -1
- data/lib/authpwn_rails/user_extensions/password_field.rb +17 -14
- data/lib/authpwn_rails/user_model.rb +9 -7
- data/test/cookie_controller_test.rb +22 -16
- data/test/credentials/facebook_credential_test.rb +17 -17
- data/test/credentials/password_credential_test.rb +1 -1
- data/test/credentials/password_reset_token_test.rb +1 -1
- data/test/credentials/session_uid_token_test.rb +1 -0
- data/test/credentials/token_crendential_test.rb +2 -4
- data/test/facebook_controller_test.rb +14 -14
- data/test/helpers/action_controller.rb +8 -0
- data/test/helpers/db_setup.rb +11 -9
- data/test/helpers/routes.rb +14 -9
- data/test/http_basic_controller_test.rb +35 -20
- data/test/routes_test.rb +18 -18
- data/test/session_controller_api_test.rb +76 -83
- data/test/test_helper.rb +4 -1
- data/test/user_extensions/email_field_test.rb +1 -1
- data/test/user_extensions/facebook_fields_test.rb +5 -5
- data/test/user_extensions/password_field_test.rb +2 -2
- metadata +14 -27
@@ -1,22 +1,20 @@
|
|
1
1
|
class CreateCredentials < ActiveRecord::Migration
|
2
2
|
def change
|
3
3
|
create_table :credentials do |t|
|
4
|
-
t.references :user, :
|
5
|
-
t.string :type, :
|
6
|
-
t.string :name, :
|
4
|
+
t.references :user, null: false
|
5
|
+
t.string :type, limit: 32, null: false
|
6
|
+
t.string :name, limit: 128, null: true
|
7
7
|
|
8
|
-
t.timestamp :updated_at, :
|
8
|
+
t.timestamp :updated_at, null: false
|
9
9
|
|
10
|
-
t.binary :key, :
|
10
|
+
t.binary :key, limit: 2.kilobytes, null: true
|
11
11
|
end
|
12
12
|
|
13
13
|
# All the credentials (maybe of a specific type) belonging to a user.
|
14
|
-
add_index :credentials, [:user_id, :type], :
|
15
|
-
:null => false
|
14
|
+
add_index :credentials, [:user_id, :type], unique: false
|
16
15
|
# A specific credential, to find out what user it belongs to.
|
17
|
-
add_index :credentials, [:type, :name],
|
16
|
+
add_index :credentials, [:type, :name], unique: true
|
18
17
|
# Expired credentials (particularly useful for tokens).
|
19
|
-
add_index :credentials, [:type, :updated_at], :
|
20
|
-
:null => false
|
18
|
+
add_index :credentials, [:type, :updated_at], unique: false
|
21
19
|
end
|
22
20
|
end
|
@@ -11,7 +11,7 @@
|
|
11
11
|
<p class="password_age_notice">
|
12
12
|
Your have been using the same password for
|
13
13
|
<span class="password_age">
|
14
|
-
<%= time_ago_in_words @credential.updated_at, true %>.
|
14
|
+
<%= time_ago_in_words @credential.updated_at, :include_seconds => true %>.
|
15
15
|
</span>
|
16
16
|
</p>
|
17
17
|
<% end %>
|
@@ -34,7 +34,7 @@ class SessionController < ApplicationController
|
|
34
34
|
format.html do
|
35
35
|
case token
|
36
36
|
when Tokens::EmailVerification
|
37
|
-
redirect_to session_url, :
|
37
|
+
redirect_to session_url, notice: 'E-mail address confirmed'
|
38
38
|
when Tokens::PasswordReset
|
39
39
|
redirect_to change_password_session_url
|
40
40
|
# Handle other token types here.
|
@@ -20,7 +20,7 @@ class SessionControllerTest < ActionController::TestCase
|
|
20
20
|
old_token = credentials(:jane_session_token)
|
21
21
|
old_token.updated_at = Time.now - 1.year
|
22
22
|
old_token.save!
|
23
|
-
post :create, :
|
23
|
+
post :create, email: @email_credential.email, password: 'password'
|
24
24
|
assert_equal @user, session_current_user, 'session'
|
25
25
|
assert_redirected_to session_url
|
26
26
|
assert_nil Tokens::Base.with_code(old_token.code).first,
|
@@ -29,7 +29,7 @@ class SessionControllerTest < ActionController::TestCase
|
|
29
29
|
|
30
30
|
test "user logged in JSON request" do
|
31
31
|
set_session_current_user @user
|
32
|
-
get :show, :
|
32
|
+
get :show, format: 'json'
|
33
33
|
|
34
34
|
assert_equal @user.exuid,
|
35
35
|
ActiveSupport::JSON.decode(response.body)['user']['exuid']
|
@@ -43,7 +43,7 @@ class SessionControllerTest < ActionController::TestCase
|
|
43
43
|
end
|
44
44
|
|
45
45
|
test "user not logged in with JSON request" do
|
46
|
-
get :show, :
|
46
|
+
get :show, format: 'json'
|
47
47
|
|
48
48
|
assert_equal({}, ActiveSupport::JSON.decode(response.body))
|
49
49
|
end
|
@@ -61,16 +61,16 @@ class SessionControllerTest < ActionController::TestCase
|
|
61
61
|
end
|
62
62
|
|
63
63
|
test "e-mail verification link" do
|
64
|
-
get :token, :
|
64
|
+
get :token, code: @token_credential.code
|
65
65
|
assert_redirected_to session_url
|
66
66
|
assert @email_credential.reload.verified?, 'Email not verified'
|
67
67
|
end
|
68
68
|
|
69
69
|
test "password reset link" do
|
70
70
|
password_credential = credentials(:jane_password)
|
71
|
-
get :token, :
|
71
|
+
get :token, code: credentials(:jane_password_token).code
|
72
72
|
assert_redirected_to change_password_session_url
|
73
|
-
assert_nil Credential.where(:
|
73
|
+
assert_nil Credential.where(id: password_credential.id).first,
|
74
74
|
'Password not cleared'
|
75
75
|
end
|
76
76
|
|
@@ -93,10 +93,10 @@ class SessionControllerTest < ActionController::TestCase
|
|
93
93
|
@password_credential.destroy
|
94
94
|
get :password_change
|
95
95
|
|
96
|
-
assert_select 'span[class="password_age"]', :
|
96
|
+
assert_select 'span[class="password_age"]', count: 0
|
97
97
|
assert_select 'form[action=?][method="post"]',
|
98
98
|
change_password_session_path do
|
99
|
-
assert_select 'input[name="old_password"]', :
|
99
|
+
assert_select 'input[name="old_password"]', count: 0
|
100
100
|
assert_select 'input[name=?]', 'credential[password]'
|
101
101
|
assert_select 'input[name=?]', 'credential[password_confirmation]'
|
102
102
|
assert_select 'input[type=submit]'
|
@@ -107,7 +107,7 @@ class SessionControllerTest < ActionController::TestCase
|
|
107
107
|
ActionMailer::Base.deliveries = []
|
108
108
|
|
109
109
|
assert_difference 'Credential.count', 1 do
|
110
|
-
post :reset_password, :
|
110
|
+
post :reset_password, email: @email_credential.email
|
111
111
|
end
|
112
112
|
|
113
113
|
assert !ActionMailer::Base.deliveries.empty?, 'email generated'
|
@@ -51,10 +51,10 @@ module HttpBasicControllerInstanceMethods
|
|
51
51
|
|
52
52
|
respond_to do |format|
|
53
53
|
format.html do
|
54
|
-
render 'session/forbidden', :
|
54
|
+
render 'session/forbidden', status: :forbidden
|
55
55
|
end
|
56
56
|
format.json do
|
57
|
-
render :
|
57
|
+
render json: { error: "You're not allowed to access that" }
|
58
58
|
end
|
59
59
|
end
|
60
60
|
end
|
data/lib/authpwn_rails/routes.rb
CHANGED
@@ -22,24 +22,24 @@ module MapperMixin
|
|
22
22
|
paths = options[:paths] || controller
|
23
23
|
methods = options[:method_names] || 'session'
|
24
24
|
|
25
|
-
get "/#{paths}/token/:code", :
|
26
|
-
:
|
27
|
-
|
28
|
-
get "/#{paths}", :
|
29
|
-
:
|
30
|
-
get "/#{paths}/new", :
|
31
|
-
:
|
32
|
-
post "/#{paths}", :
|
33
|
-
delete "/#{paths}", :
|
34
|
-
|
35
|
-
get "/#{paths}/change_password", :
|
36
|
-
:
|
37
|
-
:
|
38
|
-
post "/#{paths}/change_password", :
|
39
|
-
:
|
40
|
-
post "/#{paths}/reset_password", :
|
41
|
-
:
|
42
|
-
:
|
25
|
+
get "/#{paths}/token/:code", controller: controller, action: 'token',
|
26
|
+
as: :"token_#{methods}"
|
27
|
+
|
28
|
+
get "/#{paths}", controller: controller, action: 'show',
|
29
|
+
as: :"#{methods}"
|
30
|
+
get "/#{paths}/new", controller: controller, action: 'new',
|
31
|
+
as: :"new_#{methods}"
|
32
|
+
post "/#{paths}", controller: controller, action: 'create'
|
33
|
+
delete "/#{paths}", controller: controller, action: 'destroy'
|
34
|
+
|
35
|
+
get "/#{paths}/change_password", controller: controller,
|
36
|
+
action: 'password_change',
|
37
|
+
as: "change_password_#{methods}"
|
38
|
+
post "/#{paths}/change_password", controller: controller,
|
39
|
+
action: 'change_password'
|
40
|
+
post "/#{paths}/reset_password", controller: controller,
|
41
|
+
action: 'reset_password',
|
42
|
+
as: "reset_password_#{methods}"
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -78,16 +78,16 @@ module ControllerInstanceMethods
|
|
78
78
|
format.html do
|
79
79
|
@redirect_url = redirect_url
|
80
80
|
if current_user
|
81
|
-
render 'session/forbidden', :
|
81
|
+
render 'session/forbidden', status: :forbidden
|
82
82
|
else
|
83
83
|
flash[:auth_redirect_url] = redirect_url
|
84
|
-
render 'session/forbidden', :
|
84
|
+
render 'session/forbidden', status: :forbidden
|
85
85
|
end
|
86
86
|
end
|
87
87
|
format.json do
|
88
88
|
message = current_user ? "You're not allowed to access that" :
|
89
89
|
'Please sign in'
|
90
|
-
render :
|
90
|
+
render json: { error: message }
|
91
91
|
end
|
92
92
|
end
|
93
93
|
end
|
@@ -12,7 +12,7 @@ module SessionController
|
|
12
12
|
|
13
13
|
included do
|
14
14
|
skip_filter :authenticate_using_session
|
15
|
-
authenticates_using_session :
|
15
|
+
authenticates_using_session except: [:create, :reset_password, :token]
|
16
16
|
|
17
17
|
# If set, every successful login will cause a database purge.
|
18
18
|
class_attribute :auto_purge_sessions
|
@@ -33,20 +33,19 @@ module SessionController
|
|
33
33
|
welcome
|
34
34
|
unless performed?
|
35
35
|
respond_to do |format|
|
36
|
-
format.html { render :
|
37
|
-
format.json { render :
|
36
|
+
format.html { render action: :welcome }
|
37
|
+
format.json { render json: {} }
|
38
38
|
end
|
39
39
|
end
|
40
40
|
else
|
41
41
|
home
|
42
42
|
unless performed?
|
43
43
|
respond_to do |format|
|
44
|
-
format.html { render :
|
44
|
+
format.html { render action: :home }
|
45
45
|
format.json do
|
46
46
|
user_data = @user.as_json
|
47
47
|
user_data = user_data['user'] if @user.class.include_root_in_json
|
48
|
-
render :
|
49
|
-
:csrf => form_authenticity_token }
|
48
|
+
render json: { user: user_data, csrf: form_authenticity_token }
|
50
49
|
end
|
51
50
|
end
|
52
51
|
end
|
@@ -74,16 +73,15 @@ module SessionController
|
|
74
73
|
if current_user.class.include_root_in_json
|
75
74
|
user_data = user_data['user']
|
76
75
|
end
|
77
|
-
render :
|
78
|
-
:csrf => form_authenticity_token }
|
76
|
+
render json: { user: user_data, csrf: form_authenticity_token }
|
79
77
|
end
|
80
78
|
else
|
81
79
|
error_text = bounce_notice_text auth
|
82
80
|
format.html do
|
83
|
-
redirect_to new_session_url, :
|
84
|
-
:
|
81
|
+
redirect_to new_session_url, flash: { alert: error_text,
|
82
|
+
auth_redirect_url: @redirect_url }
|
85
83
|
end
|
86
|
-
format.json { render :
|
84
|
+
format.json { render json: { error: auth, text: error_text } }
|
87
85
|
end
|
88
86
|
end
|
89
87
|
end
|
@@ -101,17 +99,17 @@ module SessionController
|
|
101
99
|
respond_to do |format|
|
102
100
|
if user
|
103
101
|
format.html do
|
104
|
-
redirect_to new_session_url, :
|
102
|
+
redirect_to new_session_url, alert:
|
105
103
|
'Please check your e-mail for instructions'
|
106
104
|
end
|
107
|
-
format.json { render :
|
105
|
+
format.json { render json: { } }
|
108
106
|
else
|
109
107
|
error_text = 'Invalid e-mail'
|
110
108
|
format.html do
|
111
|
-
redirect_to new_session_url, :
|
109
|
+
redirect_to new_session_url, alert: error_text
|
112
110
|
end
|
113
111
|
format.json do
|
114
|
-
render :
|
112
|
+
render json: { error: :not_found, text: notice }
|
115
113
|
end
|
116
114
|
end
|
117
115
|
end
|
@@ -129,10 +127,10 @@ module SessionController
|
|
129
127
|
error_text = bounce_notice_text auth
|
130
128
|
respond_to do |format|
|
131
129
|
format.html do
|
132
|
-
redirect_to new_session_url, :
|
133
|
-
:
|
130
|
+
redirect_to new_session_url, flash: { alert: error_text,
|
131
|
+
auth_redirect_url: session_url }
|
134
132
|
end
|
135
|
-
format.json { render :
|
133
|
+
format.json { render json: { error: auth, text: error_text } }
|
136
134
|
end
|
137
135
|
else
|
138
136
|
self.set_session_current_user auth
|
@@ -145,8 +143,7 @@ module SessionController
|
|
145
143
|
if current_user.class.include_root_in_json
|
146
144
|
user_data = user_data['user']
|
147
145
|
end
|
148
|
-
render :
|
149
|
-
:csrf => form_authenticity_token }
|
146
|
+
render json: { user: user_data, csrf: form_authenticity_token }
|
150
147
|
end
|
151
148
|
end
|
152
149
|
end
|
@@ -194,29 +191,46 @@ module SessionController
|
|
194
191
|
if @credential
|
195
192
|
# An old password is set, must verify it.
|
196
193
|
if @credential.check_password params[:old_password]
|
197
|
-
success = @credential.update_attributes
|
194
|
+
success = @credential.update_attributes(
|
195
|
+
change_password_params[:credential])
|
198
196
|
else
|
199
197
|
success = false
|
200
198
|
flash[:alert] = 'Incorrect old password. Please try again.'
|
201
199
|
end
|
202
200
|
else
|
203
|
-
@credential = Credentials::Password.new
|
201
|
+
@credential = Credentials::Password.new(
|
202
|
+
change_password_params[:credential])
|
204
203
|
@credential.user = current_user
|
205
204
|
success = @credential.save
|
206
205
|
end
|
207
206
|
respond_to do |format|
|
208
207
|
if success
|
209
208
|
format.html do
|
210
|
-
redirect_to session_url, :
|
209
|
+
redirect_to session_url, notice: 'Password updated'
|
211
210
|
end
|
212
211
|
format.json { head :ok }
|
213
212
|
else
|
214
|
-
format.html { render :
|
215
|
-
format.json { render :
|
213
|
+
format.html { render action: :password_change }
|
214
|
+
format.json { render json: { error: :invalid } }
|
216
215
|
end
|
217
216
|
end
|
218
217
|
end
|
219
218
|
|
219
|
+
if defined? ActiveModel::ForbiddenAttributesProtection
|
220
|
+
# Rails 4.
|
221
|
+
|
222
|
+
# Parameters used to change the user's password.
|
223
|
+
def change_password_params
|
224
|
+
params.permit :format, :old_password,
|
225
|
+
credential: [ :password, :password_confirmation ]
|
226
|
+
end
|
227
|
+
else
|
228
|
+
# Rails 3.
|
229
|
+
def change_password_params
|
230
|
+
params
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
220
234
|
# True for controllers belonging to the authentication implementation.
|
221
235
|
#
|
222
236
|
# Controllers that return true here are responsible for performing their own
|
@@ -16,9 +16,9 @@ module SessionMailer
|
|
16
16
|
@host.slice! -1 if @host[-1] == ?/
|
17
17
|
hostname = @host.split(':', 2).first # Strip out any port.
|
18
18
|
|
19
|
-
mail :
|
20
|
-
:
|
21
|
-
:
|
19
|
+
mail to: @token.email,
|
20
|
+
subject: email_verification_subject(token, hostname, @protocol),
|
21
|
+
from: email_verification_from(token, hostname, @protocol)
|
22
22
|
end
|
23
23
|
|
24
24
|
# The subject line in an e-mail verification e-mail.
|
@@ -48,8 +48,8 @@ module SessionMailer
|
|
48
48
|
@host.slice! -1 if @host[-1] == ?/
|
49
49
|
|
50
50
|
hostname = @host.split(':', 2).first # Strip out any port.
|
51
|
-
mail :
|
52
|
-
:
|
51
|
+
mail to: email, from: reset_password_from(token, hostname, @protocol),
|
52
|
+
subject: reset_password_subject(token, hostname, @protocol)
|
53
53
|
end
|
54
54
|
|
55
55
|
# The subject line in a password reset e-mail.
|
@@ -11,7 +11,7 @@ module TestExtensions
|
|
11
11
|
# the credential matches the given argument, and nil otherwise.
|
12
12
|
def with_blocked_credential(blocked_credential, reason = :blocked, &block)
|
13
13
|
# Stub a method in all User instances for this test only.
|
14
|
-
#
|
14
|
+
# mocha.any_instance doesn't work because ActiveRecord doesn't use new
|
15
15
|
# to instantiate records.
|
16
16
|
::User.class_eval do
|
17
17
|
alias_method :_auth_bounce_reason_wbc_stub, :auth_bounce_reason
|
@@ -42,7 +42,7 @@ module ControllerTestExtensions
|
|
42
42
|
def set_session_current_user(user)
|
43
43
|
if user
|
44
44
|
# Avoid database inserts, if at all possible.
|
45
|
-
if token = Tokens::SessionUid.where(:
|
45
|
+
if token = Tokens::SessionUid.where(user_id: user.id).first
|
46
46
|
token.spend # Only bump updated_at if necessary.
|
47
47
|
else
|
48
48
|
token = Tokens::SessionUid.random_for user, '127.0.0.1', 'UnitTests'
|
@@ -75,17 +75,17 @@ module ControllerTestExtensions
|
|
75
75
|
|
76
76
|
if password.nil?
|
77
77
|
password = 'password'
|
78
|
-
credential = Credentials::Password.where(:
|
78
|
+
credential = Credentials::Password.where(user_id: user.id).first
|
79
79
|
if credential
|
80
|
-
credential.update_attributes! :
|
80
|
+
credential.update_attributes! password: password
|
81
81
|
else
|
82
|
-
credential = Credentials::Password.new :
|
82
|
+
credential = Credentials::Password.new password: password
|
83
83
|
credential.user_id = user.id
|
84
84
|
credential.save!
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
-
credential = Credentials::Email.where(:
|
88
|
+
credential = Credentials::Email.where(user_id: user.id).first
|
89
89
|
unless credential
|
90
90
|
raise RuntimeError, "Can't specify an user without an e-mail"
|
91
91
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_model'
|
2
|
+
require 'active_record'
|
2
3
|
require 'active_support'
|
3
4
|
|
4
5
|
# :nodoc: namespace
|
@@ -6,30 +7,46 @@ module Authpwn
|
|
6
7
|
|
7
8
|
# :nodoc: namespace
|
8
9
|
module UserExtensions
|
9
|
-
|
10
|
+
|
10
11
|
# Augments the User model with an email virtual attribute.
|
11
12
|
module EmailField
|
12
13
|
extend ActiveSupport::Concern
|
13
|
-
|
14
|
+
|
14
15
|
included do
|
15
|
-
validates :email, :
|
16
|
-
:
|
17
|
-
|
16
|
+
validates :email, format: /\A[A-Za-z0-9.+_]+@[^@]*\.(\w+)\Z/,
|
17
|
+
presence: true
|
18
|
+
if ActiveRecord::Base.respond_to? :mass_assignment_sanitizer=
|
19
|
+
attr_accessible :email
|
20
|
+
end
|
18
21
|
end
|
19
|
-
|
22
|
+
|
20
23
|
module ClassMethods
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
24
|
+
begin
|
25
|
+
ActiveRecord::QueryMethods.instance_method :references
|
26
|
+
# Rails 4.
|
27
|
+
|
28
|
+
# The user who has a certain e-mail, or nil if the e-mail is unclaimed.
|
29
|
+
def with_email(email)
|
30
|
+
credential = Credentials::Email.where(name: email).
|
31
|
+
includes(:user).references(:user).first
|
32
|
+
credential && credential.user
|
33
|
+
end
|
34
|
+
rescue NameError
|
35
|
+
# Rails 3.
|
36
|
+
|
37
|
+
def with_email(email)
|
38
|
+
credential = Credentials::Email.where(name: email).includes(:user).
|
39
|
+
first
|
40
|
+
credential && credential.user
|
41
|
+
end
|
25
42
|
end
|
26
43
|
end
|
27
|
-
|
44
|
+
|
28
45
|
# Credentials::Email instance associated with this user.
|
29
46
|
def email_credential
|
30
47
|
credentials.find { |c| c.instance_of?(Credentials::Email) }
|
31
48
|
end
|
32
|
-
|
49
|
+
|
33
50
|
# The e-mail from the user's Email credential.
|
34
51
|
#
|
35
52
|
# Returns nil if this user has no Email credential.
|
@@ -37,7 +54,7 @@ module EmailField
|
|
37
54
|
credential = self.email_credential
|
38
55
|
credential && credential.email
|
39
56
|
end
|
40
|
-
|
57
|
+
|
41
58
|
# Sets the e-mail on the user's Email credential.
|
42
59
|
#
|
43
60
|
# Creates a new Credentials::Email instance if necessary.
|
@@ -45,12 +62,12 @@ module EmailField
|
|
45
62
|
if credential = self.email_credential
|
46
63
|
credential.email = new_email
|
47
64
|
else
|
48
|
-
credentials << Credentials::Email.new(:
|
65
|
+
credentials << Credentials::Email.new(email: new_email)
|
49
66
|
end
|
50
67
|
new_email
|
51
68
|
end
|
52
69
|
end # module Authpwn::UserExtensions::EmailField
|
53
|
-
|
70
|
+
|
54
71
|
end # module Authpwn::UserExtensions
|
55
|
-
|
72
|
+
|
56
73
|
end # module Authpwn
|
@@ -22,7 +22,7 @@ module FacebookFields
|
|
22
22
|
|
23
23
|
# The user who has a certain e-mail, or nil if the e-mail is unclaimed.
|
24
24
|
def with_facebook_uid(facebook_uid)
|
25
|
-
credential = Credentials::Facebook.where(:
|
25
|
+
credential = Credentials::Facebook.where(name: facebook_uid).
|
26
26
|
includes(:user).first
|
27
27
|
credential && credential.user
|
28
28
|
end
|
@@ -6,30 +6,33 @@ module Authpwn
|
|
6
6
|
|
7
7
|
# :nodoc: namespace
|
8
8
|
module UserExtensions
|
9
|
-
|
9
|
+
|
10
10
|
# Augments the User model with a password virtual attribute.
|
11
11
|
module PasswordField
|
12
12
|
extend ActiveSupport::Concern
|
13
|
-
|
13
|
+
|
14
14
|
included do
|
15
|
-
validates :password, :
|
16
|
-
:
|
17
|
-
|
15
|
+
validates :password, presence: { on: :create },
|
16
|
+
confirmation: { allow_nil: true }
|
17
|
+
|
18
|
+
if ActiveRecord::Base.respond_to? :mass_assignment_sanitizer=
|
19
|
+
attr_accessible :password, :password_confirmation
|
20
|
+
end
|
18
21
|
end
|
19
|
-
|
22
|
+
|
20
23
|
module ClassMethods
|
21
24
|
# The user who has a certain e-mail, or nil if the e-mail is unclaimed.
|
22
25
|
def with_email(email)
|
23
|
-
credential = Credentials::Email.where(:
|
26
|
+
credential = Credentials::Email.where(name: email).includes(:user).first
|
24
27
|
credential && credential.user
|
25
28
|
end
|
26
29
|
end
|
27
|
-
|
30
|
+
|
28
31
|
# Credentials::Password instance associated with this user.
|
29
32
|
def password_credential
|
30
33
|
credentials.find { |c| c.instance_of?(Credentials::Password) }
|
31
34
|
end
|
32
|
-
|
35
|
+
|
33
36
|
# The password from the user's Password credential, or nil.
|
34
37
|
#
|
35
38
|
# Returns nil if this user has no Password credential.
|
@@ -37,7 +40,7 @@ module PasswordField
|
|
37
40
|
credential = self.password_credential
|
38
41
|
credential && credential.password
|
39
42
|
end
|
40
|
-
|
43
|
+
|
41
44
|
# The password_confirmation from the user's Password credential, or nil.
|
42
45
|
#
|
43
46
|
# Returns nil if this user has no Password credential.
|
@@ -53,7 +56,7 @@ module PasswordField
|
|
53
56
|
if credential = self.password_credential
|
54
57
|
credential.password = new_password
|
55
58
|
else
|
56
|
-
credentials << Credentials::Password.new(:
|
59
|
+
credentials << Credentials::Password.new(password: new_password)
|
57
60
|
end
|
58
61
|
new_password
|
59
62
|
end
|
@@ -65,13 +68,13 @@ module PasswordField
|
|
65
68
|
if credential = self.password_credential
|
66
69
|
credential.password_confirmation = new_password_confirmation
|
67
70
|
else
|
68
|
-
credentials << Credentials::Password.new(:
|
71
|
+
credentials << Credentials::Password.new(password_confirmation:
|
69
72
|
new_password_confirmation)
|
70
73
|
end
|
71
74
|
new_password_confirmation
|
72
75
|
end
|
73
76
|
end # module Authpwn::UserExtensions::PasswordField
|
74
|
-
|
77
|
+
|
75
78
|
end # module Authpwn::UserExtensions
|
76
|
-
|
79
|
+
|
77
80
|
end # module Authpwn
|
@@ -17,18 +17,20 @@ module UserModel
|
|
17
17
|
#
|
18
18
|
# This is decoupled from "id" column to avoid leaking information about
|
19
19
|
# the application's usage.
|
20
|
-
validates :exuid, :
|
20
|
+
validates :exuid, presence: true, length: 1..32, uniqueness: true
|
21
21
|
|
22
22
|
# Credentials used to authenticate the user.
|
23
|
-
has_many :credentials, :
|
24
|
-
:
|
23
|
+
has_many :credentials, dependent: :destroy, inverse_of: :user,
|
24
|
+
autosave: true
|
25
25
|
validates_associated :credentials
|
26
26
|
|
27
27
|
# Automatically assign exuid.
|
28
|
-
before_validation :set_default_exuid, :
|
28
|
+
before_validation :set_default_exuid, on: :create
|
29
29
|
|
30
|
-
|
31
|
-
|
30
|
+
if ActiveRecord::Base.respond_to? :mass_assignment_sanitizer=
|
31
|
+
# Forms should not be able to touch any attribute.
|
32
|
+
attr_accessible :credentials_attributes
|
33
|
+
end
|
32
34
|
end
|
33
35
|
|
34
36
|
# Class methods on models that include Authpwn::UserModel.
|
@@ -38,7 +40,7 @@ module UserModel
|
|
38
40
|
# @param [String] param value returned by User#to_param
|
39
41
|
# @return [ActiveRecord::Relation]
|
40
42
|
def with_param(param)
|
41
|
-
where(:
|
43
|
+
where(exuid: param)
|
42
44
|
end
|
43
45
|
|
44
46
|
# Queries the database using the value returned by User#to_param.
|