create and moove into new directories for BegushiyBashkir and
yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarba
This commit is contained in:
@@ -0,0 +1,269 @@
|
||||
// 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"})
|
||||
}
|
||||
Reference in New Issue
Block a user