minimalist_authentication 2.7.0 → 3.1.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: eb8cc19088eea71ab56f803fe72724911988a9dea1eaf2df45ab6eab1127fea9
4
+ data.tar.gz: 648dad4be8864624cf3bc9158c9cc207fc19da57256c363415c2c4b3cbe6b3ef
5
5
  SHA512:
6
- metadata.gz: 31b964fc19564faf080f6a93c6a36108baea9748f0305eaaf85b3e5cf37d68024f6a2f0fc71bb350b7dd41c5b8c853a40924f4f33fe69750c04124fcf14e86a1
7
- data.tar.gz: 96ad19ef5f1a5b4cee6d99782c5ee52b3033e57bb8db59288876d223098442fd3ab567c355f48c4c030e50095c9b684dbb85a2b0600c172754babf989aa21eb0
6
+ metadata.gz: fdce2aed67b60fb4adc4d6227523001c52099ea9df6458aa420ce89616467986e05e12362afba71811502d25ab406e2356d2857bc62f640ce7942dc00dc408f4
7
+ data.tar.gz: a9c0c9ac343602975b60415c0b53c13e50f748e08a63bf37a1ecb6ca64c20eea1e4e6402096c1900b45255cd13ee736a0ef664cce7a25639fccf73486ede9e12
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
 
@@ -73,18 +73,16 @@ MinimalistAuthentication.configure do |configuration|
73
73
  configuration.verify_email = true # default is true
74
74
  configuration.login_redirect_path = :custom_path # default is :root_path
75
75
  configuration.logout_redirect_path = :custom_path # default is :new_session_path
76
- configuration.email_prefix = '[Custom Prefix]' # default is application name
77
76
  end
78
77
  ```
79
78
 
80
79
 
81
80
  ## Fixtures
82
- Use **MinimalistAuthentication::Password.create** to create a password for
83
- fixture users.
81
+ Use **MinimalistAuthentication::TestHelper::PASSWORD_DIGEST** to create a password_digest for fixture users.
84
82
  ```yaml
85
83
  example_user:
86
- email: user@example.com
87
- password_hash: <%= MinimalistAuthentication::Password.create("test-password") %>
84
+ email: user@example.com
85
+ password_digest: <%= MinimalistAuthentication::TestHelper::PASSWORD_DIGEST %>
88
86
  ```
89
87
 
90
88
 
@@ -124,6 +122,8 @@ bin/rails generate migration AddEmailVerifiedAtToUsers email_verified_at:datetim
124
122
 
125
123
 
126
124
  ## Conversions
125
+
126
+ ### Upgrading to Version 2.0
127
127
  Pre 2.0 versions of MinimalistAuthentication supported multiple hash algorithms
128
128
  and stored the hashed password and salt as separate fields in the database
129
129
  (crypted_password and salt). The current version of MinimalistAuthentication
@@ -141,10 +141,26 @@ MinimalistAuthentication::Conversions::MergePasswordHash.run!
141
141
  When the conversion is complete the **crypted_password**, **salt**, and
142
142
  **using_digest_version** fields can safely be removed.
143
143
 
144
+ ### Upgrading to Version 3.0
145
+ 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
146
 
145
- ## Build
146
- [![Build Status](https://travis-ci.org/wwidea/minimalist_authentication.svg?branch=master)](https://travis-ci.org/wwidea/minimalist_authentication)
147
+ #### Rename the **password_hash** column to **password_digest**
148
+ Add a migration to rename the column in your users table:
149
+ ```bash
150
+ bin/rails generate migration rename_users_password_hash_to_password_digest
151
+ ```
147
152
 
153
+ Update the change method:
154
+ ```ruby
155
+ def change
156
+ rename_column :users, :password_hash, :password_digest
157
+ end
158
+ ```
159
+
160
+ #### Alternatively, add **alias_attribute** to your user model
161
+ ```ruby
162
+ alias_attribute :password_digest, :password_hash
163
+ ```
148
164
 
149
165
  ## License
150
166
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT)..
@@ -11,7 +11,7 @@ class EmailVerificationsController < ApplicationController
11
11
 
12
12
  def create
13
13
  current_user.regenerate_verification_token
14
- MinimalistAuthenticationMailer.verify_email(current_user).deliver_now
14
+ MinimalistAuthenticationMailer.with(user: current_user).verify_email.deliver_now
15
15
 
16
16
  redirect_to dashboard_path, notice: t(".notice", email: current_user.email)
17
17
  end
@@ -14,7 +14,7 @@ class PasswordResetsController < ApplicationController
14
14
  def create
15
15
  if user
16
16
  user.regenerate_verification_token
17
- MinimalistAuthenticationMailer.update_password(user).deliver_now
17
+ MinimalistAuthenticationMailer.with(user:).update_password.deliver_now
18
18
  end
19
19
  # always display notice even if the user was not found to prevent leaking user emails
20
20
  redirect_to new_session_path, notice: "Password reset instructions were mailed to #{email}"
@@ -1,24 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class MinimalistAuthenticationMailer < ApplicationMailer
4
- def verify_email(user)
5
- @verify_email_link = email_verification_url(token: user.verification_token)
6
- send_to(user, "Email Address Verification")
4
+ before_action { @user = params[:user] }
5
+ after_action :mail_user
6
+
7
+ def verify_email
8
+ @verify_email_link = email_verification_url(token: @user.verification_token)
7
9
  end
8
10
 
9
- def update_password(user)
10
- @edit_password_link = edit_user_password_url(user, token: user.verification_token)
11
- send_to(user, "Update Password")
11
+ def update_password
12
+ @edit_password_link = edit_user_password_url(@user, token: @user.verification_token)
12
13
  end
13
14
 
14
15
  private
15
16
 
16
- def send_to(user, subject)
17
- @user = user
18
- mail to: @user.email, subject: prefixed_subject(subject)
19
- end
20
-
21
- def prefixed_subject(subject)
22
- "#{MinimalistAuthentication.configuration.email_prefix} #{subject}"
17
+ def mail_user
18
+ mail(to: @user.email)
23
19
  end
24
20
  end
@@ -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 %>
@@ -19,6 +19,8 @@ en:
19
19
  minimalist_authentication_mailer:
20
20
  update_password:
21
21
  opening: Please click the link below to update your password.
22
+ subject: Update Password
22
23
  verify_email:
23
- opening: Please click the link below to complete your email verification.
24
24
  closing: If you did not request email verification you can safely ignore this message.
25
+ opening: Please click the link below to complete your email verification.
26
+ subject: "Email Address Verification"
@@ -13,37 +13,44 @@ module MinimalistAuthentication
13
13
  # Params examples:
14
14
  # { email: 'user@example.com', password: 'abc123' }
15
15
  # { username: 'user', password: 'abc123' }
16
- # Returns user object upon successful authentication.
17
- def self.authenticated_user(params)
16
+ def self.authenticate(params)
18
17
  hash = params.to_h.with_indifferent_access
18
+ field, value = hash.find { |key, _| LOGIN_FIELDS.include?(key) }
19
+ new(field:, value:, password: hash["password"]).authenticated_user
20
+ end
19
21
 
20
- # Extract login field from hash
21
- field = (hash.keys & LOGIN_FIELDS).first
22
-
23
- # Attempt to authenticate user
24
- new(field:, value: hash[field], password: hash["password"]).authenticated_user
22
+ def self.authenticated_user(params)
23
+ MinimalistAuthentication.deprecator.warn(<<-MSG.squish)
24
+ Calling MinimalistAuthentication::Authenticator.authenticated_user is deprecated.
25
+ Use MinimalistAuthentication::Authenticator.authenticate instead.
26
+ MSG
27
+ authenticate(params)
25
28
  end
26
29
 
30
+ # Initializes a new Authenticator instance with the provided field, value, and password.
27
31
  def initialize(field:, value:, password:)
28
32
  @field = field
29
33
  @value = value
30
34
  @password = password
31
35
  end
32
36
 
33
- # Returns user upon successful authentication, otherwise returns nil.
37
+ # Returns an authenticated and enabled user or nil.
34
38
  def authenticated_user
35
- user if valid? && user&.authenticated?(password)
39
+ authenticated&.enabled if valid?
40
+ end
41
+
42
+ private
43
+
44
+ # Attempts to authenticate a user based on the provided field, value, and password.
45
+ # Returns user upon successful authentication, otherwise returns nil.
46
+ def authenticated
47
+ MinimalistAuthentication.configuration.user_model.authenticate_by(field => value, password:)
36
48
  end
37
49
 
38
50
  # Returns true if all the authentication attributes are present.
51
+ # Otherwise returns false.
39
52
  def valid?
40
53
  [field, value, password].all?(&:present?)
41
54
  end
42
-
43
- private
44
-
45
- def user
46
- @user ||= MinimalistAuthentication.configuration.user_model.active.find_by(field => value)
47
- end
48
55
  end
49
56
  end
@@ -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
 
@@ -51,10 +51,6 @@ module MinimalistAuthentication
51
51
  # Defaults to :new_session_path
52
52
  attr_accessor :logout_redirect_path
53
53
 
54
- # Email subject prefix for MinimalistAuthenticationMailer messages
55
- # Defaults to application name
56
- attr_accessor :email_prefix
57
-
58
54
  def initialize
59
55
  self.user_model_name = "::User"
60
56
  self.session_key = :user_id
@@ -64,7 +60,10 @@ module MinimalistAuthentication
64
60
  self.verify_email = true
65
61
  self.login_redirect_path = :root_path
66
62
  self.logout_redirect_path = :new_session_path
67
- self.email_prefix = default_email_prefix
63
+ end
64
+
65
+ def email_prefix=(_)
66
+ MinimalistAuthentication.deprecator.warn("The #email_prefix configuration setting is no longer supported.")
68
67
  end
69
68
 
70
69
  # Returns the user_model class
@@ -73,11 +72,5 @@ module MinimalistAuthentication
73
72
  def user_model
74
73
  user_model_name.constantize
75
74
  end
76
-
77
- private
78
-
79
- def default_email_prefix
80
- "[#{Rails.application.engine_name.delete_suffix('_application').titleize}]"
81
- end
82
75
  end
83
76
  end
@@ -19,9 +19,7 @@ module MinimalistAuthentication
19
19
  end
20
20
 
21
21
  def find_session_user
22
- return unless session_user_id
23
-
24
- MinimalistAuthentication.configuration.user_model.active.find_by(id: session_user_id)
22
+ MinimalistAuthentication.configuration.user_model.find_enabled(session_user_id)
25
23
  end
26
24
 
27
25
  def session_user_id
@@ -48,9 +46,5 @@ module MinimalistAuthentication
48
46
  def store_location
49
47
  session["return_to"] = url_for(request.params.merge(format: :html, only_path: true))
50
48
  end
51
-
52
- def redirect_back_or_default(default)
53
- redirect_to(session.delete("return_to") || default)
54
- end
55
49
  end
56
50
  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
 
@@ -34,11 +37,12 @@ module MinimalistAuthentication
34
37
  end
35
38
 
36
39
  def authenticated_user
37
- @authenticated_user ||= MinimalistAuthentication::Authenticator.authenticated_user(user_params)
40
+ @authenticated_user ||= MinimalistAuthentication::Authenticator.authenticate(user_params)
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,62 +9,79 @@ 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
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?)
29
25
 
30
26
  # Password validations
31
- validates(
32
- :password,
33
- confirmation: true,
34
- length: { minimum: :password_minimum, maximum: :password_maximum },
35
- presence: true,
36
- if: :validate_password?
37
- )
27
+ # Adds validations for minimum password length and exclusivity.
28
+ # has_secure_password adds validations for presence, maximum length, confirmation,
29
+ # and password_challenge.
30
+ validates :password, length: { minimum: :password_minimum }, if: :validate_password?
31
+ validate :password_exclusivity, if: :password?
38
32
 
39
33
  # Active scope
40
- scope :active, ->(state = true) { where(active: state) }
41
- scope :inactive, -> { active(false) }
34
+ scope :active, ->(state = true) { where(active: state) }
42
35
  end
43
36
 
44
37
  module ClassMethods
38
+ # Finds a user by their id and returns the user if they are enabled.
39
+ # Returns nil if the user is not found or not enabled.
40
+ def find_enabled(id)
41
+ find_by(id:)&.enabled if id.present?
42
+ end
43
+
44
+ def inactive
45
+ MinimalistAuthentication.deprecator.warn(<<-MSG.squish)
46
+ Calling #inactive is deprecated. Use #active(false) instead.
47
+ MSG
48
+ active(false)
49
+ end
50
+
45
51
  # Returns a frozen user with the email set to GUEST_USER_EMAIL.
46
52
  def guest
47
53
  new(email: GUEST_USER_EMAIL).freeze
48
54
  end
49
55
  end
50
56
 
57
+ # Called after a user is authenticated to determine if the user object should be returned.
58
+ def enabled
59
+ self if enabled?
60
+ end
61
+
62
+ # Returns true if the user is enabled.
63
+ # Override this method in your user model to implement custom logic that determines if a user is eligible to log in.
64
+ def enabled?
65
+ active?
66
+ end
67
+
68
+ # Remove the has_secure_password password blank error if password is not required.
69
+ def errors
70
+ super.tap { |errors| errors.delete(:password, :blank) unless validate_password? }
71
+ end
72
+
51
73
  # Returns true if the user is not active.
52
74
  def inactive?
75
+ MinimalistAuthentication.deprecator.warn("Calling #inactive? is deprecated.")
53
76
  !active?
54
77
  end
55
78
 
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.
79
+ # Returns true if password matches the hashed_password, otherwise returns false.
58
80
  def authenticated?(password)
59
- return false unless password_object == password
60
-
61
- update_hash!(password) if password_object.stale?
62
- true
63
- end
64
-
65
- def logged_in
66
- # Use update_column to avoid updated_on trigger
67
- update_column(:last_logged_in_at, Time.current)
81
+ MinimalistAuthentication.deprecator.warn(<<-MSG.squish)
82
+ Calling #authenticated? is deprecated. Use #authenticate instead.
83
+ MSG
84
+ authenticate(password)
68
85
  end
69
86
 
70
87
  # Check if user is a guest based on their email attribute
@@ -72,54 +89,47 @@ module MinimalistAuthentication
72
89
  email == GUEST_USER_EMAIL
73
90
  end
74
91
 
92
+ # Sets #last_logged_in_at to the current time without updating the updated_at timestamp.
93
+ def logged_in
94
+ update_column(:last_logged_in_at, Time.current)
95
+ end
96
+
75
97
  # Minimum password length
76
98
  def password_minimum = 12
77
99
 
78
- # Maximum password length
79
- def password_maximum = 40
80
-
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
100
+ # Checks for password presence
101
+ def password?
102
+ password.present?
90
103
  end
91
104
 
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
105
+ private
98
106
 
99
- # Returns a MinimalistAuthentication::Password object.
100
- def password_object
101
- Password.new(password_hash)
107
+ # Ensure password does not match username or email.
108
+ def password_exclusivity
109
+ %w[username email].each do |field|
110
+ errors.add(:password, "can not match #{field}") if password.casecmp?(try(field))
111
+ end
102
112
  end
103
113
 
104
114
  # Require password for active users that either do no have a password hash
105
115
  # stored OR are attempting to set a new password. Set **password_required**
106
116
  # to true to force validations even when the password field is blank.
107
117
  def validate_password?
108
- active? && (password_hash.blank? || password? || password_required?)
118
+ active? && (password_digest.blank? || password? || password_required?)
109
119
  end
110
120
 
111
- # Validate email for active users.
121
+ # Validate email for all users.
112
122
  # Applications can turn off email validation by setting the validate_email
113
123
  # configuration attribute to false.
114
124
  def validate_email?
115
- MinimalistAuthentication.configuration.validate_email && active?
125
+ MinimalistAuthentication.configuration.validate_email
116
126
  end
117
127
 
118
128
  # Validate email presence for active users.
119
129
  # Applications can turn off email presence validation by setting
120
130
  # validate_email_presence configuration attribute to false.
121
131
  def validate_email_presence?
122
- MinimalistAuthentication.configuration.validate_email_presence && validate_email?
132
+ MinimalistAuthentication.configuration.validate_email_presence && validate_email? && active?
123
133
  end
124
134
  end
125
135
  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.1.0"
5
5
  end
@@ -6,9 +6,12 @@ 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"
12
+
13
+ module MinimalistAuthentication
14
+ def self.deprecator
15
+ @deprecator ||= ActiveSupport::Deprecation.new("4.0", name)
16
+ end
17
+ end
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.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Baldwin
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-11-03 00:00:00.000000000 Z
12
+ date: 2024-11-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bcrypt
@@ -37,14 +37,14 @@ dependencies:
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 6.0.0
40
+ version: 7.1.0
41
41
  type: :runtime
42
42
  prerelease: false
43
43
  version_requirements: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 6.0.0
47
+ version: 7.1.0
48
48
  description: A Rails authentication plugin that takes a minimalist approach. It is
49
49
  designed to be simple to understand, use, and modify for your application.
50
50
  email:
@@ -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
@@ -96,7 +94,6 @@ licenses:
96
94
  - MIT
97
95
  metadata:
98
96
  homepage_uri: https://github.com/wwidea/minimalist_authentication
99
- source_code_uri: https://github.com/wwidea/minimalist_authentication
100
97
  rubygems_mfa_required: 'true'
101
98
  post_install_message:
102
99
  rdoc_options: []
@@ -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