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  }