189 lines
4.8 KiB
Go
189 lines
4.8 KiB
Go
package crypto
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/golang-jwt/jwt"
|
|
"golang.org/x/crypto/bcrypt"
|
|
|
|
"furtuna-be/internal/common/errors"
|
|
"furtuna-be/internal/entity"
|
|
)
|
|
|
|
func NewCrypto(config CryptoConfig) *CryptoImpl {
|
|
return &CryptoImpl{
|
|
Config: config,
|
|
}
|
|
}
|
|
|
|
type CryptoConfig interface {
|
|
AccessTokenSecret() string
|
|
AccessTokenOrderSecret() string
|
|
AccessTokenOrderExpiresDate() time.Time
|
|
AccessTokenExpiresDate() time.Time
|
|
AccessTokenResetPasswordSecret() string
|
|
AccessTokenResetPasswordExpire() time.Time
|
|
}
|
|
|
|
type CryptoImpl struct {
|
|
Config CryptoConfig
|
|
}
|
|
|
|
func (c *CryptoImpl) CompareHashAndPassword(hash string, password string) bool {
|
|
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
|
return err == nil
|
|
}
|
|
|
|
func (c *CryptoImpl) ValidateWT(tokenString string) (*jwt.Token, error) {
|
|
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
|
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
|
}
|
|
return []byte(c.Config.AccessTokenSecret()), nil
|
|
})
|
|
|
|
return token, err
|
|
}
|
|
|
|
func (c *CryptoImpl) GenerateJWT(user *entity.User) (string, error) {
|
|
partnerID := int64(0)
|
|
if user.PartnerID != nil {
|
|
partnerID = *user.PartnerID
|
|
}
|
|
|
|
siteID := int64(0)
|
|
if user.SiteID != nil {
|
|
siteID = *user.SiteID
|
|
}
|
|
|
|
claims := &entity.JWTAuthClaims{
|
|
StandardClaims: jwt.StandardClaims{
|
|
Subject: strconv.FormatInt(user.ID, 10),
|
|
ExpiresAt: c.Config.AccessTokenExpiresDate().Unix(),
|
|
IssuedAt: time.Now().Unix(),
|
|
NotBefore: time.Now().Unix(),
|
|
},
|
|
UserID: user.ID,
|
|
Name: user.Name,
|
|
Email: user.Email,
|
|
Role: int(user.RoleID),
|
|
PartnerID: partnerID,
|
|
SiteID: siteID,
|
|
SiteName: user.SiteName,
|
|
}
|
|
|
|
token, err := jwt.
|
|
NewWithClaims(jwt.SigningMethodHS256, claims).
|
|
SignedString([]byte(c.Config.AccessTokenSecret()))
|
|
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return token, nil
|
|
}
|
|
|
|
func (c *CryptoImpl) GenerateJWTReseetPassword(user *entity.User) (string, error) {
|
|
claims := &entity.JWTAuthClaims{
|
|
StandardClaims: jwt.StandardClaims{
|
|
Subject: strconv.FormatInt(user.ID, 10),
|
|
ExpiresAt: c.Config.AccessTokenResetPasswordExpire().Unix(),
|
|
IssuedAt: time.Now().Unix(),
|
|
NotBefore: time.Now().Unix(),
|
|
},
|
|
UserID: user.ID,
|
|
Name: user.Name,
|
|
Email: user.Email,
|
|
}
|
|
|
|
token, err := jwt.
|
|
NewWithClaims(jwt.SigningMethodHS256, claims).
|
|
SignedString([]byte(c.Config.AccessTokenResetPasswordSecret()))
|
|
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return token, nil
|
|
}
|
|
|
|
func (c *CryptoImpl) ParseAndValidateJWT(tokenString string) (*entity.JWTAuthClaims, error) {
|
|
token, err := jwt.ParseWithClaims(tokenString, &entity.JWTAuthClaims{}, func(token *jwt.Token) (interface{}, error) {
|
|
return []byte(c.Config.AccessTokenSecret()), nil
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if claims, ok := token.Claims.(*entity.JWTAuthClaims); ok && token.Valid {
|
|
return claims, nil
|
|
} else {
|
|
return nil, errors.ErrorUnauthorized
|
|
}
|
|
}
|
|
|
|
func (c *CryptoImpl) GenerateJWTOrder(order *entity.Order) (string, error) {
|
|
claims := &entity.JWTOrderClaims{
|
|
StandardClaims: jwt.StandardClaims{
|
|
Subject: strconv.FormatInt(order.ID, 10),
|
|
ExpiresAt: c.Config.AccessTokenOrderExpiresDate().Unix(),
|
|
IssuedAt: time.Now().Unix(),
|
|
NotBefore: time.Now().Unix(),
|
|
},
|
|
PartnerID: order.PartnerID,
|
|
OrderID: order.ID,
|
|
}
|
|
|
|
token, err := jwt.
|
|
NewWithClaims(jwt.SigningMethodHS256, claims).
|
|
SignedString([]byte(c.Config.AccessTokenOrderSecret()))
|
|
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return token, nil
|
|
}
|
|
|
|
func (c *CryptoImpl) ValidateJWTOrder(tokenString string) (int64, int64, error) {
|
|
token, err := jwt.ParseWithClaims(tokenString, &entity.JWTOrderClaims{}, func(token *jwt.Token) (interface{}, error) {
|
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
|
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
|
}
|
|
return []byte(c.Config.AccessTokenOrderSecret()), nil
|
|
})
|
|
|
|
if err != nil {
|
|
return 0, 0, err
|
|
}
|
|
|
|
claims, ok := token.Claims.(*entity.JWTOrderClaims)
|
|
if !ok || !token.Valid {
|
|
return 0, 0, fmt.Errorf("invalid token %v", token.Header["alg"])
|
|
}
|
|
|
|
return claims.PartnerID, claims.OrderID, nil
|
|
}
|
|
|
|
func (c *CryptoImpl) ValidateResetPassword(tokenString string) (int64, error) {
|
|
token, err := jwt.ParseWithClaims(tokenString, &entity.JWTOrderClaims{}, func(token *jwt.Token) (interface{}, error) {
|
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
|
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
|
}
|
|
return []byte(c.Config.AccessTokenResetPasswordSecret()), nil
|
|
})
|
|
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
claims, ok := token.Claims.(*entity.JWTAuthClaims)
|
|
if !ok || !token.Valid {
|
|
return 0, fmt.Errorf("invalid token %v", token.Header["alg"])
|
|
}
|
|
|
|
return claims.UserID, nil
|
|
}
|