Module: Exwiw::DefaultMask
- Defined in:
- lib/exwiw/default_mask.rb
Overview
The replace_with value safe mode attaches to a newly discovered column.
Only types a constant can safely stand in for are masked: a default the
column cannot hold would fail the restore the dump feeds, which is worse
than exporting the column while its needs_mask_decision flag keeps the
change from being merged.
Constant Summary collapse
- FIXED_DATE =
"2000-01-01"- FIXED_TIME =
"2000-01-01 00:00:00"- EMPTY_JSON =
"{}"- JSON_TYPES =
%i[json jsonb].freeze
- MIN_TEXT_LIMIT =
Skip the mask when the column is too short to hold
masked-<primary key>for a realistic key; the rendered length is only known per row at dump time. 20- MIN_EMAIL_LIMIT =
40
Class Method Summary collapse
-
.constant_mask(type, column_default) ⇒ Object
The column's own default wins over the per-type constant: it is a value the column provably holds and the one the application treats as neutral, so masking a
default: trueflag does not turn the feature off for every row. -
.default_value(type, value) ⇒ Object
The default as a mask value, or nil when it cannot be one.
-
.for(name:, type:, limit:, primary_key:, array: false, unique: false, column_default: nil) ⇒ Object
The default mask for a column, or nil when no safe constant fits it.
- .scalar_default(value) ⇒ Object
- .text_mask(name, limit, primary_key) ⇒ Object
- .varies_per_row?(mask, primary_key) ⇒ Boolean
Class Method Details
.constant_mask(type, column_default) ⇒ Object
The column's own default wins over the per-type constant: it is a value the
column provably holds and the one the application treats as neutral, so
masking a default: true flag does not turn the feature off for every row.
A default the database computes (now()) arrives as nil and falls through.
48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/exwiw/default_mask.rb', line 48 def constant_mask(type, column_default) from_default = default_value(type, column_default) return from_default unless from_default.nil? case type when :integer, :decimal, :float then 0 when :boolean then false when :date then FIXED_DATE when :datetime, :timestamp, :time then FIXED_TIME when :json, :jsonb then EMPTY_JSON end end |
.default_value(type, value) ⇒ Object
The default as a mask value, or nil when it cannot be one. A JSON column's default is serialized as JSON whatever Ruby class it arrives as, so a string default keeps its quoting. Anything whose JSON contains an object is rejected rather than mis-parsed, so an array of objects falls back to the empty-JSON constant too.
66 67 68 69 70 71 72 73 |
# File 'lib/exwiw/default_mask.rb', line 66 def default_value(type, value) return nil if value.nil? mask = JSON_TYPES.include?(type) ? value.to_json : scalar_default(value) return nil if mask.is_a?(String) && mask.match?(MaskValue::PLACEHOLDER) mask end |
.for(name:, type:, limit:, primary_key:, array: false, unique: false, column_default: nil) ⇒ Object
The default mask for a column, or nil when no safe constant fits it.
primary_key is what keeps a text mask unique per row, so without one text
is left unmasked too. Under a unique index (unique) only a mask that
varies per row is allowed, or every row would collide on restore.
29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/exwiw/default_mask.rb', line 29 def for(name:, type:, limit:, primary_key:, array: false, unique: false, column_default: nil) return nil if array mask = case type when :string, :text then text_mask(name, limit, primary_key) else constant_mask(type, column_default) end return nil if mask.nil? return nil if unique && !varies_per_row?(mask, primary_key) mask end |
.scalar_default(value) ⇒ Object
75 76 77 78 79 80 81 82 83 84 |
# File 'lib/exwiw/default_mask.rb', line 75 def scalar_default(value) case value when nil then nil when true, false, Integer, Float, String then value when Numeric then value.to_f when Time, DateTime then value.strftime("%Y-%m-%d %H:%M:%S") when Date then value.strftime("%Y-%m-%d") when Hash, Array then value.to_json end end |
.text_mask(name, limit, primary_key) ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/exwiw/default_mask.rb', line 86 def text_mask(name, limit, primary_key) return nil if primary_key.nil? if name.to_s.include?("mail") return nil if limit && limit < MIN_EMAIL_LIMIT "masked-{#{primary_key}}@example.com" else return nil if limit && limit < MIN_TEXT_LIMIT "masked-{#{primary_key}}" end end |
.varies_per_row?(mask, primary_key) ⇒ Boolean
100 101 102 |
# File 'lib/exwiw/default_mask.rb', line 100 def varies_per_row?(mask, primary_key) mask.is_a?(String) && mask.include?("{#{primary_key}}") end |