minimalist_authentication 2.7.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c4bb59b8f43fd47739bb2d9751c0c3922100c563a244c24b33760d421c87e25c
4
- data.tar.gz: 0cdfcf49e0fb66c595cc1be8f24f8dbab0b8c072158f5571caad2dc47f7d9799
3
+ metadata.gz: a82f3a3833f400b37555173885d052000dfbd5e4a67da90068384558f8d97705
4
+ data.tar.gz: 48b819ddbb26a5cb5deaa03c5cd3ef943394e93d6390286d3f30cbae7e5e8477
5
5
  SHA512:
6
- metadata.gz: 31b964fc19564faf080f6a93c6a36108baea9748f0305eaaf85b3e5cf37d68024f6a2f0fc71bb350b7dd41c5b8c853a40924f4f33fe69750c04124fcf14e86a1
7
- data.tar.gz: 96ad19ef5f1a5b4cee6d99782c5ee52b3033e57bb8db59288876d223098442fd3ab567c355f48c4c030e50095c9b684dbb85a2b0600c172754babf989aa21eb0
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 password_hash:string last_logged_in_at:datetime
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 password_hash:string last_logged_in_at:datetime
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::Password.create** to create a password for
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: user@example.com
87
- password_hash: <%= MinimalistAuthentication::Password.create("test-password") %>
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
- ## Build
146
- [![Build Status](https://travis-ci.org/wwidea/minimalist_authentication.svg?branch=master)](https://travis-ci.org/wwidea/minimalist_authentication)
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)..
@@ -1,5 +1,7 @@
1
1
  <h1>Edit Password</h1>
2
2
 
3
+ <%= @user.errors.full_messages if @user.errors.any? %>
4
+
3
5
  <%= form_for @user, as: :user, url: user_password_path(@user, token: @token), html: { method: :put } do |form| %>
4
6
  <div>
5
7
  <%= form.label :password %>
@@ -39,7 +39,7 @@ module MinimalistAuthentication
39
39
  # Defaults to true
40
40
  attr_accessor :request_email
41
41
 
42
- # Vefify users email address at login.
42
+ # Verify users email address at login.
43
43
  # Defaults to true.
44
44
  attr_accessor :verify_email
45
45
 
@@ -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
- scrub_session!
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
- scrub_session!
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
- redirect_back_or_default(login_redirect_to)
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
- # Stores the plain text password.
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, scope: :active },
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. Upon successful
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
- return false unless password_object == password
55
+ authenticate(password)
56
+ rescue ::BCrypt::Errors::InvalidHash
57
+ false
58
+ end
60
59
 
61
- update_hash!(password) if password_object.stale?
62
- true
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
- private
82
-
83
- # Set self.password to password, hash, and save if user is valid.
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
- # Hash password and store in hash_password unless password is blank.
93
- def hash_password
94
- return if password.blank?
95
-
96
- self.password_hash = Password.create(password)
97
- end
81
+ private
98
82
 
99
- # Returns a MinimalistAuthentication::Password object.
100
- def password_object
101
- Password.new(password_hash)
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? && (password_hash.blank? || password? || password_required?)
94
+ active? && (password_digest.blank? || password? || password_required?)
109
95
  end
110
96
 
111
- # Validate email for active users.
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 && active?
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MinimalistAuthentication
4
- VERSION = "2.7.0"
4
+ VERSION = "3.0.0"
5
5
  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: 2.7.0
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,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module MinimalistAuthentication
4
- class NullPassword
5
- # does not match any object
6
- def ==(_other)
7
- false
8
- end
9
- end
10
- end
@@ -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