sorcery 0.5.21 → 0.6.1
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/Gemfile +2 -2
- data/Gemfile.lock +96 -81
- data/README.rdoc +9 -1
- data/Rakefile +3 -3
- data/VERSION +1 -1
- data/lib/sorcery/controller/submodules/activity_logging.rb +11 -7
- data/lib/sorcery/controller/submodules/brute_force_protection.rb +8 -5
- data/lib/sorcery/controller/submodules/external.rb +11 -6
- data/lib/sorcery/controller/submodules/http_basic_auth.rb +11 -6
- data/lib/sorcery/controller/submodules/remember_me.rb +14 -5
- data/lib/sorcery/controller/submodules/session_timeout.rb +3 -1
- data/lib/sorcery/controller.rb +12 -9
- data/lib/sorcery/crypto_providers/aes256.rb +8 -5
- data/lib/sorcery/crypto_providers/bcrypt.rb +12 -6
- data/lib/sorcery/crypto_providers/sha256.rb +2 -1
- data/lib/sorcery/crypto_providers/sha512.rb +2 -1
- data/lib/sorcery/initializers/initializer.rb +125 -36
- data/lib/sorcery/model/adapters/active_record.rb +2 -2
- data/lib/sorcery/model/adapters/mongoid.rb +4 -4
- data/lib/sorcery/model/submodules/activity_logging.rb +7 -6
- data/lib/sorcery/model/submodules/brute_force_protection.rb +10 -6
- data/lib/sorcery/model/submodules/external.rb +4 -2
- data/lib/sorcery/model/submodules/remember_me.rb +4 -3
- data/lib/sorcery/model/submodules/reset_password.rb +16 -8
- data/lib/sorcery/model/submodules/user_activation.rb +23 -10
- data/lib/sorcery/model/temporary_token.rb +3 -2
- data/lib/sorcery/model.rb +58 -26
- data/lib/sorcery/test_helpers/internal/rails.rb +6 -2
- data/lib/sorcery/test_helpers/internal/sinatra.rb +1 -1
- data/lib/sorcery/test_helpers/internal/sinatra_modular.rb +1 -1
- data/lib/sorcery/test_helpers/internal.rb +2 -1
- data/sorcery.gemspec +41 -23
- data/spec/Gemfile +2 -2
- data/spec/Gemfile.lock +33 -32
- data/spec/rails3/Gemfile.lock +7 -7
- data/spec/rails3/spec/controller_oauth2_spec.rb +4 -25
- data/spec/rails3/spec/controller_oauth_spec.rb +3 -24
- data/spec/rails3/spec/controller_spec.rb +2 -2
- data/spec/rails3/spec/user_activation_spec.rb +2 -168
- data/spec/rails3/spec/user_activity_logging_spec.rb +2 -30
- data/spec/rails3/spec/user_brute_force_protection_spec.rb +2 -35
- data/spec/rails3/spec/user_oauth_spec.rb +2 -26
- data/spec/rails3/spec/user_remember_me_spec.rb +2 -45
- data/spec/rails3/spec/user_reset_password_spec.rb +3 -168
- data/spec/rails3/spec/user_spec.rb +3 -283
- data/spec/rails3_mongoid/Gemfile.lock +7 -7
- data/spec/rails3_mongoid/app/models/authentication.rb +3 -3
- data/spec/rails3_mongoid/spec/user_activation_spec.rb +2 -171
- data/spec/rails3_mongoid/spec/user_activity_logging_spec.rb +2 -25
- data/spec/rails3_mongoid/spec/user_brute_force_protection_spec.rb +2 -35
- data/spec/rails3_mongoid/spec/user_oauth_spec.rb +2 -28
- data/spec/rails3_mongoid/spec/user_remember_me_spec.rb +2 -45
- data/spec/rails3_mongoid/spec/user_reset_password_spec.rb +2 -176
- data/spec/rails3_mongoid/spec/user_spec.rb +3 -285
- data/spec/shared_examples/controller_oauth2_shared_examples.rb +37 -0
- data/spec/shared_examples/controller_oauth_shared_examples.rb +37 -0
- data/spec/shared_examples/user_activation_shared_examples.rb +173 -0
- data/spec/shared_examples/user_activity_logging_shared_examples.rb +27 -0
- data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +37 -0
- data/spec/shared_examples/user_oauth_shared_examples.rb +31 -0
- data/spec/shared_examples/user_remember_me_shared_examples.rb +47 -0
- data/spec/shared_examples/user_reset_password_shared_examples.rb +177 -0
- data/spec/shared_examples/user_shared_examples.rb +292 -0
- data/spec/sinatra/Gemfile.lock +7 -7
- data/spec/sinatra/spec/controller_oauth2_spec.rb +3 -24
- data/spec/sinatra/spec/controller_oauth_spec.rb +3 -24
- data/spec/sinatra/spec/controller_spec.rb +2 -2
- data/spec/sinatra_modular/Gemfile.lock +7 -7
- data/spec/sinatra_modular/spec_modular/controller_oauth2_spec.rb +3 -24
- data/spec/sinatra_modular/spec_modular/controller_oauth_spec.rb +3 -24
- data/spec/sinatra_modular/spec_modular/controller_spec.rb +2 -2
- metadata +28 -12
|
@@ -1,25 +1,35 @@
|
|
|
1
1
|
# The first thing you need to configure is which modules you need in your app.
|
|
2
2
|
# The default is nothing which will include only core features (password encryption, login/logout).
|
|
3
|
-
# Available submodules are: :user_activation, :http_basic_auth, :remember_me,
|
|
3
|
+
# Available submodules are: :user_activation, :http_basic_auth, :remember_me,
|
|
4
|
+
# :reset_password, :session_timeout, :brute_force_protection, :activity_logging, :external
|
|
4
5
|
Rails.application.config.sorcery.submodules = []
|
|
5
6
|
|
|
6
7
|
# Here you can configure each submodule's features.
|
|
7
8
|
Rails.application.config.sorcery.configure do |config|
|
|
8
9
|
# -- core --
|
|
9
|
-
# config.not_authenticated_action = :not_authenticated # what controller action to call for
|
|
10
|
-
|
|
11
|
-
#
|
|
10
|
+
# config.not_authenticated_action = :not_authenticated # what controller action to call for
|
|
11
|
+
# non-authenticated users.
|
|
12
|
+
# You can also override 'not_authenticated'
|
|
13
|
+
# instead.
|
|
14
|
+
|
|
15
|
+
# config.save_return_to_url = true # when a non logged in user tries to enter
|
|
16
|
+
# a page that requires login,
|
|
17
|
+
# save the URL he wanted to reach,
|
|
18
|
+
# and send him there after login, using
|
|
19
|
+
# 'redirect_back_or_to'.
|
|
12
20
|
|
|
13
21
|
# -- session timeout --
|
|
14
22
|
# config.session_timeout = 3600 # how long in seconds to keep the session alive.
|
|
15
|
-
# config.session_timeout_from_last_action = false # use the last action as the beginning of
|
|
23
|
+
# config.session_timeout_from_last_action = false # use the last action as the beginning of
|
|
24
|
+
# session timeout.
|
|
16
25
|
|
|
17
26
|
# -- http_basic_auth --
|
|
18
27
|
# config.controller_to_realm_map = {"application" => "Application"} # What realm to display for which controller name.
|
|
19
28
|
# For example {"My App" => "Application"}
|
|
20
29
|
|
|
21
30
|
# -- external --
|
|
22
|
-
# config.external_providers = [] # What providers are supported by this app,
|
|
31
|
+
# config.external_providers = [] # What providers are supported by this app,
|
|
32
|
+
# i.e. [:twitter, :facebook] .
|
|
23
33
|
#
|
|
24
34
|
# config.twitter.key = "eYVNBjBDi33aa9GkA3w"
|
|
25
35
|
# config.twitter.secret = "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8"
|
|
@@ -34,56 +44,135 @@ Rails.application.config.sorcery.configure do |config|
|
|
|
34
44
|
# --- user config ---
|
|
35
45
|
config.user_config do |user|
|
|
36
46
|
# -- core --
|
|
37
|
-
# user.username_attribute_name = :username # change default username
|
|
38
|
-
|
|
47
|
+
# user.username_attribute_name = :username # change default username
|
|
48
|
+
# attribute, for example,
|
|
49
|
+
# to use :email as the login.
|
|
50
|
+
|
|
51
|
+
# user.password_attribute_name = :password # change *virtual* password
|
|
52
|
+
# attribute, the one which is used
|
|
53
|
+
# until an encrypted one is
|
|
54
|
+
# generated.
|
|
55
|
+
|
|
39
56
|
# user.email_attribute_name = :email # change default email attribute.
|
|
40
|
-
|
|
41
|
-
# user.
|
|
57
|
+
|
|
58
|
+
# user.crypted_password_attribute_name = :crypted_password # change default crypted_password
|
|
59
|
+
# attribute.
|
|
60
|
+
|
|
61
|
+
# user.salt_join_token = "" # what pattern to use to join the
|
|
62
|
+
# password with the salt
|
|
63
|
+
|
|
42
64
|
# user.salt_attribute_name = :salt # change default salt attribute.
|
|
43
|
-
|
|
44
|
-
# user.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
# user.
|
|
65
|
+
|
|
66
|
+
# user.stretches = nil # how many times to apply
|
|
67
|
+
# encryption to the password.
|
|
68
|
+
|
|
69
|
+
# user.encryption_key = nil # encryption key used to encrypt
|
|
70
|
+
# reversible encryptions such as
|
|
71
|
+
# AES256.
|
|
72
|
+
|
|
73
|
+
# user.custom_encryption_provider = nil # use an external encryption
|
|
74
|
+
# class.
|
|
75
|
+
|
|
76
|
+
# user.encryption_algorithm = :bcrypt # encryption algorithm name. See
|
|
77
|
+
# 'encryption_algorithm=' for
|
|
78
|
+
# available options.
|
|
79
|
+
|
|
80
|
+
# user.subclasses_inherit_config = false # make this configuration
|
|
81
|
+
# inheritable for subclasses.
|
|
82
|
+
# Useful for ActiveRecord's STI.
|
|
48
83
|
|
|
49
84
|
# -- user_activation --
|
|
50
|
-
# user.activation_state_attribute_name = :activation_state # the attribute name to hold
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
85
|
+
# user.activation_state_attribute_name = :activation_state # the attribute name to hold
|
|
86
|
+
# activation state
|
|
87
|
+
# (active/pending).
|
|
88
|
+
|
|
89
|
+
# user.activation_token_attribute_name = :activation_token # the attribute name to hold
|
|
90
|
+
# activation code (sent by email).
|
|
91
|
+
|
|
92
|
+
# user.activation_token_expires_at_attribute_name = :activation_token_expires_at # the attribute name to hold
|
|
93
|
+
# activation code expiration date.
|
|
94
|
+
|
|
95
|
+
# user.activation_token_expiration_period = nil # how many seconds before the
|
|
96
|
+
# activation code expires. nil for
|
|
97
|
+
# never expires.
|
|
98
|
+
|
|
54
99
|
# user.user_activation_mailer = nil # your mailer class. Required.
|
|
55
|
-
|
|
56
|
-
# user.
|
|
57
|
-
|
|
100
|
+
|
|
101
|
+
# user.activation_needed_email_method_name = :activation_needed_email # activation needed email method
|
|
102
|
+
# on your mailer class.
|
|
103
|
+
|
|
104
|
+
# user.activation_success_email_method_name = :activation_success_email # activation success email method
|
|
105
|
+
# on your mailer class.
|
|
106
|
+
|
|
107
|
+
# user.prevent_non_active_users_to_login = true # do you want to prevent or allow
|
|
108
|
+
# users that did not activate by
|
|
109
|
+
# email to login?
|
|
58
110
|
|
|
59
111
|
# -- reset_password --
|
|
60
|
-
# user.reset_password_token_attribute_name = :reset_password_token # reset password code
|
|
61
|
-
|
|
62
|
-
|
|
112
|
+
# user.reset_password_token_attribute_name = :reset_password_token # reset password code
|
|
113
|
+
# attribute name.
|
|
114
|
+
|
|
115
|
+
# user.reset_password_token_expires_at_attribute_name = :reset_password_token_expires_at # expires at attribute
|
|
116
|
+
# name.
|
|
117
|
+
|
|
118
|
+
# user.reset_password_email_sent_at_attribute_name = :reset_password_email_sent_at # when was email sent,
|
|
119
|
+
# used for hammering
|
|
120
|
+
# protection.
|
|
121
|
+
|
|
63
122
|
# user.reset_password_mailer = nil # mailer class. Needed.
|
|
64
|
-
|
|
65
|
-
# user.
|
|
66
|
-
|
|
123
|
+
|
|
124
|
+
# user.reset_password_email_method_name = :reset_password_email # reset password email
|
|
125
|
+
# method on your mailer
|
|
126
|
+
# class.
|
|
127
|
+
|
|
128
|
+
# user.reset_password_expiration_period = nil # how many seconds
|
|
129
|
+
# before the reset
|
|
130
|
+
# request expires. nil
|
|
131
|
+
# for never expires.
|
|
132
|
+
|
|
133
|
+
# user.reset_password_time_between_emails = 5 * 60 # hammering protection,
|
|
134
|
+
# how long to wait
|
|
135
|
+
# before allowing
|
|
136
|
+
# another email to be
|
|
137
|
+
# sent.
|
|
67
138
|
|
|
68
139
|
# -- brute_force_protection --
|
|
69
140
|
# user.failed_logins_count_attribute_name = :failed_logins_count # failed logins attribute name.
|
|
70
|
-
|
|
141
|
+
|
|
142
|
+
# user.lock_expires_at_attribute_name = :lock_expires_at # this field indicates whether
|
|
143
|
+
# user is banned and when it will
|
|
144
|
+
# be active again.
|
|
145
|
+
|
|
71
146
|
# user.consecutive_login_retries_amount_limit = 50 # how many failed logins allowed.
|
|
72
|
-
|
|
147
|
+
|
|
148
|
+
# user.login_lock_time_period = 60 * 60 # how long the user should be
|
|
149
|
+
# banned. in seconds. 0 for
|
|
150
|
+
# permanent.
|
|
73
151
|
|
|
74
152
|
# -- activity logging --
|
|
75
153
|
# user.last_login_at_attribute_name = :last_login_at # last login attribute name.
|
|
76
154
|
# user.last_logout_at_attribute_name = :last_logout_at # last logout attribute name.
|
|
77
155
|
# user.last_activity_at_attribute_name = :last_activity_at # last activity attribute name.
|
|
78
|
-
# user.activity_timeout = 10 * 60 # how long since last activity is
|
|
156
|
+
# user.activity_timeout = 10 * 60 # how long since last activity is
|
|
157
|
+
# the user defined logged out?
|
|
79
158
|
|
|
80
159
|
# -- external --
|
|
81
|
-
# user.authentications_class = nil # class which holds the various
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
160
|
+
# user.authentications_class = nil # class which holds the various
|
|
161
|
+
# external provider data for this
|
|
162
|
+
# user.
|
|
163
|
+
|
|
164
|
+
# user.authentications_user_id_attribute_name = :user_id # user's identifier in
|
|
165
|
+
# authentications class.
|
|
166
|
+
|
|
167
|
+
# user.provider_attribute_name = :provider # provider's identifier in
|
|
168
|
+
# authentications class.
|
|
169
|
+
|
|
170
|
+
# user.provider_uid_attribute_name = :uid # user's external unique
|
|
171
|
+
# identifier in authentications
|
|
172
|
+
# class.
|
|
85
173
|
end
|
|
86
174
|
|
|
87
175
|
# This line must come after the 'user config' block.
|
|
88
|
-
config.user_class = User
|
|
176
|
+
config.user_class = "User" # define which model authenticates
|
|
177
|
+
# with sorcery.
|
|
89
178
|
end
|
|
@@ -11,7 +11,7 @@ module Sorcery
|
|
|
11
11
|
where("#{@sorcery_config.username_attribute_name} = ?", credentials[0]).first
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def
|
|
14
|
+
def find_by_sorcery_token(token_attr_name, token)
|
|
15
15
|
where("#{token_attr_name} = ?", token).first
|
|
16
16
|
end
|
|
17
17
|
|
|
@@ -25,4 +25,4 @@ module Sorcery
|
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
|
-
end
|
|
28
|
+
end
|
|
@@ -19,8 +19,8 @@ module Sorcery
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def find_by_provider_and_uid(provider, uid)
|
|
22
|
-
user_klass
|
|
23
|
-
where(user_klass.sorcery_config.provider_attribute_name => provider, user_klass.sorcery_config.provider_uid_attribute_name => uid).first
|
|
22
|
+
@user_klass ||= ::Sorcery::Controller::Config.user_class.to_s.constantize
|
|
23
|
+
where(@user_klass.sorcery_config.provider_attribute_name => provider, @user_klass.sorcery_config.provider_uid_attribute_name => uid).first
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def find_by_id(id)
|
|
@@ -43,7 +43,7 @@ module Sorcery
|
|
|
43
43
|
tap(&blk)
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
def
|
|
46
|
+
def find_by_sorcery_token(token_attr_name, token)
|
|
47
47
|
where(token_attr_name => token).first
|
|
48
48
|
end
|
|
49
49
|
|
|
@@ -61,4 +61,4 @@ module Sorcery
|
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
end
|
|
64
|
-
end
|
|
64
|
+
end
|
|
@@ -3,8 +3,8 @@ module Sorcery
|
|
|
3
3
|
module Submodules
|
|
4
4
|
# This submodule keeps track of events such as login, logout, and last activity time, per user.
|
|
5
5
|
# It helps in estimating which users are active now in the site.
|
|
6
|
-
# This cannot be determined absolutely because a user might be reading a page without clicking anything
|
|
7
|
-
|
|
6
|
+
# This cannot be determined absolutely because a user might be reading a page without clicking anything
|
|
7
|
+
# for a while.
|
|
8
8
|
# This is the model part of the submodule, which provides configuration options.
|
|
9
9
|
module ActivityLogging
|
|
10
10
|
def self.included(base)
|
|
@@ -14,7 +14,8 @@ module Sorcery
|
|
|
14
14
|
attr_accessor :last_login_at_attribute_name, # last login attribute name.
|
|
15
15
|
:last_logout_at_attribute_name, # last logout attribute name.
|
|
16
16
|
:last_activity_at_attribute_name, # last activity attribute name.
|
|
17
|
-
:activity_timeout # how long since last activity is
|
|
17
|
+
:activity_timeout # how long since last activity is
|
|
18
|
+
#the user defined logged out?
|
|
18
19
|
end
|
|
19
20
|
|
|
20
21
|
base.sorcery_config.instance_eval do
|
|
@@ -38,9 +39,9 @@ module Sorcery
|
|
|
38
39
|
protected
|
|
39
40
|
|
|
40
41
|
def define_activity_logging_mongoid_fields
|
|
41
|
-
field sorcery_config.last_login_at_attribute_name,
|
|
42
|
-
field sorcery_config.last_logout_at_attribute_name,
|
|
43
|
-
field sorcery_config.last_activity_at_attribute_name, type
|
|
42
|
+
field sorcery_config.last_login_at_attribute_name, :type => DateTime
|
|
43
|
+
field sorcery_config.last_logout_at_attribute_name, :type => DateTime
|
|
44
|
+
field sorcery_config.last_activity_at_attribute_name, :type => DateTime
|
|
44
45
|
end
|
|
45
46
|
end
|
|
46
47
|
end
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
module Sorcery
|
|
2
2
|
module Model
|
|
3
3
|
module Submodules
|
|
4
|
-
# This module helps protect user accounts by locking them down after too many failed attemps
|
|
5
|
-
#
|
|
4
|
+
# This module helps protect user accounts by locking them down after too many failed attemps
|
|
5
|
+
# to login were detected.
|
|
6
|
+
# This is the model part of the submodule which provides configuration options and methods
|
|
7
|
+
# for locking and unlocking the user.
|
|
6
8
|
module BruteForceProtection
|
|
7
9
|
def self.included(base)
|
|
8
10
|
base.sorcery_config.class_eval do
|
|
9
11
|
attr_accessor :failed_logins_count_attribute_name, # failed logins attribute name.
|
|
10
|
-
:lock_expires_at_attribute_name, # this field indicates whether user
|
|
12
|
+
:lock_expires_at_attribute_name, # this field indicates whether user
|
|
13
|
+
# is banned and when it will be active again.
|
|
11
14
|
:consecutive_login_retries_amount_limit, # how many failed logins allowed.
|
|
12
|
-
:login_lock_time_period # how long the user should be banned.
|
|
15
|
+
:login_lock_time_period # how long the user should be banned.
|
|
16
|
+
# in seconds. 0 for permanent.
|
|
13
17
|
end
|
|
14
18
|
|
|
15
19
|
base.sorcery_config.instance_eval do
|
|
@@ -30,8 +34,8 @@ module Sorcery
|
|
|
30
34
|
protected
|
|
31
35
|
|
|
32
36
|
def define_brute_force_protection_mongoid_fields
|
|
33
|
-
field sorcery_config.failed_logins_count_attribute_name,
|
|
34
|
-
field sorcery_config.lock_expires_at_attribute_name,
|
|
37
|
+
field sorcery_config.failed_logins_count_attribute_name, :type => Integer
|
|
38
|
+
field sorcery_config.lock_expires_at_attribute_name, :type => DateTime
|
|
35
39
|
end
|
|
36
40
|
end
|
|
37
41
|
|
|
@@ -5,9 +5,11 @@ module Sorcery
|
|
|
5
5
|
# This is the model part which handles finding the user using access tokens.
|
|
6
6
|
# For the controller options see Sorcery::Controller::External.
|
|
7
7
|
#
|
|
8
|
-
# Socery assumes (read: requires) you will create external users in the same table where
|
|
8
|
+
# Socery assumes (read: requires) you will create external users in the same table where
|
|
9
|
+
# you keep your regular users,
|
|
9
10
|
# but that you will have a separate table for keeping their external authentication data,
|
|
10
|
-
# and that that separate table has a few rows for each user, facebook and twitter
|
|
11
|
+
# and that that separate table has a few rows for each user, facebook and twitter
|
|
12
|
+
# for example (a one-to-many relationship).
|
|
11
13
|
#
|
|
12
14
|
# External users will have a null crypted_password field, since we do not hold their password.
|
|
13
15
|
# They will not be sent activation emails on creation.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
module Sorcery
|
|
2
2
|
module Model
|
|
3
3
|
module Submodules
|
|
4
|
-
# The Remember Me submodule takes care of setting the user's cookie so that he will
|
|
4
|
+
# The Remember Me submodule takes care of setting the user's cookie so that he will
|
|
5
|
+
# be automatically logged in to the site on every visit,
|
|
5
6
|
# until the cookie expires.
|
|
6
7
|
module RememberMe
|
|
7
8
|
def self.included(base)
|
|
@@ -31,8 +32,8 @@ module Sorcery
|
|
|
31
32
|
protected
|
|
32
33
|
|
|
33
34
|
def define_remember_me_mongoid_fields
|
|
34
|
-
field sorcery_config.remember_me_token_attribute_name,
|
|
35
|
-
field sorcery_config.remember_me_token_expires_at_attribute_name, type
|
|
35
|
+
field sorcery_config.remember_me_token_attribute_name, :type => String
|
|
36
|
+
field sorcery_config.remember_me_token_expires_at_attribute_name, :type => Time
|
|
36
37
|
end
|
|
37
38
|
|
|
38
39
|
end
|
|
@@ -5,7 +5,8 @@ module Sorcery
|
|
|
5
5
|
# When the user requests an email is sent to him with a url.
|
|
6
6
|
# The url includes a token, which is also saved with the user's record in the db.
|
|
7
7
|
# The token has configurable expiration.
|
|
8
|
-
# When the user clicks the url in the email, providing the token has not yet expired,
|
|
8
|
+
# When the user clicks the url in the email, providing the token has not yet expired,
|
|
9
|
+
# he will be able to reset his password via a form.
|
|
9
10
|
#
|
|
10
11
|
# When using this submodule, supplying a mailer is mandatory.
|
|
11
12
|
module ResetPassword
|
|
@@ -13,11 +14,18 @@ module Sorcery
|
|
|
13
14
|
base.sorcery_config.class_eval do
|
|
14
15
|
attr_accessor :reset_password_token_attribute_name, # reset password code attribute name.
|
|
15
16
|
:reset_password_token_expires_at_attribute_name, # expires at attribute name.
|
|
16
|
-
:reset_password_email_sent_at_attribute_name, # when was email sent, used for hammering
|
|
17
|
+
:reset_password_email_sent_at_attribute_name, # when was email sent, used for hammering
|
|
18
|
+
# protection.
|
|
19
|
+
|
|
17
20
|
:reset_password_mailer, # mailer class. Needed.
|
|
18
|
-
:reset_password_email_method_name, # reset password email method on your
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
:reset_password_email_method_name, # reset password email method on your
|
|
22
|
+
# mailer class.
|
|
23
|
+
|
|
24
|
+
:reset_password_expiration_period, # how many seconds before the reset request
|
|
25
|
+
# expires. nil for never expires.
|
|
26
|
+
|
|
27
|
+
:reset_password_time_between_emails # hammering protection, how long to wait
|
|
28
|
+
# before allowing another email to be sent.
|
|
21
29
|
|
|
22
30
|
end
|
|
23
31
|
|
|
@@ -61,9 +69,9 @@ module Sorcery
|
|
|
61
69
|
end
|
|
62
70
|
|
|
63
71
|
def define_reset_password_mongoid_fields
|
|
64
|
-
field sorcery_config.reset_password_token_attribute_name,
|
|
65
|
-
field sorcery_config.reset_password_token_expires_at_attribute_name,
|
|
66
|
-
field sorcery_config.reset_password_email_sent_at_attribute_name,
|
|
72
|
+
field sorcery_config.reset_password_token_attribute_name, :type => String
|
|
73
|
+
field sorcery_config.reset_password_token_expires_at_attribute_name, :type => DateTime
|
|
74
|
+
field sorcery_config.reset_password_email_sent_at_attribute_name, :type => DateTime
|
|
67
75
|
end
|
|
68
76
|
end
|
|
69
77
|
|
|
@@ -8,14 +8,27 @@ module Sorcery
|
|
|
8
8
|
module UserActivation
|
|
9
9
|
def self.included(base)
|
|
10
10
|
base.sorcery_config.class_eval do
|
|
11
|
-
attr_accessor :activation_state_attribute_name, # the attribute name to hold activation state
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
:
|
|
11
|
+
attr_accessor :activation_state_attribute_name, # the attribute name to hold activation state
|
|
12
|
+
# (active/pending).
|
|
13
|
+
|
|
14
|
+
:activation_token_attribute_name, # the attribute name to hold activation code
|
|
15
|
+
# (sent by email).
|
|
16
|
+
|
|
17
|
+
:activation_token_expires_at_attribute_name, # the attribute name to hold activation code
|
|
18
|
+
# expiration date.
|
|
19
|
+
|
|
20
|
+
:activation_token_expiration_period, # how many seconds before the activation code
|
|
21
|
+
# expires. nil for never expires.
|
|
22
|
+
|
|
15
23
|
:user_activation_mailer, # your mailer class. Required.
|
|
16
|
-
:activation_needed_email_method_name, # activation needed email method on your
|
|
17
|
-
|
|
18
|
-
|
|
24
|
+
:activation_needed_email_method_name, # activation needed email method on your
|
|
25
|
+
# mailer class.
|
|
26
|
+
|
|
27
|
+
:activation_success_email_method_name, # activation success email method on your
|
|
28
|
+
# mailer class.
|
|
29
|
+
|
|
30
|
+
:prevent_non_active_users_to_login # do you want to prevent or allow users that
|
|
31
|
+
# did not activate by email to login?
|
|
19
32
|
end
|
|
20
33
|
|
|
21
34
|
base.sorcery_config.instance_eval do
|
|
@@ -67,9 +80,9 @@ module Sorcery
|
|
|
67
80
|
|
|
68
81
|
def define_user_activation_mongoid_fields
|
|
69
82
|
self.class_eval do
|
|
70
|
-
field sorcery_config.activation_state_attribute_name,
|
|
71
|
-
field sorcery_config.activation_token_attribute_name,
|
|
72
|
-
field sorcery_config.activation_token_expires_at_attribute_name, type
|
|
83
|
+
field sorcery_config.activation_state_attribute_name, :type => String
|
|
84
|
+
field sorcery_config.activation_token_attribute_name, :type => String
|
|
85
|
+
field sorcery_config.activation_token_expires_at_attribute_name, :type => DateTime
|
|
73
86
|
end
|
|
74
87
|
end
|
|
75
88
|
end
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
module Sorcery
|
|
2
2
|
module Model
|
|
3
3
|
# This module encapsulates the logic for temporary token.
|
|
4
|
-
# A temporary token is created to identify a user in scenarios
|
|
4
|
+
# A temporary token is created to identify a user in scenarios
|
|
5
|
+
# such as reseting password and activating the user by email.
|
|
5
6
|
module TemporaryToken
|
|
6
7
|
def self.included(base)
|
|
7
8
|
base.extend(ClassMethods)
|
|
@@ -10,7 +11,7 @@ module Sorcery
|
|
|
10
11
|
module ClassMethods
|
|
11
12
|
def load_from_token(token, token_attr_name, token_expiration_date_attr)
|
|
12
13
|
return nil if token.blank?
|
|
13
|
-
user =
|
|
14
|
+
user = find_by_sorcery_token(token_attr_name,token)
|
|
14
15
|
if !user.blank? && !user.send(token_expiration_date_attr).nil?
|
|
15
16
|
return Time.now.utc < user.send(token_expiration_date_attr) ? user : nil
|
|
16
17
|
end
|
data/lib/sorcery/model.rb
CHANGED
|
@@ -3,7 +3,8 @@ module Sorcery
|
|
|
3
3
|
# It should be included into the ORM base class.
|
|
4
4
|
# In the case of Rails this is usually ActiveRecord (actually, in that case, the plugin does this automatically).
|
|
5
5
|
#
|
|
6
|
-
# When included it defines a single method: 'activate_sorcery!' which when called adds the other capabilities
|
|
6
|
+
# When included it defines a single method: 'activate_sorcery!' which when called adds the other capabilities
|
|
7
|
+
# to the class.
|
|
7
8
|
# This method is also the place to configure the plugin in the Model layer.
|
|
8
9
|
module Model
|
|
9
10
|
def self.included(klass)
|
|
@@ -14,39 +15,58 @@ module Sorcery
|
|
|
14
15
|
self.class_eval do
|
|
15
16
|
extend ClassMethods # included here, before submodules, so they can be overriden by them.
|
|
16
17
|
include InstanceMethods
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
include_required_submodules!
|
|
21
|
+
|
|
22
|
+
# This runs the options block set in the initializer on the model class.
|
|
23
|
+
::Sorcery::Controller::Config.user_config.tap{|blk| blk.call(@sorcery_config) if blk}
|
|
24
|
+
|
|
25
|
+
init_mongoid_support! if defined?(Mongoid) and self.ancestors.include?(Mongoid::Document)
|
|
17
26
|
|
|
27
|
+
init_orm_hooks!
|
|
28
|
+
|
|
29
|
+
@sorcery_config.after_config << :add_config_inheritance if @sorcery_config.subclasses_inherit_config
|
|
30
|
+
@sorcery_config.after_config.each { |c| send(c) }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
protected
|
|
34
|
+
|
|
35
|
+
# includes required submodules into the model class,
|
|
36
|
+
# which usually is called User.
|
|
37
|
+
def include_required_submodules!
|
|
38
|
+
self.class_eval do
|
|
18
39
|
@sorcery_config.submodules = ::Sorcery::Controller::Config.submodules
|
|
19
40
|
@sorcery_config.submodules.each do |mod|
|
|
20
41
|
begin
|
|
21
42
|
include Submodules.const_get(mod.to_s.split("_").map {|p| p.capitalize}.join(""))
|
|
22
43
|
rescue NameError
|
|
23
|
-
# don't stop on a missing submodule. Needed because some submodules are only defined
|
|
44
|
+
# don't stop on a missing submodule. Needed because some submodules are only defined
|
|
45
|
+
# in the controller side.
|
|
24
46
|
end
|
|
25
47
|
end
|
|
26
48
|
end
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# defines mongoid fields on the model class,
|
|
52
|
+
# using 1.8.x hash syntax to perserve compatibility.
|
|
53
|
+
def init_mongoid_support!
|
|
32
54
|
self.class_eval do
|
|
33
|
-
field sorcery_config.username_attribute_name,
|
|
34
|
-
|
|
35
|
-
field sorcery_config.
|
|
36
|
-
field sorcery_config.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
55
|
+
field sorcery_config.username_attribute_name, :type => String
|
|
56
|
+
field sorcery_config.email_attribute_name, :type => String unless sorcery_config.username_attribute_name == sorcery_config.email_attribute_name
|
|
57
|
+
field sorcery_config.crypted_password_attribute_name, :type => String
|
|
58
|
+
field sorcery_config.salt_attribute_name, :type => String
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# add virtual password accessor and ORM callbacks.
|
|
63
|
+
def init_orm_hooks!
|
|
41
64
|
self.class_eval do
|
|
42
65
|
attr_accessor @sorcery_config.password_attribute_name
|
|
43
66
|
attr_protected @sorcery_config.crypted_password_attribute_name, @sorcery_config.salt_attribute_name
|
|
44
67
|
before_save :encrypt_password, :if => Proc.new { |record| record.send(sorcery_config.password_attribute_name).present? }
|
|
45
68
|
after_save :clear_virtual_password, :if => Proc.new { |record| record.send(sorcery_config.password_attribute_name).present? }
|
|
46
69
|
end
|
|
47
|
-
|
|
48
|
-
@sorcery_config.after_config << :add_config_inheritance if @sorcery_config.subclasses_inherit_config
|
|
49
|
-
@sorcery_config.after_config.each { |c| send(c) }
|
|
50
70
|
end
|
|
51
71
|
end
|
|
52
72
|
end
|
|
@@ -147,26 +167,38 @@ module Sorcery
|
|
|
147
167
|
end
|
|
148
168
|
|
|
149
169
|
# Each class which calls 'activate_sorcery!' receives an instance of this class.
|
|
150
|
-
# Every submodule which gets loaded may add accessors to this class so that all
|
|
170
|
+
# Every submodule which gets loaded may add accessors to this class so that all
|
|
171
|
+
# options will be configured from a single place.
|
|
151
172
|
class Config
|
|
152
173
|
|
|
153
|
-
attr_accessor :username_attribute_name, # change default username attribute, for example, to use :email
|
|
154
|
-
|
|
174
|
+
attr_accessor :username_attribute_name, # change default username attribute, for example, to use :email
|
|
175
|
+
# as the login.
|
|
176
|
+
|
|
177
|
+
:password_attribute_name, # change *virtual* password attribute, the one which is used
|
|
178
|
+
# until an encrypted one is generated.
|
|
179
|
+
|
|
155
180
|
:email_attribute_name, # change default email attribute.
|
|
156
181
|
:crypted_password_attribute_name, # change default crypted_password attribute.
|
|
157
182
|
:salt_join_token, # what pattern to use to join the password with the salt
|
|
158
183
|
:salt_attribute_name, # change default salt attribute.
|
|
159
184
|
:stretches, # how many times to apply encryption to the password.
|
|
160
|
-
:encryption_key, # encryption key used to encrypt reversible encryptions such as
|
|
161
|
-
|
|
185
|
+
:encryption_key, # encryption key used to encrypt reversible encryptions such as
|
|
186
|
+
# AES256.
|
|
187
|
+
|
|
188
|
+
:subclasses_inherit_config, # make this configuration inheritable for subclasses. Useful for
|
|
189
|
+
# ActiveRecord's STI.
|
|
162
190
|
|
|
163
191
|
:submodules, # configured in config/application.rb
|
|
164
|
-
:before_authenticate, # an array of method names to call before authentication
|
|
165
|
-
|
|
192
|
+
:before_authenticate, # an array of method names to call before authentication
|
|
193
|
+
# completes. used internally.
|
|
194
|
+
|
|
195
|
+
:after_config # an array of method names to call after configuration by user.
|
|
196
|
+
# used internally.
|
|
166
197
|
|
|
167
198
|
attr_reader :encryption_provider, # change default encryption_provider.
|
|
168
199
|
:custom_encryption_provider, # use an external encryption class.
|
|
169
|
-
:encryption_algorithm # encryption algorithm name. See 'encryption_algorithm=' below
|
|
200
|
+
:encryption_algorithm # encryption algorithm name. See 'encryption_algorithm=' below
|
|
201
|
+
# for available options.
|
|
170
202
|
|
|
171
203
|
def initialize
|
|
172
204
|
@defaults = {
|