1- import logger , { setLevel } from "../../src/common/log" ;
1+ import logger , { setLevel , redactMessage } from "../../src/common/log" ;
22
33describe ( "log level print" , ( ) => {
44 test ( "normal connect" , async ( ) => {
@@ -21,3 +21,103 @@ describe("log level print", () => {
2121 expect ( isLevel ) . toEqual ( true ) ;
2222 } ) ;
2323} ) ;
24+
25+ describe ( "redact message" , ( ) => {
26+ test ( "redacts password field in JSON-like string" , ( ) => {
27+ const input = '{"password": "secret123"}' ;
28+ const output = redactMessage ( input ) ;
29+ expect ( output ) . toBe ( '{"password": "[REDACTED]"}' ) ;
30+ } ) ;
31+
32+ test ( "redacts token in query string" , ( ) => {
33+ const input = "https://example.com?token=abcdef123456&other=1" ;
34+ const output = redactMessage ( input ) ;
35+ expect ( output ) . toBe (
36+ "https://example.com?token=[REDACTED]&other=1"
37+ ) ;
38+ } ) ;
39+
40+ test ( "redacts bearer token in query string" , ( ) => {
41+ const input = "https://example.com?bearer_token=abcdef123456&other=1" ;
42+ const output = redactMessage ( input ) ;
43+ expect ( output ) . toBe (
44+ "https://example.com?bearer_token=[REDACTED]&other=1"
45+ ) ;
46+ } ) ;
47+
48+ test ( "is case-insensitive for password key" , ( ) => {
49+ const input = '{"PassWord": "secret123"}' ;
50+ const output = redactMessage ( input ) ;
51+ expect ( output ) . toBe ( '{"PassWord": "[REDACTED]"}' ) ;
52+ } ) ;
53+
54+ test ( "leaves string without sensitive data unchanged" , ( ) => {
55+ const input = "normal message without secrets" ;
56+ const output = redactMessage ( input ) ;
57+ expect ( output ) . toBe ( input ) ;
58+ } ) ;
59+
60+ test ( "redacts password and token fields on plain object" , ( ) => {
61+ const input = {
62+ user : "u1" ,
63+ password : "secret" ,
64+ token : "abc123" ,
65+ bearer_token : "def456" ,
66+ other : "keep" ,
67+ } ;
68+ const output = redactMessage ( input ) as any ;
69+
70+ expect ( output . user ) . toBe ( "u1" ) ;
71+ expect ( output . password ) . toBe ( "[REDACTED]" ) ;
72+ expect ( output . token ) . toBe ( "[REDACTED]" ) ;
73+ expect ( output . bearer_token ) . toBe ( "[REDACTED]" ) ;
74+ expect ( output . other ) . toBe ( "keep" ) ;
75+ } ) ;
76+
77+ test ( "redacts nested objects recursively" , ( ) => {
78+ const input = {
79+ level1 : {
80+ password : "p1" ,
81+ nested : {
82+ token : "t1" ,
83+ value : 42 ,
84+ } ,
85+ } ,
86+ } ;
87+ const output = redactMessage ( input ) as any ;
88+
89+ expect ( output . level1 . password ) . toBe ( "[REDACTED]" ) ;
90+ expect ( output . level1 . nested . token ) . toBe ( "[REDACTED]" ) ;
91+ expect ( output . level1 . nested . value ) . toBe ( 42 ) ;
92+ } ) ;
93+
94+ test ( "redacts objects inside array" , ( ) => {
95+ const input = [
96+ { password : "p1" } ,
97+ { token : "t2" , ok : true } ,
98+ ] ;
99+ const output = redactMessage ( input ) as any [ ] ;
100+
101+ expect ( output [ 0 ] . password ) . toBe ( "[REDACTED]" ) ;
102+ expect ( output [ 1 ] . token ) . toBe ( "[REDACTED]" ) ;
103+ expect ( output [ 1 ] . ok ) . toBe ( true ) ;
104+ } ) ;
105+
106+ test ( "returns same primitive for non-object/non-string" , ( ) => {
107+ expect ( redactMessage ( 123 ) ) . toBe ( 123 ) ;
108+ expect ( redactMessage ( null ) ) . toBeNull ( ) ;
109+ expect ( redactMessage ( undefined ) ) . toBeUndefined ( ) ;
110+ } ) ;
111+
112+ test ( "redacts password in ws url user:password@" , ( ) => {
113+ const input = "ws://root:taosdata@localhost:6041/ws" ;
114+ const output = redactMessage ( input ) ;
115+ expect ( output ) . toBe ( "ws://root:[REDACTED]@localhost:6041/ws" ) ;
116+ } ) ;
117+
118+ test ( "does not change url without credentials" , ( ) => {
119+ const input = "ws://localhost:6041/ws" ;
120+ const output = redactMessage ( input ) ;
121+ expect ( output ) . toBe ( input ) ;
122+ } ) ;
123+ } ) ;
0 commit comments