github.com/mundipagg/boleto-api@v0.0.0-20230620145841-3f9ec742599f/util/mask.go (about) 1 package util 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strings" 7 8 mxj "github.com/clbanning/mxj/v2" 9 "github.com/go-xmlfmt/xmlfmt" 10 "github.com/mundipagg/boleto-api/config" 11 "github.com/mundipagg/boleto-api/log" 12 ) 13 14 var ( 15 fieldsShouldBeMasked = map[string]bool{ 16 "access_token": true, 17 "refresh_token": true, 18 "AUTENTICACAO": true, 19 "CdtrId": true, 20 "ticket": true, 21 "clientId": true, 22 "clientSecret": true, 23 } 24 ) 25 26 type Mask struct { 27 log *log.Log 28 messageType string 29 } 30 31 func NewMask(log *log.Log, messageType string) *Mask { 32 return &Mask{ 33 log: log, 34 messageType: messageType, 35 } 36 } 37 38 func (mask *Mask) MaskJsonContentFields(content string) string { 39 if !config.Get().MaskLogs { 40 return content 41 } 42 43 contentMap := mask.jsonStringToMap(content) 44 45 if contentMap == nil { 46 return content 47 } 48 49 if !mask.mask(contentMap) { 50 return content 51 } 52 53 maskContent := mask.mapToJson(contentMap) 54 55 if maskContent == "" { 56 return content 57 } 58 59 return maskContent 60 } 61 62 func (mask *Mask) MaskXMLContentFields(content string) string { 63 if !config.Get().MaskLogs { 64 return content 65 } 66 67 contentMap := mask.xmlStringToMap(content) 68 69 if contentMap == nil { 70 return content 71 } 72 73 if !mask.mask(contentMap) { 74 return content 75 } 76 77 maskContent := mask.mapToXML(contentMap) 78 79 if maskContent == "" { 80 return content 81 } 82 83 return maskContent 84 } 85 86 func (mask *Mask) MaskQueryParamsContentFields(content string) string { 87 if !config.Get().MaskLogs { 88 return content 89 } 90 91 contentMap := mask.queryParamsStringToMap(content) 92 93 if contentMap == nil { 94 return content 95 } 96 97 if !mask.mask(contentMap) { 98 return content 99 } 100 101 maskContent := mask.mapToQueryParams(contentMap) 102 103 if maskContent == "" { 104 return content 105 } 106 107 return maskContent 108 } 109 110 //JsonStringToMap Converte uma string json para um map[string]interface 111 //Caso a string não seja compatível com um json retorna nulo 112 func (mask *Mask) jsonStringToMap(value string) map[string]interface{} { 113 defer mask.log.HandleMaskErrors("JsonStringToMap", mask.messageType, value) 114 115 var m map[string]interface{} 116 117 if err := json.Unmarshal([]byte(value), &m); err != nil { 118 return nil 119 } 120 121 return m 122 } 123 124 //MapToJson Converte um map[string]interface para uma string json 125 func (mask *Mask) mapToJson(m map[string]interface{}) string { 126 defer mask.log.HandleMaskErrors("MapToJson", mask.messageType, m) 127 128 jsonBytes, err := json.Marshal(m) 129 if err != nil { 130 return "" 131 } 132 133 return string(jsonBytes) 134 } 135 136 //XMLStringToMap Converte uma string xml para um map[string]interface 137 //Caso a string não seja compatível com um json retorna nulo 138 func (mask *Mask) xmlStringToMap(xml string) map[string]interface{} { 139 defer mask.log.HandleMaskErrors("XMLStringToMap", mask.messageType, xml) 140 141 xmlVal := []byte(xml) 142 mapVal, _ := mxj.NewMapXml(xmlVal) 143 144 return mapVal 145 } 146 147 //MapToXML Converte um map[string]interface para uma string xml 148 func (mask *Mask) mapToXML(m map[string]interface{}) string { 149 defer mask.log.HandleMaskErrors("MapToXML", mask.messageType, m) 150 xmlMap := mxj.Map(m) 151 xmlContent, _ := xmlMap.Xml() 152 formattedXml := xmlfmt.FormatXML(string(xmlContent), "\t", " ") 153 154 return formattedXml 155 } 156 157 //mask Função recursiva para mascarar campos do content 158 func (mask *Mask) mask(contentMap map[string]interface{}) bool { 159 defer mask.log.HandleMaskErrors("mask", mask.messageType, contentMap) 160 161 for key, value := range contentMap { 162 switch value := value.(type) { 163 case map[string]interface{}: 164 mask.mask(value) 165 case string: 166 innerMap := mask.jsonStringToMap(value) 167 if innerMap != nil { 168 mask.mask(innerMap) 169 contentMap[key] = innerMap 170 } else { 171 if _, exists := fieldsShouldBeMasked[key]; exists { 172 contentMap[key] = "[REDACTED]" 173 } 174 } 175 default: 176 break 177 } 178 } 179 180 return true 181 } 182 183 //queryParamsStringToMap Converte uma string com parâmetros URI no formato key1=value1&keyN=valueN para um map[string]interface 184 func (mask *Mask) queryParamsStringToMap(queryParams string) map[string]interface{} { 185 defer mask.log.HandleMaskErrors("QueryParamsStringToMap", mask.messageType, queryParams) 186 187 m := make(map[string]interface{}) 188 listParams := strings.Split(queryParams, "&") 189 190 for _, p := range listParams { 191 pair := strings.SplitN(p, "=", 2) 192 m[pair[0]] = pair[1] 193 } 194 195 return m 196 } 197 198 //mapToQueryParams Converte um map em uma string com parâmetros URI no formato key1=value1&keyN=valueN 199 func (mask *Mask) mapToQueryParams(m map[string]interface{}) string { 200 defer mask.log.HandleMaskErrors("MapToQueryParams", mask.messageType, m) 201 202 var queryParams strings.Builder 203 var parameter string 204 n := 1 205 206 for k, v := range m { 207 if n < len(m) { 208 parameter = fmt.Sprintf("%s=%s&", k, v) 209 } else { 210 parameter = fmt.Sprintf("%s=%s", k, v) 211 } 212 queryParams.WriteString(parameter) 213 n++ 214 } 215 216 return queryParams.String() 217 }