Não é possível suspender/desativar usuários em massa no console Rails no Discourse 3.5.0.beta5-dev

Olá a todos,

Estou enfrentando um problema persistente ao tentar suspender/desativar usuários em massa na minha instância do Discourse (versão 3.5.0.beta5-dev) através do console Rails. Estou tentando excluir minha conta de administrador (hoangthai, ID de usuário 100) e suspender permanentemente todos os outros usuários ativos que não são administradores/moderadores com um motivo personalizado “Chưa gia hạn tài khoản” (Renovação de conta pendente).

Eu tentei várias abordagens com base em comandos comuns do console Discourse e sugestões de depuração, mas as contas permanecem active: true mesmo que suspended_at e suspended_till sejam definidos.

Aqui está um resumo do que eu tentei e os erros/resultados:

Meu objetivo: Suspender todos os usuários permanentemente (exceto hoangthai, ID 100) com o motivo “Chưa gia hạn tài khoản” (Renovação de conta pendente).

Tentativas e Problemas:

  1. Tentativa inicial (Definindo suspend_reason, suspended_at, suspended_till diretamente):

    admin_id_to_exclude = 100
    User.where.not(id: admin_id_to_exclude).each do |user|
      if user.active? && !user.admin? && !user.moderator?
        user.suspend_reason = "Tài khoản tạm khóa do nghỉ phép dài hạn." # Primeira tentativa de motivo
        user.suspended_at = Time.current
        user.suspended_till = Time.current + 100.years
        user.save!
        puts "Khóa tài khoản: #{user.username}"
      end
    end
    
    • Resultado: NoMethodError: undefined method 'suspend_reason=' for an instance of User (sugerido suspended_at=). Isso indicou que suspend_reason não era o atributo correto.
  2. Segunda tentativa (Usando UserSuspension.suspend_user como sugerido para versões mais recentes):

    admin_id_to_exclude = 100
    User.where.not(id: admin_id_to_exclude).each do |user|
      if user.active? && !user.admin? && !user.moderator?
        UserSuspension.suspend_user(
            user,
            Time.current + 100.years,
            nil, # suspend_reason_id
            "Tài khoản tạm khóa: Nghỉ phép dài hạn.", # custom_suspend_reason
            Discourse.system_user
        )
        puts "Đã khóa tài khoản: #{user.username}"
      end
    end
    
    • Resultado: NameError: uninitialized constant UserSuspension (sugerido UserSuspender). Isso indicou que o nome da classe estava incorreto.
  3. Terceira tentativa (Nome da classe corrigido para UserSuspender):

    admin_id_to_exclude = 100
    User.where.not(id: admin_id_to_exclude).each do |user|
      if user.active? && !user.admin? && !user.moderator?
        UserSuspender.suspend_user( # Ainda tentando suspend_user
            user,
            Time.current + 100.years,
            nil,
            "Tài khoản tạm khóa: Nghỉ phép dài hạn.",
            Discourse.system_user
        )
        puts "Đã khóa tài khoản: #{user.username}"
      end
    end
    
    • Resultado: NoMethodError: undefined method 'suspend_user' for class UserSuspender (sugerido UserSuspended?). Isso mostrou que o nome do método também estava incorreto.
  4. Quarta Tentativa (Usando UserSuspender.new(...).suspend como o padrão de objeto de serviço):

    admin_id_to_exclude = 100
    User.where.not(id: admin_id_to_exclude).each do |user|
      if user.active? 					begin
            UserSuspender.new(
                user,
                Discourse.system_user,
                reason: "Tài khoản tạm khóa: Nghỉ phép dài hạn.",
                suspended_till: nil # Para suspensão permanente
            ).suspend
            puts "Đã khóa tài khoản: #{user.username}"
        rescue => e
            puts "Lỗi khi khóa tài khoản #{user.username}: #{e.message}"
        end
      end
    end
    
    • Resultado: Este comando foi executado sem erros no console. Imprimiu “Đã khóa tài khoản: [username]”.
    • No entanto, ao verificar o status do usuário na interface do administrador ou consultar diretamente user.active no console, os usuários ainda mostravam active: true. Apenas suspended_at e suspended_till foram atualizados (por exemplo, suspended_at: "2025-05-26 00:37:01.406064419 +0000", suspended_till: nil). As contas ainda conseguiam fazer login.
  5. Quinta Tentativa (Definindo diretamente active = false junto com os campos de suspensão):

    admin_id_to_exclude = 100
    User.where.not(id: admin_id_to_exclude).each do |user|
      if user.active? 					begin
            user.suspended_at = Time.current
            user.suspended_till = nil # Permanente
            user.custom_suspension_reason = "Chưa gia hạn tài khoản" # Motivo personalizado
            user.active = false # Parte crucial
            user.save!
            puts "Đã **khóa VĨNH VIỄN** và vô hiệu hóa tài khoản: #{user.username}"
        rescue => e
            puts "LỖI khi xử lý tài khoản #{user.username}: #{e.message}"
        end
      end
    end
    
    • Resultado: Este comando também foi executado sem erros e imprimiu mensagens de sucesso.
    • No entanto, o resultado foi o mesmo: active: true permaneceu, e suspended_at/suspended_till foram atualizados, mas as contas não foram realmente desativadas…
1 curtida

Não acredito que a desativação faça parte do processo de suspensão de usuários. Na interface do usuário, você precisaria pressionar o botão ‘desativar’ separadamente se quisesse que um usuário suspenso que retorna também reverificasse seu e-mail.

Decidir se é isso que você quer e tratá-lo como uma operação separada pode trazer melhores resultados. :crossed_fingers:

Há algumas orientações para suspensões em massa neste tópico, se isso ajudar: Administrative Bulk Operations

Embora, se você tentar isso e descobrir que está desatualizado, informe-os e eles deverão ser capazes de atualizar o guia de acordo.

1 curtida