package controllers import ( "github.com/gofiber/fiber/v2" "github.com/golang-jwt/jwt" "golang.org/x/crypto/bcrypt" "log" "main/database" "main/models" "os" "time" "github.com/joho/godotenv" ) // Глобальная переменная для хранения ключа var SecretKey string func init() { // Загружаем .env файл err := godotenv.Load() if err != nil { log.Fatal("Ошибка загрузки .env файла") } // Читаем ключ из переменной окружения SecretKey = os.Getenv("JWT_SECRET_KEY") if SecretKey == "" { log.Fatal("JWT_SECRET_KEY не задан в .env") } } // Регистрируем пользователя func Register(c *fiber.Ctx) error { var data map[string]string if err := c.BodyParser(&data); err != nil { return err } if data["password"] == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"message": "Password is required"}) } // Проверка на существующего пользователя var existingUser models.User if err := database.DB.Where("email = ?", data["email"]).First(&existingUser).Error; err == nil { return c.Status(fiber.StatusConflict).JSON(fiber.Map{"message": "Email already taken"}) } password, _ := bcrypt.GenerateFromPassword([]byte(data["password"]), bcrypt.DefaultCost) user := models.User{ Name: data["name"], Email: data["email"], Password: password, } database.DB.Create(&user) return c.JSON(user) } // Генерация JWT-токена func generateToken(user models.User) (string, error) { claims := jwt.MapClaims{ "user_id": user.Id, "exp": time.Now().Add(time.Hour * 24).Unix(), // Токен на 24 часа } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString([]byte(SecretKey)) } func Login(c *fiber.Ctx) error { var data map[string]string if err := c.BodyParser(&data); err != nil { return err } // Найти пользователя по email var user models.User database.DB.Where("email = ?", data["email"]).First(&user) if user.Id == 0 { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"message": "Invalid email or password"}) } // Проверяем пароль if err := bcrypt.CompareHashAndPassword(user.Password, []byte(data["password"])); err != nil { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"message": "Invalid email or password"}) } // Генерируем токен token, err := generateToken(user) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"message": "Could not generate token"}) } // Сохраняем токен в cookie c.Cookie(&fiber.Cookie{ Name: "jwt", Value: token, Expires: time.Now().Add(time.Hour * 24), HTTPOnly: true, }) return c.JSON(fiber.Map{"message": "Login successful"}) } // Получаем пользователя по токену func User(c *fiber.Ctx) error { cookie := c.Cookies("jwt") token, err := jwt.ParseWithClaims(cookie, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) { return []byte(SecretKey), nil }) if err != nil { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"message": "Unauthorized"}) } claims := token.Claims.(*jwt.StandardClaims) if claims.ExpiresAt < time.Now().Unix() { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"message": "Token expired"}) } var user models.User database.DB.Where("id = ?", claims.Issuer).First(&user) return c.JSON(user) } // Логаут func Logout(c *fiber.Ctx) error { cookie := fiber.Cookie{ Name: "jwt", Value: "", Expires: time.Now().Add(-time.Hour), HTTPOnly: true, SameSite: "Strict", } c.Cookie(&cookie) return c.JSON(fiber.Map{"message": "Logout success"}) }