LCOV - code coverage report
Current view: top level - middlewares - auth.go (source / functions) Hit Total Coverage
Test: sdk.lcov Lines: 38 62 61.3 %
Date: 2024-12-20 13:58:22 Functions: 0 0 -

          Line data    Source code
       1             : package middlewares
       2             : 
       3             : import (
       4             :         "encoding/json"
       5             :         "fmt"
       6             :         "io"
       7             :         "net/http"
       8             :         "strings"
       9             : 
      10             :         "github.com/gin-gonic/gin"
      11             : 
      12             :         "github.com/woofdogtw/sylvia-iot-go/sdk/constants"
      13             : )
      14             : 
      15             : // The information contains `GetTokenInfoData` and access token.
      16             : type FullTokenInfo struct {
      17             :         Token string
      18             :         Info  GetTokenInfoData
      19             : }
      20             : 
      21             : // The user/client information of the token.
      22             : type GetTokenInfo struct {
      23             :         Data GetTokenInfoData `json:"data"`
      24             : }
      25             : 
      26             : // User/client information of the token.
      27             : type GetTokenInfoData struct {
      28             :         UserID   string          `json:"userId"`
      29             :         Account  string          `json:"account"`
      30             :         Roles    map[string]bool `json:"roles"`
      31             :         Name     string          `json:"name"`
      32             :         ClientID string          `json:"clientId"`
      33             :         Scopes   []string        `json:"scopes"`
      34             : }
      35             : 
      36             : // Constants.
      37             : const (
      38             :         TokenInfoKey = "FullTokenInfo"
      39             : )
      40             : 
      41             : // Generate the Gin authentication middleware.
      42           4 : func AuthMiddleware(authUri string) func(*gin.Context) {
      43          11 :         return func(c *gin.Context) {
      44           7 :                 token := c.GetHeader("Authorization")
      45           7 :                 token = strings.TrimSpace(token)
      46          11 :                 if len(token) < 8 || strings.ToLower(token[:7]) != "bearer " {
      47           4 :                         c.JSON(http.StatusBadRequest, gin.H{
      48           4 :                                 "code":    constants.ErrParam.String(),
      49           4 :                                 "message": "not bearer token",
      50           4 :                         })
      51           4 :                         return
      52           4 :                 }
      53             : 
      54           3 :                 req, err := http.NewRequest(http.MethodGet, authUri, nil)
      55           3 :                 if err != nil {
      56           0 :                         c.JSON(http.StatusServiceUnavailable, gin.H{
      57           0 :                                 "code":    constants.ErrRsc.String(),
      58           0 :                                 "message": err.Error(),
      59           0 :                         })
      60           0 :                         return
      61           0 :                 }
      62           3 :                 req.Header.Set("Authorization", "Bearer "+token[7:])
      63           3 :                 client := http.Client{}
      64           3 :                 res, err := client.Do(req)
      65           4 :                 if err != nil {
      66           1 :                         c.JSON(http.StatusServiceUnavailable, gin.H{
      67           1 :                                 "code":    constants.ErrRsc.String(),
      68           1 :                                 "message": err.Error(),
      69           1 :                         })
      70           1 :                         return
      71           1 :                 }
      72           2 :                 defer res.Body.Close()
      73           2 :                 body, err := io.ReadAll(res.Body)
      74           2 :                 if err != nil {
      75           0 :                         c.JSON(http.StatusServiceUnavailable, gin.H{
      76           0 :                                 "code":    constants.ErrRsc.String(),
      77           0 :                                 "message": err.Error(),
      78           0 :                         })
      79           0 :                         return
      80           0 :                 }
      81           3 :                 if res.StatusCode == http.StatusUnauthorized {
      82           1 :                         c.JSON(http.StatusUnauthorized, gin.H{"code": constants.ErrAuth.String()})
      83           1 :                         return
      84           2 :                 } else if res.StatusCode != http.StatusOK {
      85           0 :                         c.JSON(http.StatusServiceUnavailable, gin.H{
      86           0 :                                 "code":    constants.ErrIntMsg.String(),
      87           0 :                                 "message": fmt.Sprintf("auth error with status code %d", res.StatusCode),
      88           0 :                         })
      89           0 :                         return
      90           0 :                 }
      91           1 :                 var tokenInfo GetTokenInfo
      92           1 :                 err = json.Unmarshal(body, &tokenInfo)
      93           1 :                 if err != nil {
      94           0 :                         c.JSON(http.StatusServiceUnavailable, gin.H{
      95           0 :                                 "code":    constants.ErrIntMsg.String(),
      96           0 :                                 "message": err.Error(),
      97           0 :                         })
      98           0 :                         return
      99           0 :                 }
     100           1 :                 c.Set(TokenInfoKey, &FullTokenInfo{
     101           1 :                         Token: token[7:],
     102           1 :                         Info:  tokenInfo.Data,
     103           1 :                 })
     104           1 :                 c.Next()
     105             :         }
     106             : }

Generated by: LCOV version 1.14