redacted_struct 1.0.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +24 -9
- data/.rubocop.yml +6 -0
- data/CHANGELOG.md +9 -0
- data/Gemfile +1 -0
- data/README.md +34 -1
- data/lib/redactable.rb +70 -0
- data/lib/redacted_data.rb +18 -0
- data/lib/redacted_struct.rb +6 -25
- metadata +9 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84097ef8bb895a91b3d17f35daee43dd9e6b4d0a677c25bf4bd9c82962aba823
|
4
|
+
data.tar.gz: 3c7c5c3328485f20e92b23e9ae2f221eab868830b6efecab27ddd08221bae014
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6bc81b2aa8cf0abcaa1b69b1f748443d60d35778ce08635076f27010a37c897652fd1a154d635d72f076958a74dd3203bd7525d7e3240a432c30d99d26b6c7a
|
7
|
+
data.tar.gz: 44c61acc111af1b2ce4310fcf6e44001bbc96ccbd18eedb055f6a9d87e1bbec8ca8ea26673400b30217218531a614bd8bfe7b9b88b9f4815e284387f211b6406
|
data/.circleci/config.yml
CHANGED
@@ -1,18 +1,33 @@
|
|
1
1
|
version: 2.1
|
2
2
|
orbs:
|
3
|
-
ruby: circleci/ruby@
|
3
|
+
ruby: circleci/ruby@1.1
|
4
4
|
|
5
5
|
jobs:
|
6
|
-
|
6
|
+
test:
|
7
|
+
parameters:
|
8
|
+
ruby-version:
|
9
|
+
type: string
|
7
10
|
docker:
|
8
|
-
- image: cimg/ruby
|
9
|
-
executor: ruby/default
|
11
|
+
- image: cimg/ruby:<< parameters.ruby-version >>
|
10
12
|
steps:
|
11
13
|
- checkout
|
12
14
|
- run:
|
13
|
-
name:
|
14
|
-
|
15
|
-
|
15
|
+
name: "Add platform for Bundler"
|
16
|
+
description: "Normally the platforms lives in Gemfile.lock, but as a gem this repo does not have one, CircleCI fails if there are no platforms"
|
17
|
+
command: bundle lock --add-platform x86_64-linux
|
18
|
+
- ruby/install-deps:
|
19
|
+
bundler-version: '1.17.2'
|
20
|
+
with-cache: false
|
21
|
+
- ruby/rspec-test
|
16
22
|
- run:
|
17
|
-
name:
|
18
|
-
command: bundle exec
|
23
|
+
name: Rubocop
|
24
|
+
command: bundle exec rubocop
|
25
|
+
|
26
|
+
workflows:
|
27
|
+
build_and_test:
|
28
|
+
jobs:
|
29
|
+
- test:
|
30
|
+
matrix:
|
31
|
+
parameters:
|
32
|
+
# https://github.com/CircleCI-Public/cimg-ruby
|
33
|
+
ruby-version: ["2.6", "3.1", "3.2"]
|
data/.rubocop.yml
CHANGED
@@ -23,6 +23,12 @@ Style/TrailingCommaInArguments:
|
|
23
23
|
Layout/LineLength:
|
24
24
|
Max: 120
|
25
25
|
|
26
|
+
# require "pp" in specs is flagged in Ruby 2.6 but not in other ones
|
27
|
+
# and doing a point disable gets a "unused lint" warning, so this is easier
|
28
|
+
# to disable here
|
29
|
+
Lint/RedundantRequireStatement:
|
30
|
+
Enabled: false
|
31
|
+
|
26
32
|
Metrics/BlockLength:
|
27
33
|
Exclude:
|
28
34
|
- "spec/**/*.rb"
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [2.0.0] - 2024-01-10
|
4
|
+
|
5
|
+
- Add support to redact `Data` objects
|
6
|
+
|
7
|
+
## [1.1.0] - 2021-03-24
|
8
|
+
|
9
|
+
- Override `Struct#pretty_print` to keep redacted fields redacted when
|
10
|
+
pretty-printing via `pp`
|
11
|
+
|
3
12
|
## [1.0.0] - 2021-03-24
|
4
13
|
|
5
14
|
- Initial release
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -8,14 +8,47 @@ Config = RedactedStruct.new(
|
|
8
8
|
:username,
|
9
9
|
:password,
|
10
10
|
:timeout,
|
11
|
+
:url,
|
11
12
|
keyword_init: true,
|
12
13
|
allowed_members: [:username, :timeout]
|
13
14
|
)
|
14
15
|
|
15
|
-
Config.new(username: 'example', password: 'secret', timeout: 5)
|
16
|
+
config = Config.new(username: 'example', password: 'secret', timeout: 5, url: 'https://example.com')
|
16
17
|
=> #<struct Config username="example" password=[REDACTED] timeout=5>
|
17
18
|
```
|
18
19
|
|
20
|
+
## Pretty-Printing
|
21
|
+
|
22
|
+
The struct will automatically redact itself when pretty-printed via `#pp`:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
require 'pp'
|
26
|
+
|
27
|
+
pp config
|
28
|
+
#<struct Config
|
29
|
+
username="example",
|
30
|
+
password=[REDACTED],
|
31
|
+
timeout=5,
|
32
|
+
url="https://example.com">
|
33
|
+
```
|
34
|
+
|
35
|
+
## RedactedData
|
36
|
+
|
37
|
+
Redaction is also supported for Ruby's built-in Data class:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
Config = RedactedData.define(
|
41
|
+
:username,
|
42
|
+
:password,
|
43
|
+
:timeout,
|
44
|
+
:url,
|
45
|
+
allowed_members: [:username, :timeout]
|
46
|
+
)
|
47
|
+
|
48
|
+
config = Config.new(username: 'example', password: 'secret', timeout: 5, url: 'https://example.com')
|
49
|
+
=> #<data Config username="example" password=[REDACTED] timeout=5>
|
50
|
+
```
|
51
|
+
|
19
52
|
## Installation
|
20
53
|
|
21
54
|
Add this line to your application's Gemfile:
|
data/lib/redactable.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# A module that adds redacted functionality to a class
|
4
|
+
module Redactable
|
5
|
+
def self.included(mod)
|
6
|
+
class << mod
|
7
|
+
attr_reader :allowed_members
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def inspect
|
12
|
+
name_or_nil = self.class.name ? " #{self.class.name}" : nil
|
13
|
+
|
14
|
+
members_h = to_h
|
15
|
+
attributes = members.map do |member|
|
16
|
+
if allowed_members.include?(member)
|
17
|
+
"#{member}=#{members_h[member].inspect}"
|
18
|
+
else
|
19
|
+
"#{member}=[REDACTED]"
|
20
|
+
end
|
21
|
+
end.join(" ")
|
22
|
+
|
23
|
+
"#<#{base_name_for_inspection}#{name_or_nil} #{attributes}>"
|
24
|
+
end
|
25
|
+
|
26
|
+
def allowed_members
|
27
|
+
self.class.allowed_members
|
28
|
+
end
|
29
|
+
|
30
|
+
# Overrides for pp
|
31
|
+
# See https://github.com/ruby/pp/blob/3d925b5688b8226f653127d990a8dce48bced5fe/lib/pp.rb#L379-L391
|
32
|
+
# rubocop:disable all
|
33
|
+
def pretty_print(q)
|
34
|
+
q.group(1, sprintf("#<%s %s", base_name_for_inspection, PP.mcall(self, Kernel, :class).name), '>') {
|
35
|
+
members_h = to_h
|
36
|
+
q.seplist(PP.mcall(self, base_type_for_pp, :members), lambda { q.text "," }) {|member|
|
37
|
+
q.breakable
|
38
|
+
q.text member.to_s
|
39
|
+
q.text '='
|
40
|
+
q.group(1) {
|
41
|
+
q.breakable ''
|
42
|
+
if allowed_members.include?(member)
|
43
|
+
q.pp members_h[member]
|
44
|
+
else
|
45
|
+
q.text "[REDACTED]"
|
46
|
+
end
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
end
|
51
|
+
# rubocop:enable all
|
52
|
+
|
53
|
+
alias_method :to_s, :inspect
|
54
|
+
|
55
|
+
def base_name_for_inspection
|
56
|
+
if is_a? Struct
|
57
|
+
"struct"
|
58
|
+
else
|
59
|
+
"data"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def base_type_for_pp
|
64
|
+
if is_a? Struct
|
65
|
+
Struct
|
66
|
+
else
|
67
|
+
Data
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Style/Documentation
|
4
|
+
# rubocop:disable Style/MultilineIfModifier
|
5
|
+
# A subclass of Data that redacts members by default, and can allow some to be printed
|
6
|
+
class RedactedData < Data
|
7
|
+
include Redactable
|
8
|
+
|
9
|
+
def self.define(*members, allowed_members: [], &block)
|
10
|
+
super(*members, &block).tap do |data_class|
|
11
|
+
data_class.class_eval do
|
12
|
+
@allowed_members = Array(allowed_members)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end if defined?(Data) && Data.respond_to?(:define)
|
17
|
+
# rubocop:enable Style/MultilineIfModifier
|
18
|
+
# rubocop:enable Style/Documentation
|
data/lib/redacted_struct.rb
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "./redactable"
|
4
|
+
require_relative "./redacted_data"
|
5
|
+
|
3
6
|
# A subclass of Struct that redacts members by default, and can allow some to be printed
|
4
7
|
class RedactedStruct < Struct
|
5
|
-
|
8
|
+
include Redactable
|
9
|
+
|
10
|
+
VERSION = "2.0.0"
|
6
11
|
|
7
12
|
def self.new(*name_and_members, keyword_init: nil, allowed_members: [], &block)
|
8
13
|
super(*name_and_members, keyword_init: keyword_init, &block).tap do |struct_class|
|
@@ -11,28 +16,4 @@ class RedactedStruct < Struct
|
|
11
16
|
end
|
12
17
|
end
|
13
18
|
end
|
14
|
-
|
15
|
-
class << self
|
16
|
-
attr_reader :allowed_members
|
17
|
-
end
|
18
|
-
|
19
|
-
def allowed_members
|
20
|
-
self.class.allowed_members
|
21
|
-
end
|
22
|
-
|
23
|
-
def inspect
|
24
|
-
name_or_nil = self.class.name ? " #{self.class.name}" : nil
|
25
|
-
|
26
|
-
attributes = members.map do |member|
|
27
|
-
if allowed_members.include?(member)
|
28
|
-
"#{member}=#{self[member].inspect}"
|
29
|
-
else
|
30
|
-
"#{member}=[REDACTED]"
|
31
|
-
end
|
32
|
-
end.join(" ")
|
33
|
-
|
34
|
-
"#<struct#{name_or_nil} #{attributes}>"
|
35
|
-
end
|
36
|
-
|
37
|
-
alias_method :to_s, :inspect
|
38
19
|
end
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redacted_struct
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zach Margolis
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-10 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Help prevent logging sensitive information by accident
|
14
|
-
email:
|
14
|
+
email:
|
15
15
|
executables: []
|
16
16
|
extensions: []
|
17
17
|
extra_rdoc_files: []
|
@@ -26,6 +26,8 @@ files:
|
|
26
26
|
- Rakefile
|
27
27
|
- bin/console
|
28
28
|
- bin/setup
|
29
|
+
- lib/redactable.rb
|
30
|
+
- lib/redacted_data.rb
|
29
31
|
- lib/redacted_struct.rb
|
30
32
|
- redacted_struct.gemspec
|
31
33
|
homepage: https://github.com/zachmargolis/redacted_struct
|
@@ -34,7 +36,7 @@ metadata:
|
|
34
36
|
homepage_uri: https://github.com/zachmargolis/redacted_struct
|
35
37
|
source_code_uri: https://github.com/zachmargolis/redacted_struct
|
36
38
|
changelog_uri: https://github.com/zachmargolis/redacted_struct/blob/main/CHANGELOG.md
|
37
|
-
post_install_message:
|
39
|
+
post_install_message:
|
38
40
|
rdoc_options: []
|
39
41
|
require_paths:
|
40
42
|
- lib
|
@@ -49,8 +51,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
49
51
|
- !ruby/object:Gem::Version
|
50
52
|
version: '0'
|
51
53
|
requirements: []
|
52
|
-
rubygems_version: 3.
|
53
|
-
signing_key:
|
54
|
+
rubygems_version: 3.4.6
|
55
|
+
signing_key:
|
54
56
|
specification_version: 4
|
55
57
|
summary: A Ruby Struct that can be redacted
|
56
58
|
test_files: []
|