3x-ui/web/service/auth.go

70 lines
1.6 KiB
Go
Raw Normal View History

2025-10-07 20:59:46 +00:00
package service
import (
"errors"
"os"
"time"
"github.com/golang-jwt/jwt/v5"
"golang.org/x/crypto/bcrypt"
"github.com/mhsanaei/3x-ui/v2/database"
"github.com/mhsanaei/3x-ui/v2/database/model"
"gorm.io/gorm"
)
type AuthService struct {
DB *gorm.DB
JWTSecret []byte
}
func NewAuthService() *AuthService {
secret := os.Getenv("JWT_SECRET")
if secret == "" {
secret = "dev-secret-change-me"
}
return &AuthService{
DB: database.GetDB(),
JWTSecret: []byte(secret),
}
}
// Регистрация (используем существующую модель: Username + PasswordHash + Role)
func (s *AuthService) Register(username, rawPassword, role string) error {
if role == "" {
role = "reader"
}
hash, err := bcrypt.GenerateFromPassword([]byte(rawPassword), 12)
if err != nil {
return err
}
u := &model.User{
Username: username,
PasswordHash: string(hash),
Role: role,
}
return s.DB.Create(u).Error
}
func (s *AuthService) Login(username, rawPassword string) (string, *model.User, error) {
var u model.User
if err := s.DB.Where("username = ?", username).First(&u).Error; err != nil {
if database.IsNotFound(err) {
return "", nil, errors.New("user not found")
}
return "", nil, err
}
if err := bcrypt.CompareHashAndPassword([]byte(u.PasswordHash), []byte(rawPassword)); err != nil {
return "", nil, errors.New("invalid password")
}
claims := jwt.MapClaims{
"id": u.Id,
"username": u.Username,
"role": u.Role,
"exp": time.Now().Add(72 * time.Hour).Unix(),
}
tok, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(s.JWTSecret)
return tok, &u, err
}