mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #20835 from glittershark/if-and-unless-in-secure-token
Support :if and :unless in has_secure_token
This commit is contained in:
commit
224eddfc0e
4 changed files with 40 additions and 2 deletions
|
@ -1,3 +1,7 @@
|
|||
* Support `:if` and `:unless` options in `has_secure_token`
|
||||
|
||||
*Griffin Smith*
|
||||
|
||||
* Use `version` column as primary key for schema_migrations table because
|
||||
schema_migrations versions are guaranteed to be unique.
|
||||
|
||||
|
|
|
@ -20,14 +20,35 @@ module ActiveRecord
|
|||
#
|
||||
# <tt>SecureRandom::base58</tt> is used to generate the 24-character unique token, so collisions are highly unlikely.
|
||||
#
|
||||
# A secure token can also be only created given a condition, for example if a user should only have an
|
||||
# auto-generated invitation token if the user was invited:
|
||||
#
|
||||
# # Schema: User(token:string, invited:boolean)
|
||||
# class User < ActiveRecord::Base
|
||||
# has_secure_token if: :invited?
|
||||
# end
|
||||
#
|
||||
# user = User.new(invited: true)
|
||||
# user.save
|
||||
# user.token # => "pX27zsMN2ViQKta1bGfLmVJE"
|
||||
#
|
||||
# user = User.new(invited: false)
|
||||
# user.save
|
||||
# user.token # => nil
|
||||
#
|
||||
# The secure token creation supports all the options a `before_create` does - like +:if+ and +:unless+.
|
||||
#
|
||||
# Note that it's still possible to generate a race condition in the database in the same way that
|
||||
# {validates_uniqueness_of}[rdoc-ref:Validations::ClassMethods#validates_uniqueness_of] can.
|
||||
# You're encouraged to add a unique index in the database to deal with this even more unlikely scenario.
|
||||
def has_secure_token(attribute = :token)
|
||||
def has_secure_token(attribute = :token, **before_create_options)
|
||||
# Load securerandom only when has_secure_token is used.
|
||||
require 'active_support/core_ext/securerandom'
|
||||
|
||||
define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token }
|
||||
before_create { self.send("#{attribute}=", self.class.generate_unique_secure_token) unless self.send("#{attribute}?")}
|
||||
before_create(before_create_options) do
|
||||
self.send("#{attribute}=", self.class.generate_unique_secure_token) unless self.send("#{attribute}?")
|
||||
end
|
||||
end
|
||||
|
||||
def generate_unique_secure_token
|
||||
|
|
|
@ -29,4 +29,14 @@ class SecureTokenTest < ActiveRecord::TestCase
|
|||
|
||||
assert_equal @user.token, "custom-secure-token"
|
||||
end
|
||||
|
||||
def test_token_with_if_condition_checks_condition_on_save
|
||||
@user.token_condition = false
|
||||
@user.save
|
||||
assert_nil @user.conditional_token
|
||||
|
||||
@user.token_condition = true
|
||||
@user.save
|
||||
assert_not_nil @user.conditional_token
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
class User < ActiveRecord::Base
|
||||
has_secure_token
|
||||
has_secure_token :auth_token
|
||||
has_secure_token :conditional_token, if: :token_condition
|
||||
|
||||
attr_accessor :token_condition
|
||||
end
|
||||
|
||||
class UserWithNotification < User
|
||||
|
|
Loading…
Reference in a new issue