@@ -108,7 +108,9 @@ impl LogRedactor {
108108 pub fn add_custom_pattern ( & mut self , name : & str , pattern : & str ) -> Result < ( ) , regex:: Error > {
109109 let regex = Regex :: new ( pattern) ?;
110110 self . custom_patterns . insert ( name. to_string ( ) , regex) ;
111- self . config . enabled_patterns . push ( RedactionPattern :: Custom ( name. to_string ( ) ) ) ;
111+ self . config
112+ . enabled_patterns
113+ . push ( RedactionPattern :: Custom ( name. to_string ( ) ) ) ;
112114 Ok ( ( ) )
113115 }
114116
@@ -118,12 +120,20 @@ impl LogRedactor {
118120
119121 for pattern_type in & self . config . enabled_patterns {
120122 result = match pattern_type {
121- RedactionPattern :: SSN => self . redact_pattern ( & result, & self . patterns . ssn , "***-**-****" ) ,
123+ RedactionPattern :: SSN => {
124+ self . redact_pattern ( & result, & self . patterns . ssn , "***-**-****" )
125+ }
122126 RedactionPattern :: CreditCard => self . redact_credit_card ( & result) ,
123127 RedactionPattern :: Email => self . redact_email ( & result) ,
124- RedactionPattern :: PhoneNumber => self . redact_pattern ( & result, & self . patterns . phone , "***-***-****" ) ,
125- RedactionPattern :: IpAddress => self . redact_pattern ( & result, & self . patterns . ip_address , "***.***.***.***" ) ,
126- RedactionPattern :: BankAccount => self . redact_pattern ( & result, & self . patterns . bank_account , "********" ) ,
128+ RedactionPattern :: PhoneNumber => {
129+ self . redact_pattern ( & result, & self . patterns . phone , "***-***-****" )
130+ }
131+ RedactionPattern :: IpAddress => {
132+ self . redact_pattern ( & result, & self . patterns . ip_address , "***.***.***.***" )
133+ }
134+ RedactionPattern :: BankAccount => {
135+ self . redact_pattern ( & result, & self . patterns . bank_account , "********" )
136+ }
127137 RedactionPattern :: ApiKey => self . redact_api_key ( & result) ,
128138 RedactionPattern :: Password => self . redact_password ( & result) ,
129139 RedactionPattern :: Custom ( name) => {
@@ -146,54 +156,66 @@ impl LogRedactor {
146156
147157 /// Redact credit card numbers, preserving last 4 digits
148158 fn redact_credit_card ( & self , input : & str ) -> String {
149- self . patterns . credit_card . replace_all ( input, |caps : & regex:: Captures | {
150- let matched = caps. get ( 0 ) . unwrap ( ) . as_str ( ) ;
151- let digits: String = matched. chars ( ) . filter ( |c| c. is_ascii_digit ( ) ) . collect ( ) ;
152- if digits. len ( ) >= 4 {
153- format ! ( "****-****-****-{}" , & digits[ digits. len( ) -4 ..] )
154- } else {
155- "****-****-****-****" . to_string ( )
156- }
157- } ) . to_string ( )
159+ self . patterns
160+ . credit_card
161+ . replace_all ( input, |caps : & regex:: Captures | {
162+ let matched = caps. get ( 0 ) . unwrap ( ) . as_str ( ) ;
163+ let digits: String = matched. chars ( ) . filter ( |c| c. is_ascii_digit ( ) ) . collect ( ) ;
164+ if digits. len ( ) >= 4 {
165+ format ! ( "****-****-****-{}" , & digits[ digits. len( ) - 4 ..] )
166+ } else {
167+ "****-****-****-****" . to_string ( )
168+ }
169+ } )
170+ . to_string ( )
158171 }
159172
160173 /// Redact email addresses, preserving domain
161174 fn redact_email ( & self , input : & str ) -> String {
162- self . patterns . email . replace_all ( input, |caps : & regex:: Captures | {
163- let matched = caps. get ( 0 ) . unwrap ( ) . as_str ( ) ;
164- if let Some ( at_pos) = matched. find ( '@' ) {
165- let domain = & matched[ at_pos..] ;
166- format ! ( "****{}" , domain)
167- } else {
168- "****@****.***" . to_string ( )
169- }
170- } ) . to_string ( )
175+ self . patterns
176+ . email
177+ . replace_all ( input, |caps : & regex:: Captures | {
178+ let matched = caps. get ( 0 ) . unwrap ( ) . as_str ( ) ;
179+ if let Some ( at_pos) = matched. find ( '@' ) {
180+ let domain = & matched[ at_pos..] ;
181+ format ! ( "****{}" , domain)
182+ } else {
183+ "****@****.***" . to_string ( )
184+ }
185+ } )
186+ . to_string ( )
171187 }
172188
173189 /// Redact API keys and tokens
174190 fn redact_api_key ( & self , input : & str ) -> String {
175- self . patterns . api_key . replace_all ( input, |caps : & regex:: Captures | {
176- let matched = caps. get ( 0 ) . unwrap ( ) . as_str ( ) ;
177- if let Some ( eq_pos) = matched. find ( [ ':' , '=' ] ) {
178- let prefix = & matched[ ..=eq_pos] ;
179- format ! ( "{} [REDACTED]" , prefix. trim_end_matches( [ ':' , '=' , ' ' ] ) )
180- } else {
181- "[REDACTED API KEY]" . to_string ( )
182- }
183- } ) . to_string ( )
191+ self . patterns
192+ . api_key
193+ . replace_all ( input, |caps : & regex:: Captures | {
194+ let matched = caps. get ( 0 ) . unwrap ( ) . as_str ( ) ;
195+ if let Some ( eq_pos) = matched. find ( [ ':' , '=' ] ) {
196+ let prefix = & matched[ ..=eq_pos] ;
197+ format ! ( "{} [REDACTED]" , prefix. trim_end_matches( [ ':' , '=' , ' ' ] ) )
198+ } else {
199+ "[REDACTED API KEY]" . to_string ( )
200+ }
201+ } )
202+ . to_string ( )
184203 }
185204
186205 /// Redact passwords
187206 fn redact_password ( & self , input : & str ) -> String {
188- self . patterns . password . replace_all ( input, |caps : & regex:: Captures | {
189- let matched = caps. get ( 0 ) . unwrap ( ) . as_str ( ) ;
190- if let Some ( eq_pos) = matched. find ( [ ':' , '=' ] ) {
191- let prefix = & matched[ ..=eq_pos] ;
192- format ! ( "{} [REDACTED]" , prefix. trim_end_matches( [ ':' , '=' , ' ' ] ) )
193- } else {
194- "[REDACTED PASSWORD]" . to_string ( )
195- }
196- } ) . to_string ( )
207+ self . patterns
208+ . password
209+ . replace_all ( input, |caps : & regex:: Captures | {
210+ let matched = caps. get ( 0 ) . unwrap ( ) . as_str ( ) ;
211+ if let Some ( eq_pos) = matched. find ( [ ':' , '=' ] ) {
212+ let prefix = & matched[ ..=eq_pos] ;
213+ format ! ( "{} [REDACTED]" , prefix. trim_end_matches( [ ':' , '=' , ' ' ] ) )
214+ } else {
215+ "[REDACTED PASSWORD]" . to_string ( )
216+ }
217+ } )
218+ . to_string ( )
197219 }
198220
199221 /// Check if a string contains sensitive data
@@ -208,9 +230,10 @@ impl LogRedactor {
208230 RedactionPattern :: BankAccount => self . patterns . bank_account . is_match ( input) ,
209231 RedactionPattern :: ApiKey => self . patterns . api_key . is_match ( input) ,
210232 RedactionPattern :: Password => self . patterns . password . is_match ( input) ,
211- RedactionPattern :: Custom ( name) => {
212- self . custom_patterns . get ( name) . map_or ( false , |r| r. is_match ( input) )
213- }
233+ RedactionPattern :: Custom ( name) => self
234+ . custom_patterns
235+ . get ( name)
236+ . is_some_and ( |r| r. is_match ( input) ) ,
214237 } ;
215238 if has_match {
216239 return true ;
@@ -233,9 +256,10 @@ impl LogRedactor {
233256 RedactionPattern :: BankAccount => self . patterns . bank_account . is_match ( input) ,
234257 RedactionPattern :: ApiKey => self . patterns . api_key . is_match ( input) ,
235258 RedactionPattern :: Password => self . patterns . password . is_match ( input) ,
236- RedactionPattern :: Custom ( name) => {
237- self . custom_patterns . get ( name) . map_or ( false , |r| r. is_match ( input) )
238- }
259+ RedactionPattern :: Custom ( name) => self
260+ . custom_patterns
261+ . get ( name)
262+ . is_some_and ( |r| r. is_match ( input) ) ,
239263 } ;
240264 if has_match {
241265 found. push ( pattern_type. clone ( ) ) ;
@@ -324,7 +348,9 @@ mod tests {
324348 #[ test]
325349 fn test_custom_pattern ( ) {
326350 let mut redactor = LogRedactor :: default ( ) ;
327- redactor. add_custom_pattern ( "employee_id" , r"EMP-\d{6}" ) . unwrap ( ) ;
351+ redactor
352+ . add_custom_pattern ( "employee_id" , r"EMP-\d{6}" )
353+ . unwrap ( ) ;
328354 let input = "Employee EMP-123456 accessed system" ;
329355 let output = redactor. redact ( input) ;
330356 assert ! ( output. contains( "[REDACTED]" ) ) ;
0 commit comments