has_secure_token 0.0.2 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1148bcff41e4dab40603ae600aae8129d4fd4dab
4
- data.tar.gz: 1686f165bdc43dba2030e09a5d72c847763b718c
3
+ metadata.gz: b067e69148a2f5b30e754c459a50104225acbbdb
4
+ data.tar.gz: c9d010b6a22812ac5e6e3685890f1ad3f79a884d
5
5
  SHA512:
6
- metadata.gz: b0f969596f567eefe82d69bac7a2d5258100018f904cef879c3c4fa65690d7eddc380e7cb1c6532e380da2c2f8d6972703eb12e85693798a8c9cb5bb34a80601
7
- data.tar.gz: 7a414116ae3415f7121fe401256e23a0997d6ad7ad38b9d0b1ec6ac7e7b8af1c02ce4b2222cee86eae9f4b234cdbb74cea7da50b252aa761e1ce066226a5669f
6
+ metadata.gz: 88bf39886c95f4d9b87329dc4403d1fecfbcdc281539712106a5108efe2c9f059e271148a45b4ecf067b9d251eeedf8520bd53a698393801da233848867c1b6c
7
+ data.tar.gz: ce83ec47005732c144d9e25c579530cae9c146f1205c738784abd8fa20bd68c99ccf78e3680a3370f7ceff744afbfa54f1026900658347267a9122946c8d0e85
@@ -1,10 +1,13 @@
1
+ language: ruby
1
2
  rvm:
2
3
  - 1.9.3
3
4
  - 2.0.0
4
5
  - 2.1
5
- matrix:
6
- include:
7
- - rvm: jruby
8
- env: JRUBY_OPTS="--1.9 --server -Xcext.enabled=true"
6
+ - 2.2
7
+ gemfile:
8
+ - gemfiles/rails3.gemfile
9
+ - gemfiles/rails4_0.gemfile
10
+ - gemfiles/rails4_1.gemfile
11
+ - gemfiles/rails4_2.gemfile
9
12
  notifications:
10
13
  email: false
data/README.md CHANGED
@@ -5,6 +5,10 @@
5
5
 
6
6
  # HasSecureToken
7
7
 
8
+ HasSecureToken provides you an easily way to geneatre uniques random tokens for any model in ruby on rails. **SecureRandom::base58** is used to generate the 24-character unique token, so collisions are highly unlikely.
9
+
10
+ **Note** that it's still possible to generate a race condition in the database in the same way that **validates_uniqueness_of** can. You're encouraged to add a unique index in the database to deal
11
+
8
12
  ## Installation
9
13
 
10
14
  Add this line to your application's Gemfile:
@@ -19,21 +23,49 @@ Or install it yourself as:
19
23
 
20
24
  $ gem install has_secure_token
21
25
 
22
- ##Setting your Model
26
+
27
+ ## Setting your Model
28
+
29
+ The first step is to run the migration generator in order to add the token key field.
30
+
31
+ ```ruby
32
+ rails g migration AddTokenToUsers token:string
33
+ =>
34
+ invoke active_record
35
+ create db/migrate/20150424010931_add_token_to_users.rb
36
+ ```
37
+
38
+ Then need to run `rake db:migrate` to update the users table in the database. The next step is to update the model code
39
+
40
+ ```ruby
41
+ # Schema: User(token:string, auth_token:string)
42
+ class User < ActiveRecord::Base
43
+ has_secure_token
44
+ end
45
+
46
+ user = User.new
47
+ user.save
48
+ user.token # => "4kUgL2pdQMSCQtjE"
49
+ user.regenerate_token # => true
50
+ ```
51
+
52
+ To use a custom column to store the token key field you can use the column_name option.
23
53
 
24
54
  ```ruby
55
+ # Schema: User(token:string, auth_token:string)
25
56
  class User < ActiveRecord::Base
26
- has_secure_token :token1, :token2
57
+ has_secure_token :auth_token
27
58
  end
28
59
 
29
- user = User.create
30
- user.token1 => "44539a6a59835a4ee9d7b112b48cd76e"
31
- user.token2 => "226dd46af6be78953bde1641622497a8"
60
+ user = User.new
61
+ user.save
62
+ user.auth_token # => "4kUgL2pdQMSCQtjE"
63
+ user.regenerate_auth_token # => true
32
64
  ```
33
65
 
34
66
  ## Contributing
35
67
 
36
- 1. Fork it ( https://github.com/robertomiranda/has_secure_password/fork )
68
+ 1. Fork it ( https://github.com/robertomiranda/has_secure_token/fork )
37
69
  2. Create your feature branch (`git checkout -b my-new-feature`)
38
70
  3. Commit your changes (`git commit -am 'Add some feature'`)
39
71
  4. Push to the branch (`git push origin my-new-feature`)
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+ gemspec :path => '../'
3
+
4
+ group :development, :test do
5
+ gem 'activerecord', '~> 3.2.0'
6
+ end
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+ gemspec :path => '../'
3
+
4
+ group :development, :test do
5
+ gem 'activerecord', '~> 4.0.0'
6
+ gem 'minitest', '~> 4.2'
7
+ end
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+ gemspec :path => '../'
3
+
4
+ group :development, :test do
5
+ gem 'activerecord', '~> 4.1.0'
6
+ end
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+ gemspec :path => '../'
3
+
4
+ group :development, :test do
5
+ gem 'activerecord', '~> 4.2.0'
6
+ end
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.version = HasSecureToken::VERSION
9
9
  spec.authors = ["Roberto Miranda Altamar"]
10
10
  spec.email = ["rjmaltamar@gmail.com"]
11
- spec.summary = %q{Create uniques random tokens for any model in ruby on rails.}
12
- spec.description = %q{Add to your models an easily way to generate tokens}
11
+ spec.summary = %q{Create uniques random tokens for any model in ruby on rails. Backport of ActiveRecord::SecureToken 5 to AR 3.x and 4.x}
12
+ spec.description = %q{HasSecureToken provides you an easily way to geneatre uniques random tokens for any model in ruby on rails. **SecureRandom::base58** is used to generate the 24-character unique token, so collisions are highly unlikely.}
13
13
  spec.homepage = "https://github.com/robertomiranda/has_secure_token"
14
14
  spec.license = "MIT"
15
15
 
@@ -18,9 +18,10 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "activemodel"
21
+ spec.add_dependency "activerecord", ">= 3.0"
22
22
 
23
23
  spec.add_development_dependency "bundler", "~> 1.3"
24
24
  spec.add_development_dependency "rake"
25
- spec.add_development_dependency "minitest", "~> 5.4.2"
25
+ spec.add_development_dependency "minitest"
26
+ spec.add_development_dependency 'sqlite3'
26
27
  end
@@ -0,0 +1,23 @@
1
+ require 'securerandom'
2
+
3
+ module SecureRandom
4
+ BASE58_ALPHABET = ('0'..'9').to_a + ('A'..'Z').to_a + ('a'..'z').to_a - ['0', 'O', 'I', 'l']
5
+ # SecureRandom.base58 generates a random base58 string.
6
+ #
7
+ # The argument _n_ specifies the length, of the random string to be generated.
8
+ #
9
+ # If _n_ is not specified or is nil, 16 is assumed. It may be larger in the future.
10
+ #
11
+ # The result may contain alphanumeric characters except 0, O, I and l
12
+ #
13
+ # p SecureRandom.base58 #=> "4kUgL2pdQMSCQtjE"
14
+ # p SecureRandom.base58(24) #=> "77TMHrHJFvFDwodq8w7Ev2m7"
15
+ #
16
+ def self.base58(n = 16)
17
+ SecureRandom.random_bytes(n).unpack("C*").map do |byte|
18
+ idx = byte % 64
19
+ idx = SecureRandom.random_number(58) if idx >= 58
20
+ BASE58_ALPHABET[idx]
21
+ end.join
22
+ end
23
+ end
@@ -1,57 +1,41 @@
1
- require "active_model"
2
- require 'securerandom'
1
+ require 'active_record'
2
+ module ActiveRecord
3
+ module SecureToken
4
+ extend ActiveSupport::Concern
3
5
 
4
- module HasSecureToken
5
- extend ActiveSupport::Concern
6
- module ClassMethods
7
- # Example using Active Record (which automatically includes ActiveModel::SecurePassword):
8
- #
9
- # # Schema: User(auth_token:string, invitation_token:string)
10
- # class User < ActiveRecord::Base
11
- # has_secure_token :auth_token, :invitation_token
12
- # end
13
- #
14
- # user = User.new
15
- # user.save
16
- # user.auth_token # => "44539a6a59835a4ee9d7b112"
17
- # user.invitation_token # => "226dd46af6be78953bde1648"
18
- # user.regenerate_auth_token # => true
19
- # user.regenerate_invitation_token # => true
20
- def has_secure_token(*args)
21
- # Load securerandom only when has_secure_key is used.
22
- require 'securerandom'
23
- include InstanceMethodsOnActivation
24
- cattr_accessor :token_columns, :options
25
- options = args.extract_options!
26
-
27
- key_length = options.fetch(:key_length, 24)
28
- bytes = (key_length / 2.0).ceil
29
-
30
- args.each do |attribute|
31
- define_method("regenerate_#{attribute}!") do
32
- send(:generate_unique_secure_token, attribute, bytes, key_length)
33
- save
34
- end
6
+ module ClassMethods
7
+ # Example using has_secure_token
8
+ #
9
+ # # Schema: User(token:string, auth_token:string)
10
+ # class User < ActiveRecord::Base
11
+ # has_secure_token
12
+ # has_secure_token :auth_token
13
+ # end
14
+ #
15
+ # user = User.new
16
+ # user.save
17
+ # user.token # => "4kUgL2pdQMSCQtjE"
18
+ # user.auth_token # => "77TMHrHJFvFDwodq8w7Ev2m7"
19
+ # user.regenerate_token # => true
20
+ # user.regenerate_auth_token # => true
21
+ #
22
+ # SecureRandom::base58 is used to generate the 24-character unique token, so collisions are highly unlikely.
23
+ #
24
+ # Note that it's still possible to generate a race condition in the database in the same way that
25
+ # <tt>validates_uniqueness_of</tt> can. You're encouraged to add a unique index in the database to deal
26
+ # with this even more unlikely scenario.
27
+ def has_secure_token(attribute = :token)
28
+ # Load securerandom only when has_secure_token is used.
29
+ require 'active_support/core_ext/securerandom'
30
+ define_method("regenerate_#{attribute}") { update_attributes attribute => self.class.generate_unique_secure_token }
31
+ before_create { self.send("#{attribute}=", self.class.generate_unique_secure_token) unless self.send("#{attribute}?")}
35
32
  end
36
33
 
37
- before_create do
38
- args.each do |attribute|
39
- self.generate_unique_secure_token(attribute, bytes, key_length)
40
- end
34
+ def generate_unique_secure_token
35
+ SecureRandom.base58(24)
41
36
  end
42
37
  end
43
38
  end
44
-
45
- module InstanceMethodsOnActivation
46
- def generate_unique_secure_token(attribute, bytes, key_length)
47
- self.send("#{attribute}=", loop do
48
- random_token = SecureRandom.hex(bytes)[0..key_length]
49
- break random_token unless self.class.exists?(attribute => random_token)
50
- end)
51
- end
52
- end
53
39
  end
54
40
 
55
- ActiveSupport.on_load(:active_record) do
56
- include HasSecureToken
57
- end
41
+ ActiveRecord::Base.send(:include, ActiveRecord::SecureToken)
@@ -1,3 +1,3 @@
1
1
  module HasSecureToken
2
- VERSION = "0.0.2"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -1,37 +1,31 @@
1
1
  require "test_helper"
2
2
 
3
- class HasSecureTokenTest < MiniTest::Unit::TestCase
3
+ class SecureTokenTest < MiniTest::Unit::TestCase
4
4
  def setup
5
5
  @user = User.new
6
- @user.run_callbacks :create
7
- @visitor = Visitor.new
8
- @visitor.run_callbacks :create
9
6
  end
10
7
 
11
- def test_assing_token_values
12
- assert_not_nil @user.auth_token
13
- assert_not_nil @user.invitation_token
8
+ def test_token_values_are_generated_for_specified_attributes_and_persisted_on_save
9
+ @user.save
10
+ refute_nil @user.token
11
+ refute_nil @user.auth_token
14
12
  end
15
13
 
16
- def test_default_length_of_secure_token_is_set_to_24
17
- assert_equal 24, @user.auth_token.length
18
- assert_equal 24, @user.invitation_token.length
19
- end
14
+ def test_regenerating_the_secure_token
15
+ @user.save
16
+ old_token = @user.token
17
+ old_auth_token = @user.auth_token
18
+ @user.regenerate_token
19
+ @user.regenerate_auth_token
20
20
 
21
- def test_create_record_with_customised_length_of_secure_token
22
- assert_equal 30, @visitor.auth_token.length
23
- assert_equal 30, @visitor.invitation_token.length
21
+ refute_equal @user.token, old_token
22
+ refute_equal @user.auth_token, old_auth_token
24
23
  end
25
24
 
26
- def test_regenerate_the_secure_key_for_the_attribute
27
- old_auth_token = @user.auth_token
28
- old_invitation_token = @user.invitation_token
29
- @user.regenerate_auth_token!
30
- @user.regenerate_invitation_token!
25
+ def test_token_value_not_overwritten_when_present
26
+ @user.token = "custom-secure-token"
27
+ @user.save
31
28
 
32
- assert @user.auth_token != old_auth_token
33
- assert @user.invitation_token != old_invitation_token
34
- assert_equal 24, @user.auth_token.length
35
- assert_equal 24, @user.invitation_token.length
29
+ assert_equal @user.token, "custom-secure-token"
36
30
  end
37
31
  end
@@ -1,18 +1,4 @@
1
- class User
2
- extend ActiveModel::Callbacks
3
- include ActiveModel::Validations
4
- include HasSecureToken
5
-
6
- define_model_callbacks :create
7
- attr_accessor :auth_token, :invitation_token
8
-
9
- has_secure_token :auth_token, :invitation_token
10
-
11
- def self.exists?(attrs)
12
- false
13
- end
14
-
15
- def save
16
- true
17
- end
1
+ class User < ActiveRecord::Base
2
+ has_secure_token
3
+ has_secure_token :auth_token
18
4
  end
@@ -0,0 +1,6 @@
1
+ ActiveRecord::Schema.define(:version => 1) do
2
+ create_table :users do |t|
3
+ t.string :token
4
+ t.string :auth_token
5
+ end
6
+ end
@@ -0,0 +1,19 @@
1
+ require "test_helper"
2
+
3
+ class SecureRandomTest < MiniTest::Unit::TestCase
4
+ def test_base58
5
+ s1 = SecureRandom.base58
6
+ s2 = SecureRandom.base58
7
+
8
+ refute_equal s1, s2
9
+ assert_equal 16, s1.length
10
+ end
11
+
12
+ def test_base58_with_length
13
+ s1 = SecureRandom.base58(24)
14
+ s2 = SecureRandom.base58(24)
15
+
16
+ refute_equal s1, s2
17
+ assert_equal 24, s1.length
18
+ end
19
+ end
@@ -15,3 +15,11 @@ Dir["models/*.rb"].each {|file| require file }
15
15
  msg = message(msg) { "<#{mu_pp(exp)}> expected to not be nil" }
16
16
  assert(!exp.nil?, msg)
17
17
  end
18
+
19
+ DB_FILE = 'tmp/test_db'
20
+ FileUtils.mkdir_p File.dirname(DB_FILE)
21
+ FileUtils.rm_f DB_FILE
22
+
23
+ ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => DB_FILE
24
+
25
+ load 'schema.rb'
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: has_secure_token
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roberto Miranda Altamar
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-27 00:00:00.000000000 Z
11
+ date: 2015-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: activemodel
14
+ name: activerecord
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '3.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '3.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -56,17 +56,33 @@ dependencies:
56
56
  name: minitest
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: 5.4.2
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: 5.4.2
69
- description: Add to your models an easily way to generate tokens
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sqlite3
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: HasSecureToken provides you an easily way to geneatre uniques random
84
+ tokens for any model in ruby on rails. **SecureRandom::base58** is used to generate
85
+ the 24-character unique token, so collisions are highly unlikely.
70
86
  email:
71
87
  - rjmaltamar@gmail.com
72
88
  executables: []
@@ -79,12 +95,18 @@ files:
79
95
  - LICENSE.txt
80
96
  - README.md
81
97
  - Rakefile
98
+ - gemfiles/rails3.gemfile
99
+ - gemfiles/rails4_0.gemfile
100
+ - gemfiles/rails4_1.gemfile
101
+ - gemfiles/rails4_2.gemfile
82
102
  - has_secure_token.gemspec
103
+ - lib/active_support/core_ext/securerandom.rb
83
104
  - lib/has_secure_token.rb
84
105
  - lib/has_secure_token/version.rb
85
106
  - test/has_secure_password_test.rb
86
107
  - test/models/user.rb
87
- - test/models/visitor.rb
108
+ - test/schema.rb
109
+ - test/securerandom_test.rb
88
110
  - test/test_helper.rb
89
111
  homepage: https://github.com/robertomiranda/has_secure_token
90
112
  licenses:
@@ -109,9 +131,11 @@ rubyforge_project:
109
131
  rubygems_version: 2.2.2
110
132
  signing_key:
111
133
  specification_version: 4
112
- summary: Create uniques random tokens for any model in ruby on rails.
134
+ summary: Create uniques random tokens for any model in ruby on rails. Backport of
135
+ ActiveRecord::SecureToken 5 to AR 3.x and 4.x
113
136
  test_files:
114
137
  - test/has_secure_password_test.rb
115
138
  - test/models/user.rb
116
- - test/models/visitor.rb
139
+ - test/schema.rb
140
+ - test/securerandom_test.rb
117
141
  - test/test_helper.rb
@@ -1,15 +0,0 @@
1
- class Visitor
2
- extend ActiveModel::Callbacks
3
- include ActiveModel::SecurePassword
4
- include HasSecureToken
5
-
6
- define_model_callbacks :create
7
-
8
- has_secure_token :auth_token, :invitation_token, key_length: 30
9
-
10
- attr_accessor :auth_token, :invitation_token
11
-
12
- def self.exists?(attrs)
13
- false
14
- end
15
- end