258 lines
6.8 KiB
Go
258 lines
6.8 KiB
Go
package services
|
||
|
||
import (
|
||
"errors"
|
||
|
||
"gauth-central/internal/database"
|
||
"gauth-central/internal/models"
|
||
|
||
"golang.org/x/crypto/bcrypt"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
type UserManagementService struct{}
|
||
|
||
func NewUserManagementService() *UserManagementService {
|
||
return &UserManagementService{}
|
||
}
|
||
|
||
var ErrUserNotFound = errors.New("user not found")
|
||
|
||
// GetAllUsers - Tüm kullanıcıları getir (admin için)
|
||
func (s *UserManagementService) GetAllUsers(page, limit int) ([]models.User, int64, error) {
|
||
var users []models.User
|
||
var total int64
|
||
|
||
// Count total users
|
||
database.DB.Model(&models.User{}).Count(&total)
|
||
|
||
// Calculate offset
|
||
offset := (page - 1) * limit
|
||
|
||
// Fetch users with pagination and preload roles
|
||
err := database.DB.
|
||
Preload("Roles").
|
||
Preload("SocialAccounts").
|
||
Offset(offset).
|
||
Limit(limit).
|
||
Order("created_at DESC").
|
||
Find(&users).Error
|
||
|
||
return users, total, err
|
||
}
|
||
|
||
// GetUserByID - ID'ye göre kullanıcı getir
|
||
func (s *UserManagementService) GetUserByID(userID string) (*models.User, error) {
|
||
var user models.User
|
||
err := database.DB.
|
||
Preload("Roles").
|
||
Preload("Roles.Permissions").
|
||
Preload("SocialAccounts").
|
||
Where("id = ?", userID).
|
||
First(&user).Error
|
||
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return &user, nil
|
||
}
|
||
|
||
// CreateUser - Yeni kullanıcı oluştur (admin tarafından)
|
||
func (s *UserManagementService) CreateUser(email, password, userName string, emailVerified bool, roleNames []string) (*models.User, error) {
|
||
// Hash password
|
||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
user := &models.User{
|
||
Email: email,
|
||
UserName: userName,
|
||
Password: string(hashedPassword),
|
||
EmailVerified: &emailVerified,
|
||
}
|
||
|
||
// Create user
|
||
if err := database.DB.Create(user).Error; err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// Assign roles
|
||
if len(roleNames) > 0 {
|
||
var roles []models.Role
|
||
database.DB.Where("name IN ?", roleNames).Find(&roles)
|
||
if len(roles) > 0 {
|
||
database.DB.Model(user).Association("Roles").Append(roles)
|
||
}
|
||
} else {
|
||
// Assign default "user" role
|
||
var userRole models.Role
|
||
database.DB.Where("name = ?", "user").First(&userRole)
|
||
database.DB.Model(user).Association("Roles").Append(&userRole)
|
||
}
|
||
|
||
// Reload user with roles
|
||
database.DB.Preload("Roles").Where("id = ?", user.ID).First(user)
|
||
|
||
return user, nil
|
||
}
|
||
|
||
// UpdateUser - Kullanıcı bilgilerini güncelle
|
||
func (s *UserManagementService) UpdateUser(userID string, updates map[string]interface{}) error {
|
||
// Check if user exists
|
||
var user models.User
|
||
if err := database.DB.Where("id = ?", userID).First(&user).Error; err != nil {
|
||
return err
|
||
}
|
||
|
||
// If password is being updated, hash it
|
||
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)
|
||
}
|
||
|
||
// Use Updates with Select to update specific fields including zero values
|
||
return database.DB.Model(&user).Updates(updates).Error
|
||
}
|
||
|
||
// DeleteUser - Kullanıcıyı sil (soft delete, hard=true ise kalıcı silme)
|
||
func (s *UserManagementService) DeleteUser(userID string, hardDelete bool) error {
|
||
if hardDelete {
|
||
// Hard delete - ilişkili kayıtları da sil
|
||
var user models.User
|
||
if err := database.DB.Unscoped().Where("id = ?", userID).First(&user).Error; err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return ErrUserNotFound
|
||
}
|
||
return err
|
||
}
|
||
|
||
// Delete relations first
|
||
database.DB.Exec("DELETE FROM user_roles WHERE user_id = ?", userID)
|
||
database.DB.Exec("DELETE FROM social_accounts WHERE user_id = ?", userID)
|
||
|
||
// Permanently delete user
|
||
result := database.DB.Unscoped().Delete(&models.User{}, "id = ?", userID)
|
||
if result.Error != nil {
|
||
return result.Error
|
||
}
|
||
if result.RowsAffected == 0 {
|
||
return ErrUserNotFound
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// Soft delete
|
||
result := database.DB.Delete(&models.User{}, "id = ?", userID)
|
||
if result.Error != nil {
|
||
return result.Error
|
||
}
|
||
if result.RowsAffected == 0 {
|
||
return ErrUserNotFound
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// AssignRoles - Kullanıcıya roller ata
|
||
func (s *UserManagementService) AssignRoles(userID string, roleNames []string) error {
|
||
var user models.User
|
||
if err := database.DB.Where("id = ?", userID).First(&user).Error; err != nil {
|
||
return err
|
||
}
|
||
|
||
var roles []models.Role
|
||
if err := database.DB.Where("name IN ?", roleNames).Find(&roles).Error; err != nil {
|
||
return err
|
||
}
|
||
|
||
if len(roles) == 0 {
|
||
return errors.New("no valid roles found")
|
||
}
|
||
|
||
return database.DB.Model(&user).Association("Roles").Replace(roles)
|
||
}
|
||
|
||
// RemoveRole - Kullanıcıdan rol kaldır
|
||
func (s *UserManagementService) RemoveRole(userID string, roleName string) error {
|
||
var user models.User
|
||
if err := database.DB.Where("id = ?", userID).First(&user).Error; err != nil {
|
||
return err
|
||
}
|
||
|
||
var role models.Role
|
||
if err := database.DB.Where("name = ?", roleName).First(&role).Error; err != nil {
|
||
return err
|
||
}
|
||
|
||
return database.DB.Model(&user).Association("Roles").Delete(&role)
|
||
}
|
||
|
||
// SearchUsers - Kullanıcı ara (email, username)
|
||
func (s *UserManagementService) SearchUsers(query string, page, limit int) ([]models.User, int64, error) {
|
||
var users []models.User
|
||
var total int64
|
||
|
||
searchQuery := "%" + query + "%"
|
||
|
||
// Count total matching users
|
||
database.DB.Model(&models.User{}).
|
||
Where("email ILIKE ? OR user_name ILIKE ?", searchQuery, searchQuery).
|
||
Count(&total)
|
||
|
||
// Calculate offset
|
||
offset := (page - 1) * limit
|
||
|
||
// Fetch users
|
||
err := database.DB.
|
||
Preload("Roles").
|
||
Preload("SocialAccounts").
|
||
Where("email ILIKE ? OR user_name ILIKE ?", searchQuery, searchQuery).
|
||
Offset(offset).
|
||
Limit(limit).
|
||
Order("created_at DESC").
|
||
Find(&users).Error
|
||
|
||
return users, total, err
|
||
}
|
||
|
||
// GetDeletedUsers - Soft delete edilmiş kullanıcıları getir
|
||
func (s *UserManagementService) GetDeletedUsers(page, limit int) ([]models.User, int64, error) {
|
||
var users []models.User
|
||
var total int64
|
||
|
||
// Count total deleted users
|
||
database.DB.Model(&models.User{}).Unscoped().Where("deleted_at IS NOT NULL").Count(&total)
|
||
|
||
// Calculate offset
|
||
offset := (page - 1) * limit
|
||
|
||
// Fetch deleted users with pagination
|
||
err := database.DB.Unscoped().
|
||
Preload("Roles").
|
||
Preload("SocialAccounts").
|
||
Where("deleted_at IS NOT NULL").
|
||
Offset(offset).
|
||
Limit(limit).
|
||
Order("deleted_at DESC").
|
||
Find(&users).Error
|
||
|
||
return users, total, err
|
||
}
|
||
|
||
// RestoreUser - Soft delete edilmiş kullanıcıyı geri yükle
|
||
func (s *UserManagementService) RestoreUser(userID string) error {
|
||
var user models.User
|
||
|
||
// Find soft deleted user
|
||
if err := database.DB.Unscoped().Where("id = ? AND deleted_at IS NOT NULL", userID).First(&user).Error; err != nil {
|
||
return errors.New("deleted user not found")
|
||
}
|
||
|
||
// Restore user (set deleted_at to NULL)
|
||
return database.DB.Unscoped().Model(&user).Update("deleted_at", nil).Error
|
||
}
|