82 lines
3.1 KiB
Go
82 lines
3.1 KiB
Go
|
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)
|
|||
|
}
|