attr_masker 0.1.1 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 43cbbd6cf1150e2228d2b5fc1323bbdbae852510
4
- data.tar.gz: 614372bc5a85ac8b23112062b437a8d468064160
3
+ metadata.gz: 84f6dabd5fc0ea9d919da16d60ca4b06c46b2c97
4
+ data.tar.gz: 72d8b8eeb8eb59a24c7613c752fb8c2175be566f
5
5
  SHA512:
6
- metadata.gz: cb815eda36c7a99d2cfebf18df5a1b901a5e597df340b6f2041bd9bdb6ee722b4fac5b21dde71457ad63794de5cc3e1aec2659c02d32c2aea6e0bce7dfff2b8c
7
- data.tar.gz: 6e97866032f1d8c1323e11bb160f62d9798f001b2736b98be03907f9269f39ff462be45633ac3c59c04856621196fc8979556c1438cac3b6be5eff68f1f6c238
6
+ metadata.gz: 0274cb6920ce73043fff153a27c8140cfb3fa9ec095a020c1fe5f4180e1339d0ad75bb41cccf5a68573d351b3fb4b98ced45829ff836729e2c7966a8b9b3316e
7
+ data.tar.gz: 3e13de85e38714f92b9a10cbdcae9178ea6bf81ebca353b63e764ed33d797e759cb489803ee22f006883548b9d2ca1daad2ee2ceb17658da16d92f9097651015
data/.travis.yml CHANGED
@@ -3,6 +3,9 @@ dist: trusty
3
3
  language: ruby
4
4
  before_install: gem install bundler -v 1.15.1
5
5
 
6
+ services:
7
+ - mongodb
8
+
6
9
  script:
7
10
  - bundle exec rspec
8
11
 
@@ -26,6 +29,14 @@ matrix:
26
29
  gemfile: "gemfiles/Rails-4.1.gemfile"
27
30
  - rvm: "2.2"
28
31
  gemfile: "gemfiles/Rails-4.0.gemfile"
32
+ - rvm: "2.4"
33
+ gemfile: "gemfiles/Rails-5.1.gemfile"
34
+ env:
35
+ - WITHOUT_ACTIVE_RECORD: "1"
36
+ - rvm: "2.4"
37
+ gemfile: "gemfiles/Rails-5.1.gemfile"
38
+ env:
39
+ - WITHOUT_MONGOID: "1"
29
40
 
30
41
  allow_failures:
31
42
  - rvm: "ruby-head"
data/CHANGELOG.adoc CHANGED
@@ -1,3 +1,10 @@
1
+ == Not released yet
2
+
3
+ == 0.2.0
4
+
5
+ * `AttrMasker::Maskers::Simple` is now a class
6
+ * Added support for Mongoid
7
+
1
8
  == 0.1.1
2
9
 
3
10
  * Mask records disregarding default scope
data/README.adoc CHANGED
@@ -6,13 +6,13 @@
6
6
  image:https://img.shields.io/gem/v/attr_masker.svg["Gem Version", link="https://rubygems.org/gems/attr_masker"]
7
7
  image:https://img.shields.io/travis/riboseinc/attr_masker/master.svg["Build Status", link="https://travis-ci.org/riboseinc/attr_masker"]
8
8
 
9
- Mask ActiveRecord data with ease!
9
+ Mask ActiveRecord/Mongoid data with ease!
10
10
 
11
11
  == Introduction
12
12
 
13
13
  This gem is intended to mask sensitive data so that production database dumps
14
- can be used in staging or test environments. It works with Active Record 4+
15
- and modern Rubies.
14
+ can be used in staging or test environments. It works with Rails 4+ and modern
15
+ Rubies. It supports Active Record and Mongoid models.
16
16
 
17
17
  == Getting started
18
18
 
@@ -76,7 +76,7 @@ gem to soft-delete your data, records marked as deleted will be masked as well.
76
76
 
77
77
  === Using custom maskers
78
78
 
79
- By default, data is maksed with `AttrMasker::Maskers::SIMPLE` masker which
79
+ By default, data is maksed with `AttrMasker::Maskers::Simple` masker which
80
80
  always returns `"(redacted)"` string. But anything what responds to `#call`
81
81
  can be used instead: a lambda, `Method` instance, and more. You can specify it
82
82
  by setting the `:masker` option.
@@ -100,7 +100,7 @@ customize masker's behaviour.
100
100
 
101
101
  Attr Masker comes with several built-in maskers.
102
102
 
103
- `AttrMasker::Maskers::SIMPLE`::
103
+ `AttrMasker::Maskers::Simple`::
104
104
  +
105
105
  Simply replaces any value with the `"(redacted)"`. Only useful for columns
106
106
  containing textual data.
@@ -112,7 +112,7 @@ Example:
112
112
  [source,ruby]
113
113
  ----
114
114
  attr_masker :first_name
115
- attr_masker :last_name, :masker => AttrMasker::Maskers::SIMPLE
115
+ attr_masker :last_name, :masker => AttrMasker::Maskers::Simple.new
116
116
  ----
117
117
  +
118
118
  Would set both `first_name` and `last_name` attributes to `"(redacted)"`.
data/attr_masker.gemspec CHANGED
@@ -27,6 +27,8 @@ Gem::Specification.new do |gem|
27
27
  gem.add_development_dependency("bundler", "~> 1.15")
28
28
  gem.add_development_dependency("combustion", "~> 0.7.0")
29
29
  gem.add_development_dependency("database_cleaner", "~> 1.6")
30
+ # Older versions aren't needed as we don't support Rails < 4
31
+ gem.add_development_dependency("mongoid", ">= 5")
30
32
  gem.add_development_dependency("pry")
31
33
  gem.add_development_dependency("rspec", ">= 3.0")
32
34
  gem.add_development_dependency("rubocop", "~> 0.49.1")
@@ -1,5 +1,3 @@
1
- source "https://rubygems.org"
1
+ eval File.read "gemfiles/common.gemfile"
2
2
 
3
3
  gem "activerecord", "~> 4.0.0"
4
-
5
- gemspec path: ".."
@@ -1,5 +1,3 @@
1
- source "https://rubygems.org"
1
+ eval File.read "gemfiles/common.gemfile"
2
2
 
3
3
  gem "activerecord", "~> 4.1.0"
4
-
5
- gemspec path: ".."
@@ -1,5 +1,3 @@
1
- source "https://rubygems.org"
1
+ eval File.read "gemfiles/common.gemfile"
2
2
 
3
3
  gem "activerecord", "~> 4.2.0"
4
-
5
- gemspec path: ".."
@@ -1,5 +1,3 @@
1
- source "https://rubygems.org"
1
+ eval File.read "gemfiles/common.gemfile"
2
2
 
3
3
  gem "activerecord", "~> 5.0.0"
4
-
5
- gemspec path: ".."
@@ -1,5 +1,3 @@
1
- source "https://rubygems.org"
1
+ eval File.read "gemfiles/common.gemfile"
2
2
 
3
3
  gem "activerecord", "~> 5.1.0"
4
-
5
- gemspec path: ".."
@@ -1,6 +1,4 @@
1
- source "https://rubygems.org"
1
+ eval File.read "gemfiles/common.gemfile"
2
2
 
3
3
  gem "activerecord", github: "rails/rails"
4
4
  gem "arel", github: "rails/arel"
5
-
6
- gemspec path: ".."
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec path: ".."
4
+
5
+ gem "mongoid", require: false
data/lib/attr_masker.rb CHANGED
@@ -12,7 +12,7 @@ module AttrMasker
12
12
 
13
13
  module Maskers
14
14
  autoload :Replacing, "attr_masker/maskers/replacing"
15
- autoload :SIMPLE, "attr_masker/maskers/simple"
15
+ autoload :Simple, "attr_masker/maskers/simple"
16
16
  end
17
17
 
18
18
  require "attr_masker/railtie" if defined?(Rails)
@@ -5,8 +5,10 @@ module AttrMasker
5
5
  # +opts+ is a Hash with the key :value that gives you the current attribute
6
6
  # value.
7
7
  #
8
- SIMPLE = lambda do |_opts|
9
- "(redacted)"
8
+ class Simple
9
+ def call(_opts)
10
+ "(redacted)"
11
+ end
10
12
  end
11
13
  end
12
14
  end
@@ -82,7 +82,7 @@ module AttrMasker
82
82
  marshaler: Marshal,
83
83
  dump_method: "dump",
84
84
  load_method: "load",
85
- masker: AttrMasker::Maskers::SIMPLE,
85
+ masker: AttrMasker::Maskers::Simple.new,
86
86
  }
87
87
 
88
88
  options = args.extract_options!.
@@ -2,12 +2,8 @@
2
2
  #
3
3
  module AttrMasker
4
4
  module Performer
5
- class ActiveRecord
5
+ class Base
6
6
  def mask
7
- unless defined? ::ActiveRecord
8
- raise AttrMasker::Error, "ActiveRecord undefined. Nothing to do!"
9
- end
10
-
11
7
  # Do not want production environment to be masked!
12
8
  #
13
9
  if Rails.env.production?
@@ -44,7 +40,7 @@ module AttrMasker
44
40
  acc.merge!(column_name => masker_value)
45
41
  end
46
42
 
47
- klass.all.unscoped.update(instance.id, updates)
43
+ make_update instance, updates unless updates.empty?
48
44
  end
49
45
 
50
46
  def progressbar_for_model(klass)
@@ -59,10 +55,34 @@ module AttrMasker
59
55
  ensure
60
56
  bar.finish
61
57
  end
58
+ end
59
+
60
+ class ActiveRecord < Base
61
+ def dependencies_available?
62
+ defined? ::ActiveRecord
63
+ end
62
64
 
63
65
  def all_models
64
66
  ::ActiveRecord::Base.descendants.select(&:table_exists?)
65
67
  end
68
+
69
+ def make_update(instance, updates)
70
+ instance.class.all.unscoped.update(instance.id, updates)
71
+ end
72
+ end
73
+
74
+ class Mongoid < Base
75
+ def dependencies_available?
76
+ defined? ::Mongoid
77
+ end
78
+
79
+ def all_models
80
+ ::Mongoid.models
81
+ end
82
+
83
+ def make_update(instance, updates)
84
+ instance.class.all.unscoped.where(id: instance.id).update(updates)
85
+ end
66
86
  end
67
87
  end
68
88
  end
@@ -5,8 +5,8 @@ module AttrMasker
5
5
  # Contains information about this gem's version
6
6
  module Version
7
7
  MAJOR = 0
8
- MINOR = 1
9
- PATCH = 1
8
+ MINOR = 2
9
+ PATCH = 0
10
10
 
11
11
  # Returns a version string by joining <tt>MAJOR</tt>, <tt>MINOR</tt>, and
12
12
  # <tt>PATCH</tt> with <tt>'.'</tt>
data/lib/tasks/db.rake CHANGED
@@ -16,6 +16,13 @@ namespace :db do
16
16
  # http://stackoverflow.com/questions/14163938/activerecordconnectionnotestablished-within-a-rake-task
17
17
  #
18
18
  task :mask => :environment do
19
- AttrMasker::Performer::ActiveRecord.new.mask
19
+ performers = AttrMasker::Performer::Base.descendants.map(&:new)
20
+ performers.select!(&:dependencies_available?)
21
+
22
+ if performers.empty?
23
+ raise AttrMasker::Error, "No supported database!"
24
+ end
25
+
26
+ performers.each(&:mask)
20
27
  end
21
28
  end
@@ -0,0 +1,33 @@
1
+ # Heavily based on Mongoid's test suite
2
+ # https://github.com/mongodb/mongoid/blob/v6.2.0/spec/config/mongoid.yml
3
+ test:
4
+ clients:
5
+ default:
6
+ database: attr_masker_test
7
+ hosts:
8
+ - <%=ENV["MONGOID_SPEC_HOST"]%>:<%=ENV["MONGOID_SPEC_PORT"]%>
9
+ options:
10
+ auth_source: "admin"
11
+ read:
12
+ mode: :primary_preferred
13
+ tag_sets:
14
+ - use: web
15
+ max_pool_size: 1
16
+ reports:
17
+ database: reports
18
+ hosts:
19
+ - <%=ENV["MONGOID_SPEC_HOST"]%>:<%=ENV["MONGOID_SPEC_PORT"]%>
20
+ options:
21
+ user: "mongoid-user"
22
+ password: "password"
23
+ auth_source: "admin"
24
+ options:
25
+ include_root_in_json: false
26
+ include_type_for_serialization: false
27
+ preload_models: false
28
+ scope_overwrite_exception: false
29
+ raise_not_found_error: true
30
+ use_activesupport_time_zone: true
31
+ use_utc: false
32
+ log_level: :warn
33
+ app_name: 'testing'
@@ -0,0 +1,28 @@
1
+ # (c) 2017 Ribose Inc.
2
+ #
3
+
4
+ # No point in using ApplicationRecord here.
5
+ # rubocop:disable Rails/ApplicationRecord
6
+
7
+ require_relative "shared_examples"
8
+
9
+ RSpec.describe "Attr Masker gem", :suppress_progressbar do
10
+ context "when used with ActiveRecord" do
11
+ before do
12
+ if ENV["WITHOUT_ACTIVE_RECORD"]
13
+ expect(defined?(::ActiveRecord)).to be(nil)
14
+ skip "Active Record specs disabled with WITHOUT_ACTIVE_RECORD shell " \
15
+ "variable"
16
+ end
17
+ end
18
+
19
+ before do
20
+ allow(ActiveRecord::Base).to receive(:descendants).
21
+ and_return([ActiveRecord::SchemaMigration, user_class_definition])
22
+ end
23
+
24
+ let(:user_class_definition) { Class.new(ActiveRecord::Base) }
25
+
26
+ include_examples "Attr Masker gem feature specs"
27
+ end
28
+ end
@@ -0,0 +1,36 @@
1
+ # (c) 2017 Ribose Inc.
2
+ #
3
+
4
+ require_relative "shared_examples"
5
+
6
+ RSpec.describe "Attr Masker gem", :suppress_progressbar do
7
+ context "when used with Mongoid" do
8
+ before do
9
+ if ENV["WITHOUT_MONGOID"]
10
+ expect(defined?(::Mongoid)).to be(nil)
11
+ skip "Mongoid specs disabled with WITHOUT_MONGOID shell variable"
12
+ end
13
+ end
14
+
15
+ after do
16
+ # Remove the example-specific model from Mongoid.models
17
+ ::Mongoid.models.delete(user_class_definition)
18
+ end
19
+
20
+ let(:user_class_definition) do
21
+ Class.new do
22
+ include Mongoid::Document
23
+ include Mongoid::Timestamps
24
+
25
+ store_in collection: "users"
26
+
27
+ field :first_name
28
+ field :last_name
29
+ field :email
30
+ field :avatar
31
+ end
32
+ end
33
+
34
+ include_examples "Attr Masker gem feature specs"
35
+ end
36
+ end
@@ -1,26 +1,20 @@
1
1
  # (c) 2017 Ribose Inc.
2
2
  #
3
3
 
4
- # No point in using ApplicationRecord here.
5
- # rubocop:disable Rails/ApplicationRecord
6
-
7
4
  # No point in ensuring a trailing comma in multiline argument lists here.
8
5
  # rubocop:disable Style/TrailingCommaInArguments
9
6
 
10
7
  require "spec_helper"
11
8
 
12
- RSpec.describe "Attr Masker gem", :suppress_progressbar do
9
+ RSpec.shared_examples "Attr Masker gem feature specs" do
13
10
  before do
14
- stub_const "User", Class.new(ActiveRecord::Base)
11
+ stub_const "User", user_class_definition
15
12
 
16
13
  User.class_eval do
17
14
  def jedi?
18
15
  email.ends_with? "@jedi.example.test"
19
16
  end
20
17
  end
21
-
22
- allow(ActiveRecord::Base).to receive(:descendants).
23
- and_return([ActiveRecord::SchemaMigration, User])
24
18
  end
25
19
 
26
20
  let!(:han) do
data/spec/spec_helper.rb CHANGED
@@ -4,7 +4,7 @@
4
4
  require "bundler"
5
5
  Bundler.require :default, :development
6
6
 
7
- Dir[File.expand_path "../support/**/*.rb", __FILE__].each { |f| require f }
7
+ Dir[File.expand_path "../support/**/*.rb", __FILE__].sort.each { |f| require f }
8
8
 
9
9
  RSpec.configure do |config|
10
10
  # Enable flags like --only-failures and --next-failure
@@ -17,5 +17,3 @@ RSpec.configure do |config|
17
17
  c.syntax = :expect
18
18
  end
19
19
  end
20
-
21
- require "rails/all"
@@ -0,0 +1,9 @@
1
+ # Copied from Mongoid's test suite
2
+ # https://github.com/mongodb/mongoid/blob/v6.2.0/spec/spec_helper.rb
3
+
4
+ # These environment variables can be set if wanting to test against a database
5
+ # that is not on the local machine.
6
+ ENV["MONGOID_SPEC_HOST"] ||= "127.0.0.1"
7
+ ENV["MONGOID_SPEC_PORT"] ||= "27017"
8
+
9
+ require "mongoid" unless ENV["WITHOUT_MONGOID"]
@@ -0,0 +1,10 @@
1
+ # (c) 2017 Ribose Inc.
2
+ #
3
+
4
+ Combustion.path = "spec/dummy"
5
+
6
+ if ENV["WITHOUT_ACTIVE_RECORD"].nil?
7
+ Combustion.initialize! :active_record
8
+ else
9
+ Combustion.initialize!
10
+ end
@@ -2,9 +2,18 @@ require "database_cleaner"
2
2
 
3
3
  RSpec.configure do |config|
4
4
  config.before(:suite) do
5
- DatabaseCleaner.clean_with(:truncation)
5
+ unless ENV["WITHOUT_ACTIVE_RECORD"]
6
+ DatabaseCleaner[:active_record].strategy = :truncation
7
+ end
6
8
 
7
- DatabaseCleaner.strategy = :truncation
9
+ # Since models are defined dynamically in specs, Database Cleaner is unable
10
+ # to list them and to determine collection names to be cleaned.
11
+ # Therefore, they are specified explicitly here.
12
+ unless ENV["WITHOUT_MONGOID"]
13
+ DatabaseCleaner[:mongoid].strategy = :truncation, { only: "users" }
14
+ end
15
+
16
+ DatabaseCleaner.clean_with(:truncation)
8
17
  end
9
18
 
10
19
  config.around(:each) do |example|
@@ -5,8 +5,8 @@
5
5
 
6
6
  require "spec_helper"
7
7
 
8
- RSpec.describe AttrMasker::Maskers::SIMPLE do
9
- subject { described_class }
8
+ RSpec.describe AttrMasker::Maskers::Simple do
9
+ subject { described_class.new }
10
10
 
11
11
  example { expect(subject.(value: "Solo")).to eq("(redacted)") }
12
12
  example { expect(subject.(value: Math::PI)).to eq("(redacted)") }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attr_masker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-07 00:00:00.000000000 Z
11
+ date: 2017-09-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -86,6 +86,20 @@ dependencies:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
88
  version: '1.6'
89
+ - !ruby/object:Gem::Dependency
90
+ name: mongoid
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '5'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '5'
89
103
  - !ruby/object:Gem::Dependency
90
104
  name: pry
91
105
  requirement: !ruby/object:Gem::Requirement
@@ -169,6 +183,7 @@ files:
169
183
  - gemfiles/Rails-5.0.gemfile
170
184
  - gemfiles/Rails-5.1.gemfile
171
185
  - gemfiles/Rails-head.gemfile
186
+ - gemfiles/common.gemfile
172
187
  - lib/attr_masker.rb
173
188
  - lib/attr_masker/attribute.rb
174
189
  - lib/attr_masker/error.rb
@@ -180,12 +195,16 @@ files:
180
195
  - lib/attr_masker/version.rb
181
196
  - lib/tasks/db.rake
182
197
  - spec/dummy/config/database.yml
198
+ - spec/dummy/config/mongoid.yml
183
199
  - spec/dummy/config/routes.rb
184
200
  - spec/dummy/db/schema.rb
185
201
  - spec/dummy/public/favicon.ico
186
- - spec/features_spec.rb
202
+ - spec/features/active_record_spec.rb
203
+ - spec/features/mongoid_spec.rb
204
+ - spec/features/shared_examples.rb
187
205
  - spec/spec_helper.rb
188
- - spec/support/0_combustion.rb
206
+ - spec/support/00_mongoid_env.rb
207
+ - spec/support/20_combustion.rb
189
208
  - spec/support/db_cleaner.rb
190
209
  - spec/support/matchers.rb
191
210
  - spec/support/rake.rb
@@ -220,12 +239,16 @@ specification_version: 4
220
239
  summary: Masking attributes
221
240
  test_files:
222
241
  - spec/dummy/config/database.yml
242
+ - spec/dummy/config/mongoid.yml
223
243
  - spec/dummy/config/routes.rb
224
244
  - spec/dummy/db/schema.rb
225
245
  - spec/dummy/public/favicon.ico
226
- - spec/features_spec.rb
246
+ - spec/features/active_record_spec.rb
247
+ - spec/features/mongoid_spec.rb
248
+ - spec/features/shared_examples.rb
227
249
  - spec/spec_helper.rb
228
- - spec/support/0_combustion.rb
250
+ - spec/support/00_mongoid_env.rb
251
+ - spec/support/20_combustion.rb
229
252
  - spec/support/db_cleaner.rb
230
253
  - spec/support/matchers.rb
231
254
  - spec/support/rake.rb
@@ -1,5 +0,0 @@
1
- # (c) 2017 Ribose Inc.
2
- #
3
-
4
- Combustion.path = "spec/dummy"
5
- Combustion.initialize! :all