123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- package user
- import (
- "crypto/rand"
- "encoding/base64"
- "time"
- "github.com/0xJacky/Nginx-UI/model"
- "github.com/0xJacky/Nginx-UI/query"
- "github.com/golang-jwt/jwt/v5"
- "github.com/spf13/cast"
- "github.com/uozi-tech/cosy/logger"
- cSettings "github.com/uozi-tech/cosy/settings"
- )
- const ExpiredTime = 24 * time.Hour
- type JWTClaims struct {
- Name string `json:"name"`
- UserID uint64 `json:"user_id"`
- jwt.RegisteredClaims
- }
- func GetUser(name string) (user *model.User, err error) {
- db := model.UseDB()
- user = &model.User{}
- err = db.Where("name", name).First(user).Error
- if err != nil {
- return
- }
- return
- }
- func DeleteToken(token string) {
- q := query.AuthToken
- _, _ = q.Where(q.Token.Eq(token)).Delete()
- }
- func GetTokenUser(token string) (*model.User, bool) {
- _, err := ValidateJWT(token)
- if err != nil {
- logger.Error(err)
- return nil, false
- }
- q := query.AuthToken
- authToken, err := q.Where(q.Token.Eq(token)).First()
- if err != nil {
- return nil, false
- }
- if authToken.ExpiredAt < time.Now().Unix() {
- DeleteToken(token)
- return nil, false
- }
- u := query.User
- user, err := u.FirstByID(authToken.UserID)
- return user, err == nil
- }
- func GetTokenUserByShortToken(shortToken string) (*model.User, bool) {
- if shortToken == "" {
- return nil, false
- }
- db := model.UseDB()
- var authToken model.AuthToken
- err := db.Where("short_token = ?", shortToken).First(&authToken).Error
- if err != nil {
- return nil, false
- }
- if authToken.ExpiredAt < time.Now().Unix() {
- DeleteToken(authToken.Token)
- return nil, false
- }
- u := query.User
- user, err := u.FirstByID(authToken.UserID)
- return user, err == nil
- }
- type AccessTokenPayload struct {
- Token string `json:"token,omitempty"`
- ShortToken string `json:"short_token,omitempty"`
- }
- func GenerateJWT(user *model.User) (*AccessTokenPayload, error) {
- now := time.Now()
- claims := JWTClaims{
- Name: user.Name,
- UserID: user.ID,
- RegisteredClaims: jwt.RegisteredClaims{
- ExpiresAt: jwt.NewNumericDate(now.Add(ExpiredTime)),
- IssuedAt: jwt.NewNumericDate(now),
- NotBefore: jwt.NewNumericDate(now),
- Issuer: "Nginx UI",
- Subject: user.Name,
- ID: cast.ToString(user.ID),
- },
- }
- unsignedToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
- signedToken, err := unsignedToken.SignedString([]byte(cSettings.AppSettings.JwtSecret))
- if err != nil {
- return nil, err
- }
- // Generate 16-byte short token (16 characters)
- shortTokenBytes := make([]byte, 16)
- _, err = rand.Read(shortTokenBytes)
- if err != nil {
- return nil, err
- }
- // Use base64 URL encoding to get a 16-character string
- shortToken := base64.URLEncoding.EncodeToString(shortTokenBytes)[:16]
- q := query.AuthToken
- err = q.Create(&model.AuthToken{
- UserID: user.ID,
- Token: signedToken,
- ShortToken: shortToken,
- ExpiredAt: now.Add(ExpiredTime).Unix(),
- })
- if err != nil {
- return nil, err
- }
- return &AccessTokenPayload{
- Token: signedToken,
- ShortToken: shortToken,
- }, nil
- }
- func ValidateJWT(tokenStr string) (claims *JWTClaims, err error) {
- if tokenStr == "" {
- err = ErrTokenIsEmpty
- return
- }
- token, err := jwt.ParseWithClaims(tokenStr, &JWTClaims{}, func(token *jwt.Token) (interface{}, error) {
- return []byte(cSettings.AppSettings.JwtSecret), nil
- })
- if err != nil {
- return
- }
- var ok bool
- if claims, ok = token.Claims.(*JWTClaims); ok && token.Valid {
- return claims, nil
- }
- return nil, ErrInvalidClaimsType
- }
|