// Package handlers package handlers import ( "encoding/json" "net/http" "strconv" "github.com/go-chi/chi/v5" "gogs.fxtmmsk.ru/foxtime/photoplaces/backend/internal/middleware" "gogs.fxtmmsk.ru/foxtime/photoplaces/backend/internal/models" "gogs.fxtmmsk.ru/foxtime/photoplaces/backend/internal/repository" "gogs.fxtmmsk.ru/foxtime/photoplaces/backend/internal/validator" ) type UserHandler struct { userRepo *repository.UserRepo } func NewUserHandler(userRepo *repository.UserRepo) *UserHandler { return &UserHandler{userRepo: userRepo} } func (h *UserHandler) GetProfile(w http.ResponseWriter, r *http.Request) { userID := chi.URLParam(r, "id") if userID == "" { userID = middleware.GetUserID(r.Context()) } user, err := h.userRepo.GetByID(r.Context(), userID) if err != nil { writeError(w, http.StatusInternalServerError, "failed to get user", err) return } if user == nil { writeError(w, http.StatusNotFound, "user not found", nil) return } writeJSON(w, http.StatusOK, user) } type updateMeRequest struct { Name *string `json:"name" validate:"omitempty,max=255"` Phone *string `json:"phone" validate:"omitempty,max=20"` Bio *string `json:"bio" validate:"omitempty,max=2000"` AvatarURL *string `json:"avatar_url" validate:"omitempty,url,max=500"` Country *string `json:"country" validate:"omitempty,len=2"` } func (h *UserHandler) UpdateMe(w http.ResponseWriter, r *http.Request) { userID := middleware.GetUserID(r.Context()) r.Body = http.MaxBytesReader(w, r.Body, maxRequestBodySize) user, err := h.userRepo.GetByID(r.Context(), userID) if err != nil { writeError(w, http.StatusInternalServerError, "failed to get user", err) return } if user == nil { writeError(w, http.StatusNotFound, "user not found", nil) return } var req updateMeRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid request body", err) return } if err := validator.Validate(req); err != nil { writeValidationError(w, err) return } if req.Name != nil { user.Name = req.Name } if req.Phone != nil { user.Phone = req.Phone } if req.Bio != nil { user.Bio = req.Bio } if req.AvatarURL != nil { user.AvatarURL = req.AvatarURL } if req.Country != nil { user.Country = req.Country } if err := h.userRepo.Update(r.Context(), user); err != nil { writeError(w, http.StatusInternalServerError, "failed to update user", err) return } writeJSON(w, http.StatusOK, user) } // Admin endpoints type adminUpdateUserRequest struct { Role *string `json:"role" validate:"omitempty,user_role"` Status *string `json:"status" validate:"omitempty,user_status"` } func (h *UserHandler) AdminUpdateUser(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") r.Body = http.MaxBytesReader(w, r.Body, maxRequestBodySize) var req adminUpdateUserRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid request body", err) return } if err := validator.Validate(req); err != nil { writeValidationError(w, err) return } if req.Role != nil { if err := h.userRepo.UpdateRole(r.Context(), id, *req.Role); err != nil { writeError(w, http.StatusInternalServerError, "failed to update role", err) return } } if req.Status != nil { if err := h.userRepo.UpdateStatus(r.Context(), id, *req.Status); err != nil { writeError(w, http.StatusInternalServerError, "failed to update status", err) return } } user, err := h.userRepo.GetByID(r.Context(), id) if err != nil { writeError(w, http.StatusInternalServerError, "failed to get user", err) return } writeJSON(w, http.StatusOK, user) } func (h *UserHandler) AdminListUsers(w http.ResponseWriter, r *http.Request) { filter := models.UserFilter{ Role: r.URL.Query().Get("role"), Status: r.URL.Query().Get("status"), } if limit := r.URL.Query().Get("limit"); limit != "" { if v, err := strconv.Atoi(limit); err == nil { filter.Limit_ = v } } users, err := h.userRepo.List(r.Context(), filter) if err != nil { writeError(w, http.StatusInternalServerError, "failed to list users", err) return } if users == nil { users = []*models.User{} } writeJSON(w, http.StatusOK, map[string]interface{}{"data": users}) }