has_secure_token 0.0.2 → 1.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
  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