effective_obfuscation 1.0.0
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +190 -0
- data/Rakefile +20 -0
- data/app/models/concerns/acts_as_obfuscated.rb +174 -0
- data/lib/effective_obfuscation/engine.rb +12 -0
- data/lib/effective_obfuscation/version.rb +3 -0
- data/lib/effective_obfuscation.rb +13 -0
- data/spec/effective_obfuscation_spec.rb +7 -0
- data/spec/spec_helper.rb +33 -0
- metadata +86 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2893d0d095c6f1b6fbdc1d972a225987d42b6c76
|
4
|
+
data.tar.gz: 38c42ee37f546e9c982fba0b02c8ac420fa1d811
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b651ce15257c280d26618bd743c59ec3bd7dbf3b21d9c0eb758440b40296d873fbb2878e93a37ccd086888dcbd1d2ee9a893c357537f797b6d9bf76537879d3d
|
7
|
+
data.tar.gz: 557b20e2d11dc0eea445efd9dd39d21e48eb4ae4be04b357fbd8e85bd8c667d4299ece5c538532303ace640e2a02d62cbb6d70f33d93da0bf539ee3f876159fc
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2014 Code and Effect Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
# Effective Obfuscation
|
2
|
+
|
3
|
+
Display unique 10-digit numbers instead of ActiveRecord IDs. Hides the ID param so curious website visitors are unable to determine your user or order count.
|
4
|
+
|
5
|
+
Turn a URL like:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
http://example.com/users/3
|
9
|
+
```
|
10
|
+
|
11
|
+
into something like:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
http://example.com/users/2356513904
|
15
|
+
```
|
16
|
+
|
17
|
+
Sequential ActiveRecord ids become non-sequential, random looking, numeric ids.
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
# user 7000
|
21
|
+
http://example.com/users/5270192353
|
22
|
+
# user 7001
|
23
|
+
http://example.com/users/7107163820
|
24
|
+
# user 7002
|
25
|
+
http://example.com/user/3296163828
|
26
|
+
```
|
27
|
+
|
28
|
+
This is a Rails 4 compatible version of obfuscate_id (https://github.com/namick/obfuscate_id) which also adds totally automatic integration with Rails finder methods.
|
29
|
+
|
30
|
+
|
31
|
+
## Getting Started
|
32
|
+
|
33
|
+
Add to Gemfile:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
gem 'effective_obfuscation', :git => 'https://github.com/code-and-effect/effective_obfuscation.git'
|
37
|
+
```
|
38
|
+
|
39
|
+
Run the bundle command to install it:
|
40
|
+
|
41
|
+
```console
|
42
|
+
bundle install
|
43
|
+
```
|
44
|
+
|
45
|
+
## Usage
|
46
|
+
|
47
|
+
### Basic
|
48
|
+
|
49
|
+
Add the mixin to an existing model:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
class User
|
53
|
+
acts_as_obfuscated
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
57
|
+
Thats it. Now URLs for a User will be generated as
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
http://example.com/users/2356513904
|
61
|
+
```
|
62
|
+
|
63
|
+
As well, any find(), exists?(), find_by_id(), find_by(), where(:id => params[:id]) and all Arel table finder methods will be automatically translated to lookup the proper underlying ID.
|
64
|
+
|
65
|
+
You shouldn't require any changes to your view or controller code. Just Works with InherittedResources and ActiveAdmin.
|
66
|
+
|
67
|
+
### Formatting
|
68
|
+
|
69
|
+
Because of the underlying ScatterSwap algorithm, the obfuscated IDs must be exactly 10 digits in length.
|
70
|
+
|
71
|
+
However, if you'd like to add some formatting to make the 10-digit number more human readable and over-the-phone friendly
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
class User
|
75
|
+
acts_as_obfuscated :format => '###-####-###'
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
will generate URLs that look like
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
http://example.com/users/235-6513-904
|
83
|
+
```
|
84
|
+
|
85
|
+
Any String.parameterize-able characters will work as long as there are exactly 10 # (hash symbol) characters in the format string somewhere.
|
86
|
+
|
87
|
+
|
88
|
+
### ScatterSwap Spin
|
89
|
+
|
90
|
+
The Spin value is basically a salt used by the ScatterSwap algorithm to randomize integers.
|
91
|
+
|
92
|
+
In this gem, the default spin value is set on a per-model basis.
|
93
|
+
|
94
|
+
There is really no reason to change it; however, you can specify the spin value directly if you wish
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
class User
|
98
|
+
acts_as_obfuscated :spin => 123456789
|
99
|
+
end
|
100
|
+
```
|
101
|
+
|
102
|
+
### General Obfuscation
|
103
|
+
|
104
|
+
So maybe you just want access to the underlying ScatterSwap obfuscation algorithm including the additional model-specific formatting.
|
105
|
+
|
106
|
+
To obfuscate, pass any number as a string, or an integer
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
User.obfuscate(43) # Using acts_as_obfuscated :format => '###-####-###'
|
110
|
+
=> "990-5826-174"
|
111
|
+
```
|
112
|
+
|
113
|
+
And to de-obfuscate, pass any number as a string or an integer
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
User.deobfuscate("990-5826-174")
|
117
|
+
=> 43
|
118
|
+
|
119
|
+
User.deobfuscate(9905826174)
|
120
|
+
=> 43
|
121
|
+
```
|
122
|
+
|
123
|
+
### Searching by the Real (Database) ID
|
124
|
+
|
125
|
+
By default, all finder method except `find()` will work with both obfuscated and database IDs.
|
126
|
+
|
127
|
+
This means,
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
User.where(:id => "990-5826-174")
|
131
|
+
=> User<id: 43>
|
132
|
+
```
|
133
|
+
|
134
|
+
returns the same User as
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
User.where(:id => 43)
|
138
|
+
=> User<id: 43>
|
139
|
+
```
|
140
|
+
|
141
|
+
This behaviour is not applied to `find()` because it would allow a user to visit:
|
142
|
+
|
143
|
+
http://example.com/users/1
|
144
|
+
http://example.com/users/2
|
145
|
+
...etc...
|
146
|
+
|
147
|
+
and enumerate all users.
|
148
|
+
|
149
|
+
Please continue to use @user = User.find(params[:id]) in your controller to prevent route enumeration.
|
150
|
+
|
151
|
+
Any other internally used finder methods, `where` and `find_by_id` should respond to both obfuscated and database IDs for maximum compatibility.
|
152
|
+
|
153
|
+
## License
|
154
|
+
|
155
|
+
MIT License. Copyright [Code and Effect Inc.](http://www.codeandeffect.com/)
|
156
|
+
|
157
|
+
Code and Effect is the product arm of [AgileStyle](http://www.agilestyle.com/), an Edmonton-based shop that specializes in building custom web applications with Ruby on Rails.
|
158
|
+
|
159
|
+
|
160
|
+
## Credits
|
161
|
+
|
162
|
+
This project was inspired by
|
163
|
+
|
164
|
+
ObfuscateID (https://github.com/namick/obfuscate_id)
|
165
|
+
|
166
|
+
and uses the same (simply genius!) underlying algorithm
|
167
|
+
|
168
|
+
ScatterSwap (https://github.com/namick/scatter_swap)
|
169
|
+
|
170
|
+
|
171
|
+
## Testing
|
172
|
+
|
173
|
+
The test suite for this gem is unfortunately not yet complete.
|
174
|
+
|
175
|
+
Run tests by:
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
rake spec
|
179
|
+
```
|
180
|
+
|
181
|
+
|
182
|
+
## Contributing
|
183
|
+
|
184
|
+
1. Fork it
|
185
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
186
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
187
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
188
|
+
5. Bonus points for test coverage
|
189
|
+
6. Create new Pull Request
|
190
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
|
8
|
+
# Testing tasks
|
9
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
10
|
+
load 'rails/tasks/engine.rake'
|
11
|
+
|
12
|
+
Bundler::GemHelper.install_tasks
|
13
|
+
|
14
|
+
require 'rspec/core'
|
15
|
+
require 'rspec/core/rake_task'
|
16
|
+
|
17
|
+
desc "Run all specs in spec directory (excluding plugin specs)"
|
18
|
+
RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
|
19
|
+
|
20
|
+
task :default => :spec
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# ActsAsObfuscated
|
2
|
+
#
|
3
|
+
# This module automatically obfuscates IDs
|
4
|
+
|
5
|
+
# Mark your model with 'acts_as_obfuscated'
|
6
|
+
|
7
|
+
module ActsAsObfuscated
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
module ActiveRecord
|
11
|
+
def acts_as_obfuscated(options = nil)
|
12
|
+
@acts_as_obfuscated_opts = options || {}
|
13
|
+
|
14
|
+
# Guard against an improperly passed :format => '...' option
|
15
|
+
if @acts_as_obfuscated_opts[:format]
|
16
|
+
if @acts_as_obfuscated_opts[:format].to_s.count('#') != 10
|
17
|
+
raise Exception.new("acts_as_obfuscated :format => '...' value must contain exactly 10 # characters. Use something like :format => '###-####-###'")
|
18
|
+
end
|
19
|
+
|
20
|
+
format = @acts_as_obfuscated_opts[:format].gsub('#', '0')
|
21
|
+
|
22
|
+
if format.parameterize != format
|
23
|
+
raise Exception.new("acts_as_obfuscated :format => '...' value must contain only String.parameterize-able characters and the # character. Use something like :format => '###-####-###'")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
include ::ActsAsObfuscated
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
included do
|
32
|
+
cattr_accessor :acts_as_obfuscated_opts
|
33
|
+
self.acts_as_obfuscated_opts = @acts_as_obfuscated_opts
|
34
|
+
|
35
|
+
# Set the spin based on model name if not explicity defined
|
36
|
+
self.acts_as_obfuscated_opts[:spin] ||= (
|
37
|
+
alphabet = Array('a'..'z')
|
38
|
+
self.name.split('').map { |char| alphabet.index(char) }.first(12).join.to_i
|
39
|
+
)
|
40
|
+
|
41
|
+
# We need to track the Maximum ID of this Table
|
42
|
+
self.acts_as_obfuscated_opts[:max_id] ||= (self.unscoped.maximum(:id) rescue 2147483647)
|
43
|
+
|
44
|
+
after_commit :on => :create do
|
45
|
+
self.class.acts_as_obfuscated_opts[:max_id] = nil
|
46
|
+
end
|
47
|
+
|
48
|
+
# Work with Ransack if available
|
49
|
+
if self.respond_to?(:ransacker)
|
50
|
+
ransacker :id, :formatter => Proc.new { |v| deobfuscate(v) } { |parent| parent.table[:id] }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
module ClassMethods
|
55
|
+
def obfuscate(original)
|
56
|
+
obfuscated = EffectiveObfuscation.hide(original, acts_as_obfuscated_opts[:spin])
|
57
|
+
|
58
|
+
if acts_as_obfuscated_opts[:format] # Transform 1234567890 from ###-####-### into 123-4567-890 as per :format option
|
59
|
+
acts_as_obfuscated_opts[:format].dup.tap do |formatted|
|
60
|
+
10.times { |x| formatted.sub!('#', obfuscated[x]) }
|
61
|
+
end
|
62
|
+
else
|
63
|
+
obfuscated
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# If rescue_with_original_id is set to true the original ID will be returned when its Obfuscated Id is not found
|
68
|
+
#
|
69
|
+
# We use this as the default behaviour on everything except Class.find()
|
70
|
+
def deobfuscate(original, rescue_with_original_id = true)
|
71
|
+
if original.kind_of?(Array)
|
72
|
+
return original.map { |value| deobfuscate(value, true) } # Always rescue with original ID
|
73
|
+
elsif !(original.kind_of?(Integer) || original.kind_of?(String))
|
74
|
+
return original
|
75
|
+
end
|
76
|
+
|
77
|
+
if acts_as_obfuscated_opts[:format]
|
78
|
+
obfuscated_id = original.to_s.delete('^0-9')
|
79
|
+
else
|
80
|
+
obfuscated_id = original.to_s
|
81
|
+
end
|
82
|
+
|
83
|
+
# 2147483647 is PostgreSQL's Integer Max Value. If we return a value higher than this, we get weird DB errors
|
84
|
+
revealed = [EffectiveObfuscation.show(obfuscated_id, acts_as_obfuscated_opts[:spin]).to_i, 2147483647].min
|
85
|
+
|
86
|
+
if rescue_with_original_id && (revealed >= 2147483647 || revealed > deobfuscated_maximum_id)
|
87
|
+
original
|
88
|
+
else
|
89
|
+
revealed
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def deobfuscator(left)
|
94
|
+
acts_as_obfuscated_opts[:deobfuscators] ||= Hash.new().tap do |deobfuscators|
|
95
|
+
deobfuscators['id'] = Proc.new { |right| self.deobfuscate(right) }
|
96
|
+
|
97
|
+
reflect_on_all_associations(:belongs_to).each do |reflection|
|
98
|
+
if reflection.klass.respond_to?(:deobfuscate)
|
99
|
+
deobfuscators[reflection.foreign_key] = Proc.new { |right| reflection.klass.deobfuscate(right) }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
acts_as_obfuscated_opts[:deobfuscators][left.to_s]
|
105
|
+
end
|
106
|
+
|
107
|
+
def deobfuscated_maximum_id
|
108
|
+
acts_as_obfuscated_opts[:max_id] ||= (self.unscoped.maximum(:id) rescue 2147483647)
|
109
|
+
end
|
110
|
+
|
111
|
+
def relation
|
112
|
+
super.tap { |relation| relation.extend(FinderMethods) }
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
module FinderMethods
|
117
|
+
def find(*args)
|
118
|
+
super(deobfuscate(args.first, false))
|
119
|
+
end
|
120
|
+
|
121
|
+
def exists?(*args)
|
122
|
+
super(deobfuscate(args.first))
|
123
|
+
end
|
124
|
+
|
125
|
+
def find_by_id(*args)
|
126
|
+
super(deobfuscate(args.first))
|
127
|
+
end
|
128
|
+
|
129
|
+
def find_by(*args)
|
130
|
+
if args.first.kind_of?(Hash)
|
131
|
+
args.first.each do |left, right|
|
132
|
+
next unless (d = deobfuscator(left))
|
133
|
+
args.first[left] = d.call(right)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
super(*args)
|
138
|
+
end
|
139
|
+
|
140
|
+
def where(*args)
|
141
|
+
if args.first.kind_of?(Hash)
|
142
|
+
args.first.each do |left, right|
|
143
|
+
next unless (d = deobfuscator(left))
|
144
|
+
args.first[left] = d.call(right)
|
145
|
+
end
|
146
|
+
elsif args.first.class.parent == Arel::Nodes
|
147
|
+
deobfuscate_arel!(args.first)
|
148
|
+
end
|
149
|
+
|
150
|
+
super(*args)
|
151
|
+
end
|
152
|
+
|
153
|
+
def deobfuscate_arel!(node)
|
154
|
+
nodes = node.kind_of?(Array) ? node : [node]
|
155
|
+
|
156
|
+
nodes.each do |node|
|
157
|
+
if node.respond_to?(:children)
|
158
|
+
deobfuscate_arel!(node.children)
|
159
|
+
elsif node.respond_to?(:expr)
|
160
|
+
deobfuscate_arel!(node.expr)
|
161
|
+
elsif node.respond_to?(:left)
|
162
|
+
next unless (d = deobfuscator(node.left.name))
|
163
|
+
node.right = d.call(node.right) unless (node.right.kind_of?(String) && node.right.include?('$'))
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def to_param
|
170
|
+
self.class.obfuscate(self.id)
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module EffectiveObfuscation
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
config.autoload_paths += Dir["#{config.root}/app/models/concerns"]
|
4
|
+
|
5
|
+
# Include acts_as_addressable concern and allow any ActiveRecord object to call it
|
6
|
+
initializer 'effective_obfuscation.active_record' do |app|
|
7
|
+
ActiveSupport.on_load :active_record do
|
8
|
+
ActiveRecord::Base.extend(ActsAsObfuscated::ActiveRecord)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "effective_obfuscation/engine"
|
2
|
+
require "effective_obfuscation/version"
|
3
|
+
require 'scatter_swap'
|
4
|
+
|
5
|
+
module EffectiveObfuscation
|
6
|
+
def self.hide(id, spin)
|
7
|
+
::ScatterSwap.hash(id, spin)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.show(id, spin)
|
11
|
+
::ScatterSwap.reverse_hash(id, spin).to_i
|
12
|
+
end
|
13
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
ENV["RAILS_ENV"] ||= 'test'
|
2
|
+
|
3
|
+
require File.expand_path("../dummy/config/environment", __FILE__)
|
4
|
+
|
5
|
+
require 'rspec/rails'
|
6
|
+
require 'rspec/autorun'
|
7
|
+
|
8
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
9
|
+
# in spec/support/ and its subdirectories.
|
10
|
+
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f }
|
11
|
+
|
12
|
+
RSpec.configure do |config|
|
13
|
+
config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
14
|
+
|
15
|
+
Rails.logger.level = 4 # Output only minimal stuff to test.log
|
16
|
+
|
17
|
+
config.use_transactional_fixtures = true # Make this false to once again use DatabaseCleaner
|
18
|
+
config.infer_base_class_for_anonymous_controllers = false
|
19
|
+
config.order = 'random'
|
20
|
+
end
|
21
|
+
|
22
|
+
class ActiveRecord::Base
|
23
|
+
mattr_accessor :shared_connection
|
24
|
+
@@shared_connection = nil
|
25
|
+
|
26
|
+
def self.connection
|
27
|
+
@@shared_connection || retrieve_connection
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Forces all threads to share the same connection. This works on
|
32
|
+
# Capybara because it starts the web server in a thread.
|
33
|
+
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: effective_obfuscation
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Code and Effect
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-12-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.2.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.2.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: scatter_swap
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.0.3
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.0.3
|
41
|
+
description: Display unique 10-digit numbers instead of ActiveRecord IDs. Hides the
|
42
|
+
ID param so curious website visitors are unable to determine your user or order
|
43
|
+
count.
|
44
|
+
email:
|
45
|
+
- info@codeandeffect.com
|
46
|
+
executables: []
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- MIT-LICENSE
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- app/models/concerns/acts_as_obfuscated.rb
|
54
|
+
- lib/effective_obfuscation.rb
|
55
|
+
- lib/effective_obfuscation/engine.rb
|
56
|
+
- lib/effective_obfuscation/version.rb
|
57
|
+
- spec/effective_obfuscation_spec.rb
|
58
|
+
- spec/spec_helper.rb
|
59
|
+
homepage: https://github.com/code-and-effect/effective_obfuscation
|
60
|
+
licenses:
|
61
|
+
- MIT
|
62
|
+
metadata: {}
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
requirements: []
|
78
|
+
rubyforge_project:
|
79
|
+
rubygems_version: 2.4.3
|
80
|
+
signing_key:
|
81
|
+
specification_version: 4
|
82
|
+
summary: Display unique 10-digit numbers instead of ActiveRecord IDs. Hides the ID
|
83
|
+
param so curious website visitors are unable to determine your user or order count.
|
84
|
+
test_files:
|
85
|
+
- spec/effective_obfuscation_spec.rb
|
86
|
+
- spec/spec_helper.rb
|