package services import ( "errors" "gobeyhan/database" "gobeyhan/database/models" "golang.org/x/crypto/bcrypt" "gorm.io/gorm" ) type UserService struct{} func NewUserService() *UserService { return &UserService{} } // GetAllUsers retrieves all users, optionally including soft-deleted ones func (s *UserService) GetAllUsers(includeDeleted bool, page, limit int) ([]models.User, int64, error) { var users []models.User var total int64 query := database.DB.Preload("Roles").Preload("SocialAccounts") if includeDeleted { query = query.Unscoped() } query.Model(&models.User{}).Count(&total) err := query. Offset((page - 1) * limit). Limit(limit). Order("created_at DESC"). Find(&users).Error return users, total, err } // GetUserByID retrieves a user by ID func (s *UserService) GetUserByID(id uint64) (*models.User, error) { var user models.User err := database.DB. Preload("Roles"). Preload("SocialAccounts"). First(&user, id).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil } return nil, err } return &user, nil } // GetUserByEmail retrieves a user by email func (s *UserService) GetUserByEmail(email string) (*models.User, error) { var user models.User err := database.DB. Preload("Roles"). Preload("SocialAccounts"). Where("email = ?", email). First(&user).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil } return nil, err } return &user, nil } // CreateUser creates a new user with hashed password func (s *UserService) CreateUser(user *models.User, password string) error { // Hash password if provided if password != "" { hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return err } user.Password = string(hashedPassword) } return database.DB.Create(user).Error } // VerifyPassword checks if the provided password matches the hashed password func (s *UserService) VerifyPassword(hashedPassword, password string) bool { err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password)) return err == nil } // UpdateUser updates an existing user func (s *UserService) UpdateUser(id uint64, updates map[string]interface{}) error { // If password is being updated, hash it first if password, ok := updates["password"].(string); ok && password != "" { hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return err } updates["password"] = string(hashedPassword) } result := database.DB.Model(&models.User{}).Where("id = ?", id).Updates(updates) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return gorm.ErrRecordNotFound } return nil } // DeleteUser soft deletes a user func (s *UserService) DeleteUser(id uint64) error { result := database.DB.Delete(&models.User{}, id) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return gorm.ErrRecordNotFound } return nil } // RestoreUser restores a soft-deleted user func (s *UserService) RestoreUser(id uint64) error { result := database.DB.Model(&models.User{}).Unscoped(). Where("id = ?", id). Update("deleted_at", nil) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return gorm.ErrRecordNotFound } return nil } // AssignRole assigns a role to a user func (s *UserService) AssignRole(userID, roleID uint64) error { var user models.User if err := database.DB.First(&user, userID).Error; err != nil { return err } var role models.Role if err := database.DB.First(&role, roleID).Error; err != nil { return err } return database.DB.Model(&user).Association("Roles").Append(&role) } // RemoveRole removes a role from a user func (s *UserService) RemoveRole(userID, roleID uint64) error { var user models.User if err := database.DB.Preload("Roles").First(&user, userID).Error; err != nil { return err } var role models.Role if err := database.DB.First(&role, roleID).Error; err != nil { return err } return database.DB.Model(&user).Association("Roles").Delete(&role) } // AssignDefaultRole assigns the default 'user' role to a user func (s *UserService) AssignDefaultRole(userID uint64) error { var role models.Role // Find role by name 'user' if err := database.DB.Where("name = ?", "user").First(&role).Error; err != nil { return err } return s.AssignRole(userID, role.ID) }