1
0
Fork 0
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:
Kasper Timm Hansen 2016-01-09 22:30:21 +01:00
commit 224eddfc0e
4 changed files with 40 additions and 2 deletions

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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