package gauth import ( "errors" "fmt" "net/http" "strconv" "strings" "time" "github.com/dgrijalva/jwt-go" "github.com/gin-gonic/gin" "github.com/happierall/l" "github.com/metarare/metarare_api/helpers" "github.com/metarare/metarare_api/helpers/terror" "github.com/metarare/metarare_api/models" "gorm.io/gorm" ) const ( User = iota Dev TrendersMaster TrendersAdmin BrandMaster BrandManger Influencer ) func ObtainJWTKey() string { vv := helpers.LoadEnvs() v := vv.GetString("jwt.jwt_secret") if strings.Compare(v, "") != 0 { return v } else { l.Error("There is no JWTKey ") return "" } } // NOTE x GetCurrentUserID가 return type이 string이라서 int64로 하나 생성 func GetCurrentUserIDToInt64(c *gin.Context) (uint64, error) { s_userID, err := GetCurrentUserID(c) if err != nil { return 0, err } n_userID, err := strconv.ParseUint(s_userID, 10, 64) if err != nil { return 0, err } return n_userID, err } func GetCurrentUserID(c *gin.Context) (string, error) { return GetCustomClaim(c, "user_id") } type AdminInfo struct { AdminID uint64 `json:"admin_id,omitempty"` Permission models.AdminPermission `json:"permission,omitempty"` } // // NOTE x 어드민에대한 정보 확인 func ConfirmAdminInfo(c *gin.Context, db *gorm.DB) (models.Admin, error) { admin := models.Admin{} adminID, err := GetCurrentUserIDToInt64(c) if err != nil || adminID == 0 { return admin, err } if err := db.Where("id = ?", adminID).Preload("AdminPermission").Find(&admin).Error; err != nil { return admin, err } else if admin.ID == 0 { return admin, errors.New("not found recored") } return admin, nil } func GetCustomClaim(c *gin.Context, claimName string) (string, error) { claims, err := ValidateToken(c) if err != nil { l.Error(err) // c.AbortWithStatus(http.StatusUnauthorized) return "", err } encrpytedClaim, isValidClaim := claims[Pack(claimName)].(string) // NOTE claims에서 claimName이 존재하지 않을때 if !isValidClaim { errMsg := "invalid claimName" l.Error(errMsg) return "", errors.New(errMsg) } value := UnPack(encrpytedClaim) // l.Log("[ExtractCustomCliam] revert data :", value) return value, nil } func ValidateToken(c *gin.Context) (jwt.MapClaims, error) { accessToken := c.GetHeader("Authorization") // l.Log("Received AuthToken ", accessToken) splitedToken := strings.Split(accessToken, " ") if strings.Compare(accessToken, "") == 0 || len(splitedToken) != 2 || strings.Compare(splitedToken[0], "Bearer") != 0 { //err := fmt.Errorf("Unauthrized !!! Request header's accessToken :[", accessToken, "]") err := terror.NewErrorNoAccessToken().SetDescriptor(fmt.Sprintf("accessToken :%s", accessToken)) l.Error(err) return jwt.MapClaims{}, err } // l.Log("[ExtractCustomCliam] SplitedToken (%s)", splitedToken[1]) token, err := jwt.Parse(splitedToken[1], func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { err := fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) l.Error(err) return jwt.MapClaims{}, err } return []byte(ObtainJWTKey()), nil }) if err != nil { l.Error(err) // c.AbortWithStatus(http.StatusUnauthorized) return jwt.MapClaims{}, err } claims, ok := token.Claims.(jwt.MapClaims) if ok && !token.Valid { l.Errorf("Token is not valid") // c.AbortWithStatus(http.StatusUnauthorized) return jwt.MapClaims{}, err } exp := claims["exp"].(string) expAt, _ := time.Parse(time.RFC3339, exp) if expAt.Before(time.Now()) { l.Error("Expired JWT token") // c.AbortWithStatus(http.StatusUnauthorized) return jwt.MapClaims{}, terror.NewErrorTokenExpired() } return claims, nil } //SECTION verification of password reset token func ValidateResetToken(c *gin.Context, resetToken string) (jwt.MapClaims, error) { token, err := jwt.Parse(resetToken, func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { err := errors.New("unexpected signing method") l.Error(err) return jwt.MapClaims{}, err } return []byte(ObtainJWTKey()), nil }) if err != nil { l.Error(err) return jwt.MapClaims{}, err } claims, ok := token.Claims.(jwt.MapClaims) if ok && !token.Valid { l.Errorf("Token is not valid") return jwt.MapClaims{}, err } exp := claims["exp"].(string) expAt, _ := time.Parse(time.RFC3339, exp) if expAt.Before(time.Now()) { l.Error("Expired JWT token") return jwt.MapClaims{}, terror.NewErrorTokenExpired() } return claims, nil } func GetRegisteredClaim(c *gin.Context, claimName string) (interface{}, error) { claims, err := ValidateToken(c) if err != nil { l.Error(err) // c.AbortWithStatus(http.StatusUnauthorized) return "", err } registeredClaim := claims[claimName].(interface{}) // l.Log(registeredClaim) //l.Log("[ExtractRegisterdCliam] data :", registeredClaim) return registeredClaim, nil } func GetCurrentUserType(c *gin.Context) (string, error) { aud, err := GetRegisteredClaim(c, "aud") if err != nil { l.Error(err) // c.AbortWithStatus(http.StatusUnauthorized) return "", err } aud = int(aud.(float64)) var userType string // 7renders if aud == TrendersMaster || aud == TrendersAdmin { userType = "7renders" // brand } else if aud == BrandMaster || aud == BrandManger { userType = "brand" // influecner } else if aud == Influencer { userType = "influencer" // dev } else if aud == Dev { userType = "dev" // guest } else if aud == User { userType = "guest" } else { l.Error("Unkown auth_type(securityLevel)") c.String(http.StatusOK, "Unknown user") return "", err } return userType, nil }