Files
tp/serv_nginx/api_bb/internal/handlers/email_handler.go
T
valitovgaziz 1e678c4b7e modified: serv_nginx/api_bb/.env
modified:   serv_nginx/api_bb/go.mod
	modified:   serv_nginx/api_bb/go.sum
	modified:   serv_nginx/api_bb/internal/database/migrate.go
	modified:   serv_nginx/api_bb/internal/handlers/auth.go
	new file:   serv_nginx/api_bb/internal/handlers/email_handler.go
	modified:   serv_nginx/api_bb/internal/handlers/handlers.go
	modified:   serv_nginx/api_bb/internal/models/user.go
	new file:   serv_nginx/api_bb/internal/repository/email_repository.go
	modified:   serv_nginx/api_bb/internal/repository/user_repository.go
	modified:   serv_nginx/api_bb/internal/routes/routes.go
	new file:   serv_nginx/api_bb/internal/service/email_service.go
	modified:   serv_nginx/api_bb/internal/service/user_service.go
	new file:   serv_nginx/api_bb/pkg/email/email.go
add email sender, vrificator and reset password
2025-10-22 05:16:30 +05:00

224 lines
7.0 KiB
Go

// handlers/email_handler.go
package handlers
import (
"net/http"
"api_bb/internal/models"
"api_bb/internal/service"
"api_bb/pkg/logger"
"api_bb/pkg/middleware"
"api_bb/pkg/utils"
"go.uber.org/zap"
)
type EmailHandler struct {
logger logger.LoggerInterface
emailService *service.EmailService
}
func NewEmailHandler(emailService *service.EmailService) *EmailHandler {
return &EmailHandler{
logger: logger.NewWrapper(logger.Get().With(zap.String("handler", "email"))),
emailService: emailService,
}
}
// VerifyEmail подтверждает email пользователя
func (h *EmailHandler) VerifyEmail(w http.ResponseWriter, r *http.Request) {
h.logger.Info("handling email verification request",
zap.String("method", r.Method),
zap.String("path", r.URL.Path),
zap.String("remote_addr", r.RemoteAddr),
)
token := r.URL.Query().Get("token")
if token == "" {
h.logger.Warn("email verification failed - token is required")
utils.RespondWithError(w, http.StatusBadRequest, "Токен обязателен")
return
}
if err := h.emailService.VerifyEmail(token); err != nil {
h.logger.Error("email verification failed, expired",
zap.Error(err),
zap.String("token", token),
)
utils.RespondWithError(w, http.StatusBadRequest, "Неверный или просроченный токен")
return
}
h.logger.Info("email successfully verified",
zap.String("token", token),
)
utils.RespondWithJSON(w, http.StatusOK, map[string]string{
"message": "Email успешно подтвержден",
})
}
// RequestPasswordReset запрашивает сброс пароля
func (h *EmailHandler) RequestPasswordReset(w http.ResponseWriter, r *http.Request) {
h.logger.Info("handling password reset request",
zap.String("method", r.Method),
zap.String("path", r.URL.Path),
zap.String("remote_addr", r.RemoteAddr),
)
var req models.PasswordResetRequest
if err := utils.DecodeJSONBody(w, r, &req); err != nil {
h.logger.Warn("password reset request failed - invalid request format",
zap.Error(err),
)
utils.RespondWithError(w, http.StatusBadRequest, "Неверный формат запроса")
return
}
if err := h.emailService.SendPasswordResetEmail(req.Email); err != nil {
h.logger.Error("password reset request failed",
zap.Error(err),
zap.String("email", req.Email),
)
// Для безопасности всегда возвращаем успех
}
h.logger.Info("password reset request processed",
zap.String("email", req.Email),
)
utils.RespondWithJSON(w, http.StatusOK, map[string]string{
"message": "Если email зарегистрирован, инструкции по восстановлению пароля будут отправлены",
})
}
// ConfirmPasswordReset подтверждает сброс пароля
func (h *EmailHandler) ConfirmPasswordReset(w http.ResponseWriter, r *http.Request) {
h.logger.Info("handling password reset confirmation request",
zap.String("method", r.Method),
zap.String("path", r.URL.Path),
zap.String("remote_addr", r.RemoteAddr),
)
var req models.PasswordResetConfirm
if err := utils.DecodeJSONBody(w, r, &req); err != nil {
h.logger.Warn("password reset confirmation failed - invalid request format",
zap.Error(err),
)
utils.RespondWithError(w, http.StatusBadRequest, "Неверный формат запроса")
return
}
if err := h.emailService.ResetPassword(req.Token, req.Password); err != nil {
h.logger.Error("password reset confirmation failed",
zap.Error(err),
zap.String("token", req.Token),
)
utils.RespondWithError(w, http.StatusBadRequest, "Неверный или просроченный токен")
return
}
h.logger.Info("password successfully reset",
zap.String("token", req.Token),
)
utils.RespondWithJSON(w, http.StatusOK, map[string]string{
"message": "Пароль успешно изменен",
})
}
type NewsletterRequest struct {
Subject string `json:"subject" validate:"required"`
Content string `json:"content" validate:"required"`
}
// SendNewsletter отправляет рассылку новостей
func (h *EmailHandler) SendNewsletter(w http.ResponseWriter, r *http.Request) {
h.logger.Info("handling newsletter sending request",
zap.String("method", r.Method),
zap.String("path", r.URL.Path),
zap.String("remote_addr", r.RemoteAddr),
)
var req NewsletterRequest
if err := utils.DecodeJSONBody(w, r, &req); err != nil {
h.logger.Warn("newsletter sending failed - invalid request format",
zap.Error(err),
)
utils.RespondWithError(w, http.StatusBadRequest, "Неверный формат запроса")
return
}
if err := h.emailService.SendNewsletterToSubscribers(req.Subject, req.Content); err != nil {
h.logger.Error("newsletter sending failed",
zap.Error(err),
zap.String("subject", req.Subject),
)
utils.RespondWithError(w, http.StatusInternalServerError, "Не удалось отправить рассылку")
return
}
h.logger.Info("newsletter sent successfully",
zap.String("subject", req.Subject),
)
utils.RespondWithJSON(w, http.StatusOK, map[string]string{
"message": "Рассылка отправлена подписчикам",
})
}
// ResendVerification повторно отправляет email верификации
func (h *EmailHandler) ResendVerification(w http.ResponseWriter, r *http.Request) {
h.logger.Info("handling resend verification request",
zap.String("method", r.Method),
zap.String("path", r.URL.Path),
zap.String("remote_addr", r.RemoteAddr),
)
user, ok := middleware.GetUserFromContext(r.Context())
if !ok {
h.logger.Warn("resend verification failed - authentication required")
utils.RespondWithError(w, http.StatusUnauthorized, "Пользователь не авторизован")
return
}
// Получаем пользователя
userData, err := h.emailService.GetUserByID(user.ID)
if err != nil {
h.logger.Warn("resend verification failed - user not found",
zap.Uint("user_id", user.ID),
zap.Error(err),
)
utils.RespondWithError(w, http.StatusNotFound, "Пользователь не найден")
return
}
if userData.EmailVerified {
h.logger.Warn("resend verification failed - email already verified",
zap.Uint("user_id", user.ID),
zap.String("email", userData.Email),
)
utils.RespondWithError(w, http.StatusBadRequest, "Email уже подтвержден")
return
}
if err := h.emailService.SendVerificationEmail(userData.ID, userData.Email, userData.FirstName); err != nil {
h.logger.Error("resend verification failed",
zap.Error(err),
zap.Uint("user_id", user.ID),
zap.String("email", userData.Email),
)
utils.RespondWithError(w, http.StatusInternalServerError, "Не удалось отправить email подтверждения")
return
}
h.logger.Info("verification email resent successfully",
zap.Uint("user_id", user.ID),
zap.String("email", userData.Email),
)
utils.RespondWithJSON(w, http.StatusOK, map[string]string{
"message": "Email подтверждения отправлен повторно",
})
}