ar-tokens 0.0.4

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.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in tokens.gemspec
4
+ gemspec
5
+ gem 'rspec'
6
+ gem 'sqlite3'
@@ -0,0 +1,39 @@
1
+ For generating a token on an active record column you can use `generate_token`
2
+
3
+ Parameters
4
+ ----------
5
+
6
+ * column: the column of the active record
7
+ * options: some options for generating the token
8
+ * :length: the token length (default: 8)
9
+ * :uniq: whether the token must be uniq or not (default: true)
10
+ * :scope: the column for the scope to check the uniqueness (default: nil)
11
+
12
+ Example
13
+ -------
14
+
15
+ ```ruby
16
+ class User < ActiveRecord::Base
17
+ tokenize :email_confirmation_token, length: 16
18
+ end
19
+ ```
20
+
21
+ this is equal to
22
+
23
+ ```ruby
24
+ class User < ActiveRecord::Base
25
+ before_validation on: :create do |obj|
26
+ obj.generate_token :email_confirmation_token, length: 16
27
+ end
28
+ end
29
+ ```
30
+
31
+ Installation
32
+ ------------
33
+
34
+ Currently the gem is not available on rubyforge, so you have to install it with git:
35
+
36
+ ```
37
+ gem 'ar-tokens'
38
+ ```
39
+
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "tokens/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "ar-tokens"
7
+ s.version = Tokens::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Paul Spieker"]
10
+ s.email = ["p.spieker@duenos.de"]
11
+ s.homepage = "https://github.com/spieker/tokens"
12
+ s.summary = %q{Generating tokens on ruby objects and active record columns}
13
+ s.description = %q{This gem lets you easily generate tokens on ruby objects and provides additional methods on ActiveRecord::Base to generate tokens on records}
14
+
15
+ s.rubyforge_project = "tokens"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency 'activerecord'
23
+ end
@@ -0,0 +1,84 @@
1
+ # This mixin provides methods on ActiveRecord::Base to generate a token for
2
+ # a given column. The token for the column can have a specific length, can
3
+ # be uniq and the uniqueness can be scoped on a given column.
4
+ #
5
+ module ActiveRecord
6
+ module Mixin
7
+ module TokenGenerator
8
+ module InstanceMethods
9
+ # Generates a token for the given active record column
10
+ #
11
+ # == Parameters
12
+ # * columns: the column of the active record as symbol or an array of columns
13
+ # * options: some options for generating the token
14
+ # ** :length: the token length (default: 8)
15
+ # ** :uniq: whether the token must be uniq or not (default: true)
16
+ # ** :scope: the column for the scope to check the uniqueness (default: nil)
17
+ # ** :same_token: if an array of columns is given and this option is true, all columns will get the same token (default: false)
18
+ #
19
+ # == Example
20
+ # class User < ActiveRecord::Base
21
+ # before_validation do |obj|
22
+ # obj.generate_token :email_confirmation_token, :length => 16
23
+ # end
24
+ # end
25
+ #
26
+ def generate_token(columns, *args)
27
+ options = {
28
+ :length => 8,
29
+ :uniq => true,
30
+ :scope => nil,
31
+ :same_token => false,
32
+ :max_try => 8
33
+ }.merge(args.extract_options!)
34
+
35
+ columns = [columns] unless columns.is_a?(Array)
36
+
37
+ result = {}
38
+ token = nil
39
+ columns.each do |column|
40
+ counter = 0
41
+ begin
42
+ raise NoFreeToken.new(column) if counter >= options[:max_try]
43
+ counter += 1
44
+
45
+ token = new_token(options[:length]) if(token.blank? or not options[:same_token])
46
+ self.send("#{column}=".to_sym, token)
47
+ result[column.to_sym] = token
48
+ condition = { column => token }
49
+ condition[options[:scope]] = self[options[:scope]] if options[:scope].is_a?(Symbol) or options[:scope].is_a?(String)
50
+ end while options[:uniq] and self.class.exists?(condition)
51
+ end
52
+ result
53
+ end
54
+
55
+ end
56
+
57
+ module ClassMethods
58
+ # this method generates a token for the given columns before there get validated. Beside the
59
+ # options described at the +generate_token+ method, you can use the following options.
60
+ #
61
+ # :on: (default: :create)
62
+ #
63
+ def tokenize(column, *args)
64
+ options = {
65
+ :on => :create
66
+ }.merge(args.extract_options!)
67
+ before_validation_options = options.reject { |k,v| [:length, :uniq, :scope, :same_token].include?(k) }
68
+ options.select! { |k,v| [:length, :uniq, :scope, :same_token].include?(k) }
69
+
70
+ before_validation before_validation_options do |obj|
71
+ obj.generate_token column, options
72
+ end
73
+ end
74
+ end
75
+
76
+ def self.included(receiver)
77
+ receiver.send :include, InstanceMethods
78
+ receiver.extend ClassMethods
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ ActiveRecord::Base.send :include, ActiveRecord::Mixin::TokenGenerator
@@ -0,0 +1,5 @@
1
+ require 'object'
2
+ require 'no_free_token'
3
+ require 'securerandom'
4
+ require 'active_record'
5
+ require 'active_record/mixin/token_generator'
@@ -0,0 +1,5 @@
1
+ class NoFreeToken < Exception
2
+ def initialize(column)
3
+ super("No free token for column '#{column}' found")
4
+ end
5
+ end
@@ -0,0 +1,22 @@
1
+ # This provides a method for generating a random token of the given length.
2
+ # The generated token is base58 encoded, so the token just contains numbers,
3
+ # up- and down case characters.
4
+ #
5
+ # Example:
6
+ # Object.new_token(10) # => "S2Mq4mJBv6" (i.e.)
7
+ # or
8
+ # Object.new.new_token(10) # => "S2Mq4mJBv6" (i.e.)
9
+ #
10
+ class Object
11
+ def self.new_token(length=8, characters = ('a'..'z').to_a+('A'..'Z').to_a+(0..9).to_a)
12
+ result = ''
13
+ length.times do
14
+ result += characters[SecureRandom.random_number(characters.length)].to_s
15
+ end
16
+ result
17
+ end
18
+
19
+ def new_token(length=8, characters = ('a'..'z').to_a+('A'..'Z').to_a+(0..9).to_a)
20
+ self.class.new_token(length, characters)
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module Tokens
2
+ VERSION = "0.0.4"
3
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveRecord::Mixin::TokenGenerator do
4
+ before :each do
5
+ @klass = TokenTest.dup
6
+ end
7
+
8
+ it "geneates a token" do
9
+ SecureRandom.stub(:random_number).and_return(0)
10
+ @klass.tokenize :token
11
+ @klass.create.token.should == 'aaaaaaaa'
12
+ end
13
+
14
+ it "raises an exception if no free token is available" do
15
+ SecureRandom.stub(:random_number).and_return(0)
16
+ @klass.tokenize :token
17
+ @klass.create.token.should == 'aaaaaaaa'
18
+ expect {
19
+ @klass.create
20
+ }.to raise_error(NoFreeToken)
21
+ end
22
+
23
+ it "generates duplicate tokens if allowed" do
24
+ SecureRandom.stub(:random_number).and_return(0)
25
+ @klass.tokenize :token, :uniq => false
26
+ @klass.create.token.should == 'aaaaaaaa'
27
+ @klass.create.token.should == 'aaaaaaaa'
28
+ end
29
+
30
+ it "generates duplicate tokens in different scopes if allowed" do
31
+ SecureRandom.stub(:random_number).and_return(0)
32
+ @klass.tokenize :token, :scope => 'scope'
33
+ @klass.create(:scope => 'a').token.should == 'aaaaaaaa'
34
+ @klass.create(:scope => 'b').token.should == 'aaaaaaaa'
35
+ end
36
+
37
+ it "generates tokens with the specified length" do
38
+ (6..32).each do |i|
39
+ @klass = TokenTest.dup
40
+ @klass.tokenize :token, :length => i
41
+ 10.times do
42
+ @klass.create.token.length.should == i
43
+ end
44
+ end
45
+ end
46
+
47
+ it "generates different tokens for different columns" do
48
+ @klass.tokenize [:token, :token_two]
49
+ r = @klass.create!
50
+ r.token.should_not == r.token_two
51
+ end
52
+
53
+ it "generates the same token for two columns if specified" do
54
+ @klass.tokenize [:token, :token_two], :same_token => true
55
+ r = @klass.create!
56
+ r.token.should == r.token_two
57
+ end
58
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Object do
4
+ it "returns 8 a's if only a is given as character list" do
5
+ new_token(8, ['a']).should == 'aaaaaaaa'
6
+ end
7
+
8
+ it "returns 'bbbbbbbb' if random_number retruns 1" do
9
+ SecureRandom.stub(:random_number).and_return(1)
10
+ new_token.should == 'bbbbbbbb'
11
+ end
12
+
13
+ it "returns a random string with the given length" do
14
+ 32.times do |i|
15
+ 100.times do
16
+ new_token(i).length.should == i
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'ar-tokens'
5
+ require 'support/active_record'
6
+
7
+ RSpec.configure do |config|
8
+ config.around do |example|
9
+ ActiveRecord::Base.transaction do
10
+ example.run
11
+ raise ActiveRecord::Rollback
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ require 'active_record'
2
+ ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
3
+
4
+ ActiveRecord::Migration.create_table :token_tests do |t|
5
+ t.string :scope
6
+ t.string :token
7
+ t.string :token_two
8
+ t.timestamps
9
+ end
10
+
11
+ class TokenTest < ActiveRecord::Base
12
+ set_table_name 'token_tests'
13
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ar-tokens
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Paul Spieker
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: This gem lets you easily generate tokens on ruby objects and provides
31
+ additional methods on ActiveRecord::Base to generate tokens on records
32
+ email:
33
+ - p.spieker@duenos.de
34
+ executables: []
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - .gitignore
39
+ - Gemfile
40
+ - README.markdown
41
+ - Rakefile
42
+ - ar-tokens.gemspec
43
+ - lib/active_record/mixin/token_generator.rb
44
+ - lib/ar-tokens.rb
45
+ - lib/no_free_token.rb
46
+ - lib/object.rb
47
+ - lib/tokens/version.rb
48
+ - spec/active_record_spec.rb
49
+ - spec/object_spec.rb
50
+ - spec/spec_helper.rb
51
+ - spec/support/active_record.rb
52
+ homepage: https://github.com/spieker/tokens
53
+ licenses: []
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubyforge_project: tokens
72
+ rubygems_version: 1.8.24
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: Generating tokens on ruby objects and active record columns
76
+ test_files:
77
+ - spec/active_record_spec.rb
78
+ - spec/object_spec.rb
79
+ - spec/spec_helper.rb
80
+ - spec/support/active_record.rb
81
+ has_rdoc: