redaction 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +130 -0
- data/Rakefile +5 -0
- data/lib/redaction/railtie.rb +13 -0
- data/lib/redaction/redactable.rb +44 -0
- data/lib/redaction/redactor.rb +46 -0
- data/lib/redaction/types/base.rb +20 -0
- data/lib/redaction/types/basic.rb +11 -0
- data/lib/redaction/types/basic_html.rb +14 -0
- data/lib/redaction/types/email.rb +11 -0
- data/lib/redaction/types/html.rb +44 -0
- data/lib/redaction/types/name.rb +11 -0
- data/lib/redaction/types/phone.rb +13 -0
- data/lib/redaction/types/text.rb +15 -0
- data/lib/redaction/version.rb +3 -0
- data/lib/redaction.rb +34 -0
- data/lib/tasks/redaction.rake +15 -0
- metadata +133 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8111bc43a6fc2d4dbd6224b80664d7410bf62780c6d609b5532c9043ee3032fa
|
4
|
+
data.tar.gz: 8ab8dcfa4d70432f19c179eb77e4f9093a12b1f8261c7aad1fe0800e372bda30
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d2479196f571dfc27a21f48147d488b08140eaa4afa0821467d0d5d04b4b3f9ae3295c8db4b316d70fe7be39848de8925a6ebb84cc5533deed1c6171ddf79e14
|
7
|
+
data.tar.gz: 135321f897acb08d60cac36b3c8413ea9bd2c42280cee09bc30ac9ee999099009c7c4f8d735c128f8b1326e64d9beac1107e8d959748ea36eaba956373a9abb2
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2022 Drew Bragg
|
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,130 @@
|
|
1
|
+
# Redaction
|
2
|
+
[![Tests](https://github.com/DRBragg/redaction/actions/workflows/ci.yml/badge.svg)](https://github.com/DRBragg/redaction/actions/workflows/ci.yml)
|
3
|
+
|
4
|
+
Easily redact your ActiveRecord Models. Great for use when you use production data in staging or dev. Simply set the redaction type of the attributes you want to redact and run via the [console](#via-the-rails-console) or the included [rake task](#via-rake-task).
|
5
|
+
|
6
|
+
`redaction` uses [Faker](https://github.com/faker-ruby/faker) under the hood to generate redacted data.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
**NOTE:** This is currently an unreleased library very much in beta. Use at your own risk.
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem "redaction", git: "https://github.com/drbragg/redaction.git"
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
```bash
|
19
|
+
$ bundle
|
20
|
+
```
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
### Redacting a Model
|
24
|
+
To "redact" a models attribute add:
|
25
|
+
```ruby
|
26
|
+
class Model < ApplicationRecord
|
27
|
+
redacts :<attribute>, with: :<redactor_type>
|
28
|
+
end
|
29
|
+
```
|
30
|
+
`<redactor_type>` can be a symbol, proc, or custom class. See [Redactor Types](#redactor-types) for more information.
|
31
|
+
|
32
|
+
`redacts` accepts multiple attributes, provided they all use the same redactor type. i.e.:
|
33
|
+
```ruby
|
34
|
+
class User < ApplicationRecord
|
35
|
+
redacts :first_name, :last_name, with: :name
|
36
|
+
end
|
37
|
+
```
|
38
|
+
### Redactor Types
|
39
|
+
|
40
|
+
#### Built in
|
41
|
+
`redaction` comes with a few different redactor types:
|
42
|
+
| Type | Generates |
|
43
|
+
|:------------:|:------------:|
|
44
|
+
| `:basic` | A Sentence |
|
45
|
+
| `:basic_html`| An HTML snippet with `strong` and `em` tags wrapping some of the words |
|
46
|
+
| `:email` | A safe (will not send) email address |
|
47
|
+
| `:html` | Multiple HTML Paragraphs with a random amount of link tags, `strong` tags, and `em` tags |
|
48
|
+
| `:name` | A person first/last name |
|
49
|
+
| `:phone` | A phone number |
|
50
|
+
| `:text` | Multiple paragraphs |
|
51
|
+
|
52
|
+
To use a built in redactor type set the `with:` option of a `redacts` call to the appropriate symbol.
|
53
|
+
|
54
|
+
#### Using a Proc
|
55
|
+
A Proc `:with` value is given two arguments: the record being redacted, and a hash with the :attribute key-value pair.
|
56
|
+
```ruby
|
57
|
+
class Model < ApplicationRecord
|
58
|
+
redacts :attribute, with: -> (record, data) { record.id }
|
59
|
+
end
|
60
|
+
```
|
61
|
+
would cause `Model#attribute` to be set to `Model#id` after redaction
|
62
|
+
#### Using a custom class
|
63
|
+
Add a folder in `app/`, `redactors/` is suggested, and put custom redactors in there. A custom redactor should inherit from `Redaction::Types::Base` and should define a `content` method. Like so:
|
64
|
+
```ruby
|
65
|
+
# app/redactors/custom_redactor.rb
|
66
|
+
class CustomRedactor < Redaction::Types::Base
|
67
|
+
def content
|
68
|
+
"Some Custom Value"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
```
|
72
|
+
and then to use it:
|
73
|
+
```ruby
|
74
|
+
class Model < ApplicationRecord
|
75
|
+
redacts :attribute, with: CustomRedactor
|
76
|
+
end
|
77
|
+
```
|
78
|
+
would cause `Model#attribute` to be set to "Some Custom Value" after redaction.
|
79
|
+
Custom redactor types also get access to the record being redacted via `record`, and a hash with the `:attribute` key-value pair via `data`
|
80
|
+
|
81
|
+
### Preforming a Redaction
|
82
|
+
There are two ways to preform the redaction.
|
83
|
+
|
84
|
+
#### Via Rake Task
|
85
|
+
```bash
|
86
|
+
rails redaction:redact
|
87
|
+
```
|
88
|
+
This will target **all** the models with redacted attributes. To target specific models run:
|
89
|
+
```bash
|
90
|
+
rails redaction:redact MODELS=User,Post
|
91
|
+
```
|
92
|
+
This will only redact the `User` and `Post` Models
|
93
|
+
|
94
|
+
#### Via the Rails Console
|
95
|
+
```ruby
|
96
|
+
Redaction.redact!
|
97
|
+
```
|
98
|
+
This will target **all** the models with redacted attributes. To target specific models run:
|
99
|
+
```ruby
|
100
|
+
Redaction.redact!(models: ["User", "Post"])
|
101
|
+
```
|
102
|
+
This will only redact the `User` and `Post` Models
|
103
|
+
|
104
|
+
#### Validations and Callbacks
|
105
|
+
By default, preforming a redaction does not trigger validations or update the `updated_at` attribute.
|
106
|
+
|
107
|
+
Callbacks can be skipped with the `:redacting?` method. i.e.:
|
108
|
+
```ruby
|
109
|
+
class User < ApplicationRecord
|
110
|
+
after_save :do_something, unless: :redacting?
|
111
|
+
|
112
|
+
redacts :first_name, :last_name, with: :name
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
## Roadmap
|
117
|
+
- [ ] Raise Error or at least a message when skipping a passed in Model
|
118
|
+
- [ ] Configuration (touch, email domains, etc)
|
119
|
+
- [ ] Better Documentation
|
120
|
+
- [ ] More types
|
121
|
+
- [ ] Release v1.0 as a real gem
|
122
|
+
|
123
|
+
## Contributing
|
124
|
+
Bug reports and pull requests are welcome on GitHub at [drbragg/redaction](https://github.com/drbragg/redaction). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/DRBragg/redaction/blob/main/CODE_OF_CONDUCT.md).
|
125
|
+
|
126
|
+
## License
|
127
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
128
|
+
|
129
|
+
## Acknowledgments
|
130
|
+
`redaction` leans heavily on the awesome [Faker gem](https://github.com/faker-ruby/faker). If not for their hard work this would be a much different and probably more complex project. If you like `redaction` please consider sending them a thank you or contributing to the gem.
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
module Redaction
|
2
|
+
module Redactable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
class_attribute :redacted_attributes, instance_writer: false
|
7
|
+
|
8
|
+
after_commit do
|
9
|
+
@_redacting = false
|
10
|
+
end
|
11
|
+
|
12
|
+
def redact!
|
13
|
+
@_redacting = true
|
14
|
+
redacted_attributes.each_pair do |redactor_type, attributes|
|
15
|
+
redactor = Redaction.find(redactor_type)
|
16
|
+
|
17
|
+
attributes.each do |attribute|
|
18
|
+
if send(attribute).present?
|
19
|
+
send("#{attribute}=", redactor.call(self, {attribute: attribute}))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
save!(validate: false, touch: false, context: :redaction)
|
25
|
+
end
|
26
|
+
|
27
|
+
def redacting?
|
28
|
+
!!@_redacting
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class_methods do
|
33
|
+
def redacts(*attributes, with: :basic)
|
34
|
+
self.redacted_attributes ||= Hash.new { |hash, key| hash[key] = [] }
|
35
|
+
|
36
|
+
self.redacted_attributes[with] += attributes
|
37
|
+
end
|
38
|
+
|
39
|
+
def has_redacted_content?
|
40
|
+
self.redacted_attributes&.any?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "ruby-progressbar"
|
2
|
+
|
3
|
+
module Redaction
|
4
|
+
class Redactor
|
5
|
+
attr_reader :models_to_redact
|
6
|
+
|
7
|
+
def initialize(models: nil)
|
8
|
+
@models_to_redact = set_models(models)
|
9
|
+
end
|
10
|
+
|
11
|
+
def redact!
|
12
|
+
models_to_redact.each do |model|
|
13
|
+
next if model.redacted_attributes.empty?
|
14
|
+
|
15
|
+
model_progress = progress_bar(model.name, model.count)
|
16
|
+
|
17
|
+
model.all.unscoped.find_each do |record|
|
18
|
+
record.redact!
|
19
|
+
model_progress.increment
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def set_models(models)
|
27
|
+
if models.present?
|
28
|
+
models
|
29
|
+
.map { |model| model.constantize }
|
30
|
+
.select { |model| model.has_redacted_content? }
|
31
|
+
else
|
32
|
+
Redaction.redactable_models
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def progress_bar(title, total)
|
37
|
+
ProgressBar.create(
|
38
|
+
format: "%t %b\u{15E7}%i %p%%",
|
39
|
+
progress_mark: " ",
|
40
|
+
remainder_mark: "\u{FF65}",
|
41
|
+
title: title,
|
42
|
+
total: total
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Redaction
|
2
|
+
module Types
|
3
|
+
class Base
|
4
|
+
attr_reader :record, :data
|
5
|
+
|
6
|
+
def self.call(record, data)
|
7
|
+
new(record, data).content
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(record, data)
|
11
|
+
@record = record
|
12
|
+
@data = data
|
13
|
+
end
|
14
|
+
|
15
|
+
def content
|
16
|
+
"[REDACTED]"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "faker"
|
2
|
+
|
3
|
+
module Redaction
|
4
|
+
module Types
|
5
|
+
class BasicHtml < Base
|
6
|
+
def content
|
7
|
+
[nil, "em", "strong"].shuffle.map! do |tag|
|
8
|
+
text = Faker::Lorem.sentence(word_count: rand(1..3)).sub(/\.$/, "")
|
9
|
+
tag ? "<#{tag}>#{text}</#{tag}>" : text
|
10
|
+
end.join(" ")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "faker"
|
2
|
+
|
3
|
+
module Redaction
|
4
|
+
module Types
|
5
|
+
class Html < Base
|
6
|
+
include ActionView::Helpers::TagHelper
|
7
|
+
|
8
|
+
TAGS = %i[em strong a]
|
9
|
+
private_constant :TAGS
|
10
|
+
|
11
|
+
def content
|
12
|
+
1.upto(rand(1..3)).map { content_tag(:p, generate_paragraph.html_safe) }.join("\n")
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def generate_paragraph
|
18
|
+
sentences = Faker::Lorem.sentences(number: rand(1..5)).map! do |sentence|
|
19
|
+
words = sentence.split(/\s+/)
|
20
|
+
|
21
|
+
words.map! do |word|
|
22
|
+
case rand(10)
|
23
|
+
when 0, 1, 2
|
24
|
+
create_html_word(word)
|
25
|
+
else
|
26
|
+
word
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
words.join(" ")
|
31
|
+
end
|
32
|
+
|
33
|
+
sentences.join(" ")
|
34
|
+
end
|
35
|
+
|
36
|
+
def create_html_word(word)
|
37
|
+
tag = TAGS.sample
|
38
|
+
options = tag == :a ? {href: "http://example.com"} : {}
|
39
|
+
|
40
|
+
content_tag(tag, word, options)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "faker"
|
2
|
+
|
3
|
+
module Redaction
|
4
|
+
module Types
|
5
|
+
class Phone < Base
|
6
|
+
def content
|
7
|
+
# Use cell_phone so no extension is added
|
8
|
+
# see: https://github.com/faker-ruby/faker/blob/master/doc/default/phone_number.md
|
9
|
+
Faker::PhoneNumber.cell_phone
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/redaction.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require "redaction/version"
|
2
|
+
require "redaction/railtie"
|
3
|
+
|
4
|
+
module Redaction
|
5
|
+
module Types
|
6
|
+
autoload :Base, "redaction/types/base"
|
7
|
+
autoload :Basic, "redaction/types/basic"
|
8
|
+
autoload :BasicHtml, "redaction/types/basic_html"
|
9
|
+
autoload :Email, "redaction/types/email"
|
10
|
+
autoload :Html, "redaction/types/html"
|
11
|
+
autoload :Name, "redaction/types/name"
|
12
|
+
autoload :Phone, "redaction/types/phone"
|
13
|
+
autoload :Text, "redaction/types/text"
|
14
|
+
end
|
15
|
+
|
16
|
+
autoload :Redactable, "redaction/redactable"
|
17
|
+
autoload :Redactor, "redaction/redactor"
|
18
|
+
|
19
|
+
def self.find(redactor_type)
|
20
|
+
if redactor_type.respond_to?(:call)
|
21
|
+
redactor_type
|
22
|
+
else
|
23
|
+
"Redaction::Types::#{redactor_type.to_s.camelize}".safe_constantize || Redaction::Types::Base
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.redactable_models
|
28
|
+
ApplicationRecord.subclasses.select { |descendant| descendant.has_redacted_content? }
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.redact!(models: nil)
|
32
|
+
Redactor.new(models: models).redact!
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
namespace :redaction do
|
2
|
+
desc "Update Models with redacted data"
|
3
|
+
task redact: :environment do
|
4
|
+
if Rails.env.production?
|
5
|
+
abort "Cannot redact in production"
|
6
|
+
end
|
7
|
+
|
8
|
+
Rails.application.eager_load!
|
9
|
+
|
10
|
+
model_names = (ENV["MODELS"] || "").split(",").map(&:strip)
|
11
|
+
puts model_names.empty? ? "Redacting all models" : "Redacting models: #{model_names.join(", ")}"
|
12
|
+
|
13
|
+
Redaction.redact!(models: model_names)
|
14
|
+
end
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: redaction
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Drew Bragg
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-04-01 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: 5.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: 5.1.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faker
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: ruby-progressbar
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: standard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: appraisal
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Easily redact your ActiveRecord Models.
|
84
|
+
email:
|
85
|
+
- drbragg@hey.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- MIT-LICENSE
|
91
|
+
- README.md
|
92
|
+
- Rakefile
|
93
|
+
- lib/redaction.rb
|
94
|
+
- lib/redaction/railtie.rb
|
95
|
+
- lib/redaction/redactable.rb
|
96
|
+
- lib/redaction/redactor.rb
|
97
|
+
- lib/redaction/types/base.rb
|
98
|
+
- lib/redaction/types/basic.rb
|
99
|
+
- lib/redaction/types/basic_html.rb
|
100
|
+
- lib/redaction/types/email.rb
|
101
|
+
- lib/redaction/types/html.rb
|
102
|
+
- lib/redaction/types/name.rb
|
103
|
+
- lib/redaction/types/phone.rb
|
104
|
+
- lib/redaction/types/text.rb
|
105
|
+
- lib/redaction/version.rb
|
106
|
+
- lib/tasks/redaction.rake
|
107
|
+
homepage: https://github.com/drbragg/redaction
|
108
|
+
licenses:
|
109
|
+
- MIT
|
110
|
+
metadata:
|
111
|
+
homepage_uri: https://github.com/drbragg/redaction
|
112
|
+
source_code_uri: https://github.com/drbragg/redaction
|
113
|
+
changelog_uri: https://github.com/drbragg/redaction/blob/main/CHANGELOG.md
|
114
|
+
post_install_message:
|
115
|
+
rdoc_options: []
|
116
|
+
require_paths:
|
117
|
+
- lib
|
118
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
requirements: []
|
129
|
+
rubygems_version: 3.2.3
|
130
|
+
signing_key:
|
131
|
+
specification_version: 4
|
132
|
+
summary: Easily redact your ActiveRecord Models.
|
133
|
+
test_files: []
|