modified: internal/handlers/user.go
modified: internal/models/user.go modified: internal/repository/user_repository.go modified: internal/service/auth_service.go new file: internal/service/user_service.go modified: ../../begushiybashkir/bbvue/src/views/ProfileEdit.vue fix bag not editable profile
This commit is contained in:
@@ -33,10 +33,6 @@ func NewUserHandler(authService service.AuthService) *UserHandler {
|
|||||||
func (h *UserHandler) Routes() chi.Router {
|
func (h *UserHandler) Routes() chi.Router {
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
|
|
||||||
// Обработка OPTIONS запросов для CORS
|
|
||||||
r.Options("/profile", h.handleOptions)
|
|
||||||
r.Options("/editProfile", h.handleOptions)
|
|
||||||
|
|
||||||
r.Get("/profile", h.GetProfile)
|
r.Get("/profile", h.GetProfile)
|
||||||
r.Post("/editProfile", h.UpdateProfile)
|
r.Post("/editProfile", h.UpdateProfile)
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,17 @@ type User struct {
|
|||||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserUpdate struct {
|
||||||
|
ID uint `json:"id"`
|
||||||
|
FirstName string `json:"first_name"`
|
||||||
|
LastName string `json:"last_name"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
Experience string `json:"experience"`
|
||||||
|
Goals string `json:"goals"`
|
||||||
|
Newsletter bool `json:"newsletter"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
// HashPassword хеширует пароль перед сохранением
|
// HashPassword хеширует пароль перед сохранением
|
||||||
func (u *User) HashPassword() error {
|
func (u *User) HashPassword() error {
|
||||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package repository
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"api_bb/internal/models"
|
"api_bb/internal/models"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -11,6 +13,7 @@ type UserRepository interface {
|
|||||||
FindByEmail(email string) (*models.User, error)
|
FindByEmail(email string) (*models.User, error)
|
||||||
Update(user *models.User) error
|
Update(user *models.User) error
|
||||||
Delete(id uint) error
|
Delete(id uint) error
|
||||||
|
UpdateExcludeEmail(userUpdate *models.User) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type userRepository struct {
|
type userRepository struct {
|
||||||
@@ -44,3 +47,27 @@ func (r *userRepository) Update(user *models.User) error {
|
|||||||
func (r *userRepository) Delete(id uint) error {
|
func (r *userRepository) Delete(id uint) error {
|
||||||
return r.db.Delete(&models.User{}, id).Error
|
return r.db.Delete(&models.User{}, id).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// repository/user_repository.go
|
||||||
|
func (r *userRepository) UpdateExcludeEmail(userUpdate *models.User) error {
|
||||||
|
// Обновляем только разрешенные поля
|
||||||
|
result := r.db.Model(userUpdate).Where("id = ?", userUpdate.ID).Updates(map[string]interface{}{
|
||||||
|
"first_name": userUpdate.FirstName,
|
||||||
|
"last_name": userUpdate.LastName,
|
||||||
|
"phone": userUpdate.Phone,
|
||||||
|
"experience": userUpdate.Experience,
|
||||||
|
"goals": userUpdate.Goals,
|
||||||
|
"newsletter": userUpdate.Newsletter,
|
||||||
|
"updated_at": userUpdate.UpdatedAt,
|
||||||
|
})
|
||||||
|
|
||||||
|
if result.Error != nil {
|
||||||
|
return result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.RowsAffected == 0 {
|
||||||
|
return fmt.Errorf("user not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -3,8 +3,6 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"api_bb/internal/models"
|
"api_bb/internal/models"
|
||||||
"api_bb/internal/repository"
|
"api_bb/internal/repository"
|
||||||
@@ -38,57 +36,6 @@ func NewAuthService(userRepo repository.UserRepository, jwtService JWTService, l
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *authService) UpdateProfile(user *models.User) error {
|
|
||||||
s.logger.Info("Updating user profile",
|
|
||||||
zap.Uint("user_id", user.ID),
|
|
||||||
)
|
|
||||||
|
|
||||||
existingUser, err := s.userRepo.FindByID(user.ID)
|
|
||||||
if err != nil {
|
|
||||||
s.logger.Warn("User not found for profile update",
|
|
||||||
zap.Uint("user_id", user.ID),
|
|
||||||
zap.Error(err),
|
|
||||||
)
|
|
||||||
return fmt.Errorf("user not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
updateData := &models.User{
|
|
||||||
ID: existingUser.ID,
|
|
||||||
FirstName: user.FirstName,
|
|
||||||
LastName: user.LastName,
|
|
||||||
Phone: user.Phone,
|
|
||||||
Experience: user.Experience,
|
|
||||||
Goals: user.Goals,
|
|
||||||
Newsletter: user.Newsletter,
|
|
||||||
UpdatedAt: time.Now(),
|
|
||||||
}
|
|
||||||
|
|
||||||
s.logger.Debug("Profile update data prepared",
|
|
||||||
zap.Uint("user_id", user.ID),
|
|
||||||
zap.String("first_name", updateData.FirstName),
|
|
||||||
zap.String("last_name", updateData.LastName),
|
|
||||||
)
|
|
||||||
|
|
||||||
if err := s.userRepo.Update(updateData); err != nil {
|
|
||||||
s.logger.Error("Failed to update user profile",
|
|
||||||
zap.Uint("user_id", user.ID),
|
|
||||||
zap.Error(err),
|
|
||||||
)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
user.Email = existingUser.Email
|
|
||||||
user.Password = existingUser.Password
|
|
||||||
user.Role = existingUser.Role
|
|
||||||
user.CreatedAt = existingUser.CreatedAt
|
|
||||||
user.UpdatedAt = updateData.UpdatedAt
|
|
||||||
|
|
||||||
s.logger.Info("User profile updated successfully",
|
|
||||||
zap.Uint("user_id", user.ID),
|
|
||||||
)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *authService) Register(user *models.User) error {
|
func (s *authService) Register(user *models.User) error {
|
||||||
s.logger.Info("Registering new user",
|
s.logger.Info("Registering new user",
|
||||||
@@ -174,20 +121,3 @@ func min(a, b int) int {
|
|||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *authService) GetUserProfile(userID uint) (*models.User, error) {
|
|
||||||
s.logger.Debug("Getting user profile",
|
|
||||||
zap.Uint("user_id", userID),
|
|
||||||
)
|
|
||||||
|
|
||||||
user, err := s.userRepo.FindByID(userID)
|
|
||||||
if err != nil {
|
|
||||||
s.logger.Warn("Failed to get user profile",
|
|
||||||
zap.Uint("user_id", userID),
|
|
||||||
zap.Error(err),
|
|
||||||
)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return user, nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"api_bb/internal/models"
|
||||||
|
"api_bb/internal/repository"
|
||||||
|
"api_bb/pkg/logger"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserService interface {
|
||||||
|
GetUserProfile(userID uint) (*models.User, error)
|
||||||
|
UpdateProfile(user *models.User) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type userService struct {
|
||||||
|
userRepo repository.UserRepository
|
||||||
|
jwtService JWTService
|
||||||
|
logger logger.Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUserService(userRepo repository.UserRepository, jwtService JWTService, log logger.Interface) AuthService {
|
||||||
|
// Создаем логгер с контекстом для сервиса
|
||||||
|
serviceLogger := log.With(zap.String("service", "auth"))
|
||||||
|
|
||||||
|
return &authService{
|
||||||
|
userRepo: userRepo,
|
||||||
|
jwtService: jwtService,
|
||||||
|
logger: serviceLogger,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *authService) UpdateProfile(user *models.User) error {
|
||||||
|
s.logger.Info("Updating user profile",
|
||||||
|
zap.Uint("user_id", user.ID),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Проверяем, что пользователь существует
|
||||||
|
existingUser, err := s.userRepo.FindByID(user.ID)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("User not found for profile update",
|
||||||
|
zap.Uint("user_id", user.ID),
|
||||||
|
zap.Error(err),
|
||||||
|
)
|
||||||
|
return fmt.Errorf("user not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Убеждаемся, что email не меняется
|
||||||
|
user.Email = existingUser.Email
|
||||||
|
|
||||||
|
updateData := &models.User{
|
||||||
|
ID: user.ID,
|
||||||
|
FirstName: user.FirstName,
|
||||||
|
LastName: user.LastName,
|
||||||
|
Phone: user.Phone,
|
||||||
|
Experience: user.Experience,
|
||||||
|
Goals: user.Goals,
|
||||||
|
Newsletter: user.Newsletter,
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.userRepo.UpdateExcludeEmail(updateData)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *authService) GetUserProfile(userID uint) (*models.User, error) {
|
||||||
|
s.logger.Debug("Getting user profile",
|
||||||
|
zap.Uint("user_id", userID),
|
||||||
|
)
|
||||||
|
|
||||||
|
user, err := s.userRepo.FindByID(userID)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Warn("Failed to get user profile",
|
||||||
|
zap.Uint("user_id", userID),
|
||||||
|
zap.Error(err),
|
||||||
|
)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user