180 lines
5.9 KiB
Go
180 lines
5.9 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"messenger/internal/models"
|
|
"messenger/internal/pkg/logger"
|
|
"messenger/internal/repository"
|
|
)
|
|
|
|
type AdminService struct {
|
|
userRepo repository.UserRepository
|
|
chatRepo repository.ChatRepository
|
|
messageRepo repository.MessageRepository
|
|
fileService *FileService
|
|
}
|
|
|
|
func NewAdminService(
|
|
userRepo repository.UserRepository,
|
|
chatRepo repository.ChatRepository,
|
|
messageRepo repository.MessageRepository,
|
|
fileService *FileService,
|
|
) *AdminService {
|
|
return &AdminService{
|
|
userRepo: userRepo,
|
|
chatRepo: chatRepo,
|
|
messageRepo: messageRepo,
|
|
fileService: fileService,
|
|
}
|
|
}
|
|
|
|
// DeleteUser удаляет пользователя (каскадно)
|
|
func (s *AdminService) DeleteUser(ctx context.Context, adminUserID, targetUserID int64) error {
|
|
// Проверяем, что администратор имеет права
|
|
admin, err := s.userRepo.FindByID(ctx, adminUserID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if admin == nil || !admin.IsGlobalAdmin() {
|
|
return errors.New("only global admin can delete users")
|
|
}
|
|
|
|
// Нельзя удалить самого себя через эту функцию
|
|
if adminUserID == targetUserID {
|
|
return errors.New("cannot delete yourself")
|
|
}
|
|
|
|
// Проверяем существование пользователя
|
|
target, err := s.userRepo.FindByID(ctx, targetUserID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if target == nil {
|
|
return errors.New("user not found")
|
|
}
|
|
|
|
// Удаляем пользователя (каскадное удаление сработает через foreign keys)
|
|
if err := s.userRepo.Delete(ctx, targetUserID); err != nil {
|
|
logger.Error("Failed to delete user", "error", err)
|
|
return errors.New("failed to delete user")
|
|
}
|
|
|
|
logger.Info("User deleted by admin", "admin_id", adminUserID, "target_user_id", targetUserID)
|
|
return nil
|
|
}
|
|
|
|
// DeleteMessage удаляет любое сообщение (админское право)
|
|
func (s *AdminService) DeleteMessage(ctx context.Context, adminUserID, messageID int64) error {
|
|
// Проверяем права администратора
|
|
admin, err := s.userRepo.FindByID(ctx, adminUserID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if admin == nil || !admin.IsGlobalAdmin() {
|
|
return errors.New("only global admin can delete any message")
|
|
}
|
|
|
|
if err := s.messageRepo.Delete(ctx, messageID); err != nil {
|
|
logger.Error("Failed to delete message by admin", "error", err)
|
|
return errors.New("failed to delete message")
|
|
}
|
|
|
|
logger.Info("Message deleted by admin", "admin_id", adminUserID, "message_id", messageID)
|
|
return nil
|
|
}
|
|
|
|
// DeleteChat удаляет любой чат (админское право)
|
|
func (s *AdminService) DeleteChat(ctx context.Context, adminUserID, chatID int64) error {
|
|
// Проверяем права администратора
|
|
admin, err := s.userRepo.FindByID(ctx, adminUserID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if admin == nil || !admin.IsGlobalAdmin() {
|
|
return errors.New("only global admin can delete any chat")
|
|
}
|
|
|
|
if err := s.chatRepo.Delete(ctx, chatID); err != nil {
|
|
logger.Error("Failed to delete chat by admin", "error", err)
|
|
return errors.New("failed to delete chat")
|
|
}
|
|
|
|
logger.Info("Chat deleted by admin", "admin_id", adminUserID, "chat_id", chatID)
|
|
return nil
|
|
}
|
|
|
|
// PromoteToAdmin повышает пользователя до глобального администратора
|
|
func (s *AdminService) PromoteToAdmin(ctx context.Context, adminUserID, targetUserID int64) error {
|
|
// Проверяем права администратора
|
|
admin, err := s.userRepo.FindByID(ctx, adminUserID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if admin == nil || !admin.IsGlobalAdmin() {
|
|
return errors.New("only global admin can promote users")
|
|
}
|
|
|
|
if err := s.userRepo.UpdateRole(ctx, targetUserID, models.RoleGlobalAdmin); err != nil {
|
|
logger.Error("Failed to promote user to admin", "error", err)
|
|
return errors.New("failed to promote user")
|
|
}
|
|
|
|
logger.Info("User promoted to global admin", "admin_id", adminUserID, "target_user_id", targetUserID)
|
|
return nil
|
|
}
|
|
|
|
// DemoteFromAdmin понижает глобального администратора до обычного пользователя
|
|
func (s *AdminService) DemoteFromAdmin(ctx context.Context, adminUserID, targetUserID int64) error {
|
|
// Проверяем права администратора
|
|
admin, err := s.userRepo.FindByID(ctx, adminUserID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if admin == nil || !admin.IsGlobalAdmin() {
|
|
return errors.New("only global admin can demote users")
|
|
}
|
|
|
|
// Нельзя понизить самого себя
|
|
if adminUserID == targetUserID {
|
|
return errors.New("cannot demote yourself")
|
|
}
|
|
|
|
if err := s.userRepo.UpdateRole(ctx, targetUserID, models.RoleUser); err != nil {
|
|
logger.Error("Failed to demote user", "error", err)
|
|
return errors.New("failed to demote user")
|
|
}
|
|
|
|
logger.Info("User demoted from global admin", "admin_id", adminUserID, "target_user_id", targetUserID)
|
|
return nil
|
|
}
|
|
|
|
// GetSystemStats возвращает системную статистику
|
|
func (s *AdminService) GetSystemStats(ctx context.Context, adminUserID int64) (map[string]interface{}, error) {
|
|
// Проверяем права администратора
|
|
admin, err := s.userRepo.FindByID(ctx, adminUserID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if admin == nil || !admin.IsGlobalAdmin() {
|
|
return nil, errors.New("only global admin can view system stats")
|
|
}
|
|
|
|
// Здесь можно добавить реальную статистику из БД
|
|
// Например, количество пользователей, сообщений, чатов и т.д.
|
|
stats := make(map[string]interface{})
|
|
|
|
// Это заглушка - в реальном коде нужно добавить методы в репозитории
|
|
stats["version"] = "1.0.0"
|
|
stats["status"] = "healthy"
|
|
|
|
logger.Info("System stats viewed by admin", "admin_id", adminUserID)
|
|
return stats, nil
|
|
} |