ar-tokens 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: