github.com/mundipagg/boleto-api@v0.0.0-20230620145841-3f9ec742599f/api/middlewares.go (about)

     1  package api
     2  
     3  import (
     4  	"net/http"
     5  	"strconv"
     6  	"time"
     7  
     8  	"github.com/gin-gonic/gin"
     9  	"github.com/mundipagg/boleto-api/bank"
    10  	"github.com/mundipagg/boleto-api/log"
    11  	"github.com/mundipagg/boleto-api/metrics"
    12  	"github.com/mundipagg/boleto-api/models"
    13  	"github.com/mundipagg/boleto-api/usermanagement"
    14  )
    15  
    16  const (
    17  	boletoKey      = "boleto"
    18  	bankKey        = "bank"
    19  	serviceUserKey = "serviceuser"
    20  	responseKey    = "boletoResponse"
    21  )
    22  
    23  func returnHeaders() gin.HandlerFunc {
    24  	return func(c *gin.Context) {
    25  		c.Header("Content-Type", "application/json")
    26  		c.Next()
    27  	}
    28  }
    29  
    30  //parseBoleto Middleware de tratamento do request de registro de boleto
    31  func parseBoleto(c *gin.Context) {
    32  	var ok bool
    33  	var boleto models.BoletoRequest
    34  	var bank bank.Bank
    35  
    36  	if boleto, ok = getBoletoRequest(c); !ok {
    37  		return
    38  	}
    39  
    40  	if bank, ok = getBank(c, boleto); !ok {
    41  		return
    42  	}
    43  
    44  	if !parseExpirationDate(c, &boleto, bank) {
    45  		return
    46  	}
    47  
    48  	c.Set(boletoKey, boleto)
    49  	c.Set(bankKey, bank)
    50  }
    51  
    52  //authentication Middleware de autenticação para registro de boleto
    53  func authentication(c *gin.Context) {
    54  
    55  	cred := getHeaderCredentials(c)
    56  
    57  	if cred == nil {
    58  		c.AbortWithStatusJSON(401, models.GetBoletoResponseError("MP401", "Unauthorized"))
    59  		return
    60  	}
    61  
    62  	if !hasValidCredentials(cred) {
    63  		c.AbortWithStatusJSON(401, models.GetBoletoResponseError("MP401", "Unauthorized"))
    64  		return
    65  	}
    66  
    67  	c.Set(serviceUserKey, cred.Username)
    68  }
    69  
    70  //checkError Middleware de verificação de erros
    71  func checkError(c *gin.Context, err error, l *log.Log) bool {
    72  
    73  	if err != nil {
    74  		errResp := models.BoletoResponse{
    75  			Errors: models.NewErrors(),
    76  		}
    77  
    78  		switch v := err.(type) {
    79  
    80  		case models.ErrorResponse:
    81  			errResp.Errors.Append(v.ErrorCode(), v.Error())
    82  			c.JSON(http.StatusBadRequest, errResp)
    83  
    84  		case models.HttpNotFound:
    85  			errResp.Errors.Append("MP404", v.Error())
    86  			l.Warn(errResp, v.Error())
    87  			c.JSON(http.StatusNotFound, errResp)
    88  
    89  		case models.InternalServerError:
    90  			errResp.Errors.Append("MP500", v.Error())
    91  			l.Warn(errResp, v.Error())
    92  			c.JSON(http.StatusInternalServerError, errResp)
    93  
    94  		case models.BadGatewayError:
    95  			errResp.Errors.Append("MP502", v.Error())
    96  			l.Warn(errResp, v.Error())
    97  			c.JSON(http.StatusBadGateway, errResp)
    98  
    99  		case models.FormatError:
   100  			errResp.Errors.Append("MP400", v.Error())
   101  			l.Warn(errResp, v.Error())
   102  			c.JSON(http.StatusBadRequest, errResp)
   103  
   104  		default:
   105  			errResp.Errors.Append("MP500", "Internal Error")
   106  			l.Fatal(errResp, v.Error())
   107  			c.JSON(http.StatusInternalServerError, errResp)
   108  		}
   109  
   110  		c.Set("boletoResponse", errResp)
   111  		return true
   112  	}
   113  	return false
   114  }
   115  
   116  func hasValidCredentials(c *models.Credentials) bool {
   117  	u, hasUser := usermanagement.GetUser(c.UserKey)
   118  
   119  	if !hasUser {
   120  		return false
   121  	}
   122  
   123  	user := u.(models.Credentials)
   124  
   125  	if user.UserKey == c.UserKey && user.Password == c.Password {
   126  		c.Username = user.Username
   127  		return true
   128  	}
   129  
   130  	return false
   131  }
   132  
   133  func getHeaderCredentials(c *gin.Context) *models.Credentials {
   134  	userkey, pass, hasAuth := c.Request.BasicAuth()
   135  	if userkey == "" || pass == "" || !hasAuth {
   136  		return nil
   137  	}
   138  	return models.NewCredentials(userkey, pass)
   139  }
   140  
   141  func getBoletoRequest(c *gin.Context) (models.BoletoRequest, bool) {
   142  	boleto := models.BoletoRequest{}
   143  	errBind := c.BindJSON(&boleto)
   144  	if errBind != nil {
   145  		e := models.NewFormatError(errBind.Error())
   146  		checkError(c, e, log.CreateLog())
   147  		return boleto, false
   148  	}
   149  	return boleto, true
   150  }
   151  
   152  func getBank(c *gin.Context, boleto models.BoletoRequest) (bank.Bank, bool) {
   153  	bank, err := bank.Get(boleto)
   154  	if checkError(c, err, log.CreateLog()) {
   155  		c.Set("error", err)
   156  		return bank, false
   157  	}
   158  	return bank, true
   159  }
   160  
   161  func parseExpirationDate(c *gin.Context, boleto *models.BoletoRequest, bank bank.Bank) bool {
   162  	d, errFmt := time.Parse("2006-01-02", boleto.Title.ExpireDate)
   163  	boleto.Title.ExpireDateTime = d
   164  	if errFmt != nil {
   165  		e := models.NewFormatError(errFmt.Error())
   166  		checkError(c, e, log.CreateLog())
   167  		metrics.PushBusinessMetric(bank.GetBankNameIntegration()+"-bad-request", 1)
   168  		return false
   169  	}
   170  	return true
   171  }
   172  
   173  func getBoletoFromContext(c *gin.Context) models.BoletoRequest {
   174  	if boleto, exists := c.Get(boletoKey); exists {
   175  		return boleto.(models.BoletoRequest)
   176  	}
   177  	return models.BoletoRequest{}
   178  }
   179  
   180  func getBankFromContext(c *gin.Context) bank.Bank {
   181  	if banking, exists := c.Get(bankKey); exists {
   182  		return banking.(bank.Bank)
   183  	}
   184  	return nil
   185  }
   186  
   187  func getUserFromContext(c *gin.Context) string {
   188  	if user, exists := c.Get(serviceUserKey); exists {
   189  		return user.(string)
   190  	}
   191  	return ""
   192  }
   193  
   194  func getResponseFromContext(c *gin.Context) models.BoletoResponse {
   195  	if response, exists := c.Get(responseKey); exists {
   196  		return response.(models.BoletoResponse)
   197  	}
   198  	return models.BoletoResponse{}
   199  }
   200  
   201  func getNossoNumeroFromContext(c *gin.Context) string {
   202  	if respOurNumber := getResponseFromContext(c).OurNumber; respOurNumber != "" {
   203  		return respOurNumber
   204  	}
   205  
   206  	return strconv.FormatUint(uint64(getBoletoFromContext(c).Title.OurNumber), 10)
   207  }