idy 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5b9e139f9dd8d185f4c523382f5a7e10e2ab0f8f
4
+ data.tar.gz: 1f99aa90fa690f9d926d063df79c55a9f775faee
5
+ SHA512:
6
+ metadata.gz: 7c742d70263a6f7579cfb4e9782ee28307831b07a5400ff01e2c251262d0ab66f6ed391a46f87b66d364c5704b3b167883a4839a1df21a0cad5fb1e544007c27
7
+ data.tar.gz: 850388e0499f9030b2ac4b8daa203eec2bb973c8587e7d8d3330292d74490c8df15a58369c405fac13e5bf40cc08ad3184fdda793c4c8fc932ebe6e2739ebb4c
@@ -0,0 +1,7 @@
1
+ ## v0.1.1
2
+
3
+ - v0.1.0 had problem on `push`.
4
+
5
+ ## v0.1.0
6
+
7
+ - First release.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Washington Botelho
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,109 @@
1
+ # Idy
2
+
3
+ [![Build Status](https://travis-ci.org/wbotelhos/idy.svg)](https://travis-ci.org/wbotelhos/idy)
4
+ [![Gem Version](https://badge.fury.io/rb/idy.svg)](https://badge.fury.io/rb/idy)
5
+
6
+ An ID obfuscator for ActiveRecord.
7
+
8
+ ## Description
9
+
10
+ Do not let your users knows about your IDs:
11
+
12
+ - IDs can make hacker's life easier for a sequential attack;
13
+ - IDs can make crawler's life easier for a sequential scan;
14
+ - With few records on your database it can seem that your business is weak;
15
+ - With many records on your database it can call attention of people.
16
+
17
+ *Make it clean, make it lean, make it hidden.*
18
+
19
+ `http://example.com/articles/1` -> `http://example.com/articles/My`
20
+
21
+ It uses [Hashids](http://hashids.org/ruby) to make it pretty.
22
+
23
+ ## install
24
+
25
+ Add the following code on your `Gemfile` and run `bundle install`:
26
+
27
+ ```ruby
28
+ gem 'idy'
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ On an `ActiveRecord` model, just add `idy` callback:
34
+
35
+ ```ruby
36
+ class Article < ApplicationRecord
37
+ idy
38
+ end
39
+ ```
40
+
41
+ Try to call on your model the obfuscated ID:
42
+
43
+ ```ruby
44
+ Article.new(id: 1).idy
45
+ # My
46
+ ```
47
+
48
+ It will build you Rals URL with that ID too:
49
+
50
+ ```ruby
51
+ Article.new(id: 1).to_param
52
+ # localhost:3000/articles/My
53
+ ```
54
+
55
+ ## Security
56
+
57
+ Idy is not for encryption, it is about obfuscation.
58
+ If you want a *unbreakable* hash, it is not for you.
59
+
60
+ ## Collision
61
+
62
+ To avoid two differents models to generates the same hash for the same ID,
63
+ by default, the class name is used as a [Salt](https://en.wikipedia.org/wiki/Salt_(cryptography).
64
+
65
+ ```ruby
66
+ Article.new(id: 1).idy
67
+ # My
68
+
69
+ User.new(id: 1).idy
70
+ # ex
71
+ ```
72
+
73
+ ## Salt
74
+
75
+ You can provide you own:
76
+
77
+ ```ruby
78
+ class Article < ApplicationRecord
79
+ idy salt: 's3cr3t'
80
+ end
81
+ ```
82
+
83
+ ```ruby
84
+ Article.new(id: 1).idy
85
+ # 9A
86
+ ```
87
+
88
+ ## Find
89
+
90
+ Since you add the `idy` callback to your model, `find` method will be decorated:
91
+
92
+ ```ruby
93
+ Article.find('My').id
94
+ # 1
95
+ ```
96
+
97
+ Keep in mind that if you have some internal code, that you cannot change,
98
+ using `find`, the hash version of the id, `idy`, will be mandatory to correct find the record.
99
+
100
+ ## Inspiration
101
+
102
+ It was inpired and improved from:
103
+
104
+ - [obfuscate_id](https://github.com/namick/obfuscate_id)
105
+ - [hashids_uri](https://github.com/danieldraper/hashids_uri)
106
+
107
+ ## Love it!
108
+
109
+ Via [PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=X8HEP2878NDEG&item_name=idy) or [Gratipay](https://gratipay.com/~wbotelhos). Thanks! (:
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Idy
4
+ end
5
+
6
+ require 'hashids'
7
+ require 'idy/extension'
8
+
9
+ ActiveRecord::Base.include Idy::Extension
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Idy
4
+ module Extension
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ def idy
9
+ self.class.idy_encode id
10
+ end
11
+
12
+ def idy_options
13
+ self.class.idy_options
14
+ end
15
+
16
+ def salt
17
+ self.class.salt
18
+ end
19
+
20
+ def to_param
21
+ return super unless self.class.respond_to?(:idy?)
22
+
23
+ self.class.idy_encode id
24
+ end
25
+ end
26
+
27
+ module ClassMethods
28
+ def find(*args)
29
+ query = [args.first].flatten
30
+
31
+ if try(:idy?)
32
+ if query.size == 1
33
+ super idy_decode(query[0].to_s) || query[0]
34
+ else
35
+ super [query].flatten.map { |hash| idy_decode hash }
36
+ end
37
+ else
38
+ super [query].flatten.size == 1 ? query[0] : query
39
+ end
40
+ end
41
+
42
+ def idy(options = {})
43
+ @options = options.reverse_merge(salt: idy_default_salt)
44
+
45
+ define_singleton_method(:idy?) { true }
46
+ end
47
+
48
+ def idy_decode(hash, salt: self.salt)
49
+ encoder(salt).decode(hash).first
50
+ end
51
+
52
+ def idy_default_salt
53
+ alphabet = Array('a'..'z')
54
+
55
+ indexes = name.downcase.split('').map do |char|
56
+ alphabet.index(char) + 1
57
+ end
58
+
59
+ indexes.shift(10).join
60
+ end
61
+
62
+ def idy_encode(id, salt: self.salt)
63
+ return unless id
64
+
65
+ encoder(salt).encode id
66
+ end
67
+
68
+ def idy_options
69
+ @options || { salt: idy_default_salt }
70
+ end
71
+
72
+ def salt
73
+ idy_options[:salt]
74
+ end
75
+
76
+ private
77
+
78
+ def encoder(salt)
79
+ Hashids.new salt.to_s
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Idy
4
+ VERSION = '0.1.1'.freeze
5
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe Article, '.find_by' do
6
+ subject { described_class.create title: 'title' }
7
+
8
+ it 'works with normal id' do
9
+ record = described_class.find_by(id: subject.id)
10
+
11
+ expect(subject).to eq record
12
+ end
13
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe Article do
6
+ context 'on reload' do
7
+ subject { described_class.create id: 42, title: 'title' }
8
+
9
+ it 'reloads' do
10
+ record = described_class.find(subject.to_param)
11
+
12
+ record.update_attribute :title, 'title.updated'
13
+
14
+ expect(subject.title).to eq 'title'
15
+ expect(subject.reload.title).to eq 'title.updated'
16
+ end
17
+
18
+ context 'while locking' do
19
+ it 'does not throw an error' do
20
+ expect(-> { subject.lock! }).not_to raise_error
21
+ end
22
+ end
23
+ end
24
+
25
+ context 'finding one record as id' do
26
+ subject { described_class.find record.id }
27
+
28
+ let!(:record) { described_class.create id: 42, title: 'title-1' }
29
+
30
+ specify { expect(subject).to eq record }
31
+ end
32
+
33
+ context 'finding one record as idy' do
34
+ subject { described_class.find record.to_param }
35
+
36
+ let!(:record) { described_class.create id: 42, title: 'title-1' }
37
+
38
+ specify { expect(subject).to eq record }
39
+ end
40
+
41
+ context 'finding multiple records' do
42
+ subject { described_class.find [record_1.to_param, record_2.to_param] }
43
+
44
+ let!(:record_1) { described_class.create id: 42, title: 'title-1' }
45
+ let!(:record_2) { described_class.create id: 1 , title: 'title-2' }
46
+
47
+ it 'finds all' do
48
+ expect(subject).to eq [record_1, record_2]
49
+ end
50
+ end
51
+
52
+ context 'finding via has_many' do
53
+ let!(:article) { described_class.create }
54
+ let!(:comment) { Comment.create article: article }
55
+
56
+ specify { expect(article.comments.find(comment.id)).to eq comment }
57
+ end
58
+
59
+ context 'finding a class with no callback declared' do
60
+ let!(:record) { Clean.create }
61
+
62
+ context 'of one record' do
63
+ specify { expect(Clean.find(record.id)).to eq record }
64
+ end
65
+
66
+ context 'of multiple record' do
67
+ let!(:record_2) { Clean.create }
68
+
69
+ specify do
70
+ expect(Clean.find([record.id, record_2.id])).to eq [record, record_2]
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe '#idy_decode' do
6
+ context 'with no given salt' do
7
+ it 'undos the obfuscation of id with default class salt' do
8
+ expect(Article.idy_decode('My')).to eq 1
9
+ end
10
+ end
11
+
12
+ context 'with empty salt' do
13
+ let!(:salt) { '' }
14
+
15
+ it 'undos the obfuscation of id with given salt' do
16
+ expect(Article.idy_decode('jR', salt: salt)).to eq 1
17
+ end
18
+ end
19
+
20
+ context 'with salt' do
21
+ context 'as string' do
22
+ let!(:salt) { 'salt' }
23
+
24
+ it 'undos the obfuscation of id with given salt' do
25
+ expect(Article.idy_decode('XG', salt: salt)).to eq 1
26
+ end
27
+ end
28
+
29
+ context 'as number' do
30
+ let!(:salt) { 1 }
31
+
32
+ it 'undos the obfuscation of id with given salt as string' do
33
+ expect(Article.idy_decode('kL', salt: 1)).to eq 1
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe '#idy_default_salt' do
6
+ context 'when class name has a big length' do
7
+ it 'is bases on the first 10 class letter position index on alphabet' do
8
+ expect(Abcdefghijklm.idy_default_salt).to eq '12345678910'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe '#idy_encode' do
6
+ context 'with no given salt' do
7
+ let!(:model) { Article.new id: 1 }
8
+
9
+ it 'obfuscates the id with default class salt' do
10
+ expect(model.class.idy_encode(model.id)).to eq 'My'
11
+ end
12
+ end
13
+
14
+ context 'with empty salt' do
15
+ let!(:model) { Article.new id: 1 }
16
+ let!(:salt) { '' }
17
+
18
+ it 'obfuscates the id with empty salt' do
19
+ expect(model.class.idy_encode(model.id, salt: salt)).to eq 'jR'
20
+ end
21
+ end
22
+
23
+ context 'with salt' do
24
+ let!(:model) { Article.new id: 1 }
25
+
26
+ context 'as string' do
27
+ let!(:salt) { 'salt' }
28
+
29
+ it 'obfuscates the id with given salt' do
30
+ expect(model.class.idy_encode(model.id, salt: salt)).to eq 'XG'
31
+ end
32
+ end
33
+
34
+ context 'as number' do
35
+ let!(:salt) { 1 }
36
+
37
+ it 'obfuscates the id with given salt as string' do
38
+ expect(model.class.idy_encode(model.id, salt: salt)).to eq 'kL'
39
+ end
40
+ end
41
+ end
42
+
43
+ context 'with nil id' do
44
+ let!(:model) { Article.new }
45
+
46
+ it 'returns nil' do
47
+ expect(model.class.idy_encode(model.id)).to be_nil
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe ':idy_options' do
6
+ describe '.idy_options' do
7
+ context 'when has options' do
8
+ it 'returns the options' do
9
+ expect(Comment.new.idy_options).to eq(salt: 'salt')
10
+ end
11
+ end
12
+
13
+ context 'when has no options' do
14
+ it 'returns an default one' do
15
+ expect(Clean.new.idy_options).to eq(salt: clean_default_salt)
16
+ end
17
+ end
18
+ end
19
+
20
+ describe '#idy_options' do
21
+ before do
22
+ allow(Clean).to receive(:idy_options) { :idy_options }
23
+ end
24
+
25
+ it 'delegates to class method' do
26
+ expect(Clean.new.idy_options).to eq :idy_options
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe '.idy' do
6
+ subject { Article.new id: 1 }
7
+
8
+ it 'returns the encoded id' do
9
+ expect(subject.idy).to eq 'My'
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe Article, '.lock!' do
6
+ subject { described_class.create title: 'title' }
7
+
8
+ it 'works' do
9
+ record = described_class.find(subject.to_param)
10
+
11
+ expect { record.lock! }.not_to raise_error
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe '.idy_options' do
6
+ context 'when callback is not given' do
7
+ it 'returns a default options with a salt generated based on model name' do
8
+ expect(Clean.new.idy_options).to eq(salt: clean_default_salt)
9
+ end
10
+ end
11
+
12
+ context 'when options is not given' do
13
+ it 'returns a default options with a salt generated based on model name' do
14
+ expect(Article.idy_options).to eq(salt: article_default_salt)
15
+ end
16
+ end
17
+
18
+ context 'when salt is given' do
19
+ it 'returns a default options with a salt equal the given one' do
20
+ expect(Comment.idy_options).to eq(salt: 'salt')
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe ':salt' do
6
+ describe '#salt' do
7
+ before do
8
+ allow(Clean).to receive(:idy_options) { { salt: :salty } }
9
+ end
10
+
11
+ it 'fetchs the salt options' do
12
+ expect(Clean.salt).to eq(:salty)
13
+ end
14
+ end
15
+
16
+ describe '.salt' do
17
+ before { allow(Clean).to receive(:salt) { :salt } }
18
+
19
+ it 'delegates to class method' do
20
+ expect(Clean.new.salt).to eq :salt
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe '.to_param' do
6
+ context 'when object does not acts as idy' do
7
+ subject { Clean.new id: 1 }
8
+
9
+ it 'behaves as default' do
10
+ expect(subject.to_param).to eq '1'
11
+ end
12
+ end
13
+
14
+ context 'when object acts as idy' do
15
+ context 'with no given salt' do
16
+ let!(:model_1) { Article.new id: 1 }
17
+
18
+ it 'generates a hash' do
19
+ expect(model_1.to_param).to eq 'My'
20
+ end
21
+
22
+ context 'with comparison' do
23
+ let!(:model_2) { Post.new }
24
+
25
+ context 'with other object with same id' do
26
+ before { model_2.id = 1 }
27
+
28
+ it 'generates different hash' do
29
+ expect(model_1.to_param).not_to eq model_2.to_param
30
+ end
31
+ end
32
+ end
33
+
34
+ context 'when object is not persisted' do
35
+ context 'and has no id' do
36
+ subject { Article.new }
37
+
38
+ specify { expect(subject.to_param).to be_nil }
39
+ end
40
+
41
+ context 'and has id' do
42
+ subject { Article.new id: 1 }
43
+
44
+ it 'generates a hash' do
45
+ expect(model_1.to_param).to eq 'My'
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ ENV['RAILS_ENV'] ||= 'test'
4
+
5
+ require 'active_record/railtie'
6
+ require 'idy'
7
+ require 'pry-byebug'
8
+
9
+ ActiveRecord::Base.establish_connection adapter: :sqlite3, database: ':memory:'
10
+
11
+ Dir[File.expand_path('support/**/*.rb', __dir__)].each { |file| require file }
12
+
13
+ def article_default_salt
14
+ '1182093125'
15
+ end
16
+
17
+ def clean_default_salt
18
+ '3125114'
19
+ end
20
+
21
+ def comment_default_salt
22
+ ''
23
+ end
24
+
25
+ def user_default_salt
26
+ '1182093125'
27
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec/rails'
4
+
5
+ RSpec.configure do |config|
6
+ config.filter_run_when_matching :focus
7
+
8
+ config.disable_monkey_patching!
9
+
10
+ config.order = :random
11
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'database_cleaner'
4
+
5
+ RSpec.configure do |config|
6
+ config.before :suite do
7
+ DatabaseCleaner.strategy = :transaction
8
+
9
+ DatabaseCleaner.clean_with :transaction
10
+ end
11
+
12
+ config.before :each do
13
+ DatabaseCleaner.start
14
+ end
15
+
16
+ config.around do |spec|
17
+ DatabaseCleaner.cleaning do
18
+ spec.run
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateTables < ActiveRecord::Migration[5.0]
4
+ def change
5
+ create_table :abcdefghijklms do |t|
6
+ end
7
+
8
+ create_table :articles do |t|
9
+ t.string :title
10
+ end
11
+
12
+ create_table :cleans do |t|
13
+ end
14
+
15
+ create_table :comments do |t|
16
+ t.string :body
17
+
18
+ t.references :article, index: true, foreign_key: true
19
+ end
20
+
21
+ create_table :posts do |t|
22
+ t.string :title
23
+ end
24
+
25
+ create_table :users do |t|
26
+ t.string :name
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ CreateTables.new.change
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Abcdefghijklm < ActiveRecord::Base
4
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Article < ::ActiveRecord::Base
4
+ idy
5
+
6
+ has_many :comments
7
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Clean < ::ActiveRecord::Base
4
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Comment < ::ActiveRecord::Base
4
+ idy salt: 'salt'
5
+
6
+ belongs_to :article
7
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Post < ::ActiveRecord::Base
4
+ idy
5
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class User < ::ActiveRecord::Base
4
+ end
metadata ADDED
@@ -0,0 +1,225 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: idy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Washington Botelho
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: hashids
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '5'
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '6'
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '5'
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '6'
47
+ - !ruby/object:Gem::Dependency
48
+ name: database_cleaner
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: guard-rspec
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec-rails
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: rubocop-rspec
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: rubocop
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: sqlite3
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: pry-byebug
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ description: An ID obfuscator for ActiveRecord.
146
+ email: wbotelhos@gmail.com
147
+ executables: []
148
+ extensions: []
149
+ extra_rdoc_files: []
150
+ files:
151
+ - CHANGELOG.md
152
+ - LICENSE
153
+ - README.md
154
+ - lib/idy.rb
155
+ - lib/idy/extension.rb
156
+ - lib/idy/version.rb
157
+ - spec/lib/idy/extension/find_by_spec.rb
158
+ - spec/lib/idy/extension/find_spec.rb
159
+ - spec/lib/idy/extension/idy_decode_spec.rb
160
+ - spec/lib/idy/extension/idy_default_salt_spec.rb
161
+ - spec/lib/idy/extension/idy_encode_spec.rb
162
+ - spec/lib/idy/extension/idy_options_spec.rb
163
+ - spec/lib/idy/extension/idy_spec.rb
164
+ - spec/lib/idy/extension/lock_spec.rb
165
+ - spec/lib/idy/extension/options_spec.rb
166
+ - spec/lib/idy/extension/salt_spec.rb
167
+ - spec/lib/idy/extension/to_param_spec.rb
168
+ - spec/rails_helper.rb
169
+ - spec/support/common.rb
170
+ - spec/support/database_cleaner.rb
171
+ - spec/support/db/migrate/create_tables.rb
172
+ - spec/support/migrate.rb
173
+ - spec/support/models/abcdefghijklm.rb
174
+ - spec/support/models/article.rb
175
+ - spec/support/models/clean.rb
176
+ - spec/support/models/comment.rb
177
+ - spec/support/models/post.rb
178
+ - spec/support/models/user.rb
179
+ homepage: https://github.com/wbotelhos/idy
180
+ licenses:
181
+ - MIT
182
+ metadata: {}
183
+ post_install_message:
184
+ rdoc_options: []
185
+ require_paths:
186
+ - lib
187
+ required_ruby_version: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - ">="
190
+ - !ruby/object:Gem::Version
191
+ version: '0'
192
+ required_rubygems_version: !ruby/object:Gem::Requirement
193
+ requirements:
194
+ - - ">="
195
+ - !ruby/object:Gem::Version
196
+ version: '0'
197
+ requirements: []
198
+ rubyforge_project:
199
+ rubygems_version: 2.6.11
200
+ signing_key:
201
+ specification_version: 4
202
+ summary: An ID obfuscator for ActiveRecord.
203
+ test_files:
204
+ - spec/lib/idy/extension/find_by_spec.rb
205
+ - spec/lib/idy/extension/find_spec.rb
206
+ - spec/lib/idy/extension/idy_decode_spec.rb
207
+ - spec/lib/idy/extension/idy_default_salt_spec.rb
208
+ - spec/lib/idy/extension/idy_encode_spec.rb
209
+ - spec/lib/idy/extension/idy_options_spec.rb
210
+ - spec/lib/idy/extension/idy_spec.rb
211
+ - spec/lib/idy/extension/lock_spec.rb
212
+ - spec/lib/idy/extension/options_spec.rb
213
+ - spec/lib/idy/extension/salt_spec.rb
214
+ - spec/lib/idy/extension/to_param_spec.rb
215
+ - spec/rails_helper.rb
216
+ - spec/support/common.rb
217
+ - spec/support/database_cleaner.rb
218
+ - spec/support/db/migrate/create_tables.rb
219
+ - spec/support/migrate.rb
220
+ - spec/support/models/abcdefghijklm.rb
221
+ - spec/support/models/article.rb
222
+ - spec/support/models/clean.rb
223
+ - spec/support/models/comment.rb
224
+ - spec/support/models/post.rb
225
+ - spec/support/models/user.rb