credit_card_sanitizer 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/credit_card_sanitizer.rb +36 -28
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 98bf84c263cd302f4adb4cad41dbde01d048d979
4
- data.tar.gz: 38ce9eb0baa8c4882bb100bbd5cd6ddfe402c99b
3
+ metadata.gz: a6d9bf9f31799627015af93b4bc5101cf28cfadc
4
+ data.tar.gz: 501db783e84aaf980694e9e27ff6bb0a3ecee9de
5
5
  SHA512:
6
- metadata.gz: 0eca7811cd6c6c822e1d6c3bf3ba7a00af4fd61f099da469b1b130344067885b4a27ec0c67116852113a289333a7827308882aead6a4dba4399d3e5e7b1acffa
7
- data.tar.gz: e214f6777c5f0fa56e3fcbd6af818a63964570d2f5c7c9dff6bdc729b9ecce77d24def686bbc6c6a2a6241741f733d4301d842cf79d63d741b9d583caf10e57c
6
+ metadata.gz: fdf41fa14b877ff36471d7ff50b792d8c77274376b627c674fd8d0f2d647dad3a1cb1b68ae0801aaf670d25ec1b644279917afea8a9e366fc0e3edb851da67cf
7
+ data.tar.gz: 93a23abba82b38fb63a8e55755c7c48fbf13f0101287a033d914b2aa57f08cf25f6db70064e01d202e4f7491240ceed95fbb54fb8465de21e780343444c179db
@@ -45,7 +45,16 @@ class CreditCardSanitizer
45
45
  SCHEME_OR_PLUS = /((?:+|\+)|(?:[a-zA-Z][\-+.a-zA-Z\d]{,9}):\S+)/
46
46
  NUMBERS_WITH_LINE_NOISE = /#{SCHEME_OR_PLUS}?\d(?:#{LINE_NOISE}\d){10,18}/
47
47
 
48
- attr_reader :replacement_token, :expose_first, :expose_last, :use_groupings
48
+ DEFAULT_OPTIONS = {
49
+ replacement_token: '▇',
50
+ expose_first: 6,
51
+ expose_last: 4,
52
+ use_groupings: false
53
+ }
54
+
55
+ attr_reader :settings
56
+
57
+ Candidate = Struct.new(:text, :numbers)
49
58
 
50
59
  # Create a new CreditCardSanitizer
51
60
  #
@@ -54,12 +63,10 @@ class CreditCardSanitizer
54
63
  # :replacement_character - the character that will replace digits for redaction.
55
64
  # :expose_first - the number of leading digits that will not be redacted.
56
65
  # :expose_last - the number of ending digits that will not be redacted.
66
+ # :use_groupings - require card number groupings to match to redact.
57
67
  #
58
68
  def initialize(options = {})
59
- @replacement_token = options.fetch(:replacement_token, '▇')
60
- @expose_first = options.fetch(:expose_first, 6)
61
- @expose_last = options.fetch(:expose_last, 4)
62
- @use_groupings = options.fetch(:use_groupings, false)
69
+ @settings = DEFAULT_OPTIONS.merge(options)
63
70
  end
64
71
 
65
72
  # Finds credit card numbers and redacts digits from them
@@ -78,7 +85,9 @@ class CreditCardSanitizer
78
85
  #
79
86
  # Returns a String of the redacted text if a credit card number was detected.
80
87
  # Returns nil if no credit card numbers were detected.
81
- def sanitize!(text)
88
+ def sanitize!(text, options = {})
89
+ options = @settings.merge(options)
90
+
82
91
  text.force_encoding(Encoding::UTF_8)
83
92
  text.scrub!('�')
84
93
 
@@ -88,15 +97,14 @@ class CreditCardSanitizer
88
97
  text.gsub!(NUMBERS_WITH_LINE_NOISE) do |match|
89
98
  next match if $1
90
99
 
91
- @match = match
92
- @numbers = match.tr('^0-9', '')
100
+ candidate = Candidate.new(match, match.tr('^0-9', ''))
93
101
 
94
- if valid_numbers?
102
+ if valid_numbers?(candidate, options)
95
103
  redacted = true
96
- redact_numbers!
104
+ redact_numbers(candidate, options)
105
+ else
106
+ match
97
107
  end
98
-
99
- @match
100
108
  end
101
109
  end
102
110
 
@@ -120,8 +128,8 @@ class CreditCardSanitizer
120
128
  # => {"credit_card_number" => "4111 11▇▇ ▇▇▇▇ 1111", "password" => "[FILTERED]"}
121
129
  #
122
130
  # Returns a Proc that takes the key/value of the request parameter.
123
- def self.parameter_filter
124
- Proc.new { |_, value| new.sanitize!(value) if value.is_a?(String) }
131
+ def self.parameter_filter(options = {})
132
+ Proc.new { |_, value| new(options).sanitize!(value) if value.is_a?(String) }
125
133
  end
126
134
 
127
135
  private
@@ -130,16 +138,16 @@ class CreditCardSanitizer
130
138
  !!(numbers =~ VALID_COMPANY_PREFIXES)
131
139
  end
132
140
 
133
- def find_company
141
+ def find_company(numbers)
134
142
  CARD_COMPANIES.each do |company, pattern|
135
- return company if @numbers =~ pattern
143
+ return company if numbers =~ pattern
136
144
  end
137
145
  end
138
146
 
139
- def valid_grouping?
140
- if use_groupings
141
- if company = find_company
142
- groupings = @match.split(NONEMPTY_LINE_NOISE).map(&:length)
147
+ def valid_grouping?(candidate, options)
148
+ if options[:use_groupings]
149
+ if company = find_company(candidate.numbers)
150
+ groupings = candidate.text.split(NONEMPTY_LINE_NOISE).map(&:length)
143
151
  return true if groupings.length == 1
144
152
  if company_groupings = CARD_NUMBER_GROUPINGS[company]
145
153
  company_groupings.each do |company_grouping|
@@ -153,22 +161,22 @@ class CreditCardSanitizer
153
161
  end
154
162
  end
155
163
 
156
- def valid_numbers?
157
- LuhnChecksum.valid?(@numbers) && valid_prefix?(@numbers) && valid_grouping?
164
+ def valid_numbers?(candidate, options)
165
+ LuhnChecksum.valid?(candidate.numbers) && valid_prefix?(candidate.numbers) && valid_grouping?(candidate, options)
158
166
  end
159
167
 
160
- def redact_numbers!
161
- @match.gsub!(/\d/).with_index do |number, digit_index|
162
- if within_redaction_range?(digit_index)
163
- replacement_token
168
+ def redact_numbers(candidate, options)
169
+ candidate.text.gsub(/\d/).with_index do |number, digit_index|
170
+ if within_redaction_range?(candidate, digit_index, options)
171
+ options[:replacement_token]
164
172
  else
165
173
  number
166
174
  end
167
175
  end
168
176
  end
169
177
 
170
- def within_redaction_range?(digit_index)
171
- digit_index >= expose_first && digit_index < @numbers.size - expose_last
178
+ def within_redaction_range?(candidate, digit_index, options)
179
+ digit_index >= options[:expose_first] && digit_index < candidate.numbers.size - options[:expose_last]
172
180
  end
173
181
 
174
182
  def without_expiration(text)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: credit_card_sanitizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Chapweske
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-01-12 00:00:00.000000000 Z
13
+ date: 2016-01-15 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: appraisal