15357fd3c0
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
204 lines
6.1 KiB
Go
204 lines
6.1 KiB
Go
// handlers/user.go
|
|
package handlers
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"time"
|
|
|
|
"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 UserHandler struct {
|
|
logger logger.LoggerInterface
|
|
userService service.UserService
|
|
}
|
|
|
|
func NewUserHandler(userService service.UserService) *UserHandler {
|
|
return &UserHandler{
|
|
logger: logger.NewWrapper(logger.Get().With(zap.String("handler", "user"))),
|
|
userService: userService,
|
|
}
|
|
}
|
|
|
|
type UserResponse struct {
|
|
ID uint `json:"id"`
|
|
Email string `json:"email"`
|
|
FirstName string `json:"firstName"`
|
|
LastName string `json:"lastName"`
|
|
Avatar string `json:"avatar"`
|
|
Phone string `json:"phone"`
|
|
Experience string `json:"experience"`
|
|
Goals string `json:"goals"`
|
|
Newsletter bool `json:"newsletter"`
|
|
Role string `json:"role"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
}
|
|
|
|
// GetUsers возвращает список всех пользователей
|
|
func (h *UserHandler) GetUsers(w http.ResponseWriter, r *http.Request) {
|
|
h.logger.Info("handling get users request",
|
|
zap.String("method", r.Method),
|
|
zap.String("path", r.URL.Path),
|
|
zap.String("remote_addr", r.RemoteAddr),
|
|
)
|
|
|
|
// Получаем пользователя из контекста для проверки аутентификации
|
|
_, ok := middleware.GetUserFromContext(r.Context())
|
|
if !ok {
|
|
h.logger.Warn("get users failed - authentication required")
|
|
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
|
return
|
|
}
|
|
|
|
// Получаем список пользователей из сервиса
|
|
users, err := h.userService.GetAllUsers()
|
|
if err != nil {
|
|
h.logger.Error("failed to get users from service", zap.Error(err))
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get users: "+err.Error())
|
|
return
|
|
}
|
|
|
|
// Преобразуем в response формат
|
|
var userResponses []UserResponse
|
|
for _, user := range users {
|
|
userResponses = append(userResponses, toUserResponse(&user))
|
|
}
|
|
|
|
h.logger.Info("users list retrieved successfully",
|
|
zap.Int("users_count", len(userResponses)),
|
|
)
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, userResponses)
|
|
}
|
|
|
|
func (h *UserHandler) GetProfile(w http.ResponseWriter, r *http.Request) {
|
|
|
|
h.logger.Info("handling get profile 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("get profile failed - authentication required")
|
|
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
|
return
|
|
}
|
|
|
|
h.logger.Info("profile retrieved successfully",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.String("email", user.Email),
|
|
zap.String("avatar", user.Avatar),
|
|
)
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, toUserResponse(user))
|
|
}
|
|
|
|
type UpdateProfileRequest struct {
|
|
FirstName string `json:"firstName"`
|
|
LastName string `json:"lastName"`
|
|
Phone string `json:"phone"`
|
|
Experience string `json:"experience"`
|
|
Goals string `json:"goals"`
|
|
Newsletter bool `json:"newsletter"`
|
|
}
|
|
|
|
func (h *UserHandler) UpdateProfile(w http.ResponseWriter, r *http.Request) {
|
|
|
|
h.logger.Info("handling update profile request",
|
|
zap.String("method", r.Method),
|
|
zap.String("path", r.URL.Path),
|
|
zap.String("remote_addr", r.RemoteAddr),
|
|
)
|
|
|
|
// Логируем тело запроса для отладки
|
|
bodyBytes, err := io.ReadAll(r.Body)
|
|
if err != nil {
|
|
h.logger.Error("failed to read request body", zap.Error(err))
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Failed to read request body: "+err.Error())
|
|
return
|
|
}
|
|
|
|
// Восстанавливаем тело для дальнейшего использования
|
|
r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
|
|
|
|
h.logger.Debug("raw request body", zap.String("body", string(bodyBytes)))
|
|
|
|
// Получаем пользователя из контекста
|
|
currentUser, ok := middleware.GetUserFromContext(r.Context())
|
|
if !ok {
|
|
h.logger.Warn("update profile failed - authentication required")
|
|
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
|
return
|
|
}
|
|
|
|
var req UpdateProfileRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
h.logger.Error("failed to decode JSON payload", zap.Error(err))
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Invalid request payload: "+err.Error())
|
|
return
|
|
}
|
|
|
|
// Валидация обязательных полей
|
|
if req.FirstName == "" {
|
|
h.logger.Warn("update profile failed - first name required")
|
|
utils.RespondWithError(w, http.StatusBadRequest, "First name is required")
|
|
return
|
|
}
|
|
if req.LastName == "" {
|
|
h.logger.Warn("update profile failed - last name required")
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Last name is required")
|
|
return
|
|
}
|
|
|
|
h.logger.Info("updating user profile",
|
|
zap.Uint("user_id", currentUser.ID),
|
|
zap.String("first_name", req.FirstName),
|
|
zap.String("last_name", req.LastName),
|
|
zap.String("experience", req.Experience),
|
|
zap.String("goals", req.Goals),
|
|
zap.Bool("newsletter", req.Newsletter),
|
|
)
|
|
|
|
// Обновляем данные пользователя
|
|
updatedUser := &models.User{
|
|
ID: currentUser.ID,
|
|
FirstName: req.FirstName,
|
|
LastName: req.LastName,
|
|
Phone: req.Phone,
|
|
Experience: req.Experience,
|
|
Goals: req.Goals,
|
|
Newsletter: req.Newsletter,
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
|
|
// Сохраняем обновленные данные
|
|
if err := h.userService.UpdateProfile(updatedUser); err != nil {
|
|
h.logger.Error("failed to update profile in service",
|
|
zap.Uint("user_id", currentUser.ID),
|
|
zap.Error(err),
|
|
)
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to update profile: "+err.Error())
|
|
return
|
|
}
|
|
|
|
h.logger.Info("profile updated successfully",
|
|
zap.Uint("user_id", currentUser.ID),
|
|
)
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, map[string]interface{}{
|
|
"message": "Profile updated successfully",
|
|
"user": toUserResponse(updatedUser),
|
|
})
|
|
} |