minimalist_authentication 2.7.0 → 3.0.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.
- checksums.yaml +4 -4
- data/README.md +25 -8
- data/app/views/passwords/edit.html.erb +2 -0
- data/lib/minimalist_authentication/configuration.rb +1 -1
- data/lib/minimalist_authentication/controller.rb +0 -4
- data/lib/minimalist_authentication/sessions.rb +7 -9
- data/lib/minimalist_authentication/test_helper.rb +1 -0
- data/lib/minimalist_authentication/user.rb +24 -38
- data/lib/minimalist_authentication/version.rb +1 -1
- data/lib/minimalist_authentication.rb +0 -3
- metadata +1 -3
- data/lib/minimalist_authentication/null_password.rb +0 -10
- data/lib/minimalist_authentication/password.rb +0 -46
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a82f3a3833f400b37555173885d052000dfbd5e4a67da90068384558f8d97705
|
|
4
|
+
data.tar.gz: 48b819ddbb26a5cb5deaa03c5cd3ef943394e93d6390286d3f30cbae7e5e8477
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c867bd7daebdce0f0998e78db4d05ed89bd8d3767d6bb0dc79e362f74ca8e2ac43e930dffb0f396d3d1f4f6b517d26fee00e03e06c32a8afd4b52fb0d03984b7
|
|
7
|
+
data.tar.gz: de8329fcb5b6bd2d01e9a421818952e6f362d4ff16a3e060d30e5b3afbd4751d56e4c0d37b1a3d80d917baf48dea36b407a2fbfc8f647019fa896529d82bf3a2
|
data/README.md
CHANGED
|
@@ -16,12 +16,12 @@ $ bundle
|
|
|
16
16
|
|
|
17
17
|
Create a user model with **email** for an identifier:
|
|
18
18
|
```bash
|
|
19
|
-
bin/rails generate model user active:boolean email:string
|
|
19
|
+
bin/rails generate model user active:boolean email:string password_digest:string last_logged_in_at:datetime
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
OR create a user model with **username** for an identifier:
|
|
23
23
|
```bash
|
|
24
|
-
bin/rails generate model user active:boolean username:string
|
|
24
|
+
bin/rails generate model user active:boolean username:string password_digest:string last_logged_in_at:datetime
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
|
|
@@ -79,12 +79,11 @@ end
|
|
|
79
79
|
|
|
80
80
|
|
|
81
81
|
## Fixtures
|
|
82
|
-
Use **MinimalistAuthentication::
|
|
83
|
-
fixture users.
|
|
82
|
+
Use **MinimalistAuthentication::TestHelper::PASSWORD_DIGEST** to create a password_digest for fixture users.
|
|
84
83
|
```yaml
|
|
85
84
|
example_user:
|
|
86
|
-
email:
|
|
87
|
-
|
|
85
|
+
email: user@example.com
|
|
86
|
+
password_digest: <%= MinimalistAuthentication::TestHelper::PASSWORD_DIGEST %>
|
|
88
87
|
```
|
|
89
88
|
|
|
90
89
|
|
|
@@ -124,6 +123,8 @@ bin/rails generate migration AddEmailVerifiedAtToUsers email_verified_at:datetim
|
|
|
124
123
|
|
|
125
124
|
|
|
126
125
|
## Conversions
|
|
126
|
+
|
|
127
|
+
### Upgrading to Version 2.0
|
|
127
128
|
Pre 2.0 versions of MinimalistAuthentication supported multiple hash algorithms
|
|
128
129
|
and stored the hashed password and salt as separate fields in the database
|
|
129
130
|
(crypted_password and salt). The current version of MinimalistAuthentication
|
|
@@ -141,10 +142,26 @@ MinimalistAuthentication::Conversions::MergePasswordHash.run!
|
|
|
141
142
|
When the conversion is complete the **crypted_password**, **salt**, and
|
|
142
143
|
**using_digest_version** fields can safely be removed.
|
|
143
144
|
|
|
145
|
+
### Upgrading to Version 3.0
|
|
146
|
+
Version 3.0 of MinimalistAuthentication uses the Rails has_secure_password for authentication. This change requires either renaming the **password_hash** column to **password_digest** or adding an alias_attribute to map **password_digest** to **password_hash**.
|
|
144
147
|
|
|
145
|
-
|
|
146
|
-
|
|
148
|
+
#### Rename the **password_hash** column to **password_digest**
|
|
149
|
+
Add a migration to rename the column in your users table:
|
|
150
|
+
```bash
|
|
151
|
+
bin/rails generate migration rename_users_password_hash_to_password_digest
|
|
152
|
+
```
|
|
147
153
|
|
|
154
|
+
Update the change method:
|
|
155
|
+
```ruby
|
|
156
|
+
def change
|
|
157
|
+
rename_column :users, :password_hash, :password_digest
|
|
158
|
+
end
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### Alternatively, add **alias_attribute** to your user model
|
|
162
|
+
```ruby
|
|
163
|
+
alias_attribute :password_digest, :password_hash
|
|
164
|
+
```
|
|
148
165
|
|
|
149
166
|
## License
|
|
150
167
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT)..
|
|
@@ -48,9 +48,5 @@ module MinimalistAuthentication
|
|
|
48
48
|
def store_location
|
|
49
49
|
session["return_to"] = url_for(request.params.merge(format: :html, only_path: true))
|
|
50
50
|
end
|
|
51
|
-
|
|
52
|
-
def redirect_back_or_default(default)
|
|
53
|
-
redirect_to(session.delete("return_to") || default)
|
|
54
|
-
end
|
|
55
51
|
end
|
|
56
52
|
end
|
|
@@ -5,6 +5,9 @@ module MinimalistAuthentication
|
|
|
5
5
|
extend ActiveSupport::Concern
|
|
6
6
|
|
|
7
7
|
included do
|
|
8
|
+
# URL to redirect to after successful login
|
|
9
|
+
attr_accessor :return_to
|
|
10
|
+
|
|
8
11
|
skip_before_action :authorization_required, only: %i[new create]
|
|
9
12
|
before_action :redirect_logged_in_users, only: :new
|
|
10
13
|
end
|
|
@@ -23,7 +26,7 @@ module MinimalistAuthentication
|
|
|
23
26
|
end
|
|
24
27
|
|
|
25
28
|
def destroy
|
|
26
|
-
|
|
29
|
+
reset_session
|
|
27
30
|
redirect_to logout_redirect_to, notice: t(".notice"), status: :see_other
|
|
28
31
|
end
|
|
29
32
|
|
|
@@ -38,7 +41,8 @@ module MinimalistAuthentication
|
|
|
38
41
|
end
|
|
39
42
|
|
|
40
43
|
def log_in_user
|
|
41
|
-
|
|
44
|
+
self.return_to = session["return_to"]
|
|
45
|
+
reset_session
|
|
42
46
|
authenticated_user.logged_in
|
|
43
47
|
session[MinimalistAuthentication.configuration.session_key] = authenticated_user.id
|
|
44
48
|
end
|
|
@@ -62,7 +66,7 @@ module MinimalistAuthentication
|
|
|
62
66
|
end
|
|
63
67
|
|
|
64
68
|
def after_authentication_success
|
|
65
|
-
|
|
69
|
+
redirect_to return_to || login_redirect_to
|
|
66
70
|
end
|
|
67
71
|
|
|
68
72
|
def attempting_to_verify?
|
|
@@ -80,12 +84,6 @@ module MinimalistAuthentication
|
|
|
80
84
|
user_params.values_at(*MinimalistAuthentication::Authenticator::LOGIN_FIELDS).compact.first
|
|
81
85
|
end
|
|
82
86
|
|
|
83
|
-
def scrub_session!
|
|
84
|
-
(session.keys - %w[session_id return_to]).each do |key|
|
|
85
|
-
session.delete(key)
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
87
|
def login_redirect_to
|
|
90
88
|
send(MinimalistAuthentication.configuration.login_redirect_path)
|
|
91
89
|
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
module MinimalistAuthentication
|
|
4
4
|
module TestHelper
|
|
5
5
|
PASSWORD = "test-password"
|
|
6
|
+
PASSWORD_DIGEST = BCrypt::Password.create(PASSWORD, cost: BCrypt::Engine::MIN_COST)
|
|
6
7
|
|
|
7
8
|
def login_as(user_fixture_name, password = PASSWORD)
|
|
8
9
|
post session_path, params: { user: { email: users(user_fixture_name).email, password: } }
|
|
@@ -9,20 +9,16 @@ module MinimalistAuthentication
|
|
|
9
9
|
GUEST_USER_EMAIL = "guest"
|
|
10
10
|
|
|
11
11
|
included do
|
|
12
|
-
|
|
13
|
-
attribute :password, :string
|
|
12
|
+
has_secure_password validations: false
|
|
14
13
|
|
|
15
14
|
# Force validations for a blank password.
|
|
16
15
|
attribute :password_required, :boolean, default: false
|
|
17
16
|
|
|
18
|
-
# Hashes and stores the password on save.
|
|
19
|
-
before_save :hash_password
|
|
20
|
-
|
|
21
17
|
# Email validations
|
|
22
18
|
validates(
|
|
23
19
|
:email,
|
|
24
20
|
format: { allow_blank: true, with: URI::MailTo::EMAIL_REGEXP },
|
|
25
|
-
uniqueness: { allow_blank: true, case_sensitive: false
|
|
21
|
+
uniqueness: { allow_blank: true, case_sensitive: false },
|
|
26
22
|
if: :validate_email?
|
|
27
23
|
)
|
|
28
24
|
validates(:email, presence: true, if: :validate_email_presence?)
|
|
@@ -35,6 +31,7 @@ module MinimalistAuthentication
|
|
|
35
31
|
presence: true,
|
|
36
32
|
if: :validate_password?
|
|
37
33
|
)
|
|
34
|
+
validate :password_exclusivity, if: :password?
|
|
38
35
|
|
|
39
36
|
# Active scope
|
|
40
37
|
scope :active, ->(state = true) { where(active: state) }
|
|
@@ -53,13 +50,16 @@ module MinimalistAuthentication
|
|
|
53
50
|
!active?
|
|
54
51
|
end
|
|
55
52
|
|
|
56
|
-
# Returns true if password matches the hashed_password, otherwise returns false.
|
|
57
|
-
# authentication the user's password_hash is updated if required.
|
|
53
|
+
# Returns true if password matches the hashed_password, otherwise returns false.
|
|
58
54
|
def authenticated?(password)
|
|
59
|
-
|
|
55
|
+
authenticate(password)
|
|
56
|
+
rescue ::BCrypt::Errors::InvalidHash
|
|
57
|
+
false
|
|
58
|
+
end
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
# Check if user is a guest based on their email attribute
|
|
61
|
+
def guest?
|
|
62
|
+
email == GUEST_USER_EMAIL
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
def logged_in
|
|
@@ -67,59 +67,45 @@ module MinimalistAuthentication
|
|
|
67
67
|
update_column(:last_logged_in_at, Time.current)
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
-
# Check if user is a guest based on their email attribute
|
|
71
|
-
def guest?
|
|
72
|
-
email == GUEST_USER_EMAIL
|
|
73
|
-
end
|
|
74
|
-
|
|
75
70
|
# Minimum password length
|
|
76
71
|
def password_minimum = 12
|
|
77
72
|
|
|
78
73
|
# Maximum password length
|
|
79
74
|
def password_maximum = 40
|
|
80
75
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
def update_hash!(password)
|
|
85
|
-
self.password = password
|
|
86
|
-
return unless valid?
|
|
87
|
-
|
|
88
|
-
hash_password
|
|
89
|
-
save
|
|
76
|
+
# Checks for password presence
|
|
77
|
+
def password?
|
|
78
|
+
password.present?
|
|
90
79
|
end
|
|
91
80
|
|
|
92
|
-
|
|
93
|
-
def hash_password
|
|
94
|
-
return if password.blank?
|
|
95
|
-
|
|
96
|
-
self.password_hash = Password.create(password)
|
|
97
|
-
end
|
|
81
|
+
private
|
|
98
82
|
|
|
99
|
-
#
|
|
100
|
-
def
|
|
101
|
-
|
|
83
|
+
# Ensure password does not match username or email.
|
|
84
|
+
def password_exclusivity
|
|
85
|
+
%w[username email].each do |field|
|
|
86
|
+
errors.add(:password, "can not match #{field}") if password.casecmp?(try(field))
|
|
87
|
+
end
|
|
102
88
|
end
|
|
103
89
|
|
|
104
90
|
# Require password for active users that either do no have a password hash
|
|
105
91
|
# stored OR are attempting to set a new password. Set **password_required**
|
|
106
92
|
# to true to force validations even when the password field is blank.
|
|
107
93
|
def validate_password?
|
|
108
|
-
active? && (
|
|
94
|
+
active? && (password_digest.blank? || password? || password_required?)
|
|
109
95
|
end
|
|
110
96
|
|
|
111
|
-
# Validate email for
|
|
97
|
+
# Validate email for all users.
|
|
112
98
|
# Applications can turn off email validation by setting the validate_email
|
|
113
99
|
# configuration attribute to false.
|
|
114
100
|
def validate_email?
|
|
115
|
-
MinimalistAuthentication.configuration.validate_email
|
|
101
|
+
MinimalistAuthentication.configuration.validate_email
|
|
116
102
|
end
|
|
117
103
|
|
|
118
104
|
# Validate email presence for active users.
|
|
119
105
|
# Applications can turn off email presence validation by setting
|
|
120
106
|
# validate_email_presence configuration attribute to false.
|
|
121
107
|
def validate_email_presence?
|
|
122
|
-
MinimalistAuthentication.configuration.validate_email_presence && validate_email?
|
|
108
|
+
MinimalistAuthentication.configuration.validate_email_presence && validate_email? && active?
|
|
123
109
|
end
|
|
124
110
|
end
|
|
125
111
|
end
|
|
@@ -6,9 +6,6 @@ require "minimalist_authentication/configuration"
|
|
|
6
6
|
require "minimalist_authentication/user"
|
|
7
7
|
require "minimalist_authentication/verifiable_token"
|
|
8
8
|
require "minimalist_authentication/email_verification"
|
|
9
|
-
require "minimalist_authentication/password"
|
|
10
|
-
require "minimalist_authentication/null_password"
|
|
11
9
|
require "minimalist_authentication/controller"
|
|
12
10
|
require "minimalist_authentication/sessions"
|
|
13
11
|
require "minimalist_authentication/test_helper"
|
|
14
|
-
require "minimalist_authentication/conversions/merge_password_hash"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: minimalist_authentication
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 3.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Aaron Baldwin
|
|
@@ -84,8 +84,6 @@ files:
|
|
|
84
84
|
- lib/minimalist_authentication/conversions/merge_password_hash.rb
|
|
85
85
|
- lib/minimalist_authentication/email_verification.rb
|
|
86
86
|
- lib/minimalist_authentication/engine.rb
|
|
87
|
-
- lib/minimalist_authentication/null_password.rb
|
|
88
|
-
- lib/minimalist_authentication/password.rb
|
|
89
87
|
- lib/minimalist_authentication/sessions.rb
|
|
90
88
|
- lib/minimalist_authentication/test_helper.rb
|
|
91
89
|
- lib/minimalist_authentication/user.rb
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module MinimalistAuthentication
|
|
4
|
-
class Password
|
|
5
|
-
class << self
|
|
6
|
-
# Create a bcrypt password hash with a calibrated cost factor.
|
|
7
|
-
def create(secret)
|
|
8
|
-
new ::BCrypt::Engine.hash_secret(secret, BCrypt::Engine.generate_salt(cost))
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
# Cache the calibrated bcrypt cost factor.
|
|
12
|
-
def cost
|
|
13
|
-
@cost ||= calibrate_cost
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
private
|
|
17
|
-
|
|
18
|
-
# Calibrates cost so that new user passwords can automatically take
|
|
19
|
-
# advantage of faster server hardware in the future.
|
|
20
|
-
# Sets cost to BCrypt::Engine::MIN_COST in the test environment
|
|
21
|
-
def calibrate_cost
|
|
22
|
-
::Rails.env.test? ? ::BCrypt::Engine::MIN_COST : ::BCrypt::Engine.calibrate(750)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
attr_accessor :bcrypt_password
|
|
27
|
-
|
|
28
|
-
# Returns a password object wrapping a valid BCrypt password or a NullPassword
|
|
29
|
-
def initialize(password_hash)
|
|
30
|
-
self.bcrypt_password = ::BCrypt::Password.new(password_hash)
|
|
31
|
-
rescue ::BCrypt::Errors::InvalidHash
|
|
32
|
-
self.bcrypt_password = NullPassword.new
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# Delegate methods to bcrypt_password
|
|
36
|
-
delegate :==, :to_s, :cost, to: :bcrypt_password
|
|
37
|
-
|
|
38
|
-
# Temporary access to checksum and salt for backwards compatibility
|
|
39
|
-
delegate :checksum, :salt, to: :bcrypt_password
|
|
40
|
-
|
|
41
|
-
# Checks if the password_hash cost factor is less than the current cost.
|
|
42
|
-
def stale?
|
|
43
|
-
cost < self.class.cost
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|