package controller import ( "codeword/internal/services" "fmt" "github.com/gofiber/fiber/v2" "go.uber.org/zap" "time" ) type RecoveryController struct { Logger *zap.Logger Service *services.RecoveryService } func NewRecoveryController(logger *zap.Logger, service *services.RecoveryService) *RecoveryController { return &RecoveryController{ Logger: logger, Service: service, } } // HandleRecoveryRequest обрабатывает запрос на восстановление пароля func (r *RecoveryController) HandleRecoveryRequest(c *fiber.Ctx) error { email := c.FormValue("email") key, err := r.Service.GenerateKey() if err != nil { r.Logger.Error("Failed to generate key", zap.Error(err)) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"}) } fmt.Println(key) user, err := r.Service.FindUserByEmail(email) if err != nil { r.Logger.Error("Failed to find user by email", zap.Error(err)) return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "User not found"}) } fmt.Println(user) // сохраняем в бд signature, err := r.Service.StoreRecoveryRecord("user") if err != nil { r.Logger.Error("Failed to store recovery record", zap.Error(err)) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"}) } // тут что-то на подобии канала или что-то подобное так как отправка выполнятеся в воркере, //это пока временное решение для написания структуры кода и проверки отправки, далее перепишу // под горутины err = r.Service.SendRecoveryEmail(email, signature) if err != nil { r.Logger.Error("Failed to send recovery email", zap.Error(err)) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"}) } return c.Status(fiber.StatusOK).JSON(fiber.Map{"message": "Recovery email sent successfully"}) } // HandleRecoveryLink обрабатывает ссылку восстановления и обменивает ее на токены func (r *RecoveryController) HandleRecoveryLink(c *fiber.Ctx) error { signature := c.Params("sign") // тут получается record, err := r.Service.GetRecoveryRecord(signature) if err != nil { r.Logger.Error("Failed to get recovery record", zap.Error(err)) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"}) } // проверка на более чем 15 минут if time.Since(record.CreatedAt) > 15*time.Minute { r.Logger.Error("Recovery link expired", zap.String("signature", signature)) return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Recovery link expired"}) } tokens, err := r.Service.ExchangeForTokens(record.UserID) if err != nil { r.Logger.Error("Failed to exchange recovery link for tokens", zap.Error(err)) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"}) } return c.Status(fiber.StatusOK).JSON(tokens) }