Files
tp/serv_nginx/api_bb/internal/handlers/review_handler.go
T
valitovgaziz 6892fa8d23 modified: serv_nginx/api_bb/go.mod
modified:   serv_nginx/api_bb/go.sum
	modified:   serv_nginx/api_bb/internal/handlers/review_handler.go
	modified:   serv_nginx/api_bb/pkg/middleware/auth.go
fix bag with not authrizen requwest from back
change key String UserIDKey to middleware.UserIDKey
2025-10-16 00:53:31 +05:00

270 lines
9.2 KiB
Go

// handlers/review_handler.go
package handlers
import (
"api_bb/internal/models"
"api_bb/internal/service"
"api_bb/pkg/logger"
"api_bb/pkg/middleware"
"api_bb/pkg/utils"
"net/http"
"strconv"
"github.com/go-chi/chi/v5"
"go.uber.org/zap"
)
// ReviewHandler обрабатывает HTTP-запросы, связанные с отзывами
type ReviewHandler struct {
reviewService service.ReviewService // Сервис для работы с отзывами
logger logger.LoggerInterface // Логгер для записи событий
}
// NewReviewHandler создает новый экземпляр ReviewHandler
func NewReviewHandler(reviewService service.ReviewService, logger logger.LoggerInterface) *ReviewHandler {
return &ReviewHandler{
reviewService: reviewService,
logger: logger,
}
}
// GetReviews возвращает список отзывов с пагинацией и фильтрацией
func (h *ReviewHandler) GetReviews(w http.ResponseWriter, r *http.Request) {
page, _ := strconv.Atoi(r.URL.Query().Get("page"))
limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
sortBy := r.URL.Query().Get("sort")
filter := r.URL.Query().Get("filter")
if page < 1 {
page = 1
}
if limit < 1 {
limit = 6
}
reviews, totalPages, err := h.reviewService.GetAllReviews(page, limit, sortBy, filter)
if err != nil {
h.logger.Error("Failed to get reviews", zap.Error(err))
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get reviews")
return
}
response := map[string]interface{}{
"reviews": reviews,
"current_page": page,
"total_pages": totalPages,
"total_items": len(reviews),
}
utils.RespondWithJSON(w, http.StatusOK, response)
}
// GetReviewsStats возвращает статистику отзывов
func (h *ReviewHandler) GetReviewsStats(w http.ResponseWriter, r *http.Request) {
stats, err := h.reviewService.GetReviewsStats()
if err != nil {
h.logger.Error("Failed to get reviews stats", zap.Error(err))
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get reviews statistics")
return
}
utils.RespondWithJSON(w, http.StatusOK, stats)
}
// GetMyReviews возвращает отзывы текущего аутентифицированного пользователя
func (h *ReviewHandler) GetMyReviews(w http.ResponseWriter, r *http.Request) {
// Получаем ID пользователя из контекста (добавляется middleware аутентификации)
userID, ok := r.Context().Value("middleware.UserIDKey").(uint)
if !ok {
h.logger.Warn("Failed to get userID from context in GetMyReviews",
zap.String("path", r.URL.Path),
zap.String("method", r.Method),
zap.String("remote_addr", r.RemoteAddr),
)
utils.RespondWithError(w, http.StatusUnauthorized, "User not authenticated")
return
}
// Получаем отзывы пользователя из сервиса
reviews, err := h.reviewService.GetUserReviews(userID)
if err != nil {
h.logger.With(zap.Int("userID", int(userID))).Error("Failed to get user reviews", zap.Error(err))
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get your reviews")
return
}
utils.RespondWithJSON(w, http.StatusOK, reviews)
}
// CreateReview создает новый отзыв от имени текущего пользователя
func (h *ReviewHandler) CreateReview(w http.ResponseWriter, r *http.Request) {
// Получаем ID пользователя из контекста
userID, ok := r.Context().Value(middleware.UserIDKey).(uint)
if !ok {
h.logger.Warn("Failed to get userID from context in CreateReview",
zap.String("path", r.URL.Path),
zap.String("method", r.Method),
zap.String("remote_addr", r.RemoteAddr),
zap.Uint("userID", userID),
)
utils.RespondWithError(w, http.StatusUnauthorized, "User not authenticated")
return
}
h.logger.Debug("Successfully extracted userID from context",
zap.Uint("userID", userID),
zap.String("path", r.URL.Path),
zap.String("method", r.Method),
)
// Декодируем тело запроса
var req models.CreateReviewRequest
if err := utils.DecodeJSONBody(w, r, &req); err != nil {
h.logger.Error("Failed to decode review request",
zap.Error(err),
zap.Uint("userID", userID),
)
utils.RespondWithError(w, http.StatusBadRequest, "Invalid request body")
return
}
// Создаем отзыв через сервис
review, err := h.reviewService.CreateReview(&req, userID)
if err != nil {
h.logger.With(zap.Int("userID", int(userID))).Error("Failed to create review", zap.Error(err))
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to create review")
return
}
h.logger.Info("Review created successfully",
zap.Uint("userID", userID),
zap.Any("review_id", review.ID),
)
utils.RespondWithJSON(w, http.StatusCreated, review)
}
// GetReviewByID возвращает отзыв по его идентификатору
func (h *ReviewHandler) GetReviewByID(w http.ResponseWriter, r *http.Request) {
// Получаем ID отзыва из параметров URL
idStr := chi.URLParam(r, "id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
utils.RespondWithError(w, http.StatusBadRequest, "Invalid review ID")
return
}
// Получаем отзыв из сервиса
review, err := h.reviewService.GetReviewByID(uint(id))
if err != nil {
h.logger.With(zap.Int("id", int(id))).Error("Failed to get review", zap.Error(err))
utils.RespondWithError(w, http.StatusNotFound, "Review not found")
return
}
utils.RespondWithJSON(w, http.StatusOK, review)
}
// UpdateReview обновляет существующий отзыв
func (h *ReviewHandler) UpdateReview(w http.ResponseWriter, r *http.Request) {
// Получаем ID пользователя из контекста
userID, ok := r.Context().Value(middleware.UserIDKey).(uint)
if !ok {
h.logger.Warn("Failed to get userID from context in UpdateReview",
zap.String("path", r.URL.Path),
zap.String("method", r.Method),
zap.String("remote_addr", r.RemoteAddr),
zap.Uint("userID", userID),
)
utils.RespondWithError(w, http.StatusUnauthorized, "User not authenticated")
return
}
// Получаем флаг администратора из контекста
isAdmin, _ := r.Context().Value("IsAdmin").(bool)
// Получаем ID отзыва из параметров URL
idStr := chi.URLParam(r, "id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
utils.RespondWithError(w, http.StatusBadRequest, "Invalid review ID")
return
}
// Декодируем тело запроса
var req models.UpdateReviewRequest
if err := utils.DecodeJSONBody(w, r, &req); err != nil {
h.logger.Error("Failed to decode update review request",
zap.Error(err),
zap.Uint("userID", userID),
zap.Uint("review_id", uint(id)),
)
utils.RespondWithError(w, http.StatusBadRequest, "Invalid request body")
return
}
// Обновляем отзыв через сервис
review, err := h.reviewService.UpdateReview(uint(id), &req, userID, isAdmin)
if err != nil {
h.logger.With(zap.Int("id", int(id))).With(zap.Int("userID", int(userID))).Error("Failed to update review", zap.Error(err))
if err.Error() == "unauthorized" {
utils.RespondWithError(w, http.StatusForbidden, "You can only update your own reviews")
return
}
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to update review")
return
}
h.logger.Info("Review updated successfully",
zap.Uint("userID", userID),
zap.Uint("review_id", uint(id)),
)
utils.RespondWithJSON(w, http.StatusOK, review)
}
// DeleteReview удаляет отзыв
func (h *ReviewHandler) DeleteReview(w http.ResponseWriter, r *http.Request) {
// Получаем ID пользователя из контекста
userID, ok := r.Context().Value(middleware.UserIDKey).(uint)
if !ok {
h.logger.Warn("Failed to get userID from context in DeleteReview",
zap.String("path", r.URL.Path),
zap.String("method", r.Method),
zap.String("remote_addr", r.RemoteAddr),
)
utils.RespondWithError(w, http.StatusUnauthorized, "User not authenticated")
return
}
// Получаем флаг администратора из контекста
isAdmin, _ := r.Context().Value("IsAdmin").(bool)
// Получаем ID отзыва из параметров URL
idStr := chi.URLParam(r, "id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
utils.RespondWithError(w, http.StatusBadRequest, "Invalid review ID")
return
}
// Удаляем отзыв через сервис
err = h.reviewService.DeleteReview(uint(id), userID, isAdmin)
if err != nil {
h.logger.With(zap.Int("id", int(id))).With(zap.Int("userID", int(userID))).Error("Failed to delete review", zap.Error(err))
if err.Error() == "unauthorized" {
utils.RespondWithError(w, http.StatusForbidden, "You can only delete your own reviews")
return
}
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to delete review")
return
}
h.logger.Info("Review deleted successfully",
zap.Uint("userID", userID),
zap.Uint("review_id", uint(id)),
)
utils.RespondWithJSON(w, http.StatusOK, map[string]string{"message": "Review deleted successfully"})
}