has-secure-token-1.0.0/0000755000175000017500000000000013467553047013663 5ustar manasmanashas-secure-token-1.0.0/LICENSE.txt0000644000175000017500000000205713467553047015512 0ustar manasmanasCopyright (c) 2014 robertomiranda MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. has-secure-token-1.0.0/README.md0000644000175000017500000000450513467553047015146 0ustar manasmanas[![Build Status](https://travis-ci.org/robertomiranda/has_secure_token.png)](https://travis-ci.org/robertomiranda/has_secure_token) [![Gem Version](https://badge.fury.io/rb/has_secure_token.svg)](http://badge.fury.io/rb/has_secure_token) [![Dependency Status](https://gemnasium.com/robertomiranda/has_secure_token.svg)](https://gemnasium.com/robertomiranda/has_secure_token) [![Code Climate](https://codeclimate.com/github/robertomiranda/has_secure_token/badges/gpa.svg)](https://codeclimate.com/github/robertomiranda/has_secure_token) # HasSecureToken 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. **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 ## Installation Add this line to your application's Gemfile: gem 'has_secure_token' And then execute: $ bundle Or install it yourself as: $ gem install has_secure_token ## Setting your Model The first step is to run the migration generator in order to add the token key field. ```ruby rails g migration AddTokenToUsers token:string => invoke active_record create db/migrate/20150424010931_add_token_to_users.rb ``` Then need to run `rake db:migrate` to update the users table in the database. The next step is to update the model code ```ruby # Schema: User(token:string, auth_token:string) class User < ActiveRecord::Base has_secure_token end user = User.new user.save user.token # => "4kUgL2pdQMSCQtjE" user.regenerate_token # => true ``` To use a custom column to store the token key field you can use the column_name option. ```ruby # Schema: User(token:string, auth_token:string) class User < ActiveRecord::Base has_secure_token :auth_token end user = User.new user.save user.auth_token # => "4kUgL2pdQMSCQtjE" user.regenerate_auth_token # => true ``` ## Contributing 1. Fork it ( https://github.com/robertomiranda/has_secure_token/fork ) 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create a new Pull Request has-secure-token-1.0.0/Rakefile0000644000175000017500000000103113467553047015323 0ustar manasmanasrequire "bundler/gem_tasks" require 'rake/testtask' Bundler::GemHelper.install_tasks task :console do puts "Loading development console..." system("irb -r active_model_otp") end task :help do puts "Available rake tasks: " puts "rake console - Run a IRB console with all enviroment loaded" puts "rake test - Run tests" end task :test do Dir.chdir('test') end Rake::TestTask.new(:test) do |t| t.libs << '../lib' t.libs << '../test' t.test_files = FileList['*_test.rb'] t.verbose = false end task :default => :test has-secure-token-1.0.0/test/0000755000175000017500000000000013467553047014642 5ustar manasmanashas-secure-token-1.0.0/test/models/0000755000175000017500000000000013467553047016125 5ustar manasmanashas-secure-token-1.0.0/test/models/user.rb0000644000175000017500000000012613467553047017427 0ustar manasmanasclass User < ActiveRecord::Base has_secure_token has_secure_token :auth_token end has-secure-token-1.0.0/test/securerandom_test.rb0000644000175000017500000000056613467553047020724 0ustar manasmanasrequire "test_helper" class SecureRandomTest < MiniTest::Unit::TestCase def test_base58 s1 = SecureRandom.base58 s2 = SecureRandom.base58 refute_equal s1, s2 assert_equal 16, s1.length end def test_base58_with_length s1 = SecureRandom.base58(24) s2 = SecureRandom.base58(24) refute_equal s1, s2 assert_equal 24, s1.length end end has-secure-token-1.0.0/test/test_helper.rb0000644000175000017500000000126713467553047017513 0ustar manasmanastestdir = File.dirname(__FILE__) $LOAD_PATH.unshift testdir unless $LOAD_PATH.include?(testdir) libdir = File.dirname(File.dirname(__FILE__)) + '/lib' $LOAD_PATH.unshift libdir unless $LOAD_PATH.include?(libdir) require "rubygems" require "has_secure_token" require "minitest/autorun" require "minitest/unit" Dir["models/*.rb"].each {|file| require file } def assert_not_nil(exp, msg=nil) msg = message(msg) { "<#{mu_pp(exp)}> expected to not be nil" } assert(!exp.nil?, msg) end DB_FILE = 'tmp/test_db' FileUtils.mkdir_p File.dirname(DB_FILE) FileUtils.rm_f DB_FILE ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => DB_FILE load 'schema.rb' has-secure-token-1.0.0/test/schema.rb0000644000175000017500000000020213467553047016421 0ustar manasmanasActiveRecord::Schema.define(:version => 1) do create_table :users do |t| t.string :token t.string :auth_token end end has-secure-token-1.0.0/test/has_secure_password_test.rb0000644000175000017500000000132713467553047022274 0ustar manasmanasrequire "test_helper" class SecureTokenTest < MiniTest::Unit::TestCase def setup @user = User.new end def test_token_values_are_generated_for_specified_attributes_and_persisted_on_save @user.save refute_nil @user.token refute_nil @user.auth_token end def test_regenerating_the_secure_token @user.save old_token = @user.token old_auth_token = @user.auth_token @user.regenerate_token @user.regenerate_auth_token refute_equal @user.token, old_token refute_equal @user.auth_token, old_auth_token end def test_token_value_not_overwritten_when_present @user.token = "custom-secure-token" @user.save assert_equal @user.token, "custom-secure-token" end end has-secure-token-1.0.0/.travis.yml0000644000175000017500000000032513467553047015774 0ustar manasmanaslanguage: ruby rvm: - 1.9.3 - 2.0.0 - 2.1 - 2.2 gemfile: - gemfiles/rails3.gemfile - gemfiles/rails4_0.gemfile - gemfiles/rails4_1.gemfile - gemfiles/rails4_2.gemfile notifications: email: false has-secure-token-1.0.0/has_secure_token.gemspec0000644000175000017500000000246613467553047020561 0ustar manasmanas# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'has_secure_token/version' Gem::Specification.new do |spec| spec.name = "has_secure_token" spec.version = HasSecureToken::VERSION spec.authors = ["Roberto Miranda Altamar"] spec.email = ["rjmaltamar@gmail.com"] 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} 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.} spec.homepage = "https://github.com/robertomiranda/has_secure_token" spec.license = "MIT" spec.files = `git ls-files -z`.split("\x0") spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] spec.add_dependency "activerecord", ">= 3.0" spec.add_development_dependency "bundler", "~> 1.3" spec.add_development_dependency "rake" spec.add_development_dependency "minitest" spec.add_development_dependency 'sqlite3' end has-secure-token-1.0.0/Gemfile0000644000175000017500000000014713467553047015160 0ustar manasmanassource 'https://rubygems.org' # Specify your gem's dependencies in has_secure_password.gemspec gemspec has-secure-token-1.0.0/gemfiles/0000755000175000017500000000000013467553047015456 5ustar manasmanashas-secure-token-1.0.0/gemfiles/rails4_2.gemfile0000644000175000017500000000017013467553047020425 0ustar manasmanassource 'https://rubygems.org' gemspec :path => '../' group :development, :test do gem 'activerecord', '~> 4.2.0' end has-secure-token-1.0.0/gemfiles/rails4_1.gemfile0000644000175000017500000000017013467553047020424 0ustar manasmanassource 'https://rubygems.org' gemspec :path => '../' group :development, :test do gem 'activerecord', '~> 4.1.0' end has-secure-token-1.0.0/gemfiles/rails4_0.gemfile0000644000175000017500000000022313467553047020422 0ustar manasmanassource 'https://rubygems.org' gemspec :path => '../' group :development, :test do gem 'activerecord', '~> 4.0.0' gem 'minitest', '~> 4.2' end has-secure-token-1.0.0/gemfiles/rails3.gemfile0000644000175000017500000000017013467553047020203 0ustar manasmanassource 'https://rubygems.org' gemspec :path => '../' group :development, :test do gem 'activerecord', '~> 3.2.0' end has-secure-token-1.0.0/.gitignore0000644000175000017500000000027113467553047015653 0ustar manasmanas*.gem *.rbc .bundle .config .yardoc Gemfile.lock InstalledFiles _yardoc coverage doc/ lib/bundler/man pkg rdoc spec/reports test/tmp test/version_tmp tmp *.bundle *.so *.o *.a mkmf.log has-secure-token-1.0.0/lib/0000755000175000017500000000000013467553047014431 5ustar manasmanashas-secure-token-1.0.0/lib/has_secure_token/0000755000175000017500000000000013467553047017752 5ustar manasmanashas-secure-token-1.0.0/lib/has_secure_token/version.rb0000644000175000017500000000005613467553047021765 0ustar manasmanasmodule HasSecureToken VERSION = "1.0.0" end has-secure-token-1.0.0/lib/active_support/0000755000175000017500000000000013467553047017500 5ustar manasmanashas-secure-token-1.0.0/lib/active_support/core_ext/0000755000175000017500000000000013467553047021310 5ustar manasmanashas-secure-token-1.0.0/lib/active_support/core_ext/securerandom.rb0000644000175000017500000000142113467553047024322 0ustar manasmanasrequire 'securerandom' module SecureRandom BASE58_ALPHABET = ('0'..'9').to_a + ('A'..'Z').to_a + ('a'..'z').to_a - ['0', 'O', 'I', 'l'] # SecureRandom.base58 generates a random base58 string. # # The argument _n_ specifies the length, of the random string to be generated. # # If _n_ is not specified or is nil, 16 is assumed. It may be larger in the future. # # The result may contain alphanumeric characters except 0, O, I and l # # p SecureRandom.base58 #=> "4kUgL2pdQMSCQtjE" # p SecureRandom.base58(24) #=> "77TMHrHJFvFDwodq8w7Ev2m7" # def self.base58(n = 16) SecureRandom.random_bytes(n).unpack("C*").map do |byte| idx = byte % 64 idx = SecureRandom.random_number(58) if idx >= 58 BASE58_ALPHABET[idx] end.join end end has-secure-token-1.0.0/lib/has_secure_token.rb0000644000175000017500000000305613467553047020303 0ustar manasmanasrequire 'active_record' module ActiveRecord module SecureToken extend ActiveSupport::Concern module ClassMethods # Example using has_secure_token # # # Schema: User(token:string, auth_token:string) # class User < ActiveRecord::Base # has_secure_token # has_secure_token :auth_token # end # # user = User.new # user.save # user.token # => "4kUgL2pdQMSCQtjE" # user.auth_token # => "77TMHrHJFvFDwodq8w7Ev2m7" # user.regenerate_token # => true # user.regenerate_auth_token # => true # # SecureRandom::base58 is used to generate the 24-character unique token, so collisions are highly unlikely. # # 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 # with this even more unlikely scenario. def has_secure_token(attribute = :token) # Load securerandom only when has_secure_token is used. require 'active_support/core_ext/securerandom' define_method("regenerate_#{attribute}") { update_attributes attribute => self.class.generate_unique_secure_token } before_create { self.send("#{attribute}=", self.class.generate_unique_secure_token) unless self.send("#{attribute}?")} end def generate_unique_secure_token SecureRandom.base58(24) end end end end ActiveRecord::Base.send(:include, ActiveRecord::SecureToken)